zoukankan      html  css  js  c++  java
  • 自定义ASP.NET MVC Html标签辅助方法

    原文:https://blog.csdn.net/a497785609/article/details/50184779

     

    在ASP.NET MVC中,Html辅助方法给我们程序员带来很多方便,其重要性也就不言自明。有时候,我们不想重复地写一些HTML代码,或者MS没有提供我们想要的那个HTML标签的Html辅助方法,那么,我们就可以通过自己定义一个Html扩展方法来达到这个目的。

    比如,到目前为止,Html扩展方法中没有关于<input type="file" />这类标签的辅助方法,那么我们就可以自已实现一个。本文以实现<input type="file" />标签为例,演示如何实现自定义Html扩展方法。

     

    一、实现自定义弱类型Html扩展方法

    其实实现自定义Html扩展方法并不难,有兴趣的同学可以去看下MVC源代码,关于Html扩展方法部分。要用到System.Web.Mvc命名空间下的TagBuilder类,MvcHtmlString类。TagBuilder类为Html辅助方法生成HTML标签,MvcHtmlString代表HTML编码的字符串。扩展方法代码如下所示:

    public static class MyInputExtensions
    {
        public static MvcHtmlString Input(this HtmlHelper htmlHelper, string name)
        {
    
            TagBuilder tagBuilder = new TagBuilder("input");//设置标签类型为input
    
            tagBuilder.Attributes.Add("type", "file");//为标签添加type属性及值
    
            tagBuilder.Attributes.Add("name", name);//为标签添加name属性及值
    
            tagBuilder.GenerateId(name);//为标签生成Id,name参数代码Id的值
    
            //创建经过HTML加密的字符串
    
            //TagRenderMode.SelfClosing枚举值代表当前标签是自动关闭的
    
            return MvcHtmlString.Create(tagBuilder.ToString(TagRenderMode.SelfClosing));
        }
    }
    

      

    需要特别提醒的是,扩展方法类所在的命名空间最好设置为System.Web.Mvc,这样,我们在View中可以通过智能感知轻易找到,也不容易出错或者无法通过VS智能感知找到我们自定义的Html辅助方法,可以为我们省去很多不必要的麻烦。将上面代码编译,我们即可在View中通过智能感知看到我们自定义的Html辅助方法。如下图所示:

    使用方法和其它Html辅助方法一样,如下代码所示:

          <%: Html.Input("Path") %> //字符串参数Path代表生成标签的name属性和id属性的值 

    需要说明的是,本例所示是为了生成<input type="file">标签,是不用设置值的,读者可以通过自身情况定义扩展方法。然后运行,通过浏览器查看HTML源代码,如下图所示:

    二、实现自定义强类型Html辅助方法

    强类型辅助方法的一个好处是,我们可以通过编译器为我们检测一些错误,为我们节省一些排错的时间与精力。所以,强类型Html辅助方法是不可缺少的。代码如下:

     public static class MyInputExtensions
    
     {
    
         public static MvcHtmlString Input<TModel, TValue>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TValue>> expression)
    
         {
    
             string modelName = ExpressionHelper.GetExpressionText(expression);//从Lambda表达式中获取模型对应属性的名称
    
              TagBuilder tagBuilder = new TagBuilder("input");//设置标签类型为input
    
             tagBuilder.Attributes.Add("type", "file");//为标签添加type属性及值
    
              tagBuilder.Attributes.Add("name", modelName);//为标签添加name属性及值
    
              tagBuilder.GenerateId(modelName);//为标签生成Id,name参数代码Id的值
    
              //创建经过HTML加密的字符串
    
              //TagRenderMode.SelfClosing枚举值代表当前标签是自动关闭的
    
             return MvcHtmlString.Create(tagBuilder.ToString(TagRenderMode.SelfClosing));
    
         }
    
     }
    

      

    然后我们编译,在View中,我们就可以通过智能感知看到我们新扩展的强类型Html辅助方法了。如下图所示:

      

    我们可以通过如下代码使用新扩展的Html辅助方法:

           <%: Html.Input(model => model.Path) %>//Path代表model的Path属性,生成标签的name和id的属性值均会是Path

    运行,我们通过浏览器查看生成的Html源代码如下图所示:

      

    三、为标签错误输入添加CSS支持

    对于要求输入的标签,如Text,如果用户输入错误内容,我们可以为当前标签添加CSS错误提示,为用户提供一个更加友好、人性化的界面。代码如下所示:

    ModelState modelState;
    
    if (htmlHelper.ViewData.ModelState.TryGetValue(name, out modelState))
    
    {
    
        if (modelState.Errors.Count > 0)
    
        {
    
            //添加错误提示CSS
    
             tagBuilder.AddCssClass(HtmlHelper.ValidationInputCssClassName);
    
         }
    
     }
    

      

    将以上代码复制到我们自定义的扩展方法的返回MvcHtmlString字符串之前即可。

    四、总结

    本文通过演示如果实现自定义<input type="file" />标签的Html辅助方法,展示了如何在ASP.NET MVC中实现自定义Html辅助方法。对于ASP.NET MVC程序员来说,这是非常实用的。

     

    五、补充

    一个完整的扩展示例方法:

    public static MvcHtmlString InputText<TModel, TValue>(this HtmlHelper<TModel> html,
                Expression<Func<TModel, TValue>> expression, IDictionary<string, object> htmlAttributes)
            {  
                TagBuilder tagBuilder = new TagBuilder("input");
    
                var metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);
    
                //第1步:获取模型字段的显示文本
                string text = metadata.DisplayName ?? metadata.PropertyName;
    
                //第2步:获取模型字段的字段名
                var name = ExpressionHelper.GetExpressionText(expression);
    
                //第3步:获取模型字段的值
                #region 模型字段的值
    
                string value;
                ModelState modelState;
                string fullName = html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);
                if (html.ViewData.ModelState.TryGetValue(fullName, out modelState) && modelState.Errors.Count > 0)
                {
                    tagBuilder.AddCssClass(HtmlHelper.ValidationInputCssClassName);
                }
                if (modelState != null && modelState.Value != null)
                {
                    value = modelState.Value.AttemptedValue;
                }
                else if (metadata.Model != null)
                {
                    value = metadata.Model.ToString();
                }
                else
                {
                    value = String.Empty;
                }
    
                #endregion 
    
                tagBuilder.Attributes.Add("type", "text");
                tagBuilder.Attributes.Add("name", name);
                tagBuilder.Attributes.Add("value", value);
                //第4步:填充其他自定义属性
                tagBuilder.MergeAttributes(htmlAttributes, true);
                tagBuilder.GenerateId(name);
    
                return MvcHtmlString.Create(tagBuilder.ToString(TagRenderMode.SelfClosing));
            }
    

      

    另外一个例子

        public static class FileUploadExtension
        {
    
            private const string CanReadExts = ".doc;.docx;.rtf;.xml;.html;.htm;.odt;.xls;.xlsx;.ppt;.pptx;.pdf;.txt;.mpp";
            private const string ImgExts = ".jpg;.jpeg;.png;.bmp;.gif";
            private const string CanEditExts = ".doc;.docx";
    
            /// <summary>
            /// 上传文件扩展,绑定到模型字段
            /// </summary>
            /// <typeparam name="TModel">模型</typeparam>
            /// <typeparam name="TProperty">模型对应属性</typeparam>
            /// <param name="helper"></param>
            /// <param name="pathsExpr">保存上传文件路径的属性表达式</param>
            /// <param name="multi">是否多文件上传(false时为单文件)</param>
            /// <param name="fileTypeExts">上传文件扩展名,用“分号”分割不同扩展名(如: '.jpg','.png')</param>
            /// <param name="htmlAttributes">html属性集合对象</param>
            /// <param name="editMode">是否为编辑模式</param>
            /// <param name="onlineView">是否可以在线阅读</param>
            /// <param name="onlineEdit">是否可以在线编辑</param>
            /// <param name="callBack">上传成功的回掉函数</param>
            /// <returns></returns>
            public static MvcHtmlString FileUploadFor<TModel, TProperty>
                (this HtmlHelper<TModel> helper,
                Expression<Func<TModel, TProperty>> pathsExpr,
                bool multi = true,
                string fileTypeExts = null,
                object htmlAttributes = null,
                bool editMode = true,
                bool onlineView = true,
                bool onlineEdit = false, string callBack = "")
            {
                //检查model是否存在
                if (helper.ViewData != null && null == helper.ViewData.Model)
                    throw new NoNullAllowedException("View Model 不能为空! 请确保 View Model 被创建了并且传输到当前视图.");
    
                //从model中获得数据
                if (helper.ViewData != null)
                {
                    var model = helper.ViewData.Model;
    
                    //检查是否绑定到了model的属性上
                    var name = ExpressionHelper.GetExpressionText(pathsExpr);
                    if (String.IsNullOrEmpty(name))
                        throw new ArgumentException("名称不能为空!", "pathsExpr");
    
                    //获得已经上传文件名称列表
                    var pathsFunc = pathsExpr.Compile();
                    var nameStr = "";
                    if (pathsFunc(model) != null)
                    {
                        nameStr = pathsFunc(model).ToString();
                    }
    
                    var metadata = ModelMetadata.FromLambdaExpression(pathsExpr, helper.ViewData);
                    var isRequired = metadata.IsRequired;
                    var displayName = isRequired ? metadata.DisplayName : "";
    
                    return FileUpload(helper, name, nameStr, multi, fileTypeExts, htmlAttributes, editMode, onlineView,
                        onlineEdit, isRequired, displayName, callBack);
                }
                else
                {
                    return new MvcHtmlString("");
                }
            }
    
            /// <summary>
            /// 上传文件,指定name和value不需要绑定到字段
            /// </summary>
            /// <param name="helper">上下文</param>
            /// <param name="name">后台接收时使用的名称</param>
            /// <param name="value">值,上传文件的标识串</param>
            /// <param name="multi">是否可以上传多个</param>
            /// <param name="fileTypeExts">文件类型扩展名列表</param>
            /// <param name="htmlAttributes">附加的html属性</param>
            /// <param name="editMode">是否为编辑模式</param>
            /// <param name="onlineView">是否可以在线阅读</param>
            /// <param name="onlineEdit">是否允许在线编辑</param>
            /// <param name="isRequired">是否非空验证</param>
            /// <param name="displayName">非空时提示名称</param>
            /// <param name="callBack">上传成功的回掉函数</param>
            /// <returns></returns>
            public static MvcHtmlString FileUpload<TModel>
                (
                this HtmlHelper<TModel> helper,
                string name,
                string value,
                bool multi = true,
                string fileTypeExts = null,
                object htmlAttributes = null,
                bool editMode = true,
                bool onlineView = true,
                bool onlineEdit = false,
                bool isRequired = false,
                string displayName = "",
                string callBack = ""
                )
            {
                var id = Utils.CreateTagId("fine-uploader");
    
                return FileUpload(helper, id, name, value, multi, fileTypeExts, htmlAttributes, editMode, onlineView, onlineEdit, isRequired: isRequired, displayName: displayName, callBack: callBack);
            }
    
            /// <summary>
            /// 上传文件,指定name和value不需要绑定到字段
            /// </summary>
            /// <param name="helper">上下文</param>
            /// <param name="id">容器ID</param>
            /// <param name="name">后台接收时使用的名称</param>
            /// <param name="value">值,上传文件的标识串</param>
            /// <param name="multi">是否可以上传多个</param>
            /// <param name="fileTypeExts">文件类型扩展名列表</param>
            /// <param name="htmlAttributes">附加的html属性</param>
            /// <param name="editMode">是否为编辑模式</param>
            /// <param name="onlineView">是否可以在线阅读</param>
            /// <param name="onlineEdit">是否允许在线编辑</param>
            /// <param name="width">上传文件内容显示宽度</param>
            /// <param name="isRequired">是否非空验证</param>
            /// <param name="displayName">非空时提示名称</param>
            /// <param name="callBack">上传成功的回掉函数</param>
            /// <returns></returns>
            public static MvcHtmlString FileUpload<TModel>
                (this HtmlHelper<TModel> helper,
                string id,
                string name,
                string value,
                bool multi = true,
                string fileTypeExts = null,
                object htmlAttributes = null,
                bool editMode = true,
                bool onlineView = true,
                bool onlineEdit = false,
                int width = 722,
                bool isRequired = false,
                string displayName = "",
                string callBack = "")
            {
                //内容容器
                var div = new TagBuilder("div");
                div.MergeAttribute("id", id);
                div.MergeAttribute("data-multi", multi.ToString().ToLower());
                div.MergeAttribute("data-filetypeexts", fileTypeExts);
                div.MergeAttribute("data-editmode", editMode.ToString().ToLower());
                div.MergeAttribute("data-onlineView", onlineView.ToString().ToLower());
                div.MergeAttribute("data-onlineEdit", onlineEdit.ToString().ToLower());
                div.MergeAttribute("data-canReadExts", CanReadExts.ToLower());
                div.MergeAttribute("data-canEditExts", CanEditExts.ToLower());
    
                div.MergeAttributes(HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
                if (width <= 0) width = 692;
                var widthStr = "" + width + "px";
                div.MergeAttribute("style", widthStr);
                //值保存位置
                var input = new TagBuilder("input");
                input.MergeAttribute("type", "text");
                input.MergeAttribute("id", id + "-hidden");
                input.MergeAttribute("name", name);
                input.MergeAttribute("value", value);
                input.MergeAttribute("style", "visibility: hidden;height: 0; 0;position:absolute;");
                if (isRequired)
                {
                    input.MergeAttribute("data-val", "true");
                    input.MergeAttribute("data-val-required", displayName + "不能为空");
                }
    
                //产生上传文件的区域代码
                var uploadedFileStr = CreateUploadedTag(helper, value, editMode, onlineView, onlineEdit);
    
                //隐藏已上传文件的html内容
                var hidDiv = new TagBuilder("div");
                hidDiv.AddCssClass("fileUploaderedHidDiv");
                hidDiv.MergeAttribute("style", "display:none");
                hidDiv.InnerHtml = uploadedFileStr;
    
                div.InnerHtml += hidDiv.ToString();
    
                //初始化脚本
                var script = new TagBuilder("script");
                script.InnerHtml += "jQuery(function(){createUploader('" + id + "'," + editMode.ToString().ToLower() + ",'" +
                                    uploadedFileStr + "'," + multi.ToString().ToLower() + ",'" + fileTypeExts + "','" + callBack + "');});";
    
    
    
                return MvcHtmlString.Create(div + input.ToString() + script);
            }
        }
    

      

  • 相关阅读:
    [poj_3469]多核CPU
    割点与桥,强连通分量,点双,边双[poj_1236]学校网络
    Iview 启动报错 TypeError [ERR_INVALID_CALLBACK]: Callback must be a function
    修改JAVA_HOME失效
    命令模式
    gradle implementation runtimeOnly 和api 区别
    spring boot 整合 RabbitMQ 错误
    关于技术的想法
    eclipse 背景绿豆沙颜色
    抽象工厂模式
  • 原文地址:https://www.cnblogs.com/fireicesion/p/14666638.html
Copyright © 2011-2022 走看看