ホームページ バックエンド開発 C#.Net チュートリアル ASP.NETのフィルターとモデルバインディングの例の詳細な説明

ASP.NETのフィルターとモデルバインディングの例の詳細な説明

May 11, 2017 am 10:38 AM
asp.net mvc フィルター

この記事では、主に ASP.NET MVC の一般的な拡張ポイントであるフィルターとモデル バインディングについて詳しく紹介します。必要な方は参考にしてください。

1. ASP .NET MVC のすべてのリクエストは、対応するコントローラー (以下「コントローラー」と呼びます) の下の特定のアクション (以下「メソッド」と呼びます) に割り当てられます。 通常の状況では、コードを直接記述するだけで十分です。ただし、メソッドの実行前または後にロジックを処理したい場合は、ここでフィルターを使用する必要があります。

一般的に使用されるフィルターは 3 つあります: Authorize (承認フィルター)、HandleError (例外フィルター)、ActionFilter (カスタム フィルター) 対応するクラスは次のとおりです: AuthorizeAttribute、HandleErrorAttribute、および ActionFilterAttribute

Inherit

さまざまな関数を使用できます。メソッドを記述することで実装されます。

1.認可フィルター

認可フィルターはその名の通り、メソッドの実行前に実行され、リクエストがこのメソッドに入ることができるかどうかを制限するために使用されます。新しいメソッド:

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;
      }
    }
  }
ログイン後にコピー

AuthorizeAttribute を継承する新しいクラスを作成し、その中の AuthorizeCore メソッドを書き換えます。この疑似コードは、トークンに値がある場合は true を返し、値がない場合は false を返すことを実装しています。

[TokenValidate]
public JsonResult AuthorizeFilterTest()
{
  return Json(new ReturnModel_Common { msg = "hello world!" })
}
ログイン後にコピー

TokenValidate をマークした後、AuthorizeCore AuthorizeFilterTest の前にメソッドが実行されます。AuthorizeCore が true を返した場合、認可は内部で正常に実行されます。それ以外の場合、認可は失敗します。トークンが渡されていない:

トークンが渡されていない: トークンが渡されていない:

トークンが渡されていない 認可に失敗すると、MVC のデフォルトの認可されていないページに入ります。ここで改善を加えましょう。認可が成功したか失敗したかに関係なく、フロントエンドの処理を容易にするために、戻り値の形式は一貫している必要があります。現時点では、AuthorizeAttribute クラスの HandleUnauthorizedRequest メソッドを書き換えるだけです。

認可フィルター 最も広く使用されているアプリケーションは

権限管理

システムです。

ユーザーログインが成功すると、サーバーは暗号化されたトークンを出力し、AuthorizeCoreメソッドでトークンのロックを解除します。ユーザー ID を取得するには、ユーザー ID がデータベースにアクセスして、現在の

インターフェース

を要求する権限があるかどうかを確認し、そうである場合は true を返し、そうでない場合は false を返します。ログイン成功のための CookieSession と比較して、この認証方法の利点は、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;
}
ログイン後にコピー

これはシステム全体に有効です。インターフェイスまたはページ エラーが発生すると、MVC のデフォルトの

例外処理 が実行され、デフォルトのエラー ページ: 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(&#39;:&#39;);
      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。

【相关推荐】

1. ASP.NET免费视频教程

2. ASP.NET教程

3. 极客学院ASP,NET视频教程

以上がASP.NETのフィルターとモデルバインディングの例の詳細な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

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

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

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

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

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

PHP MVC アーキテクチャ: 将来に向けた Web アプリケーションの構築 PHP MVC アーキテクチャ: 将来に向けた Web アプリケーションの構築 Mar 03, 2024 am 09:01 AM

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

Vue エラー: フィルター内のフィルターが正しく使用できません。解決するにはどうすればよいですか? Vue エラー: フィルター内のフィルターが正しく使用できません。解決するにはどうすればよいですか? Aug 26, 2023 pm 01:10 PM

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

PHP MVC アーキテクチャの上級ガイド: 高度な機能のロックを解除する PHP MVC アーキテクチャの上級ガイド: 高度な機能のロックを解除する Mar 03, 2024 am 09:23 AM

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

PHP 電子メール フィルター: スパムをフィルターして識別します。 PHP 電子メール フィルター: スパムをフィルターして識別します。 Sep 19, 2023 pm 12:51 PM

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

Vue テクノロジー開発でデータをフィルターおよび並べ替える方法 Vue テクノロジー開発でデータをフィルターおよび並べ替える方法 Oct 09, 2023 pm 01:25 PM

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

Vue3 のフィルター関数: データをエレガントに処理する Vue3 のフィルター関数: データをエレガントに処理する Jun 18, 2023 pm 02:46 PM

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

PHP では、FILTER_VALIDATE_URL 定数は URL の検証に使用されるフィルターを表します PHP では、FILTER_VALIDATE_URL 定数は URL の検証に使用されるフィルターを表します Sep 14, 2023 am 10:37 AM

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 でカスタム フィルターを実装するためのヒント Jun 25, 2023 pm 05:01 PM

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

See all articles