本系列主要翻译自《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 知多少(三)

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


Q13. Asp.net mvc 中的ViewModel?

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

ViewModel的关键点:

  • ViewModel 包含在视图中呈现的字段。(LabelFor, EditorFor, DisplayFor helpers)
  • ViewModel 可以通过数据注解指定特定的验证规则。
  • ViewModel 可以包含多个来自不同数据模型或数据源的实体或对象。

Q14. 解释下 ASP.NET MVC pipeline(管道)?

Ans. 先上图:

  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执行)– 该环节按以下顺序执行:

  • 当Controller初始化后,Controller通过传递选择的action方法详情调用它自己的InvokeAction() 方法。这一步是由IActionInvoker处理。

  • 当选择合适的action方法后,model binder(模型绑定器,默认是System.Web.Mvc.DefaultModelBinder)取回传入的Http请求的数据,然后进行数据转换,数据验证(比如required、数据格式等)。同时还需要将数据映射到action方法对应的参数上。

  • Authentication Filter (认证过滤器)是在ASP.NET MVC5中引入的,它先于authorization filter(授权过滤器)执行。它主要用来对用户认证。认证过滤器处理请求中的用户凭证并返回相应的主体。在ASP.NET MVC5之前,使用 authorization filter (授权过滤器)对用户进行认证和授权。 Authenticate attribute(认证特性)默认是被用来进行认证. 可以通过实现IAuthenticationFilter接口来创建自定义的authentication filter(认证过滤器)

  • Authorization filter(授权过滤器)用来对已认证的用户执行授权操作。例如。基于角色的授权。Authorize attribute(授权特性默认用来执行授权操作)。可以通过实现IAuthorizationFilter接口来创建自定义的authentication filter(授权过滤器)。

  • Action filters (Action过滤器)在 OnActionExecuting之前OnActionExecuting之后执行。IActionFilter接口提供了两个方法 OnActionExecutingOnActionExecuting分别在action之前和之后执行。通过实现IActionFilter 该接口来自定义Action过滤器。

  • action执行后, 通过model(Business Model or Data Model)去处理用户输入并准备对应的Action Result。

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

  • Result filters(结果过滤器) 在(OnResultExecuting)之前 (OnResultExecuted)之后执行。 IResultFilter 接口提供两个方法 OnResultExecuting 、OnResultExecuted分别对应在ActionResult之前和之后执行。可以通过实现IResultFilter接口来自定义结果过滤器。
  • Action Result是BLL或者DAL对用户输入执行相应的操作后的返回结果。Action Result 的类型可以是 ViewResult, PartialViewResult, RedirectToRouteResult, RedirectResult, ContentResult,

    JsonResult, FileResult, EmptyResult。这些返回类型可以分为两类,即ViewResult类型和 NonViewResult 类型。ViewResult 类型主要用于返回并渲染html页面到浏览器。NonViewResult仅仅返回数据,比如文本、二进制、json 格式数据。

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

  • ViewResult 类型,比如 view、partial view 都是实现了 IView (System.Web.Mvc.IView) 接口并由相应的视图引擎进行渲染。
  • 这一过程主要由视图引擎的 IViewEngine (System.Web.Mvc.IViewEngine) 接口负责。默认ASP.NET MVC 提供了WebForm、Razor 两种视图引擎。可以通过实现 IViewEngine 创建自定义的视图引擎并注册自定义视图引擎到ASP.NET MVC应用程序。
  • Html Helpers 主要用来创建html输入控件,基于路由创建链接,创建ajax表带等等。Html Helpers 是 HtmlHelper的扩展类并可以很好的进行进一步扩展。 在复杂的情形中,可以渲染一个有前端验证机制的JavaScript或jquery验证。

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.运行项目,就可以在网页的下方,可以看到罗列的路由定义及匹配到的路由。效果如图:

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:

  • 特性路由应该在基于约定的路由之前配置。
  • 如果同时使用特性路由和基于约定的路由,若action上未定义特性路由,那么action将按照基于约定的路由进行路由。在上面的示例中Contact()action将应用基于约定的路由,即 /Home/Contact
  • 当仅仅定义了特性路由而没有基于约定的路由时,若某个action未定义特性路由时,该action将不能被成功路由,会返回404。

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。但是它们的实现方式是十分不同的,主要区别在:

  • URL rewriting(URL重写)注重将一个URL映射到另一个URL。 而Routing(路由)注重将一个URL映射到一个资源。
  • URL rewriting(URL重写)重写你的旧的URL到一个新的URL。而Routing(路由)只是将URL映射到它对应的原始路由。

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()方法负责创建了路由表。

Asp.net mvc 知多少(二)的更多相关文章

  1. Asp.net mvc 知多少(三)

    本系列主要翻译自<ASP.NET MVC Interview Questions and Answers >- By Shailendra Chauhan,想看英文原版的可访问http:/ ...

  2. Asp.net mvc 知多少(六)

    本系列主要翻译自<ASP.NET MVC Interview Questions and Answers >- By Shailendra Chauhan,想看英文原版的可访问http:/ ...

  3. Asp.net mvc 知多少(七)

    本系列主要翻译自<ASP.NET MVC Interview Questions and Answers >- By Shailendra Chauhan,想看英文原版的可访问http:/ ...

  4. Asp.net mvc 知多少(八)

    本系列主要翻译自<ASP.NET MVC Interview Questions and Answers >- By Shailendra Chauhan,想看英文原版的可访问[http: ...

  5. Asp.net mvc 知多少(九)

    本系列主要翻译自<ASP.NET MVC Interview Questions and Answers >- By Shailendra Chauhan,想看英文原版的可访问http:/ ...

  6. Asp.net mvc 知多少(十)

    本系列主要翻译自<ASP.NET MVC Interview Questions and Answers >- By Shailendra Chauhan,想看英文原版的可访问http:/ ...

  7. Asp.net mvc 知多少(一)

    本系列主要翻译自<ASP.NET MVC Interview Questions and Answers >- By Shailendra Chauhan,想看英文原版的可访问http:/ ...

  8. Asp.net mvc 知多少(五)

    本系列主要翻译自<ASP.NET MVC Interview Questions and Answers >- By Shailendra Chauhan,想看英文原版的可访问http:/ ...

  9. Asp.net mvc 知多少(四)

    本系列主要翻译自<ASP.NET MVC Interview Questions and Answers >- By Shailendra Chauhan,想看英文原版的可访问http:/ ...

随机推荐

  1. 前端面试题(3) cookie,sessionStorage和localStorage的区别

    cookie是网站为了标示用户身份存在用户本地终端上的数据(经过加密). cookie数据时钟在同源的http请求中携带(即使不需要),即会在浏览器和服务器之间传递. seeeionStorage和l ...

  2. 通过游戏认识 --- JQuery与原生JS的差异

      前言 jQuery是一个快速.简洁的JavaScript框架,是继Prototype之后又一个优秀的JavaScript代码库( 或JavaScript框架).jQuery设计的宗旨是“write ...

  3. Unity3D高性能战争迷雾实现

    效果图 先上效果图吧,这是为了吸引到你们的ヽ(。◕‿◕。)ノ゚ 战争迷雾效果演示图 战争调试界面演示图 由于是gif录制,为了压缩图片,帧率有点低,实际运行时,参数调整好是不会像这样一卡一顿的. 战争 ...

  4. postman 时间戳和加密

    在使用postman进行接口测试的时候,对于有些接口字段需要时间戳加密,这个时候我们就遇到2个问题,其一是接口中的时间戳如何得到?其二就是对于现在常用的md5加密操作如何在postman中使用代码实现 ...

  5. 安卓自定义控件(一)Canvas、Paint、Shader、Xfermode

    关于自定义控件,之前就写过一篇自定义控件,上图下字的Button,图片任意指定大小,但是使用效果还是让人感觉不幸福,这次索性彻彻底底地对自定义控件做一次彻彻底底的总结. 我会花4篇博客来介绍自定义控件 ...

  6. H5+JS+JQuery+ECharts实现异步加载

    这几天,看了一下ECharts官网的API和Demo发现很有意思,于是就利用模型预测产生的数据做一个伪实时的动态数据显示 . 首先,创建一个index.html的文件,我用的vscode打开的,进行编 ...

  7. 01.redis初识

    Redis学习: redis是什么? Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库.缓存和消息中间件. 不过Redis在生产环境中使用最多的功能是缓存系统.至于其 ...

  8. #openstack centos6 centos7 kvm镜像制作

    #openstack centos6 centos7 kvm 镜像制作 openstack windows 2008镜像 制作 http://www.cnblogs.com/elvi/p/800129 ...

  9. 算法训练 区间K大数

    算法训练 区间k大数查询 时间限制:1.0s   内存限制:256.0MB 问题描述 给定一个序列,每次询问序列中第l个数到第r个数中第K大的数是哪个. 输入格式 第一行包含一个数n,表示序列长度. ...

  10. thinkphp5.0 微信公众号接入支付宝支付

    ---恢复内容开始--- 真是无力吐槽这个需求了,想骂客户,好端端的非要在微信公众号接入支付宝,都知道微信公众号是拒绝支付宝的,屏蔽了支付宝,所以在微信公众号接入支付宝的话就必须手动复制链接跳出微信内 ...