• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

ASP.NETMVCURL、路由、与区域Part2

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

感谢作者的翻译,这里只是译文。 原书名:Pro ASP.NET MVC 3 Framework

 

第十一章 URL、路由、与区域 PART2

 

生成输出URL

处理输入URL只是故事的一部分。我们还需要能够把我们的URL Schema 用来生成嵌入到我们视图的输出URL。这样,用户点击链接、以及把表单回递给应用程序,都能以正确的控制器和动作为目标。在本节中,我们将向你演示生成输出URL的不同技术。

WHAT NOT TO DO: MANUALLY DEFINEDURLS
不要做:手工定义的URL 

------------------------------------------------------------------------------------------------------------------------------------------------- 

定义输出URL最快、且最容易的方式是手工做这件事。例如,根据清单11-28所定义的简单方案,我们可以把以下链接添加到我们的一个视图:

<href="/Home/About">About this application</a>

这个HTML元素以一个URL生成了一个链接,当它被我们的应用程序作为输入URL接收时,它将以Home控制器的About动作方法为目标。

手工定义URL快而简单,但它们也有很大的危险。每一次你修改应用程序的URL方案时,你都要放弃所有输出URL。然后,你必须拉网式地检查应用程序的所有视图,并更新所有控制器和动作方法的引用。正如我们在后面几节所解释的,可以用路由系统根据URL方案来生成URL,这样,当方案变化时,你视图中的输出URL也会随之而变。这是一种有意义得多的办法,它只需要一点点初期的投入,但却有长期的巨大好处。 

准备项目

我们打算继续使用本章前面的项目,但借此机会删掉一些示例。我们已经修改了Global.asax中的RegisterRoutes方法,使之如清单11-30所示,并删掉了AdditionalControllers项目。

Listing 11-30. The Tidied Up RegisterRoutes Method

public static void RegisterRoutes(RouteCollection routes) {
    routes.MapRoute("MyRoute","{controller}/{action}/{id}",
        new { controller = "Home", action ="Index", id = UrlParameter.Optional });
}

在视图中生成输出(Outgoing)URL

在一个视图中生成一个输出(outgoing)URL最简单的办法是,在视图中调用@Html.ActionLink方法,如清单11-31所示。

Listing 11-31. Calling the ActionLink Helper Method

@Html.ActionLink("About this application""About")

传递给ActionLink方法的参数是,链接文本、以及该链接的目标动作名称。ActionLink方法所生成的HTML是基于当前路由方案的。例如,运用清单11-30所定义的方案(并假设该视图是通过对Home控制器的请求来渲染的),我们得到这样的HTML

<href="/Home/About">About this application</a>

但是,假设我们通过添加一条新路由修改了这个方案,像这样:

public static void RegisterRoutes(RouteCollection routes) {
    routes.MapRoute("NewRoute","App/Do{action}",
        new {controller = "Home" });
    routes.MapRoute("MyRoute","{controller}/{action}/{id}",
        new { controller = "Home", action ="Index", id = UrlParameter.Optional });
}

那么,当我们渲染这个页面时,我们从ActionLink辅助方法得到的是以下HTML

<href="/App/DoAbout">About this application</a>

你可以看出针对这种维护问题来生成链接的方式,我们可以修改我们的路由Schema,并在我们的视图中自动地获得反映这种修改的输出连接。

UNDERSTANDING OUTBOUND URL ROUTEMATCHING
理解出站URL的路由匹配

-------------------------------------------------------------------------------------------------------------------------------------------------

你已经看到了,改变定义URL方案的路由,会改变生成输出URL的方式。应用程序通常会定义几条路由,而重要的只是理解生成URL的路由是如何选择的。路由系统是按照传递给RegisterRoutes方法的RouteCollection对象中的路由顺序来处理路由的。每一条路由都会被检测,以考查它是否是一个匹配,这需要满足三个条件:

·         URL模式中所定义的每个片段变量,必须有一个可用的值。为了找到每个片段的值,路由系统首先查看我们已经提供的值(用匿名类型的属性),然后是当前请求的变量值,最后是该路由中定义的默认值。(本章稍后我们会再次回到这些值的话题。)

·         在我们给片段变量提供的值中,应当没有值会违背这条路由所定义的只默认变量。这些已经提供了默认值、但不在URL模式中出现的变量(指只默认变量 —译者注)。例如,在以下路由定义中,myVar就是一个只默认变量:(原文:None of the values we provided for the segment variables may disagree with the default-only variables defined in the route.These are variables for which default values have been provided, but which do not occur in the URL pattern. For example, in this route definition, myVar is a default-only variable:

routes.MapRoute("MyRoute","{controller}/{action}",
    new { myVar = "true" });

为了匹配这条路由,我们必须小心不要给myVar提供一个值,或者,要确保我们肯定提供了与这个默认值匹配的值。

·         所有片段变量的值必须满足路由约束

要十分清楚地意识到:路由系统不会试图查找最佳匹配的路由。它只找出最先匹配,此时,它用这条路由生成URL,任何后继的路由都被忽略。出于这一原因,你应该首先定义最明确的路由。测试你生成的出站URL重要的 。如果你试图生成一个无法找到匹配路由的URL,你将会生成一个含有空href属性的链接,像这样:

<href="">About this application</a>

这个链接会被渲染到视图中,但在用户点击它时没有目标功能。如果你恰好生成了这种URL(稍后我们演示如何生成),那么,其结果将为null,它在视图中渲染成空字符串。你可以通过使用命名路由的办法对路由匹配施加一些控制。参见本章稍后的生成特定路由的URL”小节。 

满足这些条件的第一条Route对象将产生一个非空的URL,并终止URL生成过程。所选的参数值将替换各个片段参数,忽略任何后继的默认值。如果你明确地提供了一些参数,它们与片段参数或默认参数不相符,那么,该方法将把它们以名字/对的查询字串形式进行追加。

单元测试:测试输出URL

测试输出URL生成最简单的办法是使用静态的UrlHelper.GenerateUrl方法,它含有指导路由生成的各种办法的参数例如,通过指定路由名、控制器、动作、片段值等等。以下是根据清单11-29所定义的路由,来检验URL生成的一个测试方法。

[TestMethod]
public void TestOutgoingRoutes() {
    // Arrange
    RouteCollection routes = new RouteCollection();
    MvcApplication.RegisterRoutes(routes);
    RequestContext context = new RequestContext(CreateHttpContext(), new RouteData());
    // Act - generate the URL
    string result = UrlHelper.GenerateUrl(null,"Index""Home"null,
    routes, context, true);
    // Assert
    Assert.AreEqual("/", result);
}

我们生成了一个URL,而不是一个链接,因此我们不必考虑HTML的相关测试。UrlHelper.GenerateUrl方法需要一个RequestContext对象,它是我们用CreateHttpContext测试辅助方法模仿HttpContextBase对象生成的。

以其它控制器为目标

ActionLink方法的默认版本是:假设你希望以引发视图渲染的同一个控制器中的动作方法为目标。为了生成一个以不同控制器为目标的输出URL,你可以用它的一个重载方法,它允许你指定控制器名,如清单11-32所示。

Listing 11-32. Targeting a Different Controller Using the ActionLink Helper Method

@Html.ActionLink("About thisapplication""About""MyController")

When you render the view, you will see the following HTML generated:
当你渲染该视图时,你将看到生成了以下HTML

<href="/MyController/About">About this application</a>

注意:路由系统在生成输出URL时,对我们应用程序的了解并不比处理输入请求时多。这意味着,不会对你提供给动作方法和控制器的值进行校验,因此,你必须小心不要指定不存在的目标。

传递额外的值

你可以用一个匿名类型把值传递给片段变量,在匿名类型中以属性表示片段。清单11-33提供了一个示例。

Listing 11-33. Supplying Values for Segment Variables

@Html.ActionLink("About this application""About"new { id = "MyID" })

上例中,我们给名为id的片段变量提供了一个值。如果我们的应用程序使用清单11-30所示的路由,那么,在渲染视图时,我们便得到了以下HTML

<href="/Home/About/MyID">About this application</a>

注意,我们所提供的值已经被添加为一个URL片段,以匹配我们应用程序路由的URL模式。

UNDERSTANDING SEGMENT VARIABLE REUSE
理解片段变量重用

--------------------------------------------------------------------------------------------------------------------------------------------------在我们描述对出站URL进行路由匹配的方式时,我们提到,在为一条路由的URL模式中的每个片段变量查找值的过程中,路由系统将考查当前请求的值。这是一种让许多程序员迷惑的行为,并可能导致较多的调试。

假设我们的应用程序只有一条路由,如下所示:

routes.MapRoute("MyRoute","{controller}/{action}/{color}/{page}");

现在,假设一个用户当前所处的URL/Catalog/List/Purple/123,而且,我们渲染了一个如下所示的连接:

@Html.ActionLink("Click me","List""Catalog"new {page=789}, null)

你可能期望路由系统不能匹配这条路由,因为我们还没有给颜色片段变量提供值,并且也没有定义默认值。然而你错了。路由系统将根据我们已经定义的这条路由进行匹配。它将生成以下HTML

<ahref="/Catalog/List/Purple/789">Click me</a>

路由系统是渴望形成一条路由匹配的,在这个意义上,它将重用输入URL的片段变量值。在这种情况下,根据我们假想的用户开始的这条URL,最终color变量的值为Purple

这不是最终采取的行为。路由系统将运用这一技术作为它常规评估路由的一部分,即使后面可能有匹配的路由,它们不需要重用当前请求的值。路由系统将只对某些片段变量使用重用值,这些片段变量在URL模式中的出现早于提供给Html.CactionLink方法的参数。假设我们试图生成一个像这样的连接:

@Html.ActionLink("Click me","List""Catalog"new {color="Aqua"}, null)

我们已经给color提供了一个值,但对page没提供。但在这个URL模式中,color的出现早于page,因此,路由系统不会重用输入URL的值,于是这条路由将不匹配。

处理上面这种行为最好的办法是阻止类似情况的发生。我们强烈建议你不要依赖这种行为,并建议你为URL模式中的所有片段变量都提供值。依靠上面行为将不仅使你的代码更难于阅读,也会使你最终要设想用户形成请求的顺序,这会最终在你的应用程序进入维护期时,对你造成伤害。

当我们给属性提供的值与片段变量不一致时,这些值将作为查询字串被追加到输出URL。例如,考虑以下对ActionLink辅助方法的调用:

@Html.ActionLink("About this application""About",
    new { id= "MyID", myVariable = "MyValue" })

它会生成以下HTML

<ahref="/Home/About/MyID?myVariable=MyValue">About this application</a>

如果我们给一个变量提供的一个值碰巧匹配我们在路由中指定的默认值,那么,路由系统在输出URL中会忽略这个值。例如,考虑以下对ActionLink方法的调用:

@Html.ActionLink("About this application""Index""Home")

我们已经为动作方法和控制器传递了参数,它们匹配清单11-27路由的默认值。调


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
asp.net显示用户信息发布时间:2022-07-10
下一篇:
分享:ASP.NET避免VIEWSTATE过大发布时间:2022-07-10
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap