HTML5技术

Asp.Net MVC 扩展 Html.ImageFor 方法详解 - stoneniqiu

字号+ 作者:H5之家 来源:H5之家 2016-07-03 10:00 我要评论( )

背景: 在Asp.net MVC中定义模型的时候,DataType有DataType.ImageUrl这个类型,但htmlhelper却无法输出一个img,当用脚手架自动生成一些form或表格的时候,这些Url字段总是需要再手动改一次,特别是我想在img上面包裹一个a标签。并限定大小,比如: 方法1:

背景:

在Asp.net MVC中定义模型的时候,DataType有DataType.ImageUrl这个类型,但htmlhelper却无法输出一个img,当用脚手架自动生成一些form或表格的时候,这些Url字段总是需要再手动改一次,特别是我想在img上面包裹一个a标签。并限定大小,比如:

方法1:分部视图

在做后台表格的时候经常要修改这样的问题,于是首先想到的就是做一个分部视图,叫tableimg。

@model string @if (!string.IsNullOrEmpty(Model)) { }

使用的时候:

@Html.Partial("tableimg",Model.Img)

方便是方便了些,但还是不够灵活。宽度是写死的;而且还要记住这个视图,如果这样的片段多了都不知道谁是谁了;和脚手架生成的代码TextBoxFor,DisplayFor等风格也不一样;如果要增加参数呢,还得去改模型

方法2:UIHint

这个方法和分部视图相似,也是使用模板,需要先在shared文件夹下创建一个EditorTemplates文件夹,然后新建一个视图。这里命名为ImageLink。内容和上面一样。

@model string @if (!string.IsNullOrEmpty(Model)) { }

只是调用方法不一样:

[DataType(DataType.ImageUrl)] )] public string Img { get; set; }

在视图里面通过EditorFor调用:

@Html.EditorFor(model => model.Img)

这修改的地方比较多,感觉不太舒服。能不能一劳永逸呢?当然是可以的,这需要自定义一个ModelMetadataProvider,来告诉MVC这个数据类型的属性就用这个模板显示。

public class ImageModelMetadataProvider : DataAnnotationsModelMetadataProvider { protected override ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName) { var meta= base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName); if (meta.DataTypeName==DataType.ImageUrl.ToString() && string.IsNullOrEmpty(meta.TemplateHint)) { ; } return meta; } }

ModelMetadata是用来描述模型数据结构的数据,比如数据类型、约束、显示名称等,而ModelMetadataProvider就是用来提供Model的模型元数据的。

然后全局注册:

protected void Application_Start() { AreaRegistration.RegisterAllAreas(); WebApiConfig.Register(GlobalConfiguration.Configuration); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); ModelMetadataProviders.Current = new ImageModelMetadataProvider(); }

模型的定义里面,不再需要加UiHint了

[DataType(DataType.ImageUrl)] public string Img { get; set; }

视图里面调用的时候,需要用EditorFor。回头看一下,这种方式还是不够灵活,要实现一个效果,首先要增加一个模板,然后注册模型元数据提供器,然后每一个要显示计划效果的模型还要强制的使用DataType特性以及Html.EditorFor输出,这让人有点束缚的感觉。

可不可以只改一个地方呢?于是想到扩展htmlhelper

方法3:Html.Image

新建一个静态类,Htmlhelpers,增加一个Image的扩展方法,有url和length两个参数。用tagbuilder创建标签,增加属性。

public static MvcHtmlString Image(this HtmlHelper helper, string url, int length) { ); tagA.MergeAttribute(, url); tagA.MergeAttribute(, ); ); img.MergeAttribute(, url); img.MergeAttribute(, , length)); tagA.InnerHtml = img.ToString(); return MvcHtmlString.Create(tagA.ToString()); }

最后返回MvcHtmlString ,但上面体现不了tagbuilder的好处。如果觉得写tag比较麻烦,可以这样:

, url, length); return MvcHtmlString.Create(str);

调用的时候传入参数:

@Html.Image(Model.Img,100)

结果显示ok:

但如果要增加宽度以及更多的样式,想将这个img的id指定为模型属性的名字呢 ,那就得用ImageFor了。

方法4:Html.ImageFor

开始不会写,就想到参考MVC源码,于是用强大的ILSpy(直接把System.Web.MVC.dll拖进来)找到了System.Web.MVC.HTML中的源码,直接可以看到LabelExtension和DisplayExtension等,常用的TextBoxFor位于InputExtension。

 所以这里我借鉴了上面的方法,先产生一个img,在用a表情包裹着。这里如果还用string.Format那就太糟糕了。

internal static MvcHtmlString ImageHelper(HtmlHelper html, ModelMetadata metadata, IDictionary<string, object> htmlAttributes = null) { value = metadata.Model.ToString(); (string.IsNullOrEmpty(value)) { return MvcHtmlString.Empty; } ); , value); img.Attributes.Add("id", metadata.PropertyName);
img.MergeAttributes(htmlAttributes, true); ); tagA.MergeAttribute(,value); tagA.MergeAttribute(, ); tagA.InnerHtml = img.ToString(); return MvcHtmlString.Create(tagA.ToString()); } public static MvcHtmlString ImageFor<TModel, TProperty>(this HtmlHelper<TModel> html, Expression<Func<TModel, TProperty>> expression, object htmlAttributes) { ModelMetadata modelMetadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData); //var propertyName = ExpressionHelper.GetExpressionText(expression); //也能获取到属性名 var htmlAttributes2 = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes); return ImageHelper(html, modelMetadata, htmlAttributes2); } public static MvcHtmlString ImageFor<TModel, TProperty>(this HtmlHelper<TModel> html, Expression<Func<TModel, TProperty>> expression) { return ImageFor(html, expression, null); }

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • 如何在 ASP.NET Core 中发送邮件 - Savorboard

    如何在 ASP.NET Core 中发送邮件 - Savorboard

    2017-05-02 08:02

  • 十二个 ASP.NET Core 例子 - Savorboard

    十二个 ASP.NET Core 例子 - Savorboard

    2017-04-27 16:01

  • ASP.NET MVC5请求管道和生命周期 - 雪飞鸿

    ASP.NET MVC5请求管道和生命周期 - 雪飞鸿

    2017-04-24 08:04

  • ASP.NET Core MVC 源码学习:详解 Action 的激活 - Savorboard

    ASP.NET Core MVC 源码学习:详解 Action 的激活 - Savorboard

    2017-04-14 13:04

网友点评
r