本系列翻译自 Kazi Manzur Rashid 的博客,由于翻译水平有限,本系列可能存在误解偏差或者翻译不准的地方,建议对比原文进行阅读。由于篇幅关系,原文中的一篇文章在本系列中将拆解成多篇发布。本篇包括原文第二部分。如果你没有看过之前的第一部分,也许你想先看看 《ASP.NET MVC 最佳实践(一)》和《ASP.NET MVC 最佳实践(二)》。
15. 关于路由的思考
如果你在开发的是一个纯 ASP.NET MVC 的应用程序,可以先关闭已有的路由文件检查,这样可以去除不必要的文件系统检查。如果你这样做了,那么就还需要考虑另外的一些事情。请记住如果你的应用程序运行于 IIS 7集成模式,那么 ASP.NET 应用程序将会拦截所有的请求,不管文件的后缀名是什么。所以你必须要在过滤列表中加一些东西,以便让 ASP.NET MVC 应用程序不处理它们。这其中可能包括静态文件,例如 html、htm、文本文件(尤其是robots.txt)、favicon.ico、脚本、图片和css等等。这也是我在第一部分第2节中提到不喜欢默认文件结构的原因之一。以下是我为 IIS7 定制的路由定义标准模板:
_routes.Clear(); // Turns off the unnecessary file exists check _routes.RouteExistingFiles = true; // Ignore text, html, files. _routes.IgnoreRoute("{file}.txt"); _routes.IgnoreRoute("{file}.htm"); _routes.IgnoreRoute("{file}.html"); // Ignore axd files such as assest, image, sitemap etc _routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); // Ignore the assets directory which contains images, js, css & html _routes.IgnoreRoute("assets/{*pathInfo}"); // Ignore the error directory which contains error pages _routes.IgnoreRoute("ErrorPages/{*pathInfo}"); //Exclude favicon (google toolbar request gif file as fav icon which is weird) _routes.IgnoreRoute("{*favicon}", new { favicon = @"(.*/)?favicon.([iI][cC][oO]|[gG][iI][fF])(/.*)?" }); //Actual routes of my application
接下来是我的一些不同于手册指南的个人偏好。默认情况下 ASP.NET MVC 产生的 url 形如 {controller}/{action},在你开发一个多模块的应用程序是这是不错的选择,但是对于一些很小的应用程序,我通常喜欢从 url 中去掉控制器(controller)只留下方法名(action name)。如此一来,原来的“www.yourdomain.com/Story/Dashboard” 及 “www.yourdomain.com/Membership/Signin” 就会变成 “www.yourdomain.com/Dashboard” 和“www.yourmain.com/Signin”。所以我要添加一些新路由:
_routes.MapRoute("SignUp", "SignUp", new { controller = "Membership", action = "SignUp" }); _routes.MapRoute("SignIn", "SignIn", new { controller = "Membership", action = "SignIn" }); _routes.MapRoute("ForgotPassword", "ForgotPassword", new { controller = "Membership", action = "ForgotPassword" }); _routes.MapRoute("SignOut", "SignOut", new { controller = "Membership", action = "SignOut" }); _routes.MapRoute("Profile", "Profile", new { controller = "Membership", action = "Profile" }); _routes.MapRoute("ChangePassword", "ChangePassword", new { controller = "Membership", action = "ChangePassword" }); _routes.MapRoute("Dashboard", "Dashboard/{tab}/{orderBy}/{page}", new { controller = "Story", action = "Dashboard", tab = StoryListTab.Unread.ToString(), orderBy = OrderBy.CreatedAtDescending.ToString(), page = 1 }); _routes.MapRoute("Update", "Update", new { controller = "Story", action = "Update" }); _routes.MapRoute("Submit", "Submit", new { controller = "Story", action = "Submit" }); _routes.MapRoute("Home", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = string.Empty });
16. 如果需要的话,创建新的ActionResult
ASP.NET MVC 包含有很多种用于不同目的的 ActionResult,但我们仍有可能会需要新的 ActionResult。例如xml、rss、atom等等。在这种情况下,我的建议是不要使用通用的 ContentResult, 而是创建一种新的 ActionResult. MVCContrib 项目中有一个 XmlResult,你可以用它来返回 xml,但是不支持 feed。显然依靠它来将未知对象转换为 rss/atom 是很困难的,这时你就可以创建一个定义ActionResult的模型。例如:
public class AtomResult : ActionResult { public AtomResult(string siteTitle, string feedTitle, IEnumerable<IStory> stories) { SiteTitle = siteTitle; FeedTitle = feedTitle; Stories = stories; } public string SiteTitle { get; private set; } public string FeedTitle { get; private set; } public IEnumerable<IStory> Stories { get; private set; } public override void ExecuteResult(ControllerContext context) { string xml = Build(context); HttpResponseBase response = context.HttpContext.Response; response.ContentType = "application/atom+xml"; response.Write(xml); } }
[AcceptVerbs(HttpVerbs.Get), OutputCache(CacheProfile = "Atom")] public ActionResult Shared() { IEnumerable<stories> stories = GetSharedStories(); return new AtomResult("My Site", "My shared stories in atom", stories); }
17. 把你的视图拆分为多个视图控件
如果你的视图文件变得越来越大,那你可以考虑把它拆分为多个视图控件。至于视图空间是否在多个页面中重用,并没有关系。因为这样做可以让真正的视图文件变得更加具有可读性。考虑一下下面的视图:
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> My Secret App : Dashboard </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <div id="heading"></div> <div class="columns"> <div id="main" class="column"> <div id="storyListTabs" class="ui-tabs ui-widget ui-widget-content ui-corner-all"> <% Html.RenderPartial("TabHeader", Model);%> <div id="tabContent" class="ui-tabs-panel ui-widget-content ui-corner-bottom"> <div id="storyList"> <% Html.RenderPartial("SortBar", Model);%> <div class="clear"></div> <% Html.RenderPartial("NoLinkMessage", Model);%> <form id="update" action="<%= Url.Update()%>" method="post"> <% Html.RenderPartial("List", Model);%> <% Html.RenderPartial("ActionBar", Model);%> <% Html.RenderPartial("Pager", Model);%> </form> </div> </div> </div> <%Html.RenderPartial("Submit", new StorySubmitViewModel());%> </div> <div id="sideBar" class="column"></div> </div> </asp:Content>
继续阅读:《ASP.NET MVC 最佳实践(四)》
作者:小李刀刀
原文链接:ASP.NET MVC 最佳实践(三)
裁纸刀下版权所有,允许非商业用途转载,转载时请原样转载并标明来源、作者,保留原文链接。
看不太明白,路漫漫其修远兮。
Pingback引用通告: ASP.NET MVC 最佳实践(二) | 所谓技术 - 小李刀刀博客
Pingback引用通告: ASP.NET MVC Archived Buzz, Page 1