• (转)MVC模式参数传递的探究


    原文地址:http://www.cnblogs.com/dingding3/archive/2010/08/21/MVC.html

    最近公司一直在用MVC模式写程序,所以最近一直再查MVC的资料,目前在研究MVC的参数传递方法,因此有了此文。
    MVC模式既可以通过Model传递参数,也可以用ViewData来保存数据,两种方式的组合传递参数就是一种新的模式了。
    使用这种组合传参的新模式可以非常快的实现,但美中不足的是输入错误会导致错误,不能在编译时发现错误原因,而且ViewData必须要用as来转换。
    从Controller传递数据到View视图模板
    MVC模式一个典型的特征是严格的功能隔离。Model模型、Controller控制器和View视图各自定义了作用和职责,且相互之间以定义好的方式进行沟通。这有助于提升测试性和代码重用。
    当Controller决定呈现HTML响应给客户端是,它负责显式传递给View模板所有需要的数据。View模板从不执行任何数据查询或应用程序逻辑 – 仅仅负责呈现Model或Controller传递过来的数据。

    当需要从Controller传递不止一个Model对象时,就要用到ViewData字典或ViewModel模式。例如,当我们需要Controller在View呈现Dinner对象和支持的Countries列表的时候,采用如下两种方式来实现。

    使用ViewData 字典

    Controller基类公开了一个ViewData 字典属性,用来从Controllers传递额外的数据给Views视图。
         Controller中代码

    1 [Authorize]
    2 public ActionResult Edit(int id)
    3 {
    4     Dinner dinner = dinnerRepository.GetDinner(id);
    5      ViewData["Countries"] = new SelectList(PhoneValidator.Countries, dinner.Country);
    6     return View(dinner);
    7 }

        上面代码中SelectList构造函数的第一个参数显示国家列表,第二个参数指定当前选中的国家。    
        View中代码
     
    1 <%= Html.DropDownList("Country", ViewData["Countries"] as SelectList)%>

        上面代码中第一个参数表示输出的HTML表单元素名称,第二个参数是通过ViewData传递的模型类。
       使用ViewModel模式:
        ViewData的优点:非常快,容易实现
        ViewData的缺点:输入错误会导致错误;不能在编译期发现错误原因;在View视图模板中使用强类型时,ViewData要用as来转换。
        ViewModel模式:
        1.针对特定的View视图创建强类型的类
        2.公开View模板需要的动态参数值或内容
        3.Controller类填充和传递这些类给View模板去用
        4.优点:类型安全、编译期检查和编辑器的智能提示

        示例代码:
    01 public class DinnerFormViewModel
    02 {
    03        public Dinner Dinner {get; private set;}
    04         public SelectList Countries{get; private set;}
    05        public DinnerFormViewModel(Dinner dinner)
    06        {
    07             Dinner = dinner;
    08             Countries = new SelectList(PhoneValidator.Countries,dinner.Country);
    09        }
    10 }

        在Controller类中

    1 [Authorize]
    2 public ActionResult Edit(int id)
    3 {
    4     Dinner dinner = dinnerRepository.GetDinner(id);
    5     return View(new DinnerFormViewModel(dinner));
    6 }

        在View视图模板中
        头部Inherits = "System.Web.Mvc.ViewPage<NerdDinner.Models.Dinner>"改为
        Inherits = "System.Web.Mvc.ViewPage<NerdDinner.Controllers.DinnerFormViewModel>"
        绑定列表即为<% = Html.DropDownList("Country".Model.Countries) %>
    下面我们需要更新视图中的代码。对于表单中的HTML元素的名称不需要更新,仍旧保持为Title、Country等等,我们需要更新HTML辅助方法,使用DinnerFormViewModel类来获取属性值。
    01 <p>
    02 <label for="Title">Dinner Title:</label>
    03 <%= Html.TextBox("Title", Model.Dinner.Title) %>
    04 <%= Html.ValidationMessage("Title", "*") %>
    05 </p>
    06 <p>
    07 <label for="Country">Country:</label>
    08 <%= Html.DropDownList("Country", Model.Countries) %>
    09 <%= Html.ValidationMessage("Country", "*") %>
    10 </p>
    同样地,我们也需要更新Edit Post方法,在产生错误时,使用DinnerFormViewModel类传递给视图模板:
    01 //
    02 // POST: /Dinners/Edit/5
    03 [
    04 AcceptVerbs(HttpVerbs.Post)]
    05 public ActionResult Edit(int id, FormCollection collection) {
    06 Dinner dinner = dinnerRepository.GetDinner(id);
    07 try {
    08 UpdateModel(dinner);
    09 dinnerRepository.Save();
    10 return RedirectToAction("Details", new { id=dinner.DinnerID });
    11 }
    12 catch {
    13 ModelState.AddModelErrors(dinner.GetRuleViolations());
    14 return View(new DinnerFormViewModel(dinner));
    15 }
    16 }
    我们也更新Create() Action方法,重用相同的DinnerFormViewModel类,在View中实现Country下拉列表框。下面是HTTP-GET的实现代码:
    1 //
    2 // GET: /Dinners/Create
    3 public ActionResult Create() {
    4 Dinner dinner = new Dinner() {
    5 EventDate = DateTime.Now.AddDays(7)
    6 };
    7 return View(new DinnerFormViewModel(dinner));
    8 }
    下面是HTTP-POST Create方法的实现代码:
    01 //
    02 // POST: /Dinners/Create
    03 [AcceptVerbs(HttpVerbs.Post)]
    04 public ActionResult Create(Dinner dinner) {
    05 if (ModelState.IsValid) {
    06 try {
    07 dinner.HostedBy = "SomeUser";
    08 dinnerRepository.Add(dinner);
    09 dinnerRepository.Save();
    10 return RedirectToAction("Details", new { id=dinner.DinnerID });
    11 }
    12 catch {
    13 ModelState.AddModelErrors(dinner.GetRuleViolations());
    14 }
    15 }
    16 return View(new DinnerFormViewModel(dinner));
    17 }
    定制ViewModel类(Custom-shaped ViewModel Classes
    在上面的实现方案中,DinnerFormViewModel类直接公开了2个公有属性:Dinner 模型对象和SelectList模型属性。这一方法适合于View模板中HTML用户界面元素和业务Model对象比较接近的场景。
    如果不符合这一情况,可以考虑创建定制的ViewModel类,根据视图的使用情况创建优化的对象模型 – 该对象模型可能完全不同于底层的业务模型对象(Domain Model Object)。例如,该ViewModel类有可能公开不同的属性或者从多个Model对象中汇总的属性。
    定制的ViewModel类不仅可用来从Controller传递数据到View去呈现,而且可用来处理从表单提交回来给Controller的action方法的数据。针对后一种情况,你可以让Action方法根据表单提交回来的数据更新ViewModel对象,接着使用ViewModel实例来映射或者获取时间的业务模型对象(Domain Model Object)。
    定制ViewModel类提供了很好的灵活性,在任何时候,你发现View模板中的呈现代码或Action方法中表单提交代码越来越开始复杂时,你可以考虑使用定制的ViewModel了。通常,这意味着业务模型对象和View视图中的用户界面元素不一致,一个中介的定制ViewModel类就可以发挥作用了。

    MVC模式还有很多妙用,以后还会写更多有关MVC的文章。

  • 相关阅读:
    SSH异常
    jquery效果摘要
    js随笔
    html随笔
    demo小样
    SVG图标
    jQuery笔记
    html / css学习笔记-3
    angular 学习笔记
    ng-route使用笔记
  • 原文地址:https://www.cnblogs.com/fcsh820/p/1805767.html
Copyright © 2020-2023  润新知