ASP.NETのフィルターとモデルバインディングの例の詳細な説明
この記事では、主に ASP.NET MVC の一般的な拡張ポイントであるフィルターとモデル バインディングについて詳しく紹介します。必要な方は参考にしてください。
1. ASP .NET MVC のすべてのリクエストは、対応するコントローラー (以下「コントローラー」と呼びます) の下の特定のアクション (以下「メソッド」と呼びます) に割り当てられます。 通常の状況では、コードを直接記述するだけで十分です。ただし、メソッドの実行前または後にロジックを処理したい場合は、ここでフィルターを使用する必要があります。
一般的に使用されるフィルターは 3 つあります: Authorize (承認フィルター)、HandleError (例外フィルター)、ActionFilter (カスタム フィルター) 対応するクラスは次のとおりです: AuthorizeAttribute、HandleErrorAttribute、および ActionFilterAttributeInherit
さまざまな関数を使用できます。メソッドを記述することで実装されます。認可フィルターはその名の通り、メソッドの実行前に実行され、リクエストがこのメソッドに入ることができるかどうかを制限するために使用されます。新しいメソッド:
public JsonResult AuthorizeFilterTest() { return Json(new ReturnModel_Common { msg = "hello world!" }); }
この AuthorizeFilterTest メソッドがバックグラウンド メソッドであると仮定すると、ユーザーはそれにアクセスするには有効なトークンを持っている必要があります。一般的な方法は、トークンを受信して検証することです。 AuthorizeFilterTest メソッドを使用しますが、さらにメソッドが増えると、各メソッドに検証コードを記述するのは明らかに非現実的になります。このとき、認可フィルターが使用されます。
public class TokenValidateAttribute : AuthorizeAttribute { /// <summary> /// 授权验证的逻辑处理。返回true则通过授权,false则相反 /// </summary> /// <param name="httpContext"></param> /// <returns></returns> protected override bool AuthorizeCore(HttpContextBase httpContext) { string token = httpContext.Request["token"]; if (string.IsNullOrEmpty(token)) { return false; } else { return true; } } }
[TokenValidate] public JsonResult AuthorizeFilterTest() { return Json(new ReturnModel_Common { msg = "hello world!" }) }
トークンが渡されていない: トークンが渡されていない:
トークンが渡されていない 認可に失敗すると、MVC のデフォルトの認可されていないページに入ります。ここで改善を加えましょう。認可が成功したか失敗したかに関係なく、フロントエンドの処理を容易にするために、戻り値の形式は一貫している必要があります。現時点では、AuthorizeAttribute クラスの HandleUnauthorizedRequest メソッドを書き換えるだけです。
権限管理
システムです。ユーザーログインが成功すると、サーバーは暗号化されたトークンを出力し、AuthorizeCoreメソッドでトークンのロックを解除します。ユーザー ID を取得するには、ユーザー ID がデータベースにアクセスして、現在の
を要求する権限があるかどうかを確認し、そうである場合は true を返し、そうでない場合は false を返します。ログイン成功のための Cookie や Session と比較して、この認証方法の利点は、1 つのインターフェイスを PC とアプリの両方で使用できることです。 2. HandleError 例外フィルター 例外フィルターはコード例外を処理し、MVC がデフォルトで例外フィルターを実装し、App_Start ディレクトリの FilterConfig.cs に登録されているときに実行されます。
/// <summary> /// 授权失败处理 /// </summary> /// <param name="filterContext"></param> protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) { base.HandleUnauthorizedRequest(filterContext); var json = new JsonResult(); json.Data = new ReturnModel_Common { success = false, code = ReturnCode_Interface.Token过期或错误, msg = "token expired or error" }; json.JsonRequestBehavior = JsonRequestBehavior.AllowGet; filterContext.Result = json; }
例外処理 が実行され、デフォルトのエラー ページ: Views/Shared/Error (これはプログラムがサーバーに送信されたときにのみ表示されます) を返します。エラーを報告するため) このページ、ローカルの デバッグ
には高い権限があり、特定のエラー情報を表示することができます)filters.Add(new HandleErrorAttribute());
1) エラー報告では、エラー コードが存在するコントローラーとメソッド、およびエラー報告時のリクエスト パラメーターと時刻を記録できます。
2) 特定の形式で JSON を返します。フロントエンド処理を容易にします。現在、システムのほとんどは Ajax リクエストを使用しているため、エラーが報告されると MVC のデフォルトのエラー ページに戻ります。これは、フロントエンドでの処理が困難です。HandleErrorAttribute を継承し、内部 OnException メソッドをオーバーライドする新しいクラス LogExceptionAttribute を作成します。 :public override void OnException(ExceptionContext filterContext) { if (!filterContext.ExceptionHandled) { string controllerName = (string)filterContext.RouteData.Values["controller"]; string actionName = (string)filterContext.RouteData.Values["action"]; string param = Common.GetPostParas(); string ip = HttpContext.Current.Request.UserHostAddress; LogManager.GetLogger("LogExceptionAttribute").Error("Location:{0}/{1} Param:{2}UserIP:{3} Exception:{4}", controllerName, actionName, param, ip, filterContext.Exception.Message); filterContext.Result = new JsonResult { Data = new ReturnModel_Common { success = false, code = ReturnCode_Interface.服务端抛错, msg = filterContext.Exception.Message }, JsonRequestBehavior = JsonRequestBehavior.AllowGet }; } if (filterContext.Result is JsonResult) filterContext.ExceptionHandled = true;//返回结果是JsonResult,则设置异常已处理 else base.OnException(filterContext);//执行基类HandleErrorAttribute的逻辑,转向错误页面 }
异常过滤器就不像授权过滤器一样标注在方法上面了,直接到App_Start目录下的FilterConfig.cs注册下,这样所有的接口都可以生效了:
filters.Add(new LogExceptionAttribute());
异常过滤器里使用了NLog作为日志记录工具,Nuget安装命令:
Install-Package NLog Install-Package NLog.Config
相比Log4net,NLog配置简单,仅几行代码即可,NLog.config:
<?xml version="1.0" encoding="utf-8" ?> <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <targets> <target xsi:type="File" name="f" fileName="${basedir}/log/${shortdate}.log" layout="${uppercase:${level}} ${longdate} ${message}" /> <target xsi:type="File" name="f2" fileName="D:\log\MVCExtension\${shortdate}.log" layout="${uppercase:${level}} ${longdate} ${message}" /> </targets> <rules> <logger name="*" minlevel="Debug" writeTo="f2" /> </rules> </nlog>
如果报错,日志就记录在D盘的log目录下的MVCExtension目录下,一个项目一个日志目录,方便管理。全部配置完成,看下代码:
public JsonResult HandleErrorFilterTest() { int i = int.Parse("abc"); return Json(new ReturnModel_Data { data = i }); }
字符串强转成int类型,必然报错,页面响应:
同时日志也记录下来了:
3.ActionFilter自定义过滤器
自定义过滤器就更加灵活了,可以精确的注入到请求前、请求中和请求后。继承抽象类ActionFilterAttribute并重写里面的方法即可:
public class SystemLogAttribute : ActionFilterAttribute { public string Operate { get; set; } public override void OnActionExecuted(ActionExecutedContext filterContext) { filterContext.HttpContext.Response.Write("<br/>" + Operate + ":OnActionExecuted"); base.OnActionExecuted(filterContext); } public override void OnActionExecuting(ActionExecutingContext filterContext) { filterContext.HttpContext.Response.Write("<br/>" + Operate + ":OnActionExecuting"); base.OnActionExecuting(filterContext); } public override void OnResultExecuted(ResultExecutedContext filterContext) { filterContext.HttpContext.Response.Write("<br/>" + Operate + ":OnResultExecuted"); base.OnResultExecuted(filterContext); } public override void OnResultExecuting(ResultExecutingContext filterContext) { filterContext.HttpContext.Response.Write("<br/>" + Operate + ":OnResultExecuting"); base.OnResultExecuting(filterContext); } }
这个过滤器适合做系统操作日志记录功能:
[SystemLog(Operate = "添加用户")] public string CustomerFilterTest() { Response.Write("<br/>Action 执行中..."); return "<br/>Action 执行结束"; }
看下结果:
四个方法执行顺序:OnActionExecuting—>OnActionExecuted—>OnResultExecuting—>OnResultExecuted,非常精确的控制了整个请求过程。
实战中记录日志过程是这样的:在OnActionExecuting方法里写一条操作日志到数据库里,全局变量存下这条记录的主键,到OnResultExecuted方法里说明请求结束了,这个时候自然知道用户的这个操作是否成功了,根据主键更新下这条操作日志的是否成功字段。
二、模型绑定(ModelBinder)
先看一个普通的方法:
public ActionResult Index(Student student) { return View(); }
这个方法接受的参数是一个Student对象,前端传递过来的参数跟Student对象里的属性保持一直,那么就自动被绑定到这个对象里了,不需要在方法里new Student这个对象并挨个绑定属性了,绑定的过程由MVC中的DefaultModelBinder完成的,DefaultModelBinder同时继承了IModelBinder接口,现在就利用IModelBinder接口和DefaultModelBinder来实现更加灵活的模型绑定。
场景一、前端传过来了一个加密的字符串token,方法里需要用token里的某些字段,那就得在方法里接收这个字符串、解密字符串、转换成对象,这样一个方法还好说,多了的话重复代码非常多,就算提取通用方法,还是要在方法里调用这个通用方法,有没有办法直接在参数里就封装好这个对象?
模型绑定的对象:
public class TokenModel { /// <summary> /// 主键 /// </summary> public int Id { get; set; } /// <summary> /// 姓名 /// </summary> public string Name { set; get; } /// <summary> /// 简介 /// </summary> public string Description { get; set; } }
新建一个TokenBinder继承IModelBinder接口并实现其中的BindModel方法:
public class TokenBinder : IModelBinder { public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { var token = controllerContext.HttpContext.Request["token"]; if (!string.IsNullOrEmpty(token)) { string[] array = token.Split(':'); if (array.Length == 3) { return new TokenModel() { Id = int.Parse(array[0]), Name = array[1], Description = array[2] }; } else { return new TokenModel() { Id = 0 }; } } else { return new TokenModel() { Id = 0 }; } } }
这个方法里接收了一个token参数,并对token参数进行了解析和封装。代码部分完成了需要到Application_Start方法里进行下注册:
ModelBinders.Binders.Add(typeof(TokenModel), new TokenBinder());
现在模拟下这个接口:
public JsonResult TokenBinderTest(TokenModel tokenModel) { var output = "Id:" + tokenModel.Id + ",Name:" + tokenModel.Name + ",Description:" + tokenModel.Description; return Json(new ReturnModel_Common { msg = output }); }
调用下:
可以看出,“1:汪杰:oppoic.cnblogs.com”已经被绑定到tokenModel这个对象里面了。但是如果稍复杂的模型绑定IModelBinder就无能为力了。
场景二、去除对象某个属性的首位空格
public class Student { public int Id { get; set; } public string Name { get; set; } public string Class { get; set; } }
如果前端传来的Name属性有空格,如何去除呢?利用DefaultModelBinder即可实现更灵活的控制
public class TrimModelBinder : DefaultModelBinder { protected override object GetPropertyValue(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor, IModelBinder propertyBinder) { var obj = base.GetPropertyValue(controllerContext, bindingContext, propertyDescriptor, propertyBinder); if (obj is string && propertyDescriptor.Attributes[typeof(TrimAttribute)] != null)//判断是string类型且有[Trim]标记 { return (obj as string).Trim(); } return obj; } }
标注下需要格式化首位属性的实体:
[ModelBinder(typeof(TrimModelBinder))] public class Student { public int Id { get; set; } [Trim] public string Name { get; set; } public string Class { get; set; } }
好了,测试下:
public JsonResult TrimBinderTest(Student student) { if (string.IsNullOrEmpty(student.Name) || string.IsNullOrEmpty(student.Class)) { return Json(new ReturnModel_Common { msg = "未找到参数" }); } else { return Json(new ReturnModel_Common { msg = "Name:" + student.Name + ",长度:" + student.Name.Length + " Class:" + student.Class + ",长度:" + student.Class.Length }); } }
可见,标注了Trim属性的Name长度是去除空格的长度:7,而没有标注的Class属性的长度则是6。
【相关推荐】
2. ASP.NET教程
以上がASP.NETのフィルターとモデルバインディングの例の詳細な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











はじめに 今日の急速に進化するデジタル世界では、堅牢かつ柔軟で保守可能な WEB アプリケーションを構築することが重要です。 PHPmvc アーキテクチャは、この目標を達成するための理想的なソリューションを提供します。 MVC (Model-View-Controller) は、アプリケーションのさまざまな側面を独立したコンポーネントに分離する、広く使用されている設計パターンです。 MVC アーキテクチャの基礎 MVC アーキテクチャの核となる原則は、関心事の分離です。 モデル: アプリケーションのデータとビジネス ロジックをカプセル化します。ビュー: データの表示とユーザー インタラクションの処理を担当します。コントローラー: モデルとビュー間の対話を調整し、ユーザーのリクエストとビジネス ロジックを管理します。 PHPMVC アーキテクチャ phpMVC アーキテクチャは従来の MVC パターンに従いますが、言語固有の機能も導入しています。以下はPHPMVCです

Vue エラー: フィルター内のフィルターが正しく使用できません。解決するにはどうすればよいですか?はじめに: Vue では、フィルターはデータの書式設定やフィルター処理に使用できる一般的に使用される関数です。ただし、使用中にフィルターを正しく使用できないという問題が発生する場合があります。この記事では、いくつかの一般的な原因と解決策について説明します。 1. 原因分析: フィルターが正しく登録されていません: Vue のフィルターは、テンプレートで使用する前に登録する必要があります。フィルタが正常に登録されなかった場合は、

MVC アーキテクチャ (モデル-ビュー-コントローラー) は、コードを編成し、WEB アプリケーションの開発を簡素化するための明確な構造を提供するため、PHP 開発で最も一般的なパターンの 1 つです。基本的な MVC 原則はほとんどの Web アプリケーションには十分ですが、複雑なデータを処理したり高度な機能を実装する必要があるアプリケーションにはいくつかの制限があります。モデル層の分離 モデル層の分離は、高度な MVC アーキテクチャでは一般的な手法です。これには、モデル クラスを小さなサブクラスに分割し、それぞれが特定の機能に焦点を当てることが含まれます。たとえば、電子商取引アプリケーションの場合、メイン モデル クラスを注文モデル、製品モデル、顧客モデルに分割できます。この分離により、コードの保守性と再利用性が向上します。依存関係注入を使用する

PHP 電子メール フィルター: スパムをフィルターして識別します。電子メールの普及に伴い、スパムの量も増え続けています。ユーザーにとって、受信するスパムの量は情報過多や時間の無駄につながる可能性があります。したがって、スパムメールをフィルタリングして識別する効率的な方法が必要です。この記事では、PHP を使用してシンプルだが効果的な電子メール フィルターを作成する方法と、具体的なコード例を示します。電子メール フィルタの基本原則 電子メール フィルタの基本原則は、電子メールが

Vue テクノロジ開発でデータをフィルタリングおよび並べ替える方法 Vue テクノロジ開発では、データのフィルタリングと並べ替えは非常に一般的で重要な機能です。データのフィルタリングと並べ替えを通じて、必要な情報を迅速にクエリして表示できるため、ユーザー エクスペリエンスが向上します。この記事では、Vue でデータをフィルターおよび並べ替える方法を紹介し、読者がこれらの関数をよりよく理解して使用できるように具体的なコード例を示します。 1. データのフィルタリング データのフィルタリングとは、特定の条件に基づいて要件を満たすデータをフィルタリングすることを指します。 Vue では、comp を渡すことができます

Vue3 のフィルター関数: データをエレガントに処理する Vue は、大規模なコミュニティと強力なプラグイン システムを備えた人気のある JavaScript フレームワークです。 Vue のフィルター関数は、テンプレート内のデータを処理して書式設定できる非常に実用的なツールです。 Vue3 のフィルター関数にはいくつかの変更が加えられています。この記事では、Vue3 のフィルター関数を詳しく説明し、それらを使用してデータを適切に処理する方法を学びます。フィルター機能とは何ですか? Vue のフィルター関数は次のとおりです。

FILTER_VALIDATE_URL 定数は、URL を検証するために使用されます。フラグ FILTER_FLAG_SCHEME_REQUIRED-URL は RFC に準拠している必要があります。 FILTER_FLAG_HOST_REQUIRED - URL にはホスト名が含まれている必要があります。 FILTER_FLAG_PATH_REQUIRED - URL にはドメイン名の後にパスが必要です。 FILTER_FLAG_QUERY_REQUIRED - URL にはクエリ文字列が必要です。戻り値 FILTER_VALIDATE_URL

プラグインを使用して Vue でカスタム フィルターを実装するためのヒント Vue.js には、ビュー データのフィルター処理の必要性に対処する便利な方法、つまりフィルター (Filter) が提供されます。フィルターは主に、ビュー内のデータの書式設定と処理を担当して、データをより直感的で理解しやすくします。 Vue には、日付書式設定、通貨書式設定などの一般的に使用されるフィルターがいくつか組み込まれており、カスタム フィルターもサポートしています。この記事では、Vue プラグインを使用してカスタム フィルターを実装する方法を紹介し、いくつかの実用的なフィルター手法を提供します。
