ホームページ >バックエンド開発 >C#.Net チュートリアル >Asp.Net MVCフィルターの詳細なコード説明
この記事では、Asp.Net MVC の学習概要のフィルターの詳細な説明を主に紹介します。編集者が非常に優れていると考えたので、参考として共有します。エディターで見てみましょう
1. フィルターの概要
1.1. フィルターとは何かを理解します
1. フィルターは、リクエスト処理パイプラインに追加のロジックを挿入します。横断的な懸念事項を実装するためのシンプルかつエレガントな方法を提供します。 2. MVC フレームワークのいわゆるフィルター (フィルター) は、ASP.NET プラットフォームの Request.Filters オブジェクトと Response.Filter オブジェクトとはまったく異なり、主に要求ストリームと応答ストリームの送信を実装します。通常、フィルターと呼ばれるものは、MVC フレームワークのフィルターを指します。 3. フィルターは、C# の属性の実装に基づいて、リクエスト処理パイプラインにコード ロジックを挿入できます。 Action の呼び出しを担当するクラス ControllerActionInvoker が Action を呼び出して実行すると、アクションの属性がチェックされ、これらの属性が追加のコード挿入処理のために指定されたインターフェイスを実装しているかどうかが確認されます1.2. フィルターが使用される理由を理解する
小さなプロジェクトを作成しましたが、その機能の 1 つはユーザー情報モジュールを操作し、認証されたユーザーによって操作される必要があります。以下に示すように、各アクション メソッドで認証要求を確認できます。 :using MvcFilterDmo.Core; using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Security; namespace MvcFilterDmo.Controllers { public class HomeController : Controller { public ActionResult Index() { if (!Request.IsAuthenticated) { FormsAuthentication.RedirectToLoginPage(); } //操作部分... return View(); } public ActionResult Insert() { if (!Request.IsAuthenticated) { FormsAuthentication.RedirectToLoginPage(); } //操作部分... return View(); } public ActionResult Update() { if (!Request.IsAuthenticated) { FormsAuthentication.RedirectToLoginPage(); } //操作部分... return View(); } public ActionResult Delete() { if (!Request.IsAuthenticated) { FormsAuthentication.RedirectToLoginPage(); } //操作部分... return View(); } //其他Action操作方法 //... } }上記のコードを見ると、このメソッドを使用してリクエストの認証を確認する際に多くの重複があることがわかります。これが、フィルターを使用することで同じ効果が得られる理由です。以下に示すように:
using MvcFilterDmo.Core; using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Security; namespace MvcFilterDmo.Controllers { [Authorize] public class HomeController : Controller { public ActionResult Index() { //操作部分... return View(); } public ActionResult Insert() { //操作部分... return View(); } public ActionResult Edit() { //操作部分... return View(); } public ActionResult Delete() { //操作部分... return View(); } //其他Action操作方法 //... } }フィルターは、リクエスト処理パイプラインに追加する追加メソッドを提供する .NET の属性 (属性) です。ここで Authorize フィルターを使用しても同じ効果が得られますが、コードは明らかに以前よりも簡潔でエレガントになっています。
2. フィルターの使用
2.1. フィルターの基本的なタイプ
フィルター実装のメカニズム: MVC フレームワークは、アクションを呼び出す前に、その特性がアクションの定義に実装されているかどうかを確認します。メソッド (属性) が実装されている場合、この属性で定義されたメソッドがリクエスト処理パイプラインの適切なポイントで呼び出されます。 ActionFilterAttribute クラスは、IactionFilter インターフェイスと IResultFilter インターフェイスの両方を実装します。これは抽象クラスであるため、実装を提供する必要があります。 AuthorizeAttribute クラスと HandleErrorAttribute クラスにはいくつかの便利な機能が含まれており、派生クラスを作成せずに使用できます。2.2. フィルターの適用、適用メソッド、および実行シーケンス
適用: フィルターはコントローラーまたはアクション メソッドに適用できます。これは、すべてのアクション メソッドが混合できることを意味します。または、以下に示すように複数回使用されます。[A] //表示所有的Action方法都会应用A过滤器 Public class DemoController:Controller { [B]//B,C过滤器只作用于此Action方法,但它也会有A过滤器的应用效果 [C] Public ActionResult Index() { //操作部分... return View(); } }
Apply メソッド: Characteristic メソッド。上記のコードに示されています。
実行順序: 同じタイプのフィルターの場合、メソッドに近い実行順序が最初に実行されます。異なるタイプのフィルターの一般的な実行順序は [authorize--->action--->] です。例外フィルターに関しては、例外がスローされるたびに区別がありません。実行順序を調整したい場合は、Order メソッドの値を調整することで実行順序を制御できます。値が小さいほど早く実行されます。次の図は、Action/Result フィルター アプリケーションの実行シーケンス図です
(1)。同じタイプのフィルター アプリケーションの例: 2 つのカスタム アクション フィルター MyFirstFilter と MyThreeFilter が同じ Action メソッド Index に適用されます。 Three コントローラーのコードは次のとおりです: MyFirstFilter のコードは次のとおりです: MyThreeFilter のコードは次のとおりです: 演算結果は次のとおりです:(2 )、さまざまなタイプのフィルタリング サーバー アプリケーションの例: カスタム アクション フィルター MyFirstFilter とカスタム結果フィルター MySecondFilter があり、これらは同じアクション メソッド Index に適用されます。 3 つのコントローラー コードは次のとおりです: MyFirstFilter コードは次のとおりです: MySecondFilter コードは次のとおりです:
运行结果如下:
看完上面的解释,可能你现在对这些过滤器的执行顺序,以及如何自定义过滤器还不明白,不要紧,下面我们会逐一介绍这几个基本的过滤器的使用,以及如何自定义过滤器。
2.3、使用授权过滤器
所有实现了IAuthorizationFilter接口的都可以称之为授权过滤器:其定义如下:
public interface IAuthorizationFilter { void OnAuthorization(AuthorizationContext filterContext); }
由于MVC框架系统自带的AuthorizeAttribute实现有一些突出的功能,而这种牵涉到安全的代码一定要谨慎的编写,所以一般我们不会直接实现这个接口,而是去继承AuthorizeAttribute这个类,并重写其AuthorizeCore方法,签名为: bool AuthorizeCore(HttpContextBase httpContext) 而处理授权失败的时候,可以重写其HandleUnauthorizedRequest方法,其签名为: void HandleUnauthorizedRequest(AuthorizationContext context) 。注意:验证与授权是两回事,验证发生在授权之前。
默认的授权过滤器已经有了验证的功能,其验证的机理是利用Asp.net平台自带的验证机制,如表单验证和Windows验证。除了验证功能,它本身还有授权的功能。授权过滤器是所有过滤器中最早运行的。
经过Route到达了控制器的时候,在调用Action之前,MVC框架会检测在相关的Action上是否有授权过滤器,如果有会调用OnAuthorization方法,如果此方法批准了请求,才会调用相应的Action。
使用授权过滤器几种情况如下:
1.直接在Action上或者控制器上加Authorize,表示启用了验证,但不牵涉到授权。
2.添加Authorize(Users=“a,b”)],表示启用了验证,并且也启用了授权,只有a或者b用户能访问此控制器。
3.当添加Authorize(Roles=“admin,Member”)]时的步骤如下:
---利用asp.net自带的角色提供者,或者实现自己的角色提供者,实现自己的角色提供者时,只需要集成RoleProvider类型,并实现其中的所有方法或部分方法,最好实现所有方法。
---在Web程序的根目录的Web.config文件中配置角色管理者。
---在适当的Action中利用Roles类型来访问自己创建的RoleProvider中的相关方法。
使用内置的授权过滤器
MVC框架内置的授权过滤器AuthorizeAttribute,它允许我们使用这个类的两个公共属性来指定授权策略,如下所示:
Users和Roles两者是并且的关系,例如Users=“a,b,c”,Roles=“admin”,表示用户是a,b,c 其中一个并且是Admin角色才能访问。
创建自定义的授权过滤器
方式一:直接实现IAuthorizationFilter接口,但不推荐这样做,因为牵涉到安全方面的代码。
方式二:继承AuthorizeAttribute这个类,并重写其AuthorizeCore方法,签名为: bool AuthorizeCore(HttpContextBase httpContext),代码如下所示:
public class MyAuthorizeAttribute : AuthorizeAttribute { private string[] allowedUsers; public MyAuthorizeAttribute(params string[] users) { allowedUsers = new string[] { "admin", "user1", "xf" }; } protected override bool AuthorizeCore(HttpContextBase httpContext) { return httpContext.Request.IsAuthenticated &&allowedUsers.Contains(httpContext.User.Identity.Name, StringComparer.InvariantCultureIgnoreCase); } }
2.4、使用动作过滤器
动作过滤器是可以以用于任何目的的多用途过滤器,创建自定义动作过滤器需要实现IActionFilter接口,该接口代码如下所示:
该接口定义了两个方法,MVC框架在调用动作方法之前,会调用OnActionExecting方法。在调用动作方法之后,则会调用OnActionExecuted方法。
实现OnActionExecting方法
参数ActionExecutingContext对象继承于ControllerContext,其中的2个属性:
ActionDescriptor:提供了关于Action方法的相关信息
Result:类型为ActionResult,通过给这个属性设置一个非null的值就可以取消这个请求。
我们可以用过滤器来取消一个请求,通过设置Result属性即可。代码如下所示:
public class MyActionFilterAttribute : FilterAttribute, IActionFilter { public void OnActionExecuting(ActionExecutingContext filterContext) { if(filterContext.HttpContext.Request.IsLocal) { filterContext.Result = new HttpNotFoundResult(); } } public void OnActionExecuted(ActionExecutedContext filterContext) { //未做实现 } }
这个例子通过用OnActionExecuting方法检查请求是否来自本地机器,如果是,编队用户返回一个“404”未找到的响应。运行结果如下图:
实现OnActionExecuted方法
我们也可以通过OnActionExecuted方法来执行一些跨越动作方法的任务,下面这个例子是计算动作方法运行的时间,代码如下:
public class MyActionFilterAttribute : FilterAttribute, IActionFilter { private Stopwatch timer; public void OnActionExecuting(ActionExecutingContext filterContext) { timer = Stopwatch.StartNew(); } public void OnActionExecuted(ActionExecutedContext filterContext) { timer.Stop(); if (filterContext.Exception == null) { filterContext.HttpContext.Response.Write( string.Format("动作方法延迟的时间: {0}", timer.Elapsed.TotalSeconds)); } } } }
我们将自定义的动作过滤器MyActionFilter应用到HomeController的Index方法上,运行结果如下:
2.5、使用结果过滤器
结果过滤器是多用途的过滤器,他会对动作方法所产生结果进行操作,结果过滤器实现IResultFilter接口,创建自定义结果过滤器需要现IResultFilter接口,该接口代码如下所示:
当结果过滤器运用于一个动作方法时,会在动作方法返回动作结果之前,调用OnResultExecuting方法,在返回动作结果之后,会调用OnResultExecuted方法。下面这个例子是计算动作方法返回结果运行的时间,代码如下:
public class MyResultFilterAttribute : FilterAttribute, IResultFilter { private Stopwatch timer; public void OnResultExecuting(ResultExecutingContext filterContext) { timer = Stopwatch.StartNew(); } public void OnResultExecuted(ResultExecutedContext filterContext) { timer.Stop(); filterContext.HttpContext.Response.Write(string.Format("结果执行延迟时间: {0}", timer.Elapsed.TotalSeconds)); } }
我们将自定义的结果过滤器MyResultFilter应用到HomeController的Index方法上,运行结果如下:
需要注意的是:动作过滤器是运行在页面输出之前,结果过滤器是运行在页面输出之后。
2.6、使用异常过滤器
异常过滤器只有在调用一个动作方法而抛出未处理的异常才会运行,这种异常来自以下位置:
A、另一种过滤器(授权、动作、或结果过滤器)。
B、动作方法本身。
C、当动作结果被执行时。
使用内置的异常过滤器
HandleErrorAttribute(处理程序错误特性),它是MVC内嵌的异常过滤器,有以下3个重要的属性:
1.ExceptionType:类型为Type,表示希望被此过滤器处理的异常类型,包括其子类型,默认值为System.Exception
2.View:类型为string,表示此过滤器呈递的视图页面,默认值为Error
3.Master:呈递的视图页的母板页,如果不指定,视图会用其默认的母版页
内嵌的HandleErrorException只有在配置文件Web.config中配置的CustomError 的mode设置为on的时候才生效(其默认模式为RemoteOnly),如下图所示:
此过滤器还会给视图传递一个HandleErrorInfo类型的对象给视图,以便视图可以显示一些额外的关于错误的信息。下面是使用异常过滤器的示例。
应用到Index动作方法上:
在Views/Shared文件夹下添加一个显示异常信息的视图页SpecialError.cshtml,页面代码如下:
@model HandleErrorInfo <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>SpecialError</title> </head> <body> <p> <p> There was a<b>@Model.Exception.GetType().Name</b> while rendering<b>@Model.ControllerName</b>'s <b>@Model.ActionName</b> action </p> </p> </body> </html>
运行结果如下:
创建自定义的异常过滤器
如果我们对异常过滤器有特殊的需求,可以通过自定义的异常过滤器来完成,创建自定义异常过滤器必须实现IExceptionFilter接口,该接口代码如下:
当一个未知处理异常发生时,OnException方法会被调用。该方法的传递一个ExceptionContext对象,派生于ControllerContext类,定义了一些额外的过滤器专有属性如下表所示:
抛出的异常通过Exception属性是可以访问的。通过把ExceptionHandled属性设置为true,一个异常过滤器可以报告它已经处理了该异常,应用于一个动作的所有异常过滤器都会被调用。
需要注意的是:如果一个动作方法的所有异常过滤器均为把ExceptionHandled属性设置为true,MVC框架将使用默认的ASP.NET异常处理程序。
Result属性有异常过滤器使用,以告诉MVC框架要做什么,异常过滤器的两个主要应用是记录该异常到日志,并把适当的消息显示给用户。下面的代码将演示通过创建一个自定义的异常过滤器,当一个特定的钟类的未处理异常出现时,把该用户重定向到一个指定的错误页面。
public class MyExectionAttribute:FilterAttribute,IExceptionFilter { public void OnException(ExceptionContext filterContext) { if(!filterContext.ExceptionHandled&& filterContext.Exception is NullReferenceException) { filterContext.Result = new RedirectResult("~/Content/SpecialErrorPage.html"); filterContext.ExceptionHandled = true; } } }
然后在项目根目录添加一个名为Content的文件夹,在该文件夹下创建SpeciErrorPage.html文件,当异常被处理时,将以这个错误页面显示个用户。该页面代码如下:
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title></title> </head> <body> <h1>Sorry</h1> <p>this is a Excetption test</p> There was aNullReferenceException while renderingHome's Index action </body> </html>
在控制器中应用MyExection异常过滤器,并主动让其抛出一个空引用异常,以便测试。
public class HomeController : Controller { [MyExection] public ActionResult Index() { throw new NullReferenceException(); } }
运行结果如下:
概要: この記事では、フィルターの理解と、MVC フレームワークを使用して基本的なフィルターを構築する方法、およびフィルターとアプリケーションをカスタマイズする方法について簡単にまとめます。
以上がAsp.Net MVCフィルターの詳細なコード説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。