一、请求从路由开始
1.为什么需要路由?
(1).屏蔽物理路径、提高安全性
(2).有利于搜索引擎优化
2.定义路由的规则
(1).基于模式匹配的路由规则
语法:{占位符1}字面量1{占位符2}字面量2...{占位符n}...字面量n
注:字面量可能是一个固定的字符,比较常见的是"/",也可以是一个字符串,如:"User"
占位符也是一个字符或字符串,如可以是"x"、"id"、"pageIndex"等
eg:
{Conlltrller}/{action}/{id} /Books/Edit/1,/Books/Detail/2
{first}/{secpnd}/{third} /Books/Edit/1,/Books/Detail/2
{table}/Details.aspx /Users/Detail.aspx
Blog/{action}/{id} Blog/show/1001
{language}-{country}/{action} /zh-cn/display
URL模式匹配是不区分大小写的
两个占位符之间不能连续
"/"和一般的字面相比,是比较特殊的
在路由的URL模式中,不能以"/"或"~"字符开头,并且不能包含"?"字符
(2).路由数据
在ASP.NET MVC路由系统中,提供了RouteData对象。RouData对象用来保存URL模式和实际URL匹配产生的路由数据
eg:
{Conlltrller}/{action}/{id} /Books/Edit/1 Key=Controller,Value=Books
Key=action,Value=Edit
Key=id,value=1
在动作方法中使用RouteData
string id = RouteData.Values["id"];
在视图中使用RouteData
@(RouteData.Values["id"])
其中RouteData.Values是RouteDataDictionary类型,在视图中科院遍历它的值
var html="";
foreach(KeyValuePair<string,object> d in RouteData.Values)
{
html+=d.key+"="+(d.Value??string.Enpty)+"<br/>";
}
(3).特殊的路由模式
1) * 匹配
* 用来匹配URL的剩余部分,如{Conlltrller}/{action}/{query}/{*plus}
2) 贪婪匹配
在URL模式和实际URL匹配过程中,可能会出现多种情况
如:{filename}.{ext} /food.xml.aspx
会产生下面两种路由数据
filename=food,ext=xml.aspx
filename=food.xml,ext=aspx
事实上,只可能产生后面这种情况的路由数据
(4).路由的默认值
当路由含默认值时,还必须遵循一些特殊规则,主要有以下两点:
1) 只提供中间参数的默认值不起作用
2) 包含字面量时默认值不起作用
当URL模式中包含除“/”之外的字面量时,为占位符定义的默认值可能不起作用
(5).路由约束
通过constraints
eg:
routes.MapRoute(
name: "Blog",
url: "{year}/{month}/{day}",
defaults: new { year = "Book", month = "Index", day = UrlParameter.Optional },
namespaces: new string[] { "CH01DemoRazor.Controllers" },
constraints:new {year=@"\d{4}",month=@"\d{2}",dat=@"\d{2}"}
);
3.定义多个路由
1 routes.MapRoute( 2 name: "Test", 3 url: "{controller}/{action}/{id}", 4 defaults: new { controller = "Book", action = "Index", id = UrlParameter.Optional }, 5 namespaces: new string[] { "CH01DemoRazor.Controllers" } 6 ); 7 8 routes.MapRoute( 9 name: "Default", 10 url: "{controller}/{action}/{id}", 11 defaults: new { controller = "Book", action = "Index", id = UrlParameter.Optional }, 12 namespaces: new string[] { "CH01DemoRazor.Controllers" } 13 );
多条路由和这个URL模式匹配,那么就是排在最前面的优先匹配
4.由路由生成URL
(1).Url.Action()
public string Action(string actionName);
public string Action(string actionName,object routeValues);
public string Action(string actionName,string controllerName,object routeValues);
actionName:动作方法名称
controllerName:控制器名称 默认使用当前上下文的控制器
routeValues:需要传递的参数,传的值时一个匿名类型的对象
(2).Html.ActionLink()在生成链接的时候,同样应用了路由规则
MvchtmlString ActionLink(string linkText,string actionName,
string controllerName,object routeValues,object htmlAttributes);
linkText:生成的连接文本
htmlAttributes:生成的HTML属性,传的值时一个匿名类型的对象
eg:
<%: Html.ActionLink("C#高级","Detail","Books",new {id=4096},
new {class="link",title="书籍名称"}) %>
生成的HTML
<a href="/Books/Detail/4096" class="link",title="书籍名称">C#高级</a>
注:可以使用Html.Action()代替Url.Action(),使用Html.RouteLink()代替Html.ActionLink()
二、数据传递——从控制器到视图
1.ViewData对象
ViewDate同时属于视图基类和控制器基类的属性,常见的用法是在控制器中写入数据,在视图中读取数据
eg:
//控制器中的代码
1 public class BookController : Controller 2 { 3 public ActionResult Index() 4 { 5 ViewData["data"] = "Hello,ASP.NET MVC"; 6 return View(); 7 } 8 }
//视图代码
<h1>@ViewData["data"]</h1>
注:ViewData的Value是Object类型,即可用保存任意类型的数据
2.动态对象ViewBag
ViewBag是dynamic类型的对象,同时属于视图基类和控制器基类的属性
eg:
//控制器中的代码
1 public class BookController : Controller 2 { 3 public ActionResult Index() 4 { 5 ViewBag.data = "Hello,ASP.NET MVC"; 6 return View(); 7 } 8 }
//视图代码
<h1>@ViewBag.data</h1>
注:ViewBag是对ViewData数据的包装,也就是使用ViewData保存的数据,可以使用ViewBag读取,
相反ViewData也可以读取ViewBag的数据,ViewData["data"]数据,使用ViewBag.Data也可以访问到
3.跨请求数据传递————TempData
TempData也能用于从控制器想视图传递数据,与ViewDate十分相识,但是是完全独立的
eg:
//控制器中的代码
1 public class BookController : Controller 2 { 3 public ActionResult Index() 4 { 5 TempData["data"] = "Hello,ASP.NET MVC"; 6 Response.Redirect("~/Home/Detail"); 7 return View(); 8 } 9 }
//视图代码
<h1>@TempData["data"]</h1>
注:Index()方法中,进行了一次页面重定向,第二次请求的整个生命周期类都可以使用上一次保存的TempData数据
TempData:默认保存的机制是Session,如果TempData使用过,就会被清除,如果没有被使用过,那么它保存
的时间则是Session的生存期
4.强类型视图
在使用ViewData向视图传递数据时,一个明显的缺陷就是在使用的时候要做类型转换。其实除了使用ViewDat之外,
还有一种更好的解决方案,就是使用强类型视图
强类型视图在控制器中传递数据的方式变成直接使用View()的一个带“model”的方法参数的重载方法,在视图中可以直接
通过模型类的属性使用传递的数据
eg:
//动作方法
Book book = manager.GetBookById(Id);
return View(Book);
//视图中的代码
<div>
作者:@(Model.Author) 著</br>
出版社:@(Model.Publisher.Name)
</div>