原文: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:" + 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;width: 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);
}
}

  

自定义ASP.NET MVC Html标签辅助方法的更多相关文章

  1. MVC 之HTML辅助方法

    顾名思义,HTML辅助方法(HTML Helper)就是用来辅助产生HTML之用,在开发View的时候一定会面对许多HTML标签,处理这些HTML的工作非常繁琐,为了降低View的复杂度,可以使用HT ...

  2. 【未完待续】MVC 之HTML辅助方法

    顾名思义,HTML辅助方法(HTML Helper)就是用来辅助产生HTML之用, 在开发View的时候一定会面对许多HTML标签,处理这些HTML的工作非常繁琐,为了降低View的复杂度,可以使用H ...

  3. ASP.NET MVC 5 - 验证编辑方法(Edit method)和编辑视图(Edit view)

    在本节中,您将验证电影控制器生成的编辑方法(Edit action methods)和视图.但是首先将修改点代码,使得发布日期属性(ReleaseDate)看上去更好.打开Models \ Movie ...

  4. [转]ASP.NET MVC 5 - 验证编辑方法(Edit method)和编辑视图(Edit view)

    在本节中,您将验证电影控制器生成的编辑方法(Edit action methods)和视图.但是首先将修改点代码,使得发布日期属性(ReleaseDate)看上去更好.打开Models \ Movie ...

  5. [转]自定义ASP.NET MVC JsonResult序列化结果

    本文转自:http://blog.163.com/luckcq@yeah/blog/static/17174770720121293437119/ 最近项目中前台页面使用EasyUI的jQuery插件 ...

  6. vs 2013下自定义ASP.net MVC 5/Web API 2 模板(T4 视图模板/控制器模板)

    vs 2013下自定义ASP.net MVC 5/Web API 2  模板(T4 视图模板/控制器模板): Customizing ASP.NET MVC 5/Web API 2 Scaffoldi ...

  7. 转:自定义ASP.NET MVC Html辅助方法

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

  8. 【MVC】自定义ASP.NET MVC Html辅助方法

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

  9. [转载]自定义ASP.NET MVC Html辅助方法 TagBuilder

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

随机推荐

  1. 解决ubuntu突然无法联网问题

    一.问题描述 今天使用笔记本远程办公的时候,突然电脑无法联网了,使用chrome浏览器访问网页出现如下错误 This site can't be reachedwww.baidu.com's serv ...

  2. Wavelet Transforms

    目录 目标 小波变换 Scaling Functions Wavelet Functions 二者的联系 离散的情形 高效变换 二维的情形 示例 目标 首先, 既然是变换, 那么就是从一个域到另一个域 ...

  3. [opencv]KAZE、AKAZE特征检测、匹配与对象查找

    AkAZE是KAZE的加速版 与SIFT,SUFR比较: 1.更加稳定 2.非线性尺度空间 3.AKAZE速度更加快 4.比较新的算法,只有Opencv新的版本才可以用 AKAZE局部匹配介绍 1.A ...

  4. CapstoneCS5212替代RTD2166|DP转VGA转换电路设计方法|CS5212替代方案

    Capstone CS5212适用于设计DP转VGA转换电路,主要用在嵌入式单片机基于工业机或者INTEL X86主板上面,也适用于多个电子配件市场和显示器应用程序,如笔记本电脑.主板.台式机.适配器 ...

  5. 大二 mysql高级+html响应式+Java高级50道试题

    1.CSS3中过渡属性 transition-timing-function的值包括哪些 A. ease B. inline C. ease-in D. easeout 答案:A,C 解析:过渡属性 ...

  6. Mysql 8.0版本以上和8.0以下jar包版本 需要注意的 URL连接参数useSSL、serverTimezone 相关问题

    在语法上的需要注意的: MySQL 8.0 以下版本 - JDBC 驱动名及数据库 URL static final String JDBC_DRIVER = "com.mysql.jdbc ...

  7. 编写Java程序,使用Swing布局管理器与常用控件,实现用户登录界面

    返回本章节 返回作业目录 需求说明: 使用Swing布局管理器与常用控件,实现用户登录界面 实现思路: 创建用户登录界面的类LoginFrame,在该类中创建无参数的构造方法,在构造方法中,设置窗体大 ...

  8. iis站点下发布多个vue项目

    记录一下iis上某个域名下发布多个vue项目的过程,主要分为webpack打包前的配置和iis重定向的配置. vue打包配置: 1.在webpack 配置文件中(以vue.config.js为例),指 ...

  9. SpringCloud创建Config Client通过Eureka访问Config

    1.说明 本文详细介绍配置中心客户端使用方法, 即Config Client到Config Server读取配置. 读取配置的方式有两种, 第一种是直接配置Configer Server的URL, 第 ...

  10. go语言 装饰器模式

    package decoratorimport ( "fmt" "reflect")func Decorator(decoPtr, fn interface{} ...