ホームページ > バックエンド開発 > C#.Net チュートリアル > MVC でのサーバー側検証を使用した ASP.NET フルスタック開発 (2)

MVC でのサーバー側検証を使用した ASP.NET フルスタック開発 (2)

无忌哥哥
リリース: 2018-07-20 09:20:12
オリジナル
1793 人が閲覧しました

まず最初に、このブログ投稿は、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 很显然它的基类也需要一个具体类型,不行,继续往上走,诶,发现了AbstractValidator继承自IValidator,并且IValidator定义了Validate方法。这不就好了吗,我as 为IValidator类型,就可以用了。这里使用了(里氏转换原则)。我尽量写得通俗易懂,也将许多基础东西提一下,但不肯能面面俱到,所以还是建立在一部分基础之上的。(当然更重要的一点是,通过这次遇到的问题让我以后在设计泛型类结构的时候,都要去继承一个非泛型的接口,如果FluentValidator没有继承自IValidator 而只是继承自IValidator其实从简单使用上来讲,并没有什么影响啊,但到了我们刚刚这里,问题就出来了,所以这也是给我们狠狠地上了一课啊)

现在我就可以在这里进行验证了,我们知道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 サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート