文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

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

2023-01-31 02:37

关注

处理发来的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。如果你不想担心路由的顺序,那么这个特点很有用。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯