博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
mvc(5)——URL路由_1_定义路由(映射url到动作方法)
阅读量:2241 次
发布时间:2019-05-09

本文共 10050 字,大约阅读时间需要 33 分钟。

  在使用mvc的过程中,我们经常用到的就是路由,今天我们来了解一下路由的一些东西。

  在我们进行路由的讲解之前,我们要做一些准备,新建一个项目。

新建一个项目

  用”Empty(空)”模板创建一个新的MVC应用程序,并称此项目“UrIsAndRoutes”。

这里写图片描述
这里写图片描述

创建控制器

  为了演示路由特性,对此示例应用程序添加一些简单的控制器,以此对URL进行解释以调用动作方法的方式,因此,所用的视图模型都是视图包中的一些字符串值,用它们来报告控制器和动作方法的名称。首先,创建一个Home控制器,并设置其内容如下:

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;namespace urlAndRoutes.Controllers{    public class HomeController : Controller    {        // GET: Home        public ActionResult Index()        {            ViewBag.Controller = "Home";            ViewBag.Action = "Index";            return View("ActionName");        }    }}

创建一个customer控制器,代码如下:

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;namespace urlAndRoutes.Controllers{    public class CustomerController : Controller    {        // GET: Customer        public ActionResult Index()        {            ViewBag.Controller = "Customer";            ViewBag.Action = "Index";            return View("ActionName");        }        public ActionResult List()        {            ViewBag.Controller = "Customer";            ViewBag.Action = "List";            return View("ActionName");        }    }}

创建admin控制器,代码如下:

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;namespace urlAndRoutes.Controllers{    public class AdminController : Controller    {        // GET: Admin        public ActionResult Index()        {            ViewBag.Controller = "Admin";            ViewBag.Action = "Index";            return View("ActionName");        }    }}

创建视图

  在这些控制器的所有动作方法中,小编指定的都是ActionName视图,这让小编只需定义一个视图,并将它用于整个示例应用程序。在Views文件夹中创建Shared文件夹,并添加一个新的名为ActionName.cshtml的视图,内容如下:

@{    Layout = null;}    
ActionName
The Controller is :@ViewBag.Controller
The action is :@ViewBag.Action

此时启动下面,如下图:

这里写图片描述

URL模式

  路由系统用一组路由来实现它的功能。这些路由共同组成了应用程序的URL架构(Schema)或方案(Scheme),这种URL架构(或方案)是应用程序能够识别并能对之做出响应的一组URL。

  我们不需要手动输入应用程序中打算支持的各个URL,而是让每一条路由都包含一个URL模式(Pattern),用它与一个输入URL进行比较。如果该模式与这个URL匹配,那么它(URL模式)便被路由系统用来对这个URL进行处理。让我们先从上述示例应用程序的一个URL开始:

这里写图片描述

这里写图片描述

  URLs可以分成几个片段。除主机名和查询字符串之外,这些URL的组成部分都用“/”字符进行分割。在这个示例URL中有两个片段,第一个片段含有单词“home”,第二个片段含有单词“Index”。很显然,第一个片段与控制器有关,而第二个片段与动作有关。

  当然,需要以一种路由系统能够理解的方式来表示这种关系。以下是做这件事的一个URL模式:{controller}/{action}
  当处理一个输入请求时,路由系统的工作是将这个请求URL与一个模式进行匹配,然后从此URL为这个模式中定义的片段变量提取出相应的值。片段变量用花括号(“{”和“}”字符)表示。上述示例模式有两个片段变量,其名称分别为”controller”和”action”,因此,controller片段变量的值将是home,而action片段变量的值将是Index。
  所谓“与一个模式匹配”是指,一个MVC应用程序通常会有几条路由,而路由系统会把输入URL逐一与每条路由的URL模式相比较,直到能找到一条匹配的路由为止(意即,这条路由中的URL模式与这个输入URL匹配)。
  默认情况下,一个URL模式将匹配具有正确片段数的任何URL。例如,模式
{controIler}/{action}将匹配任何具有两个片段的URL,如下表:

请求URL 片段变量
controller=Admin action=Index
controller=Index action=Admin
Controller=Apples action=Oranges
不匹配一一一片段太少
不匹配一一片段太多

  表中突出了URL模式的两个关键行为:

  • URL模式是保守的(Conservative),因而只匹配与模式具有相同片段数的URL你可以从表中的第四、第五个例子看到这种情况(片段数不同就是不匹配)。
  • URL模式是宽松的(Liberal)。如果一个URL正好具有正确的片段数,该模式就会用来为片段变量提取值,而不管这个值可能是什么。

      正如前面己经提到的,路由系统并不知道关于MVC应用程序的任何情况,因此,即使不存在从一个URL提取出来的值所对应的控制器或动作,URL模式也会进行匹配(这里的含义是,只要模式匹配,路由系统便会从URL中为片段变量提取值,至于应用程序中是否实际存在相应的控制器和动作,路由系统是不管的)。你可以从表中的第二个例子中看到这种情况的演示。这个例子的URL中调换了Admin和Index片段,因此,从这个URL提取的值也被调换了,尽管示例项目中没有Index控制器。

      了解了这些,我们开始正式定义路由啦!!!!!

创建一条简单的路由

一旦在头脑中有了URL模式,便可以用它来定义一条路由。路由是在RouteConfig.cs文件中进行定义的,该文件位于项目的App_Start文件夹中。内容如下:

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;using System.Web.Routing;namespace urlAndRoutes{    public class RouteConfig    {        public static void RegisterRoutes(RouteCollection routes)        {            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");            routes.MapRoute(                name: "Default",                url: "{controller}/{action}/{id}",                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }            );        }    }}

  在RouteConfig.cs文件中定义的静态RegisterRoutes方法是通过Global.asax.cs文件进行调用的,当启动应用程序时,它建立了一些核心的MVC特性。代码如下:

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;using System.Web.Routing;namespace urlAndRoutes{    public class MvcApplication : System.Web.HttpApplication    {        protected void Application_Start()        {            AreaRegistration.RegisterAllAreas();            RouteConfig.RegisterRoutes(RouteTable.Routes);   //RouteConfig·RegisterRoutes方法的调用        }    }}

  下面将介绍如何在RouteConfig.cs文件的RegisterRoutes方法中,使用URL模式来创建一条路由。(我们删除了原有的url模式)。

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;using System.Web.Routing;namespace urlAndRoutes{    public class RouteConfig    {        public static void RegisterRoutes(RouteCollection routes)        {            Route myRoute = new Route("{controller}/{action}",new MvcRouteHandler());            routes.Add("myRoute",myRoute);        }    }}

  该清单创建了一个新的Route,以URL模式作为一个构造器参数,并将其表示成一个字符串。

  另外,还为构造器传递了一个MvcRouteHandIer实例。不同的ASP.NET技术提供了不同的类来定制路由的行为,而这个类(指MvcRouteHandIer类)是用于ASP.NETMVC应用程序的类。一旦创建了这个路由,就可以用Add方法把它添加到RouteCoIIection对象,在其中传递给这条路由所起的名字和已经创建的这条路由。

  上面是注册路由的方法,下面是另外一种更加方便的方法:

  使用在RouteCollection类所定义的MapRoute方法。下面的代码介绍如何用这个方法来注册路由。它和前面的示例有同样的效果,但语法更简洁。

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;using System.Web.Routing;namespace urlAndRoutes{    public class RouteConfig    {        public static void RegisterRoutes(RouteCollection routes)        {            routes.MapRoute("MyRoute", "{controller}/{action}");        }    }}

  通过运行应用程序,可以看到对路由所做修改的效果。当浏览器试图导航到应用程序的根URL时,你将看到一个错误。

这里写图片描述

  但如果导航到一个与{controIler}/{action}模式匹配的URL,将会出现下图的结果:

这里写图片描述
  上面的配置文件中,简单路由并未告诉MVC框架,如何对根URL的请求进行响应,并且只支持简单的、非常具体的URL模式。在功能上,要比VisualStudio在创建MVC项目时,添加到RouteConfig.cs文件中的路由所具备的功能暂时后退了一步(因为此刻的路由还无法对根URL进行解析)。

定义默认值

  前面曾解释过,URL模式是保守的,它们只匹配指定片段数的URL。改变这种行为的一个办法是使用默认值。当URL不包含与一个片段匹配的值时,便使用默认值。设置方法如下:

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;using System.Web.Routing;namespace urlAndRoutes{    public class RouteConfig    {        public static void RegisterRoutes(RouteCollection routes)        {            routes.MapRoute("MyRoute", "{controller}/{action}", new { Action = "Index" });        }    }}

  默认值是作为匿名类型的属性来提供的。上面的代码中为action变量提供了一个Index的默认值。这条路由将匹配所有两片段的URL,就像它之前所做的那样。例如,如果请求,该路山将为controller提取Home值,为action提取Index值。但是现在,由于己为action片段提供了一个默认值,该路由也将匹配单片段URL。当处理单片段URL时,路由系统将从唯一的URL片段中提取controller的值,并对action变量使用默认值。于是,可以请求,并调用Home控制器上的Index动作方法。

  可以更进一步,定义根本不含任何片段变量的URL,只依靠默认值来标识controller和action。下面的代码中告诉我们如何为应用程序映射根URL。

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;using System.Web.Routing;namespace urlAndRoutes{    public class RouteConfig    {        public static void RegisterRoutes(RouteCollection routes)        {            routes.MapRoute("MyRoute", "{controller}/{action}", new { Controller="Home", Action = "Index" });        }    }}

  上面的代码中已经为controller和action变量提供默认值,为了方便解释:这里己经创建了与0个、1个或2个片段的ULR匹配的路由,如下表所示:

片段数 实例 映射结果
0 controller=Home ;action=Index
1 controller=Customer;action=index
2 controller=Customer;action=List
3 不匹配一一片段数太多

  在输入URL中接收的片段数越少,所依赖的默认值便越多,直到接收一个无片段而只使用默认值的URL。重新启动该示例应用程序,你可以看到默认值的效果一一此时,当浏览器请求应用程序的根URL时,将使用controller和action片段变量的默认值,这将导致MVC框架请求Home控制器上的Index动作方法,如图所示:

这里写图片描述

使用静态的URL片段

1、带有前缀的url

  并不是一个URL模式中的所有片段都需要是可变的,也可以创建具有静态片段的模式。假设希望匹配以下这种URL,以支持带有Public前缀的URL:,可以通过使用如下代码所示的模式来做这件事。

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;using System.Web.Routing;namespace urlAndRoutes{    public class RouteConfig    {        public static void RegisterRoutes(RouteCollection routes)        {            routes.MapRoute("MyRoute", "{controller}/{action}", new { Controller="Home", Action = "Index" });            routes.MapRoute("","Public/{controller}/{action}",new { Controller="Home",Action="Index"});        }    }}

  这个新的URL模式将只匹配含有三个片段的URL,第一个必须是Public.其他两个片段可以含有任何值,并将被用于controller和action变量。如果省略后两个片段,那么将使用默认值。

这里写图片描述

2、带有可变元素片段的url

当然,还可以创建既有静态也有可变元素片段的URL模式,比如下面的代码中:

//我是代码片段11using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;using System.Web.Routing;namespace urlAndRoutes{    public class RouteConfig    {        public static void RegisterRoutes(RouteCollection routes)        {            routes.MapRoute("","X{controller}/{action}");            routes.MapRoute("MyRoute", "{controller}/{action}", new { Controller = "Home", Action = "Index" });            routes.MapRoute("","Public/{controller}/{action}",new { Controller="Home",Action="Index"});        }    }}

  这条路由中的模式匹配任意两片段URL,而第一个片段以字母”x”打头。用于controller的值取自第一个片段除”X”以外的部分,Action值取自第二个片段。如果你启动应用程序并导航到/XHome/Index,可以看到这条路由的效果,结果如图

这里写图片描述

ps:路由定义的顺序

  代码片段11中,定义了一条新路由,并把它放在RegisterRoutes方法中的所有其他路由之前。这么做是因为路由是以它们在RouteC011ection对象中出现的顺序被运用的。MapRoute方法会把一条路由添加到该集合的末尾,让路由以它们被定义的顺序来运用。

  路由系统试图根据最先被定义的路由模式来匹配一个输入URL,并且只有在不匹配时,才会继续对下一条路由进行处理。路由被依次尝试,直至找到匹配的一条,或这组路由被尝试完。其结果是,必须首先定义较具体的路由。在代码片段11中所添加的路由要比其后的路由更具体些。假设顛倒路由的顺序,如下所示:

routes.MapRoute("MyRoute", "{controller}/{action}", new { Controller = "Home", Action = "Index" });                        routes.MapRoute("","X{controller}/{action}");

那么第一条路由匹配任何具有0、1、2片段的URL,它将是被使用的一条。更具体

的路由现在是列表的第二条,它将是不可到达的。新路由(第二条)去掉URL的前导”x”但旧路由(第一条)却不会这么做,因此,像这样的一条URL:将以名为”XHome”的控制器为目标,而这是不存在的,因此,会导致一个“494一未找到”错误被发送给用户。

3、创建url中的别名

  可以结合静态片段和默认值为特定的路由创建一个别名。如果你已经公开地发布了URL方案,并且它与你的用户形成了一种契约,那么,创建这种别名可能是有用的。如果在这种情况下(指己与用户形成契约)重构应用程序,则需要保留以前的URL格式。设想以前用的是一个Shop控制器,现在要由Home控制器来替代。代码如下:

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;using System.Web.Routing;namespace urlAndRoutes{    public class RouteConfig    {        public static void RegisterRoutes(RouteCollection routes)        {            routes.MapRoute("shopdemo","shop/{action}",new { Controller="Home"});        }    }}

  添加的这条路由匹配第一个片段是”Shop”的任意两片段URL,action的值取自第二个URL片段。这个URL模式不含controller的可变片段,因而会使用所提供的默认值。这意味着对Shop控制器上一个动作的请求会被转换成对Home控制器的请求。

这里写图片描述
源码下载:

你可能感兴趣的文章
用验证曲线 validation curve 选择超参数
查看>>
用 Grid Search 对 SVM 进行调参
查看>>
用 Pipeline 将训练集参数重复应用到测试集
查看>>
PCA 的数学原理和可视化效果
查看>>
机器学习中常用评估指标汇总
查看>>
什么是 ROC AUC
查看>>
Bagging 简述
查看>>
详解 Stacking 的 python 实现
查看>>
简述极大似然估计
查看>>
用线性判别分析 LDA 降维
查看>>
用 Doc2Vec 得到文档/段落/句子的向量表达
查看>>
使聊天机器人具有个性
查看>>
使聊天机器人的对话更有营养
查看>>
一个 tflearn 情感分析小例子
查看>>
attention 机制入门
查看>>
手把手用 IntelliJ IDEA 和 SBT 创建 scala 项目
查看>>
GAN 的 keras 实现
查看>>
AI 在 marketing 上的应用
查看>>
Logistic regression 为什么用 sigmoid ?
查看>>
Logistic Regression 为什么用极大似然函数
查看>>