[转载]ASP.NET MVC 最佳开发实践(2) | EntLib.net 技术分享平台.
本文提供了一些代码设计准则,目标是帮助ASP.NET MVC 开发人员创建可靠的应用程序,当然,你可根据实际应用程序选择合适的标准。本文由EntLib.com 小组翻译,欢迎分享和交流ASP.NET MVC 项目开发设计思路。
Controller 建议 – Controller Recommendations
Controller 和指定的Action方法由路由系统根据匹配的URL规则调用。Controller 接收路由系统的输入参数,包括HTTP 请求上下文(Session、Cookies、Browser等等)。
使用Model Binding,而不是手动解析请求。
ASP.NET MVC 通过Model binding 抽象了许多对象反序列代码,Model binding机制是将Request Context数据通过反射对应到Action方法中定义的对象类型上。
如下代码是Seller类,定义了表单提交的数据:
public class Seller { public Int64 ID { get; set; } public string Name { get; set; } public string Phone { get; set; } public string Address { get; set; } }
如下的是Register View 表单:
<% using (Html.BeginForm()) { %> <legend>Account Information</legend> <p> <%= Html.TextBox("Name") %> </p> <p> <%= Html.TextBox("Phone") %> </p> <p> <%= Html.TextBox("Address") %> </p> <p> <input value="Register" /> </p> <% } %>
Controller 需要Register Action 方法,提供Model binding:
public ActionResult Register([Bind(Exclude="ID")] Seller newSeller) { ... }
默认的model binder 会寻找类中的每一个属性,以Name 为例:
(1) 先查找Request.Form[“Name”];
(2) 接着RouteData.Value[“Name”];
(3) 接着 Request.QueryString[“Name”];
(4) 最后如没有匹配,则为null;
从Register action方法可以看到,通过默认的model binder,对象属性将被赋值。Model binding系统也会进行验证逻辑,如data annotations attributes。
Model binding系统有丰富的扩展机制,可对object的创建、赋值和验证进行全面定制。
在Action方法中显示命名View。
在action方法中完成必要逻辑后,最后返回ViewResult 或 PartialViewResult对象。如不传入View名称给result 类,View 文件将默认为action 名称。如一个名为Products的Controller,有一个List 的Action方法,在List action方法调用 return View() 方法,且不传入任何参数。MVC 框架将寻找 /Views/Products/List.aspx 视图,如不存在,则继续寻找 /Views/Products/List.ascx。如仍不存在,则尝试 /Views/Shared/List.aspx和/Views/Shared/List.ascx。你可使用/Views/Shared 存放多个Controllers共享的视图。
为了避免混淆,在action方法中,显式命名View,如 return View(“explictViewName”),这样可从不同的Action调用List视图。
在提交表单时使用Post/Redirect/Get(PRG)
根据HTTP POST 和 GET 的定义:
HTTP GET 用于不更改Model数据;
HTTP POST 用于更改Model 数据;
下面是一个清晰的描述,在post back的action方法接收表单数据,返回 RedirectToAction(
传统的ASP.NET 表单回传数据,有可能导致数据的重复提交,可通过MVC Post-Redirect-Get模式解决这一问题。
但是,这一模式会造成client-side性能影响,因为redirect跳转会再次请求服务器,需要在性能成本和可用性之间进行判断。
实现HandleUnknownAction 和 HandleError
默认的unknown action响应是404(Not found)错误。可在Controller中重载HandleUnknownAction,针对这一错误实现一个默认视图。此外,可在controller的action方法添加HandleError属性,针对未捕获异常提供标准的错误视图。
路由建议 – Routing Recommendations
ASP.NET MVC 中路由映射 URL 直接到controller,而不是一个特定的文件。默认的路由添加到RouteTable,在Global.ascx文件的Application_Start中定义。该路由表负责映射特定URL到Controller和Action。
当时使用标准路由时,从特定的路由到一般路由进行排序。
路由表是有序的,因此按特定的到一般规则来创建路由。举一个示例,假定你有一个product category需要创建URL:
* http://sellmyproducts/
* http://sellmyproducts/Page#
* http://sellmyproducts/category
* http://sellmyproducts/category/Page#
假定List方法定义如下(在ProductsController 类中):
Public ViewResult List(string category, int page)
基于之前指定的URL,下面的路由规范将正确路由用户到正确的视图:
routes.MapRoute( null, "", new { controller = "Products", action = "List", category = (string)null, page = 1 } ); routes.MapRoute( null, "Page{page}", new { controller = "Products", action = "List", category = (string)null }, new { page = @"\d+" } ); routes.MapRoute( null, "{category}", new { controller = "Products", action = "List", page = 1} ); routes.MapRoute( null, "{category}/Page{page}", new { controller = "Products", action = "List"}, new { page = @"\d+" } );
使用命名的路由机制,避免路由歧义
在使用ASP.NET 路由机制时,必须知道路由机制是如何工作的。否则,会浪费很多时间去跟踪错误的路由。有一个办法是显式命名路由,可缓解这一问题。
如下路由映射定义了命名路由:
routes.MapRoute( "Default", "", new { controller = "Products", action = "List", category = (string)null, page = 1 } ); routes.MapRoute( "PageRoute", "Page{page}", new { controller = "Products", action = "List", category = (string)null }, new { page = @"\d+" } );
使用这些路由定义,可创建PageRoute路由链接:
<%= Html.RouteLink("Next", "PageRoute", new RouteValueDictionary( new { page = i + 1 } )); %>