Asp.Net MVC4系列--进阶篇之Helper(2)

本章接着介绍Asp.NetMVC4中的Helper

首先做准备工作,为了读者方便阅读,笔者把上篇文章中(Asp.Net MVC4系列—进阶篇之Helper(1)) 的代码再复制在这边一份,这篇文章都以此为开始:

Person类(Model中):

  public class Person
    {
        public int PersonId { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public DateTime BirthDate { get; set; }
        public Address HomeAddress { get; set; }
        public bool IsApproved { get; set; }
        public Role Role { get; set; }
    }
    public class Address  
    {  
        public string Line1 { get; set; }  
        public string Line2 { get; set; }  
        public string City { get; set; }  
        public string PostalCode { get; set; }  
        public string Country { get; set; }  
    }

    public  enum Role  
    {  
        Admin,  
        User,  
        Guest  
    }

PersonController.cs

    public class PersonController : Controller  
    {  
         public ActionResult CreatePerson()  
         {  
             return View(new Person());  
         }  

         [HttpPost]  
         public ActionResult CreatePerson(Person person)  
         {  
             return View(person);  
         }  
    }  

Route:

routes.MapRoute(  
name: "FormRoute",  
url:"app/forms/{controller}/{action}"  
);  

View(CreatePerson.cshtml)

<html>
@modelMVCHelperStudy.Models.Person
@{
   ViewBag.Title = "CreatePerson";

}
<h2>CreatePerson</h2>
<body>

@using(Html.BeginRouteForm("FormRoute", new {},FormMethod.Post,
new { @class ="personClass", data_formType="person"})) {
<div  class="dataElem">
<label>PersonId</label>
@Html.TextBoxFor(m =>m.PersonId)
</div>
<div class="dataElem">
<label>FirstName</label>
@Html.TextBoxFor(m => m.FirstName)
</div>
<div class="dataElem">
<label>LastName</label>
@Html.TextBoxFor(m =>m.LastName)
</div>
<div class="dataElem">
<label>Role</label>
@Html.DropDownListFor(m =>m.Role,
new SelectList(Enum.GetNames(typeof(MVCHelperStudy.Models.Role))))
</div>
<input type="submit" value="Submit" />
}

</body>
</html>

测试运行:

这里写图片描述

首先,使用模板方法重构View

把表单中间代码替换为:

<div class="dataElem">
<label>PersonId</label>
@Html.Editor("PersonId")
</div>
<div class="dataElem">
<label>FirstName</label>
@Html.Editor("FirstName")
</div>
<div class="dataElem">
<label>LastName</label>
@Html.EditorFor(m =>m.LastName)
</div>
<div class="dataElem">
<label>Role</label>
@Html.EditorFor(m => m.Role)
</div>
<div class="dataElem">
<label>BirthDate</label>
@Html.EditorFor(m =>m.BirthDate)
</div>

代码说明:使用了Html.Editor替代以前的实现。

看一下生成的html

<form action="/app/forms/Person/CreatePerson" class="personClass" data-formType="person" method="post"><div class="dataElem">
<label>PersonId</label>
<input  class="text-box single-line" data-val="true" data-val-number="The field PersonId must be anumber." data-val-required="The PersonId field is required."  id="PersonId" name="PersonId" type="number"  value="0" />
</div>
<div  class="dataElem">
<label>FirstName</label>
<input  class="text-box single-line" id="FirstName" name="FirstName" type="text" value="" />
</div>
<div class="dataElem">
<label>LastName</label>
<input class="text-boxsingle-line" id="LastName" name="LastName" type="text" value="" />
</div>
<div class="dataElem">
<label>Role</label>
<input class="text-boxsingle-line" data-val="true" data-val-required="The Rolefield is required." id="Role" name="Role" type="text" value="Admin" />
</div>
<div class="dataElem">
<label>BirthDate</label>
<input class="text-boxsingle-line" data-val="true" data-val-date="The fieldBirthDate must be a date." data-val-required="The BirthDate field isrequired." id="BirthDate" name="BirthDate" type="datetime" value="1/1/0001 12:00:00 AM" />
</div>
<input  type="submit" value="Submit" />
</form>

对比之前生成的html,区别就是多了“type”属性,好处是它使得html5根据不同的type显示不同,这需要支持html5的浏览器来实现。

常用的MVC模板helper方法

htmlhelper方法
Html.Display(“name”)
Html.DisplayFor(m=>m.name)
Html.Editor(“name”)
Html.EditorFor(m=>m.name)
Html.Label(“name”)
Html.LabelFor(m=>m.name)

Label 方法和Display方法

调整Controller代码:

public ActionResult CreatePerson()
{

  return View(newPerson()
                {
                   FirstName = "iori",
                   LastName = "l",
                   PersonId = 100,
                   BirthDate = DateTime.Now.AddYears(-20)
                });
}

返回一个默认的Person。

调整View代码:

    <div class="dataElem">  
    @Html.Label("PersonId")  
    @Html.Display("PersonId")  
    </div>  
    <div class="dataElem">  
    @Html.Label("FirstName")  
    @Html.Display("FirstName")  
    </div>  
    <div class="dataElem">  
    @Html.LabelFor(m => m.LastName)  
    @Html.DisplayFor(m => m.LastName)  
    </div>  
    <div class="dataElem">  
    @Html.LabelFor(m => m.Role)  
    @Html.DisplayFor(m => m.Role)  
    </div>  
    <div class="dataElem">  
    @Html.LabelFor(m => m.BirthDate)  
    @Html.DisplayFor(m => m.BirthDate)  
    </div>  

为了对比DisplayLabel,因此分别显示。测试结果:
这里写图片描述

可以看到,Display是显示PropertyValue,而Label是显示PropertyName

再对比一下生成的html:

    <form action="/app/forms/Person/CreatePerson" class="personClass" data-formType="person" method="post">  
    <div class="dataElem">  
    <label for="PersonId">PersonId</label>  
    100  
    </div>  
    <div class="dataElem">  
    <label for="FirstName">FirstName</label>  
    iori  
    </div>  
    <div class="dataElem">  
    <label for="LastName">LastName</label>  
    l  
    </div>  
    <div class="dataElem">  
    <label for="Role">Role</label>  
    Admin  
    </div>  
    <div class="dataElem">  
    <label for="BirthDate">BirthDate</label>  
    13/4/1994 9:24:09 PM  
    </div>  
    <input type="submit"  value="Submit"/>  
    </form>  

可以看到,label自动生成的for属性,而display则直接把值打在了页面上,甚至没有conver任何标签。

Whole-Model Template

Whole-Model Template 主要包括:

htmlhelper方法说明
Html.DisplayForModel()根据当前model每个property的类型,生成相应html(只读)
Html.EditForModel()根据当前model的每个property的类型,生成相应可编辑的html
Html.LabelForModel()根据当前的model生成标签

使用Html.EditForModel重构View代码:

@using(Html.BeginRouteForm("FormRoute", new {},FormMethod.Post,  new { @class = "personClass",data_formType="person"})) 
{  
    @Html.EditorForModel()  
    <input  type="submit" value="Submit" />  
}  

运行,查看结果
这里写图片描述

使用model metadata

1. hiddenInput

PersonId加一个属性:

[HiddenInput(DisplayValue=false)]

运行,测试:
这里写图片描述

点击submit

Debug查看Person的值,可以看到PersonId被提交了,值为100。原因是我们的attribute告诉mvcframework把这个input解析为Hidden,查看html

<input data-val="true" data-val-number="The field PersonId must be a number. " data-val-required="The PersonId field is required." id="PersonId" name="PersonId"  type="hidden" value="100"/>

可以看到,type已经被解析为了hidden

使用[ScaffoldColumn]属性

一个类中不是每个字段都是需要mvc frame解析为html的,如果希望跳过某个property,可以使用这个属性。例如:

    [ScaffoldColumn(false)]  
    public int PersonId { get; set; }  

这样的话,PersonId根本不会参与从property解析到html的过程。

使用[Display(Name=”XXX”)]

如果希望html解析出来的Label显示成别的字,可以使用这个属性。例如:

    [Display(Name = "Birth Date")]  
    public DateTime BirthDate { get; set; }  

对应的html标签:

    <label for="BirthDate">Birth Date</label>  

使用 [DataType(type)]

如果想改变mvc frame 解析的类型,可以使用此属性,例如:

    [DataType(DataType.Date)]  
    public DateTime BirthDate { get; set; }  

这样mvc解析这个property就会当做Date类型,而不是DateTime了。

相应的html标签:

<input  class="text-boxsingle-line" data-val="true"  data-val-date="The field BirthDate mustbe a date." data-val-required="The BirthDate field is required." id="BirthDate" name="BirthDate" type="date"  value="13/4/1994" />  

其他DataType可以选择的类型

DataType的类型
DateTime
Date
Time
Text
PhoneNumber
MultipleText
Password
Url
EmailAddress

使用[UIHint(“XX”)]属性

UIHint属性允许指定一个模板名称,mvc framework解析的时候,看到这个属性就会先找到对应的模板,再解析为相应的html,例如:

    [UIHint("MultilineText")]   
    public  string FirstName { get; set; }  

相应的html:

    <textarea class="text-box multi-line" id="FirstName" name="FirstName">  
    iori</textarea>  

MVC 自带的模板

MVC自带模板
Boolean
DateTime
Date
EmailAddress
HiddenInput
Html
MultiLineText
Number
Object
Password
String
Time
Text
Tel
Url

Mvc会为每个模板生成对应的html,读者可以一一尝试,根据自己的需要选择的应用到项目中。每个模板,也是可以被重写的。

使用metadata类

1 . 修改Person类为partial,去掉所有的DataTypeHint(就像一个Entity类):

    public int PersonId{ get; set; }  
          public string FirstName { get; set; }  
          public string LastName { get; set; }  
          public DateTime BirthDate { get; set; }  
          public Address HomeAddress { get; set; }  
          public bool IsApproved { get; set; }  
          public Role Role { get; set; }  

为了给Person类应用metadata 类型,需要先将其设为partial

2.创建一个metadata 类

    public partial class PersonMetaData {  
    [HiddenInput(DisplayValue=false)]  
    public int PersonId { get; set; }  
    [Display(Name="First")]  
    public string FirstName { get; set; }  
    [Display(Name = "Last")]  
    public string LastName { get; set; }  
    }  

3.在Person类加上metadatatype属性

[MetadataType(typeof(PersonMetaData))]

4.View 中使用EditFormModel

    @using(Html.BeginRouteForm("FormRoute",new {}, FormMethod.Post,  
    new { @class = "personClass",data_formType="person"})) {  
       @Html.EditorForModel()  
    <input  type="submit" value="Submit" />  
    }  

使用metadata类的目的,希望Entity类和MVC Attribute标记过的类分开,但显示的时候,希望MVCFramework会从medadata类中找到一致的Property,拿出Attribute应用。运行,查看效果,

这里写图片描述

可以看到标签名字变了,PersonId也隐藏了,因此Metadata类的Display标签和Hidden标签都产生了效果。

解析嵌套类型: Address

前面的例子,由于HomeAddress字段是class,因此MVCFramework没有识别出来,因此需要手动去再调用一下EditFor

<p>  
   @Html.EditorFor(m => m.HomeAddress)  
</p>  

运行:
这里写图片描述

可以看到这样Address类型就可以被识别了。

显示指定Template

Html.EditorFor(m =>m.SomeProperty,  "MyTemplate")

可以告诉MVC Framework,使用指定的Template

Template的查找顺序

1.Customize的template

2.Built-in的template

3.传入HelperTemplate,e.g. : Html.EditorFor(m=>m.name,”T”);

4.UIHint

5.DataType

Customize一个Template

Shared文件夹建一个EditorTemplates文件夹,因为所有的customizetemplateMVCFramework都会来这里找。

创建一个View放在EditorTemplates文件夹,可以反射出枚举的每一个成员并显示:

    @model Enum  
    @Html.DropDownListFor(m => m,Enum.GetValues(Model.GetType())  
    .Cast<Enum>()  
    .Select(m => {  
    string enumVal =Enum.GetName(Model.GetType(), m);  
    return new SelectListItem() {  
    Selected = (Model.ToString() ==enumVal),  
    Text = enumVal,  
    Value = enumVal  
    };  
    }))  

应用,在metadata类给Role成员加UIHint

    [UIHint("Enum")]  
    public Role Role { get; set; }  

运行,查看结果
这里写图片描述

可以看到,自定义的Template成功的工作了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值