ASP.NET MVC 最佳实践(三)

本系列翻译自 Kazi Manzur Rashid 的博客,由于翻译水平有限,本系列可能存在误解偏差或者翻译不准的地方,建议对比原文进行阅读。由于篇幅关系,原文中的一篇文章在本系列中将拆解成多篇发布。本篇包括原文第二部分。如果你没有看过之前的第一部分,也许你想先看看 和《》。

15. 关于路由的思考

如果你在开发的是一个纯 ASP.NET MVC 的应用程序,可以先关闭已有的路由文件检查,这样可以去除不必要的文件系统检查。如果你这样做了,那么就还需要考虑另外的一些事情。请记住如果你的应用程序运行于 IIS 7集成模式,那么 ASP.NET 应用程序将会拦截所有的请求,不管文件的后缀名是什么。所以你必须要在过滤列表中加一些东西,以便让 应用程序不处理它们。这其中可能包括静态文件,例如 html、htm、文本文件(尤其是robots.txt)、favicon.ico、脚本、图片和css等等。这也是我在中提到不喜欢默认文件结构的原因之一。以下是我为 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

接下来是我的一些不同于手册指南的个人偏好。默认情况下 产生的 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

包含有很多种用于不同目的的 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 最佳实践(三)》上有3条评论

  1. Pingback引用通告: ASP.NET MVC 最佳实践(二) | 所谓技术 - 小李刀刀博客

  2. Pingback引用通告: ASP.NET MVC Archived Buzz, Page 1

评论已关闭。