.net mvc 路由
在Global.asax文件中,默认路由如下。
routes.MapRoute(
"Default", // 路由名称
"{controller}/{action}/{id}", // 带有参数的 URL
new { controller = "Logon", action = "Logon", id = UrlParameter.Optional } // 参数默认值
);
这个路由中,在Action后面只能传入一个参数,不能传入多个参数,因此,需要增加路由信息。
在Global文件中,新增了一个路由,路由名称为“Default1",代码如下
//第一种路由 传两个参数过去
routes.MapRoute("Default1",
"{controller}/{action}/{Parma1}/{Parma2}",
new { controller = "", action = "" },
new { });
上述路由,可以传入两个参数。
在此,我们建一个TestController,添加一个Test.cshtml页面,在TestController写下代码,如下
public ActionResult Test(string date, string id)
{
ViewData["date"] = date;
ViewData["id"] = id;
return View();
}
在Test.cshtml页面中写如下代码
要查询的日志时间为:@ViewData["date"]<br />
要查询的日志ID为:@ViewData["id"]<br />
运行编译器,然后在浏览器中输入 ”http://localhost:11507/Test/Test/2013-12-18/5“,页面显示如下
要查询的日志时间为:2013-12-18
要查询的日志ID为:5
现在又有一个问题来了,需要传入多个参数,怎么办呢?当然,只有新添加新的路由”Default2"。代码如下
//第二种路由 传多个参数,只是获得的第二个下划线后的所以数据
routes.MapRoute("Default2",
"{controller}/{action}/{*id}",
new { controller = "", action = "" }
);
运行编译器,然后在浏览器中输入 ”http://localhost:11507/Test/Test/2013-12-18/5/xianrongbin“,页面显示如下
要查询的日志时间为:
要查询的日志ID为:2013-12-18/5/xianrongbin
这里我们只能得到Action后面所有的参数,对此,我们可以解析出来,比如日志时间是 “2013-12-18",日志ID为”5“,日志操作者是”xianrongbin"。
第一种方法:
1)添加路由表为:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}.html/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
);
routes.MapRoute("BlogActive",
"Blog/Archtive/{date}/{id}",
new { controller = "Blog", action = "Archtive" },
new {date = @"\d{4}-\d{2}-\d{2}"});
2)在View->Home文件中的Index.aspx文件有以下链接:
<li><%= Html.ActionLink("我的链接","Archtive/2010-04-18/4","Blog")%></li>
3)在Controllers->BlogController.cs中增加函数:
public ActionResult Archtive(string date, string id)
{
ViewData["date"] = date;
ViewData["id"] = id;
return View("Archtive");
}
4)在View->Blog文件夹中的Archtive.aspx文件中增加以下内容:
要查询的日志时间为:<%= ViewData["date"] %><br />
要查询的日志ID为:<%= ViewData["id"] %><br />
5)输入网址:http://localhost/MVCTest/Home/Index.html,页面中出现如下链接: http://localhost/MVCTest/Blog/Archtive/2010-04-18/4.html
6)点击页面中的链接,在http://localhost/MVCTest/Blog/Archtive/2010-04-18/4.html,页面中将呈现以下内容:
要查询的日志时间为:2010-04-18
要查询的日志ID为:4.html
以上说明路由正确的得到了传入的两个参数。
第二种方法:
1)在路由表中增加:
routes.MapRoute("BlogActive",
"Blog/Archtive/{*id}",
new { controller = "Blog", action = "Archtive" }
);
2)在View->Home文件中的Index.aspx文件有以下链接:
<li><%= Html.ActionLink("我的链接","Archtive/2010-04-18/4","Blog")%></li> 3)在Controllers->BlogController.cs中增加函数:
public ActionResult Archtive(string id)
{
ViewData["date"] = id;
return View("Archtive");
} 4)在View->Blog文件夹中的Archtive.aspx文件中增加以下内容:
要查询的日志时间为:<%= ViewData["date"] %><br />
5)输入网址:http://localhost/MVCTest/Home/Index.html,页面中出现如下链接:http://localhost/MVCTest/Blog/Archtive/2010-04-18/4.html
6)点击页面中的链接,在http://localhost/MVCTest/Blog/Archtive/2010-04-18/4.html页面中将呈现以下内容:
要查询的日志时间为:2010-04-18/4.html
以上说明路由正确的得到了传入的参数,但这种方式其实是将2010-04-18/4.html作为一个参数传递过去,要想得到想要的两个参数的结果,还需要进一步解析方可使用。
MVC的URL路由规则
Routing的作用:它首先是获取到View传过来的请求,并解析Url请求中Controller和Action以及数据,其次他将识别出来的数据传递给Controller的Action(Controller的方法)。这是Routing组件的两个重要的作用!
下面我们从几个例子来讲解一下Url路由的使用。
MapRoute()有6个方法可以重载,下面举5个例子相应介绍!
实例一:首先讲解的是系统默认提供的路由格式,下面是系统给的默认代码:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // 路由名称
"{controller}/{action}/{id}", // 带有参数的 URL
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // 参数默认值
);
}
Url格式为:http://localhost:0000/home/index 对应规则为:{controller}/{action}/{id} 黑体部分就是对应部分。这还是有默认值的情况。
详细匹配应该为:http://localhost:0000/Custom/Detials/1 去掉主机域名,剩下的对应就是匹配Controller和actiong了。通过Routing组件解析这个Url,Controller是Custom,Action是Detials。传递过去的Id是1。
这就是使用了MapRoute( string name, string url, object defaults);这个方法的重载。
实例二:不使用默认值的Url路由规则
函数头:MapRoute( string name, string url);
routes.MapRoute("没有默认值路由规则", "{controller}/{id}-{action}");
适合的Url例子:http://localhost:0000/Custom/1-Detials
它将不匹配http://localhost:0000/
实例三:带名称空间的Url路由规则
函数头:MapRoute( string name, string url, string[] namespaces);//路由名,Url规则,名称空间
routes.MapRoute(
"MyUrl", // 路由名称
"{controller}/{id}-{action}", // 带有参数的 URL
new { controller = "Home", action = "Index", id =
UrlParameter.Optional }, // 参数默认值
new string[] { "MvcDemo.Controllers" }//命名空间
);
Url:http://localhost:0000/Custom/1-Detials
这个例子是带命名空间的路由规则,这在Aeras使用时非常有用。不多说,后面再说!
实例四:带约束的路由规则
函数头:MapRoute( string name, string url, object defaults, object constraints);//路由名,Url规则,默认值,名称空间
routes.MapRoute(
"Rule1",
"{controller}/{action}-{Year}-{Month}-{Day}}",
new { controller = "Home", action = "Index", Year =
"2010", Month = "04", Day = "21" },
new { Year = @"^\d{4}", Month = @"\d{2}" }
);
Url:http://localhost:14039/home/index-2010-01-21
实例五:带名称空间,带约束,带默认值的路由规则
函数头:MapRoute( string name, string url, object defaults, object constraints, string[] namespaces);
routes.MapRoute(
"Rule1",
"Admin/{controller}/{action}-{Year}-{Month}-{Day}",
new { controller = "Home", action = "Index", Year =
"2010", Month = "04", Day = "21" },
new { Year = @"^\d{4}", Month = @"\d{2}" },
new string[] { "MvcDemo.Controllers" }
);
Url:http://localhost:14039/Admin/home/index-2010-01-21
实例六:捕获所有的路由
routes.MapRoute(
"All", // 路由名称
"{*Vauler}", // 带有参数的 URL
new { controller = "Home", action = "Index", id =
UrlParameter.Optional } // 参数默认值
);
关于Global.asax剩余部分的说明:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");是忽略这个规则的Url
AreaRegistration.RegisterAllAreas();//注册所有的Areas
RegisterRoutes(RouteTable.Routes);//注册我们写的规则
//RouteDebug.RouteDebugger.RewriteRoutesForTesting(RouteTable.Routes);//调试用语句,需要下载RouteDebug.dll,并添加引用!加入这句话后就可以测试Url路由了。
当你创建一个新的ASP.NET MVC 应用程序,应用程序已经配置了默认的URL路由。URL路由在两个地方设置。
第一, URL路由配置在你的应用程序WEB配置文件中(Web.config文件)。文件中有四个有关路由的配置节:
第二, system.web.httpModules节,
第三, system.web.httpHandlers节,
第四, system.webserver.modules节,和
第五, system.webserver.handlers节。小心不要删除这些配置节,因为没有这些配置节路由将不在工作。
第二,更为重要的是,一个路由表在应用程序的Global.asax文件中创建。Global.asax文件是一个特别的文件,它包含了ASP.NET应用程序生命周期事件处理。当Application Start事件开始,路由被创建。
图1是一个ASP.NET MVC应用程序的默认Global.asax文件。
图 1 – Global.asax.cs
当一个ASP.NET MVC应用程序第一次运行时, Application_Start()方法被调用。这个方法,又调用RegisterRoutes()方法,RegisterRoutes()方法创建了路由表。
默认的路由本包含一个路由(命名Default).默认路由第一段URL映射到一个控制器名字,第二段URL映射到一个动作,第三段映射到一个参数叫Id.
想象你在浏览器地址栏输入以下URL:
/Home/Index/3
默认路由映射以下这些参数:
controller = Home
action = Index
id = 3
当你请求URL /Home/Index/3,以下代码会被执行:
HomeController.Index(3)
默认路由包括默认的三个参数。如果你提供一个控制器,那默认控制器参数值就是Home.如果你不提供一个动作,那默认动作参数的值就是Index.最后,如果你不提供一个id,那id参数默认是一个空字符串。
让我们看一些默认路由如何映射URL到控制器动作的示例。想象你在浏览器地址栏输入以下URL:
/Home
因为默认路由参数,这个URL会引起HomeController 类的Index()方法如图2被调用。
图2 – HomeController.cs
在图2中, HomeController类包含一个叫Index()的方法,它接受单个叫Id的参数。URL /Home 引起值为空字符串Id参数的 Index()被调用。
因为ASP.NET MVC框架调用控制器动作这个方式,the URL /Home 也匹配图3中的HomeController类 Index()方法。
图 3 – HomeController.cs (无参数的Index action)
图3中这个Index()方法不接受任何参数。URL /Home 将引起Index()的方法被调用。URL /Home/Index/3 也调用这个方法。(Id是被忽略的)
URL /Home 也匹配图4 中HomeController类Index()方法
图 4 – HomeController.cs (可空参数Index action)
图4中, Index()有一个整型方法. 因为参数是可空类型 (值能够为空), Index() 调用不能产生错误。
最后,图5中调用Index(),URL /Home引起一个异常从Id参数不是可空类型参数,如果你尝试调用Index()方法,你得来以一个错误页面:
图5 – HomeController.cs (Index action with)
URL /Home/Index/3, 另一方面, 图5中控制器 Index 动作是可以工作的。The 请求 /Home/Index/3 引发带一个值为3 Index() 方法被调用。
/Archive/12-25-2009
当一个用户发起这个请求,你要返回一个符合12/25/2009日期的BLOG。因此处理这样的请求,你需要创建一个自定义路由。
图6中Global.asax文件包含一个新的自定义路由,叫做Blog,处理像这样/Archive/entry date的请求。
图 6 – Global.asax (自定义路由)
路由表中你增加的路由顺序是很重要的。我们自定义Blog路由是增加在默认路由之前的。假如你搞反了,那默认路由将永远替代调用自定义路由。
自定义Blog路由匹配任何/Archive/开始请求,所以它匹配所有以下URLs:
/Archive/12-25-2009
/Archive/10-6-2004
/Archive/apple
这个自定义路由映射进来的请求到一个名叫Archive控制器同时调用Entry()方法,当Entry()方法被调用时,进入日期转成一个名叫entryDate参数。
在图7中 你能使用控制器与BLOG自定义路由。
图 7 – ArchiveController.cs
注意图7中的Entry()方法接受一个DateTime 类型的参数.ASP.NET MVC 框架是智能的,它能从URL的DateTime的值自动的转换为entry date。如果entry date从URL不能转换为DateTime,将引出错误。
好下面咱就好好的说说路由Routing
第一 如果Routing 的命名空间是System.Web.Routing 在这说一下Routing不是MVC 3 独有的,第二 Routing的作用:
1. 确定Controller
2. 确定Action 3. 确定其他参数(一般就是Action方法的参数了) 4. 根据识别出来的Controller Action 将请求传递给对于的Controller 和 Action 。
第三 Routing 是怎么工作的:
我们思考一个问题对于下面的这个url http://www.cnblogs/wlitsoft/blogs/123 为什么当我访问这个url的时候是怎么实现Controller 就是 wlitsoft Action 就是 blogs 参数就是123的呢?
好我们都知道MVC 3 项目的跟目录下有个全局文件(global.asax)
1 Routes.MapRoute(
2 "Default", // 路由名称
3 "{controller}/{action}/{id}", // 带有参数的URL
4 new { controller = "Home", action = "Index", id = UrlParameter.Optional } // 参数默认值
5 );
我们会发现上面这几行代码。这几行代码就定义了一个路由匹配规则,下面我们将一下具体的参数是什么意思。
-
name 参数:规则名称,不可以重复,即路由名必须是唯一的。
- url 参数: 将要识别的参数括起来即可, 比如:
{controller}/{action}/{id} 这里的{}就是占位符
- defaults 参数:url参数的默认值,当我们新建了一个mvc 项目的时候当运行浏览可以看到地址栏没有任何的参数只有一个比如http://localhost:32112/ 它什么就转向了home下的index页面呢?这就是这个参数的作用了
它可以定义默认的controller action 以及 id参数 这个还得说一下您看上面的代码为什么id不给一个具体的值而是给一个UrlParameter.Optional 呢 这个呢 因为您不能保证id的类型是int 的还是 stirng 等等 ,写id= UrlParameter.Optional 它会根据id的类型还具体的指定什么类型的默认值比如int型的就是0吧!
- constraints参数: 这个参数在再上面的代码中没有出现 我先提前说下 然后一会儿咱再看代码吧!这个参数的作用是用来限定每个参数的规则或http请求的类型constraints属性是一个RouteValueDictionary对象,也就是一个字典表, 但是这个字典表的值可以有两种:
1.用于定义正则表达式的字符串。正则表达式不区分大小写
2. 一个用于实现
IRouteConstraint 接口且包含 match 方法的对象。
例如:通过正则表达式可以规定参数格式,比如controller 参数只能是4位数字。
new { controller = @"\d{4}"}
通过第IRouteConstraint 接口目前可以限制请求的类型。
例如:比如限制一条路由规则只能处理GET请求:
httpMethod = new HttpMethodConstraint( "GET", "POST" )
第四 怎么优化url
对于一个网站来说为了SEO友好,一个url层数不要超过3层:但是按照我们默认的匹配规则{controller}/{action}/{id} 它是3层以及不符合SEO了怎么办呢?稍微修改下就ok了看怎么修改{controller}/{action}-{id} 我们都知道C#的命名规则是字母数字下划线不能以字母开头,所以{action}-{id}
映射出来的url 不会被匹配成一个变量。
第五
路由匹配是有优先级的
路由匹配是有优先级的也就是说您定义路由规则的的时候是有顺序的,假如您定义了一个非常复杂的路由但是您放在了最下面,恰巧呢上面的路由规则有符合的那您就挂了,永远不会匹配到您定义的那个路由。怎么办捏 把不容易匹配的路由放在最上面,把最容易匹配的路由放在最下面,这里我还得说一点 有个路由能匹配所有的url什么呢 看下面代码
{*AllUrl}
第六
区域 area 比如 一个管理系统 都有后台功能吧!但是我们想让后台管理这块和网站前台分开或这说后台管理这快存再一个单独的web.config 配置文件怎么办呢?这里区域的概念出来了我们首先新建一个区域。
完事后会看到一个AreaAdminAreaRegistration.cs 文件 打开它
1 public override void RegisterArea(AreaRegistrationContext context)
2 {
3 context.MapRoute(
4 "AreaAdmin_default",
5 "AreaAdmin/{controller}/{action}/{id}",
6 new { action = "Index", id = UrlParameter.Optional }
7 );
8 }
重写了一个方法 那 全局文件中怎么识别呢 ? 看下全局文件
1 protected void Application_Start()
2 {
3 AreaRegistration.RegisterAllAreas();
4
5 RegisterRoutes(RouteTable.Routes);
6 }
第3行是不是定义了 所以 区域这个路由规则除了前面加了一个AreaAdmin 区域名 和其他的没有任何的区别了吧!下面我们新建一个Controller 比如AdminHome 我们先避免和以前的Controller重名一会儿再说为什么。看下运行结果
很正常吧!但是如果我要新建一个HomeController 呢 就是 建一个 以前前台有过的Controller ,运行一下
也没问题是吧!好下面咱再访问一下另一个homecontroller 就是 前台的那个,看下出什么异常
出问题了是吧!因为程序中存在两个HomeController 它不知道要访问哪个!,所以根据错误提示我们还得再原有的路由中加点东西 加个namespace。区分一下两个HomeController
|
第七 路由测试
我们不能保证自己写的路由规则一定能被匹配到 好下面介绍一个工具专为分析路由匹配的叫什么呢 叫RouteDebug
首先引入dll 然后再在全局文件中的Application_Start() 方法里加入如下代码
RegisterRoutes(RouteTable.Routes);
RouteDebug.RouteDebugger.RewriteRoutesForTesting(RouteTable.Routes);