• YbSoftwareFactory 代码生成插件【二十五】:Razor视图中以全局方式调用后台方法输出页面代码的三种方法


      上一篇介绍了 MVC中实现动态自定义路由 的实现,本篇将介绍Razor视图中以全局方式调用后台方法输出页面代码的三种方法。

      框架最新的升级实现了一个页面部件功能,其实就是通过后台方法查询数据库内容,把查询结果的 HTML 代码呈现到 Razor 视图中,考虑到灵活性,需要能在任意 Razor 视图中调用该方法,这样任意 Razor 页面都能以统一的方式方便地共享该页面部件的 HTML 内容,这对于代码的重用性和可维护性都是非常有必要的。

      为实现上述要求,本文介绍如下可供选择的三种方式。

      1、扩展静态类 Helper 方法,返回 HtmlString

      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)此时界面可以这样调用:

    @Html.Image("my-id", "~/Content/my-img.png", "Alt Text")

      总结:此方式最简单,但缺点也非常明显,因为是静态类,无法方便的进行依赖注入以调用其他实例方法。

      2、继承 WebViewPage<TModel> 实现自定义的 WebViewPage ,在子类中实现返回界面 HTML 字符串的方法。

      此种方式可参照Abp框架中多语言的本地化实现过程,步骤如下:

      1)继承 WebViewPage 类

    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 中配置页面视图的基类,在未配置的页面中无法进行方法的调用

      3、推荐的最佳方案

      我们换种方式实现 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 方法的全局共享,调用的时候可以使用自己定义的标签,代码可读性更强。

  • 相关阅读:
    flume和kafka整合(转)
    Flume目录
    Flume的安装配置
    HBase系统架构及数据结构(转)
    toolbar ,textfield,图片拉伸,Bundle
    poj 1017 Packets
    jQuery使用serialize(),serializeArray()方法取得表单数据+字符串和对象类型两种表单提交的方法
    Android数据加密概述及多种加密方式 聊天记录及账户加密 提供高质量的数据保护
    LintCode-落单的数 III
    LeetCode90:Subsets II
  • 原文地址:https://www.cnblogs.com/gyche/p/5597491.html
Copyright © 2020-2023  润新知