.NET Core.Net MVCdotnet

Asp.net mvc 知多少(二)

2016-12-16  本文已影响3573人  圣杰

本系列主要翻译自《ASP.NET MVC Interview Questions and Answers 》- By Shailendra Chauhan,想看英文原版的可访问http://www.dotnettricks.com/free-ebooks自行下载。该书主要分为两部分,ASP.NET MVC 5、ASP.NET WEB API2。本书最大的特点是以面试问答的形式进行展开。通读此书,会帮助你对ASP.NET MVC有更深层次的理解。
由于个人技术水平和英文水平也是有限的,因此错误在所难免,希望大家多多留言指正。
系列导航
Asp.net mvc 知多少(一)
Asp.net mvc 知多少(二)
Asp.net mvc 知多少(三)
Asp.net mvc 知多少(四)
Asp.net mvc 知多少(五)
Asp.net mvc 知多少(六)
Asp.net mvc 知多少(七)
Asp.net mvc 知多少(八)
Asp.net mvc 知多少(九)
Asp.net mvc 知多少(十)

本节主要讲解MVC的管道及路由机制


Q13. Asp.net mvc 中的ViewModel?
Ans. 在 ASP.NET MVC中, ViewModel 是一个包含将在强类型视图中展示的字段的类。它是用来将数据从Controller传递到强类型视图中。
ViewModel的关键点:


Q14. 解释下 ASP.NET MVC pipeline(管道)?
Ans. 先上图:

ASP.NET MVC pipeline
  1. Routing(路由) - 路由是管道的第一步。简单来说,它是一种模式匹配系统,去路由表中注册的Url中匹配传入的请求。在代码中主要是UrlRoutingModule(System.Web.Routing.UrlRoutingModule)在做匹配的工作,路由表对应的是RouteTable(System.Web.Routing.RouteTable)

  2. Controller Initialization(初始化控制器) - MvcHandler使用ProcessRequest方法开始对ASP.NET MVC pipeline进行实时处理。这个方法使用工厂类IControllerFactory的实例(默认是System.Web.Mvc.DefaultControllerFactory)去创建对应的Controller。

  3. Action Execution (Action执行)– 该环节按以下顺序执行:

4.Result Execution (返回执行结果阶段)- 该阶段主要包含以下步骤:

4.1 View Initialization and Rendering (视图初始化及渲染)- 可以分解为以下几个步骤:


Q15. 解释下 ASP.NET MVC 的路由机制?
Ans. 路由是一种模式匹配系统,用来监视传入的请求并决定如何处理请求。在运行时,路由引擎使用路由表去匹配传入的请求的Url,根据路由表定义的Url格式与传入的Url格式进行匹配。可以在Application_Start 事件中注册一个或多个Url格式到路由表中。
当路由引擎在路由表中找到一个与传入的Url请求匹配的路由记录,路由引擎会转发请求到对应的Controller、Action中。如果没有匹配的记录,则返回404。
大致处理流程如下图:

路由处理流程

Q16. 如何在ASP.NET MVC中定义路由?
Ans. 可以参照下面代码定义路由:

public static void RegisterRoutes(RouteCollection routes)
{
 routes.MapRoute(
 "Default", // Route name
 "{controller}/{action}/{id}", // Route Pattern
 new
 {
 controller = "Home",
 action = "Index",
 id = UrlParameter.Optional
 }// Default values for above defined parameters
 );
}
protected void Application_Start()
{
 RegisterRoutes(RouteTable.Routes);
 //TODO:
}

需要注意的是路由名称必须是唯一命名不可重复。
在以上的例子中我们定义一个{controller}/{action}/{id} 这样的路由并为Controller、Action、id参数提供了默认值。如果你的url中未包含某一项值,路由引擎会用定义的路由的默认值填充。
假设你的web应用程序挂载在 www.example.com,那么你的url应该是www.example.com/{controller}/{action}/{id}这样的。
下面是针对定义的路由的匹配结果:

路由匹配结果

Note: 总是将特殊的路由定义在路由的最上边。因为路由系统是从上往下对传入的请求进行匹配,如果有一个匹配上,就不会继续往下寻找路由进行匹配。

PS: 这里推荐一个很实用的路由检查插件RouteDebugger,进行路由的分析。
使用方法很简单:
1.在对应的mvc项目上通过Nuget包安装RouteDebugger即可。
2.运行项目,就可以在网页的下方,可以看到罗列的路由定义及匹配到的路由。效果如图:

RouteDebugger效果图

3.可以通过web.config的AppSettings节点的<add key="RouteDebugger:Enabled" value="true" />进行禁用。


Q17. 什么是特性路由,如何定义特性路由?
Ans. ASP.NET MVC5 、WEB API 2 支持的一种新路由的方式,叫做attribute routing(特性路由)。这种路由方式中,特性被用来定义路由,特性路由使我们能够更好的控制URLs,支持直接在action和controller上定义路由。

  1. Controller level routing (控制器级别路由)– 可以为一个controller定义路由,那么它所以的action都将应用此路由,除非一个特定的路由被直接定义在某一个action上。
[RoutePrefix("MyHome")]
[Route("{action=index}")] //default action
public class HomeController : Controller
{
 //new route: /MyHome/Index
 public ActionResult Index()
 {
 return View();
 }
 //new route: /MyHome/About
 public ActionResult About()
 {
 ViewBag.Message = "Your application description page.";
 return View();
 }
 //new route: /MyHome/Contact
 public ActionResult Contact()
 {
 ViewBag.Message = "Your contact page.";
 return View();
 }
}
  1. Action level routing (Action级别路由)– 可以通过在action上定义action级别路由,那么这个action将被应用这个特定的路由。
public class HomeController : Controller
{
 [Route("users/{id:int:min(100)}")] //route: /users/100
 public ActionResult Index(int id)
 {
 //TO DO:
 return View();
 }
 [Route("users/about")] //route" /users/about
 public ActionResult About()
 {
 ViewBag.Message = "Your application description page.";
 return View();
 }
 //route: /Home/Contact
 public ActionResult Contact()
 {
 ViewBag.Message = "Your contact page.";
 return View();
 }
}

Note:


Q18. 什么时候使用特性路由?
Ans. 基于约定的路由一般用来支持确定的URI格式,常见于RESTful APIs。但是通过特性路由相对来说更加简单的去定义URI格式。
例如,资源通常包含子资源,像客户拥有订单,电影有演员,书籍有作者等。通常会创建URIS去反应这种关系,类似/clients/1/orders
这种类型的URI用基于约定的路由是很难定义的。即使可以定义,如果有很多controllers、资源类型,那定义的路由也将差强人意。
使用特性路由,就会非常简单定义此类路由,只需要在controller的action上添加一个attribute即可。

[Route("clients/{clientId}/orders")]
public IEnumerable<Order> GetOrdersByClient(int clientId)
{
 //TO DO
}

Q19. 如何启用特性路由?
Ans. 通过在RouteConfig.cs文件的RegisterRoutes()方法中添加routes.MapMvcAttributeRoutes()调用即可。

public class RouteConfig
{
 public static void RegisterRoutes(RouteCollection routes)
 {
 routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

 //enabling attribute routing
 routes.MapMvcAttributeRoutes();
 }
}

特性路由和基于约定的路由可以同时使用。

public class RouteConfig
{
 public static void RegisterRoutes(RouteCollection routes)
 {
 routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
 //enabling attribute routing
 routes.MapMvcAttributeRoutes();
 //convention-based routing
 routes.MapRoute(
 name: "Default",
 url: "{controller}/{action}/{id}",
 defaults: new { controller = "Home", action = "Index", id =
UrlParameter.Optional });
 }
}


Q20. 如何在Area中定义特性路由?
Ans. 通过为Area中的Controller定义 RouteArea特性。当你为一个Area中的所有controller定义了特性路由,那就可以删除为这个area注册路由的AreaRegistration 类。

[RouteArea("Admin")]
[RoutePrefix("menu")]
[Route("{action}")]
public class MenuController : Controller
{
 // route: /admin/menu/login
 public ActionResult Login()
 {
 return View();
 }
 // route: /admin/menu/products
 [Route("products")]
 public ActionResult GetProducts()
{
 return View();
 }
 // route: /categories
 [Route("~/categories")]
 public ActionResult Categories()
 {
 return View();
 }
}

Q21. 路由与URL重写的区别是什么?
Ans. 路由和Url重写都可以用来定义出SEO友好型的URLS。但是它们的实现方式是十分不同的,主要区别在:


Q22. 什么是 Route Constraints (路由约束)?
Ans. Route constraints(路由约束)是对已定义路由进行一些验证的方式。假设我们已经定义了以下路由:

public static void RegisterRoutes(RouteCollection routes)
{
 routes.MapRoute(
 "Default", // Route name
 "{controller}/{action}/{id}", // Route Pattern
 new
 {
 controller = "Home",
 action = "Index",
 id = UrlParameter.Optional
 } // Default values for parameters
 );
}

当我们希望限制传入请求的Url中的Id参数是数学类型的,可以采用以下方式:

public static void RegisterRoutes(RouteCollection routes)
{
 routes.MapRoute(
 "Default", // Route name
 "{controller}/{action}/{id}", // Route Pattern
 new
 {
 controller = "Home",
 action = "Index",
 id = UrlParameter.Optional
 }, // Default values for parameters
 new { id = @"\d+" } //Restriction for id(限制Id未数字类型)
 );
}

这样对路由定义后,就限制了如果有第三个参数id,id必须为数字类型。只有类似http://example.com/Admin/Product/1这样的Url才能成功路由。


Q23. 路由表是如何创建的?
Ans. 当Mvc应用程序第一次启动时,global.asax类中的Application_Start() 方法调用RegisterRoutes()方法。RegisterRoutes()方法负责创建了路由表。

上一篇 下一篇

猜你喜欢

热点阅读