首页 > 技术文章 > 理解Asp.net MVC模式

MaxInfo 2021-05-07 19:45 原文

MVC是模型(Model)、视图(View)、控制器(Controller)的缩写,它是Web应用程序中一种常用的架构模式。这种模式将应用程序大体上分为3层,即Model层、View层和Controller层。它最主要的优点是实现了关注点分离(Separation of Concerns),将原本耦合在一起的3部分分离为独立的部分,这对开发、调试及测试应用程序都有极大的好处,如图3-5所示。

在ASP.NET Core MVC框架中,除了Controller、Model和Action外,它还包括路由、模型绑定、模型验证和过滤器等功能。

路由:

对于Web应用程序,路由是一个非常重要且基本的功能,它的主要功能是根据预先配置的路由信息对客户端传来的请求进行路由映射,映射完成后,再将请求传给对应的路由处理器处理。

对于ASP.NET Core MVC,定义路由的方法有以下两种。[插图] 基于约定的路由:基于约定的路由会根据一些约定来创建路由,它要在应用程序的Startup类中来定义,事实上,上面的示例就是基于约定的路由。[插图] 特性路由:使用C#特性对Controller和Action指定其路由信息。

一个应用程序可以定义多个路由,当它收到客户端的请求后,将会对每个定义的路由信息进行匹配,直到找到对应的路由。

另一种实现路由的方法是使用特性路由,即RouteAttribute。它能够为每个Controller,甚至每个Action显式地设置路由信息,只要在Controller类或Action方法上添加[Route]特性即可,因此它要更为灵活。

最后,需要说明的是,基本约定的路由与特性路由方式可以同时存在,但是如果已经为一个Action指定了特性路由,那么基本约定的路由在该Action上就不会起作用了。

模型绑定:

在ASP.NET Core MVC中,当一个HTTP请求通过其路由定位到Controller中的某一个Action上时,HTTP请求中的一部分信息会作为Action中的参数。正如在3.4.3节中所看到的,在URL中的id或name会传递给Action方法中的同名参数。将HTTP请求中的数据映射到Action中参数的过程称为模型绑定(Model Binding)。

除了从路由以及查询字符串中获取数据以外,ASP.NET Core MVC还会尝试从表单(Form)中获取数据来绑定到Action中的参数。因此,它主要使用以下3种数据源来为Action的参数提供数据,并且按照顺序来从以下每一种方式中获取。[插图] Form值:HTTP POST请求时表单中的数据。[插图] 路由值:通过路由系统解析得到。[插图] 查询字符串:从URL中的查询字符串中获取。

除了从路由以及查询字符串中获取数据以外,ASP.NET Core MVC还会尝试从表单(Form)中获取数据来绑定到Action中的参数。因此,它主要使用以下3种数据源来为Action的参数提供数据,并且按照顺序来从以下每一种方式中获取。[插图] Form值:HTTP POST请求时表单中的数据。[插图] 路由值:通过路由系统解析得到。[插图] 查询字符串:从URL中的查询字符串中获取。

模型验证:
模型验证是指数据被使用之前的验证过程,它发生在模型绑定之后。在ASP.NETCore MVC中,要实现对数据的验证,最方便的方式是使用数据注解(Dataannotation),它使用特性为数据添加额外的信息。数据注解通常用于验证,只要为类的属性添加需要的数据注解验证特性即可,这些特性均位于System.ComponentModel.DataAnnotations命名空间下。

通常情况下,这些验证特性已经能够满足常见的验证需求。然而,在特殊情况下,就需要使用复杂的、自定义的验证规则,ASP.NET Core MVC提供了两种创建自定义验证的方法,一种是创建新的特性,并使它继承自ValidationAttribute类;另一种是使待验证的Model实现IValidatableObject接口。

过滤器:

过滤器与中间件很相似,在ASP.NET Core MVC中,它们能够在某些功能前后执行,由此而形成一个管道。
ASP.NET Core MVC提供了以下5种类型的过滤器。
Authorization过滤器:最先执行,用于判断用户是否授权,如果未授权,则直接结束当前请求,这种类型的过滤器实现了IAsyncAuthorizationFilter或IAuthorizationFilter接口。
Resource过滤器:在Authorization过滤器后执行,并在执行其他过滤器(除Authorization过滤器外)之前和之后执行,由于它在Action之前执行,因而可以用来对请求判断,根据条件来决定是否继续执行Action,这种类型过滤器实现了IAsyncResourceFilter或IResourceFilter接口。
Action过滤器:在Action执行的前后执行,与Resource过滤器不一样,它在模型绑定后执行,这种类型的过滤器实现了IAsyncActionFilter或IActionFilter接口。
Exception过滤器:用于捕获异常,这种类型的过滤器实现了IAsyncExceptionFilter或IExceptionFilter接口。
Result过滤器:在IActionResult执行的前后执行,使用它能够控制Action的执行结果,比如格式化结果等。需要注意的是,它只有在Action方法成功执行完成后才会运行,这种类型过滤器实现了IAsyncResultFilter或IResultFilter接口。

当要创建过滤器时,应该实现IXXXFilter或IAsyncXXXFilter,这两个接口的区别是前者同步、后者异步。ASP.NET Core MVC会首先检查异步实现,如果没有实现异步方式,则继续检查同步实现,因此在创建过滤器时,不需要同步接口和异步接口都实现。以IAsyncActionFilter和IActionFilter为例,这两个接口的定义分别如下所示。

如果过滤器以全局有效的方式添加(即在Startup类的ConfigureServices方法中,通过调用AddMvc方法添加),则它会在ConfigureServices方法中被添加到容器中。而如果以特性的方式使用包含依赖项的过滤器时,则会出错,这是因为在自定义特性的构造函数中所定义的接口类型的参数并不是有效的特性参数。此时就需要使用[ServiceFilter]特性或[TypeFilter]特性,这两个特性都能够解决过滤器特性中引用其他依赖的问题。


欢迎关注个人公众号:
image

推荐阅读