前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >精通MVC3摘译(2)-生成URL

精通MVC3摘译(2)-生成URL

作者头像
py3study
发布2020-01-09 16:51:21
7920
发布2020-01-09 16:51:21
举报
文章被收录于专栏:python3python3

处理发来的URL只是MVC中的一部分,我们也需要生成一些URL植入到我们的view中,让用户点击,并提交表单到目标controller和action,下面会介绍一些生成URL的技巧。

最快速直接的定义外链URL的方法就是手动拼写。比如下面的URL会被放置在view中:

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

这个HTML元素创建了一个链接,当点击该链接,会定位到Home controller的About action。手动定义URL快速减掉。但也是很危险。每次你要修改URL模式的时候,你要修改所有的URL。你不得不搜罗出所以的view,更新涉及到的所有的controller和action方法。

路由系统可以结构化的生成URL,当URL结构变化,view中生成的URL也会改变。这是一个非常明智的方法,只需要做一些工作,会给后期带来巨大的便利。

准备项目

我们使用之前的项目演示,在上面做些修改。

public static void RegisterRoutes(RouteCollection routes) {

routes.MapRoute("MyRoute", "{controller}/{action}/{id}",

new { controller = "Home", action = "Index", id = UrlParameter.Optional });

}

在视图中生成友好的URL

最简单的在view中生成URL的方式是使用Html.ActionLink方法,如下:

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

ActionLink方法的参数就是link的文本内容,action方法的名字就是这个link的链接目标。ActionLink方法生成HTML基于当前的路由模式。比如,使用上面定义的路由(假设这个view是由对Home controller请求生成的),那么我们得到的HTML就是如下

<a 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就如下:

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

你能看到如何用这种方法生成链接来处理维护问题。我们可以改变路由模式,让视图中生成的URL链接自动的改变。

应用程序通常都有多个路由,理解如何选择路由生成URL非常重要。路由系统处理路由,按照他们被加入RouteCollection对象的顺序。每一个路由都会被检查是否匹配,是否满足下面的3个条件:

1.URL模式中定义的片段变量的值都存在,路由系统首先会从匿名对象的属性值中查找值,然后再是当前请求的变量值,最后是路由中定义的默认值。 2.我们提供的片段变量的值必须符合路由中的默认变量,这些变量存在默认值,但是在URL模式中没出现,比如下面的,myVar是一个默认变量 routes.MapRoute("MyRoute", "{controller}/{action}", new { myVar = "true" }); 要匹配这个路由,我们必须小心,要么不提供myVar的值,要么确定我们提供的值就是默认值。 3.所有的片段变量的值必须满足路由约束。

必须清楚,路由系统不会尝试找出最佳匹配的路由,它只会找到第一个匹配的,使用此路由生成URL。后续的路由则被忽略了。由此,定义路由的时候,越是具体特定的路由就要放在越前面。如果你生成的URL没有路由匹配,那么你的链接属性就是空的,如下:

<a href="">About this application</a>。此链接会在view中显示,但是用户点击的时候没有任何反应

第一个满足标准路由会生成一个非空URL,然后会终结URL生成进程,参数值也会被赋值。如果你显示的定义了一下不符合片段参数的参数或者默认参数,此方法会把这些变量附加为query sring。

指向其他controller

默认的ActionLink方法将你的action方法指向的是和当前view相同的controller。要生成一个指向不同controller的url,可以使用它的重载方法,如下:

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

上面的代码会生成如下的HTML

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

注意,路由系统在生成URL的时候,对我们的application也是毫不关注。这意味着,你提供的action和controller值可能是无效的,必须自己确定他们确实存在。

传递额外的值

你可以传递使用匿名类型为片段变量传值,其中匿名变量中的属性表示片段。如下:

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

上例中,我们已经提供了一个片段变量id。因此会得到以下的HTML

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

注意看到,我们提供的值,已作为匹配的URL模式的片段加上了。

当我们在描述路由匹配生成URL的方法时,我们提到,在尝试查找每个路由URL模式中的片段时,路由系统会从当前的请求中查找值,这个行为让很多程序困惑。假设我们的应用程序有个单一的路由

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

再假设用户当前在URL /Catalog/List/Purple/123上,当我们以下面的方式生成link的时候

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

你可能觉得路由系统不会匹配路由,因为我们没有提供color片段的值,并且也没有定义它的默认值。但是你错了,路由系统会根据我们定义的路由匹配。生成如下的HTML:

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

路由系统非常渴望能根据路由得到一个匹配,他会重用请求的URL中的片段变量值,上例中,我们的color中是Purple,因为用户之前的URL中color是Purple。这还不只,路由系统将这一技术作为他自己匹配方法的一部分。路由系统会为某些片段值重用URL模式中出现的值,这些片段变量必须是比 Html.ActionLink 方法中提供的其他参数先出现。假如我们创建了一个link:

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

我们为color提供了一个值,但没有为page赋值。由于color在page前面出现,路由系统不会重用之前URL中的值,路由不会匹配。

处理这种行为最佳的方法是尽量避免这种事情的发生。我们强烈建议你要依赖这种行为,为每个URL模式中的每个片段变量赋值。依靠上述行为可能让你的代码难以读懂。

当传递的值不符合片段变量时,这些值会被作为query string,例如下面的调用ActionLink的方法

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

new { id = "MyID", myVariable = "MyValue" })

生成如下的HTML:

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

如果提供的变量值碰巧匹配路由提供的默认值,那么路由系统生成的URL会忽略变量,例如:

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

为action和controller传递的参数值匹配了默认值,HTML的生成如下:

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

路由系统忽略了默认值,以最少片段生成URL。

设置HTML属性

我们可以为<a>元素设置属性,只需要提供一个匿名类型,其中它的属性和我们需要的属性一致就行。下面演示了设置id属性和css类:

@Html.ActionLink("About this application", "Index", "Home", null,

new {id = "myAnchorID", @class = "myCSSClass"})

我们创建的一个新的匿名方法,包含id和class属性,传递给ActionLink方法。我们传递null给另外的片段变量值,表示我们没有值可以提供。此方法对应的函数签名如下:

public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, object routeValues, object htmlAttributes);

注意属性前面的@字符,C#允许使用保留字作为类成员,只要前面加个@就行。

对应的生成HTML如下:

<a class="myCSSClass" href="/" id="myAnchorID">About this application</a>

以上生成的URL都是相对的URL,但是我们可以使用ActionLink生成完整路径的URL,如下:

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

"https", "myserver.mydomain.com", " myFragmentName",

new { id = "MyId"},

new { id = "myAnchorID", @class = "myCSSClass"})

这个是参数最多的ActionLink的重载方法,允许我们提供协议值,(例子中是https),目标服务器,URL片段和其他参数。生成的HTML如下:

<a class="myCSSClass" href="https://myserver.mydomain.com/Home/Index/MyId#myFragmentName"

id="myAnchorID">About this application</a>

推荐尽可能的使用相对URL,完整的URL的创建依赖于应用程序架构。我们看到过很多依赖绝对路径的大型应用程序,在切换网络结构或者调整域名的时候,就非常困难了。

Html.ActionLink方法生成完整的<a>元素,大多数情况下这真是我们需要的。但是有时我们只需要URL,只想显示url。这时,我们可以使用 Url.Action方法,只生成URL不生成<a>

...

My URL is: @Url.Action("Index", "Home", new { id = "MyId" })

...

Url.Action的使用方法和Html.ActionLink一样,除了他只是生成URL。两个方法的重载方法接受的参数也都一致,之前演示的Html.ActionLink的例子,使用Url.Action也同样可以。

之前提过,路由系统在处理URL的时候对controller和action没有任何概念,这就可以让路由系统可以更广泛的使用在其他ASP.NET应用程序。有时,象处理其他变量那样处理controller和action是很有用的,通过提供一组键值对来生成link。我们可以使用一些方法来实现。这些方法不是MVC专用的。

@Html.RouteLink("Routed Link", new { controller = "Home", action = "About", id="MyID"})

RouteLink 方法没有参数来表示controller和action的值。我们必须把他们包在匿名类型中。上述代码生成如下HTML:

<a href="/Home/About/MyID">Routed Link</a>

同样的,我们可以使用Url.RouteUrl方法来生成URL

@Url.RouteUrl(new { controller = "Home", action = "About", id = "MyID" })

这些方法很少使用,因为我们通常知道并且想要显示的设定controller和action的值。但是知道这个方法的存在也能让我们更简单的编程。

在Action方法中生成URL

多数情况下,我们会在view中生成URL,但是有时也会要在action方法中生成。如果只是要生成URL,可以使用和view中相同的方法

public ViewResult MyActionMethod() {

string myActionUrl = Url.Action("Index", new { id = "MyID" });

string myRouteUrl = Url.RouteUrl(new { controller = "Home", action = "Index" });

... do something with URLs...

}

更常见的需求是把客户端定向到其他的URL,我们可以返回RedirectToAction方法的返回值,如下:

public ActionResult MyActionMethod() {

return RedirectToAction("Index");

}

RedirectToAction方法的返回值是RedirectToRouteResult,指示MVC Framework生成一个重定向的URL,以此调用指定的action。

此方法的重载版本有许多。如果你需要从object属性中生成一个URL并且重定向 发送一个重定向URL,可是使用RedirectToRoute方法

如下:

public ActionResult MyOtherActionMethod() {

return RedirectToRoute(new { controller = "Home", action = "Index", id = "MyID" });

}

此方法也返回RedirectToRouteResult,和调用RedirectToAction的效果相同。

从指定的路由中生成URL

We have specified a name for each route we have defined in this chapter. For example, when we define

routes like this:

对我们有如下定义的路由:

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

routes.MapRoute("MyOtherRoute", "App/{action}", new { controller = "Home" });

路由的名字正是MapRoute方法的第一个参数,在此例中为MyRoute和MyOtherRoute,命名路由有2个原因

1.作为对路由目标的提示

2.可以选择指定的路由来生成URL

我们把最常规的路由放在list的第一个。这意味着,我们使用ActionLink方法的时候会按如下方式生成URL:

@Html.ActionLink("Click me", "About");

URL会由MyRoute生成。你可以通过Html.RouteLink方法覆盖默认路由,该方法提供一个参数来指示你想使用的路由,如下:

@Html.RouteLink("Click me", "MyOtherRoute", new { action = "About" });

你同样能通过Url.RouteUrl方法生成URL。如果你不想担心路由的顺序,那么这个特点很有用。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-08-27 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档