1

MVC4 アプリケーション用のカスタム バリデータを構築しています。RequiredAttribute物事をシンプルに保ち、この質問の目的に焦点を当てるために、クラスのサーバー側とクライアント側の検証を再実装しているとしましょう。

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public class MyRequiredAttribute: ValidationAttribute, IClientValidatable
{
    public MyRequiredAttribute() : base("The {0} field is required.")
    {
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (value == null)
        {
            return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
        }
        return null;
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        yield return new ModelClientValidationRequiredRule(ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()));
    }
}

これをテストするために、非常に単純なコントローラーがあります。

public class TestController : Controller
{
    public ActionResult Index()
    {
        return View(new MyThing {Value = "whatever"});
    }
    [HttpPost]
    public ActionResult Index(MyThing thing)
    {
        if (ModelState.IsValid)
        {
            return Content("Good choice!");
        }
        return View(thing);
    }
}

そして非常に単純なモデル:

public class MyThing
{
    [MyRequired]
    public string Value { get; set; }
    [Required]
    public string OtherValue { get; set; }
}

そして最後にインデックス ビュー:

@model MyThing

@{
    Layout = "~/Views/Shared/_LayoutWithAllTheAppropriateValidationScripts.cshtml";
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    <div>
        @using(Html.BeginForm()){
        @Html.ValidationSummary(true)
        @Html.EditorForModel()
        <input type="submit" value="submit"/>
        }
    </div>
</body>
</html>

ValueカスタムMyRequiredAttributeOtherValue装飾されたものと標準で装飾されたものがあることに気付くでしょうRequiredAttribute

RequiredAttributeこれらは両方ともサーバー側で美しく機能し、ポストバックで適切な検証メッセージを返しますが、クライアント側で機能するのは標準のみです。カスタムプロパティで a のModelClientValidationRequiredRule代わりに aを使用しているため、カスタムのクライアント側検証ルールを定義する必要はないと想定していますが、そこまで到達できていないため、確かなことはわかりません。デバッガーはメソッド内で中断することはなく、モデルのプロパティに対して生成された入力 html 要素には、フィールドのようにand属性がありません。これは、メソッドが実行する責任があると想定しています。ModelClientValidationRuleValidationTypeGetClientValidationRulesValuedata-val-requireddata-valOtherValueGetClientValidationRules

ここで単純なものが欠けているに違いありません...それは何ですか?

4

2 に答える 2

3

これはユーザー エラーであることが判明しましたが、今後同様の問題を抱えている他の誰かに役立つことを期待して、とにかく解決策を投稿します。

元の質問のコードは、それを使用する MVC プロジェクトとは別のアセンブリにあります。MVC プロジェクトは最近、MVC3 から MVC4 にアップグレードされました。アップグレードに関して Microsoft から提供された指示に従っていたか、そう思ったのです。web.config の 1 つが欠けていました。

<runtime>
   <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
     <dependentAssembly>
       <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35"/>
       <bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="3.0.0.0"/>
     </dependentAssembly>
   </assemblyBinding>
</runtime>

これにより、MVC プロジェクトは、以前のバージョンのアセンブリへの参照を使用してコンパイルされた、依存するアセンブリをうまく処理する方法を伝えますSystem.Web.Mvc。私のMVCプロジェクトをアップグレードした後、それはSystem.Web.Mvcv4を参照し、私の「共通」プロジェクト(拡張ValidatorAttribute実装が存在する場所IClientValidatable)はv3を参照しました。上記の構成はアップグレードで更新されているはずですが、見逃されました。この問題は、元の質問で概説されているクライアント側の検証の問題を除いて、他の方法では明らかになりませんでした。

ここで問題のある行は

       <bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="3.0.0.0"/>

あるべきだった

       <bindingRedirect oldVersion="1.0.0.0-4.0.0.0" newVersion="4.0.0.0"/>

問題を修正しました。

于 2013-09-23T17:17:00.237 に答える