美文网首页Asp.net core mvc
几个常用的HtmlHelper扩展方法

几个常用的HtmlHelper扩展方法

作者: firechun | 来源:发表于2020-01-07 11:52 被阅读0次

ASP.NET MVC的HtmlHelper类用来在网页中生成html脚本,这里有几个扩展方法,几乎每个ASP.NET MVC或ASP.NET MVC Core项目都可以用到,在这里记一下,免得每次都去翻以前的项目。

    /// <summary>
    /// 为Html类添加的扩展方法
    /// </summary>
    public static class HtmlExtensions
    {
        /// <summary>
        /// 在子视图中呈现一段脚本,用于编辑模板等不能使用@section嵌入脚本的视图
        /// <para>用法:@Html.Script(@&lt;script&gt;脚本内容&lt;/script&gt;)</para>
        /// </summary>
        /// <param name="htmlHelper"></param>
        /// <param name="template"></param>
        /// <returns></returns>
        public static string Script(this IHtmlHelper htmlHelper, Func<object, HelperResult> template)
        {
            htmlHelper.ViewContext.HttpContext.Items["_script_" + Guid.NewGuid()] = template;
            return string.Empty;
        }

        /// <summary>
        /// 呈现<see cref="Script(HtmlHelper, int, Func{object, HelperResult})"/>嵌入的脚本
        /// </summary>
        /// <param name="htmlHelper"></param>
        /// <returns></returns>
        public static string RenderScripts(this IHtmlHelper htmlHelper)
        {
            foreach (object key in htmlHelper.ViewContext.HttpContext.Items.Keys)
            {
                if (key.ToString().StartsWith("_script_"))
                {
                    var template = htmlHelper.ViewContext.HttpContext.Items[key] as Func<object, HelperResult>;
                    if (template != null)
                    {
                        htmlHelper.ViewContext.Writer.Write(template(null));
                    }
                }
            }
            return string.Empty;
        }

        /// <summary>
        /// 在网页中生成引入js文件的&lt;script src=&gt;&lt;/script&gt;代码
        /// </summary>
        /// <param name="htmlHelper"></param>
        /// <param name="action">动作方法名称,默认为当前动作方法</param>
        /// <param name="controller">控制器名称,默认为当前控制器</param>
        /// <param name="root">js文件的根目录,默认为"~/js/"</param>
        /// <returns>&lt;script&gt; src="{root}{controller.ToLower()}.{action.ToLower()}.js"&lt;/script&gt;</returns>
        public static HtmlString LoadScriptFile(this IHtmlHelper htmlHelper, string action = null, string controller = null, string root = "/js/")
        {
            if (action == null)
            {
                action = (htmlHelper.ViewContext.ActionDescriptor as ControllerActionDescriptor).ActionName;
            }
            if (controller == null)
            {
                controller = (htmlHelper.ViewContext.ActionDescriptor as ControllerActionDescriptor).ControllerName;
            }
            //AddPathSeparator(),字符串扩展方法,检查字符串是否以"\"结束,不是则加上"\"
            root = root.AddPathSeparator();
            var fileName = $"{root}{controller.ToLower()}.{action.ToLower()}.js";
#if DEBUG
            string localPath = Directory.GetParent(AppContext.BaseDirectory).Parent.Parent.Parent.FullName.AddPathSeparator();
#else
                string localPath = AppContext.BaseDirectory.AddPathSeparator();
#endif
            var localFile = $"{localPath}wwwroot{fileName}";
            if (File.Exists(localFile))
            {
                return new HtmlString($"<script src=\"{root}{controller.ToLower()}.{action.ToLower()}.js?v={File.GetLastWriteTime(localFile).Ticks}\"></script>");
            }
            return null;
        }
    }

一般情况下,我们可以在_Layout.cshtml中使用@RenderSection("Scripts", required: false)来嵌入脚本。
例如_Layout.cshtml的代码如下:

<!DOCTYPE html>
<html>
<head>
</head>
<body>
    @RenderBody()
    <script src="~/lib/jquery/jquery.min.js"></script>
    @RenderSection("Scripts", required: false)
</body>
</html>

视图代码如下:

<div>
  页面内容
</div>
@section scripts{ 
    <script>
        $(function () {

        })
    </script>
}

最后生成的网页就是下面这样:

<!DOCTYPE html>
<html>
<head>
</head>
<body>
    <div>
      页面内容
    </div>
    <script src="~/lib/jquery/jquery.min.js"></script>
    <script>
        $(function () {

        })
    </script>    
</body>
</html>

但是如果我在编辑模板中嵌入了js脚本,页面又引用了编辑模板,那么编辑模板中的脚本不会被RenderSection方法呈现出来。
例如:

编辑模板.cshtml:
<div>
  页面内容
</div>
@section scripts{ 
    <script>
        $(function () {

        })
    </script>
}
内容视图:
<form asp-action="Create" data-ajax="true" data-ajax-success="onSuccess">
    @Html.EditorForModel("编辑模板")
</form>
生成的页面:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
    <div>
      页面内容
    </div>
    <script src="~/lib/jquery/jquery.min.js"></script>
    <!--这里应该有的脚本没有出现-->
</body>
</html>

我写的扩展方法Script和RenderScripts就是用来解决这个问题的。
在编辑模板中用Script方法嵌入脚本

<div>
  页面内容
</div>
@Html.Script(
    @<script>
        $(function () {

        })
    </script>
)

在_Layout.cshtml中用RenderScipts来呈现脚本

<!DOCTYPE html>
<html>
<head>
</head>
<body>
    @RenderBody()
    <script src="~/lib/jquery/jquery.min.js"></script>
    @RenderSection("Scripts", required: false)
    @*呈现编辑模板中的脚本*@
    @Html.RenderScipts()
</body>
</html>

第三个方法LoadScriptFile方法用来加载当前网页对应的js脚本文件。如果一个页面上含有大量的js代码,我们通常都会把这些代码放到独立的js文件中,这个方法就是用来自动加载这些独立的js脚本的。
使用方式很简单,在_Layout.cshtml中需要加载脚本的地方插入@Html.LoadScriptFile(),然后把脚本文件命名为控制器名称.动作方法名称.js,并放到指定目录下就可以了。
例如HomeController中的Index的脚本文件,命名就是home.index.js,默认目录是网站根路径下的js目录,本文中的代码对应的是ASP.NET MVC Core版本,默认目录是网站根路径下wwwrooot下的js目录。
方法会自动检测脚本文件是否存在,存在则会生成<script src="文件路径"></script>代码加载脚本文件。
方法也可以指定参数:@Html.LoadScriptFile("Create","User","/scripts")加载wwwroot/scripts目录下的user.create.js脚本文件。

相关文章

网友评论

    本文标题:几个常用的HtmlHelper扩展方法

    本文链接:https://www.haomeiwen.com/subject/cmkractx.html