一、请求从路由开始
        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>