まず最初に、このブログ投稿は、MVC でサーバー側検証を使用して .ASP.NET フルスタック開発を改善することに関するものであることを述べておきます。そのため、繰り返しの内容については詳しく説明しません。多くの問題が発見されています。それを改善するには、このブログ投稿も同じで、「MVC でのサーバー側検証を使用した .ASP.NET フル スタック開発」を読んだ内容に基づいています。
前回の記事でサーバー側の検証は完了しましたが、このように検証のためにアクション内でバリデーターを呼び出す必要があります。
[HttpPost] public ActionResult ValidatorTest(Person model) {var result = this.ValidatorHub.PersonValidator.Validate(model); if (result.IsValid) { return Redirect("https://www.baidu.com"); }else { this.ValidatorErrorHandler(result); } return View(); }
気持ち悪いです。検証する必要がある場合は、すべてのアクションでこのように記述する必要があります。これは単なる実験です。本当に検証したい場合は、これを実際に実行すると、間違いなくこのコードが嫌いになると思います。少なくとも私はそう思う。だから、以前の書き方が大嫌いでした。
私は今何をしたいですか? MVC には実際にデータ検証が組み込まれていることはわかっています。ここではあまり紹介しません(たまにホイールをちゃんと見るとメリットがたくさんあります)。ここではその使い方を簡単に説明します。
[HttpPost] public ActionResult ValidatorTest(Person model) { if (ModelState.IsValid) { /// ok } return View(); }
以前に書いたものよりもはるかに合理化されていますが、それでも各アクションで ModelState.IsValid を呼び出す必要があると思います。 1 つだけ、これは私が望んでいることではなく、このようになることを願っています
[HttpPost] public ActionResult ValidatorTest(Person model) { // // 一大堆代码 // return Redirect("https://www.baidu.com"); }
通常のプログラミングに影響を与えないでください、そして私は実行しません何かの繰り返し。
つまり、データはアクションを実行する前に実際に検証されます。
そこで、MVC が提供する Filter と OnActionExecuting を考えました。ControllerEx を開いて、その中の OnActionExecuting を書き換えます。これには、ActionExecutingContext というパラメータがあります。名前から大まかに理解できます。このパラメータは、Action 関連のコンテキストです。 、その後、アクション関連のデータがインストールされているはずです。
インクは書きませんが、コードに直接進みます。実際、これらのコードは私が今書いたものです。あまり知りません。このパラメータについては、1 つずつ試してみると、徐々にコツを掴めるようになります。
protected override void OnActionExecuting(ActionExecutingContext filterContext) { var existError = false; foreach (var value in filterContext.ActionParameters.Values) { var modelValidatorPropertyInfo = this.ValidatorHub.GetType().GetProperty(value.GetType().Name + "Validator"); if (modelValidatorPropertyInfo != null) { var modelValidator = modelValidatorPropertyInfo.GetValue(this.ValidatorHub) as IValidator; var validateResult = modelValidator.Validate(value); if (!validateResult.IsValid) { this.ValidatorErrorHandler(validateResult); existError = true; } } } if (existError) { ViewData["Error"] = DicError; filterContext.Result = View(); } base.OnActionExecuting(filterContext); }
OnActionExecuting では、最初に検証が失敗したかどうかを判断するために存在エラーを定義し、次に filterContext.ActionParameters.Values
を走査しました。 filterContext を見ると、ActionParameters が Action のパラメータに関するものであることがわかります。デバッグを通じて、キーがパラメータ名であるコレクションであることがわかりました。たとえば、人を例に挙げます。
[HttpPost] public ActionResult ValidatorTest(Person model) { // // 一大堆代码 // return Redirect("https://www.baidu.com"); }
filterContext.ActionParameters コレクションにデータがあり、キーは「model」、値は model
したがって、filterContext.ActionParameters.Value をトラバースすることで各アクションのすべてのパラメーターを取得でき、各パラメーターは .getType().Name を通じてその型名を取得できます。たとえば、ここでのモデル タイプは Person です。したがって、filterContext.ActionParameters["model"].GetType().Name は「person」です。
エンティティの種類がわかったので、特定のバリデーターを取得するにはどうすればよいでしょうか?バリデータ設定 Person = PersonValidator について考えてみましょう。これは単純すぎます。これは 1 対 1 の関係ではありませんが、スイッチを介してファクトリに戻ることは不可能です。この場合、ファクトリ メソッドを維持する必要があります。もちろんそうではありません。これには、.NET
が提供する強力なリフレクション テクノロジを使用する必要があります。場合によっては、オブジェクトである匿名オブジェクトがあることもありますが、それがどのような型であり、その取得方法がわからないことがあります。 . 属性についてはどうですか?
この問題を解決できる方法があります。
public static class ReflectHelper { public static object GetPropertyByAnonymousObject(string propertyName, object obj) { var property = obj.GetType().GetProperties().Where(p => p.Name == propertyName).FirstOrDefault(); if (property == null) { throw new Exception(string.Format("{0}对象未定义{1}属性", nameof(obj), nameof(propertyName))); } return property.GetValue(obj); } }
使用法に関しては、属性名とオブジェクトを渡し、オブジェクト属性を返します。
内部で何が行われたかを見てみましょう。
最初にタイプを取得し、次に実行された属性を取得します。ああ、この属性は実際の属性ではありません。これは PropertyInfo タイプであり、リフレクションのデータ型です。実際の属性値ではありません。しかし、実際の属性値を取得するにはどうすればよいでしょうか?実際には、GetValue を呼び出すだけで済みます。これにはパラメータがあります。このパラメータは、そのオブジェクトの属性の取得を参照するため、オブジェクトを渡すだけです。
この基礎を念頭に置き、目的を振り返ってみると、Person には PersonValidator プロパティを持つ ValidatotHub というオブジェクトがあることがわかります。そのため、ValidatorHub というオブジェクトの PersonValidator プロパティを取得するだけで済みます。 。 (人物は置き換え可能であり、パラメータの型に基づいています。これについては以前に説明しました。ここでは例として人物を示します)
ここで問題が発生しました。取得した PersonValidator はオブジェクト型です。オブジェクト型はそれです。私にとっては使いにくいし、特定の型が何であるかは誰にも分からないため、明示的に特定の型に変換することはできません。死ぬほど書いたらカッコいいですよ。そうなると、スイッチを使用して保守することはできなくなり、作業負荷が再び増加することになりませんか?
我们慢慢发现PersonValidator继承自AbstractValidator
现在我就可以在这里进行验证了,我们知道value 就是那个model 所以直接对他进行验证,验证会返回一个ValidationResult类型接下来的事我就不解释了,相信上一章已经讲得很清楚了。最后根据是否存在错误在进行提前处理,如果有错误的话就直接返回视图呈现错误了,连咱们的Action都不执行了。好了,到这里咱们昨天讲得OnActionExecuted 可以直接Delete拉 。
我们现在把ValidatorTest里的验证代码都去掉来测试一下。
[HttpPost] public ActionResult ValidatorTest(Person model) { // // 一大堆代码 // return Redirect("https://www.baidu.com"); }
在 ValidatorTest 里打上断点,然后什么都不填,直接提交。
断点没触发,但错误消息已呈现。多试几次~.
同样没触发。
那我们来一次正确的验证。
断点触发了。并且值都通过了校验
F5放行,最终我们的页面跳转到了 www.baidu.com。
好了,小伙伴们还不快去改改代码造就幸福生活。
以上がMVC でのサーバー側検証を使用した ASP.NET フルスタック開発 (2)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。