当前位置 : 主页 > 网络编程 > ASP >

[ASP NET MVC] 表单 Partial View / Editor Template 使用抉择

来源:互联网 收集:自由互联 发布时间:2021-06-24
表单 Partial View / Editor Template 使用抉择 前言 最近有不少同事都会问到“为什么在这边要使用Editor Tamplate? 怎么不用Partial View来做?”,其实如果想要知道各自适用的时机,首先就必须了解

表单 Partial View / Editor Template 使用抉择


前言

最近有不少同事都会问到“为什么在这边要使用Editor Tamplate? 怎么不用Partial View来做?”,其实如果想要知道各自适用的时机,首先就必须了解两者差异为何。从以下表格不难发现,两者都是从VIEW中将ViewModel之Boo属性对象传入Partial View / Editor Template,并且都是使用@Html.EditorFor() 方法来产出Html 元素,但最终产出Html Input元素名称prefix却不相同。因此以下将针对各自特性来思考适用情境。

适用情境

使用Partial View或Editor Tempalte除共用考量因素外,就是避免页面过于庞大造成维护不易,因此在拆解复杂数据输入页面区块时,我们需要考量表单数据被送出的方式,是否所有数据都隶属于同一个表单中,亦或者会有分散在各表单的情况,需要有各自被送出的需求。以下提供两种使用情境供读者参考。

Editor Template

单一表单情况下,我们若想将各子属性类拆解成独自的检视,让复杂表单不会这么庞大时,就可以使用Editor Template来实现。简略示意图如下,在Editor Template中若是透过@Html.EditorFor()产出Html元素时,元素名称会以传入对象属性名称(VMA/VMB)作为 prefix,因此在按下Submit送出表单数据到后端时,便可依照名称将数据完整地Binding至ViewModel中。

Partial View

在多表单情况下,可考虑依照各表单Model来拆解成各自Partial View使用。简略示意图如下,在Partial View中若是透过@Html.EditorFor()产出Html元素时,元素名称并不会以传入对象属性名称(VMA/VMB)作为 prefix,因此可利用此特性,让各表单送出属于自己的Model数据至Controller中。

实践演练

假设目前有个新增使用者功能需要实践,由于画面可能会很复杂(身家调查之类),因此可能会存在许多不同种类的资讯,所以希望将表单页面稍微分割一下,把表单中连络资讯(Contact)及教育资讯(Education)给分割出来,预期界面如下所示。虽然知道此时应使用EditorTemplate来实做会比较合适,但抱持着实验的精神,我们就姑且先使用Partial View来实做,看看会发生什么问题。

首先定义检视Model(UserCreateViewModel)、连络资讯(Contact)及教育资讯(Education)相关类。

public class UserCreateViewModel
{
    public string UserName { get; set; }
    public Contact Contact { get; set; }
    public Education Education { get; set; }

}

 public class Contact
{
    public string Phone { get; set; }
    public string Email { get; set; }
}


public class Education
{
    public string HightSchool { get; set; }
    public string University { get; set; }
}

接着设计输入连络资讯(Contact)及教育资讯(Education)的Partial View页面

为了让结果更加清晰,直接透过@Html.NameFor()把输入框元素名称印出,方便后续比较使用。

_ContactPartialView.cshtml

@model PartialViewWebApp.ViewModel.Contact
@{Layout = null;}



  

 
contact @Html.LabelFor(model => model.Phone, htmlAttributes: new { @class = "control-label col-md-3" }) @Html.EditorFor(model => model.Phone, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.Phone, "", new { @class = "text-danger" }) name: @Html.NameFor(model => model.Phone) @Html.LabelFor(model => model.Email, htmlAttributes: new { @class = "control-label col-md-3" }) @Html.EditorFor(model => model.Email, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.Email, "", new { @class = "text-danger" }) name: @Html.NameFor(model => model.Email)

_EducationPartialView.cshtml

@model PartialViewWebApp.ViewModel.Education
@{Layout = null;}



  

 
Education @Html.LabelFor(model => model.HightSchool, htmlAttributes: new { @class = "control-label col-md-3" }) @Html.EditorFor(model => model.HightSchool, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.HightSchool, "", new { @class = "text-danger" }) name: @Html.NameFor(model => model.HightSchool) @Html.LabelFor(model => model.University, htmlAttributes: new { @class = "control-label col-md-3" }) @Html.EditorFor(model => model.University, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.University, "", new { @class = "text-danger" }) name: @Html.NameFor(model => model.University)

主页面(View)如下,使用Partial View来呈现连络资讯(Contact)及教育资讯(Education)输入界面。

@model PartialViewWebApp.ViewModel.UserCreateViewModel
@{ ViewBag.Title = "Create"; }

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true, "", new { @class = "text-danger" })

    
  

 
  
  @Html.LabelFor(model => model.UserName, htmlAttributes: new { @class = "control-label col-md-3" }) 
 
  
    @Html.EditorFor(model => model.UserName, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.UserName, "", new { @class = "text-danger" }) name: @Html.NameFor(model => model.UserName) 
   

 

    
  

 
    @Html.Partial("_ContactPartialView", Model.Contact)

    
  

 
    @Html.Partial("_EducationPartialView", Model.Education)

    
  

  
 
   
    
   

 
}

产生画面如下,我们可以看到元素名称并没有依照对象属性阶层来命名,因此将数据POST到后端时,除了UserName可以正确绑定至UserCreateViewModel外,其他透过Partial View产出输入框中的数据并无法正确Binding至UserCreateViewModel。

最终会造成部分数据的遗失

接着使用EditorTemplate来实做。首先建立EditorTemplates数据夹,并且在刚目录中建立Contact.cshtml及Education.cshtml来对应Contact及Education类,而各类对应的EditorTemplate内容其实与先前设计的Partial View完全相同,因此不再此赘述了。

然后调整一下主页面,改使用EditorTemplate来呈现连络资讯(Contact)及教育资讯(Education)

@model PartialViewWebApp.ViewModel.UserCreateViewModel
@{ ViewBag.Title = "Create"; }

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true, "", new { @class = "text-danger" })

    
  

 
  
  @Html.LabelFor(model => model.UserName, htmlAttributes: new { @class = "control-label col-md-3" }) 
 
  
    @Html.EditorFor(model => model.UserName, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.UserName, "", new { @class = "text-danger" }) name: @Html.NameFor(model => model.UserName) 
   

 

    
  

 
    @Html.EditorFor(m => m.Contact)

    
  

 
    @Html.EditorFor(m => m.Education)

    
  

  
 
   
    
   

 
}

产生的画面如下,我们可以看到元素名称依照对象属性阶层来命名,因此将数据POST到后端时,所有数据都可以依据名称,正确Binding至userCreateViewModel中。

结果如预期般正确Binding至userCreateViewModel中。

结论

Partial View 与 Editor Template 虽然都可以传入对象来呈现独立的检视,但是若是牵涉到表单或需要POST数据到后端时,需要特别注意两者差别。Partial View 在使用 @Html.EditorFor() 产生Html元素时,就如同一般View的情况只根据检视中定义的Model来命名Html元素名称;而使用EditorTemplate时,会依照传入对象的属性名称作为产出Html元素名称之prefix,让元素名称可对应至主Model类结构。

参考资讯

http://stackoverflow.com/questions/13746697/mvc3-4-multiple-forms-using-partial-views

http://stackoverflow.com/questions/10608766/post-a-form-with-multiple-partial-views


希望此篇文章可以帮助到需要的人

若内容有误或有其他建议请不吝留言给笔者喔 !

原文:大专栏  [ASP NET MVC] 表单 Partial View / Editor Template 使用抉择

网友评论