上一篇介紹了 MVC中實現動態自定義路由 的實現,本篇將介紹Razor視圖中以全局方式調用後臺方法輸出頁面代碼的三種方法。html
框架最新的升級實現了一個頁面部件功能,其實就是經過後臺方法查詢數據庫內容,把查詢結果的 HTML 代碼呈現到 Razor 視圖中,考慮到靈活性,須要能在任意 Razor 視圖中調用該方法,這樣任意 Razor 頁面都能以統一的方式方便地共享該頁面部件的 HTML 內容,這對於代碼的重用性和可維護性都是很是有必要的。web
爲實現上述要求,本文介紹以下可供選擇的三種方式。數據庫
一、擴展靜態類 Helper 方法,返回 HtmlStringapi
1)可參考以下代碼:框架
public static class ImageHelper { public static HtmlString Image(this HtmlHelper helper, string id, string url, string alternateText) { return Image(helper, id, url, alternateText, null); } public static HtmlString Image(this HtmlHelper helper, string id, string url, string alternateText, object htmlAttributes) { // Instantiate a UrlHelper var urlHelper = new UrlHelper(helper.ViewContext.RequestContext); // Create tag builder var builder = new TagBuilder("img"); // Create valid id builder.GenerateId(id); // Add attributes builder.MergeAttribute("src", urlHelper.Content(url)); builder.MergeAttribute("alt", alternateText); builder.MergeAttributes(new RouteValueDictionary(htmlAttributes)); // Render tag var ret = new MvcHtmlString(builder.ToString(TagRenderMode.SelfClosing)); return ret; } }
2)此時界面能夠這樣調用:post
@Html.Image("my-id", "~/Content/my-img.png", "Alt Text")
總結:此方式最簡單,但缺點也很是明顯,由於是靜態類,沒法方便的進行依賴注入以調用其餘實例方法。ui
二、繼承 WebViewPage<TModel> 實現自定義的 WebViewPage ,在子類中實現返回界面 HTML 字符串的方法。this
此種方式可參照Abp框架中多語言的本地化實現過程,步驟以下:url
1)繼承 WebViewPage 類spa
public abstract class AbpWebViewPage<TModel> : WebViewPage<TModel>
2)實現方法,返回指定 Key 名稱的本地化語言字符串
/// <summary> /// Gets localized string for given key name and current language. /// </summary> /// <param name="name">Key name</param> /// <returns> /// Localized string /// </returns> protected virtual string L(string name) { return this._localizationSource.GetString(name); }
3)在 Web.config 中配置視圖基類
<system.web.webPages.razor> <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /> <pages pageBaseType="Yb.AbpZero.Web.Views.AbpZeroTemplateWebViewPageBase"> <namespaces> <add namespace="System.Web.Mvc" /> <add namespace="System.Web.Mvc.Ajax" /> <add namespace="System.Web.Mvc.Html" /> <add namespace="System.Web.Routing" /> <add namespace="System.Web.Optimization" /> <add namespace="Yb.AbpZero.Web" /> <add namespace="Yb.AbpZero.Localization" /> </namespaces> </pages> </system.web.webPages.razor>
4)這樣視圖頁面上就能夠方便的調用 @L("Dashboard") 代碼輸出對應語言的字符串內容
總結:此種方式須要在指定文件夾下的 Web.config 中配置頁面視圖的基類,在未配置的頁面中沒法進行方法的調用
三、推薦的最佳方案
咱們換種方式實現 Helper 方法,經過使用全局 Razor 視圖中的 Helper 代碼去訪問後臺方法並輸出結果
1)繼承 System.Web.WebPages.HelperPage ,並重寫 Html 屬性
此處須要注意的是 System.Web.WebPages.HelperPage 的 Html 對象和以下重寫的 Html 對象不是同一個類,爲便於記憶、統一以 MVC Razor 中的關鍵字進行界面調用,咱們此處仍是把屬性名稱定義爲 Html 。
public class HelperPage : System.Web.WebPages.HelperPage { // Workaround - exposes the MVC HtmlHelper instead of the normal helper public static new HtmlHelper Html { get { return ((WebViewPage) WebPageContext.Current.Page).Html; } } }
2)把 Helper 方法放到 App_Code 文件夾下的 Razor 視圖中
咱們已經知道Razor能夠訪問本路徑下其餘 Razor 視圖中定義的 Helper 方法,但如今咱們考慮的是任意路徑下 Razor 視圖可均共享該 Helper 方法。
首先在 App_Code 文件夾下建立一個 Razor 視圖,該視圖將會被進行動態編譯,經過 Razor 的視圖引擎調用後臺方法輸出界面所需的 HTML 代碼,代碼以下:
@inherits YbRapidSolution.Mvc.HelperPage @using System.Web.Mvc.Html @helper Partial(string id) { Html.RenderAction("_Widget", "Home", new { id }); }
3)咱們在 _Widget 的後臺方法中來訪問數據庫,而後生成頁面部分視圖並返回至界面,代碼以下:
#region CMS部件呈現 /// <summary> /// CMS部件呈現 /// </summary> /// <param name="id"></param> /// <returns></returns> [ChildActionOnly] public PartialViewResult _Widget(string id) { if (string.IsNullOrEmpty(id)) { return PartialView("E404"); } var widget = _widgetService.GetById(id); if (widget == null) { return PartialView("E404"); } if (string.IsNullOrWhiteSpace(widget.TemplatePath)) { return PartialView("_Widget", widget); } return PartialView(widget.TemplatePath, widget); } #endregion
4)這樣就可在任意頁面進行調用以下代碼生成界面所需的 Html 字符串,而字符串的內容則可放到數據庫中,可在須要的時候在後臺進行修改和維護:
@_Widget.Partial("31dbfb04b41e4883bab880ceec2cfef3")
總結:此種方式無需額外配置便可實現 Helper 方法的全局共享,調用的時候可使用本身定義的標籤,代碼可讀性更強。