4

同じモデルにアクセスする2つの別々のビューがあります。バリデーターデータの注釈をモデルに配置すると、アドバタイズされたとおりに機能し、空白のままにするか範囲内にない場合、データが(両方のビューで)送信されないようにします。ただし、プロパティの空またはnull値を保存できるビューが1つありますが、別のビューでは、情報を入力または選択してから通過させる必要があります。つまり、一方のビューではモデル内のプロパティのバリデーターをオフにし、もう一方のビューではオンのままにしておきます。サンプルコードは次のとおりです。

モデル:

[Range(1, 999, ErrorMessage = "A submittal is required")]
public int SubmittalId { get; set; }

ビュー#1:

 <label>@Model.AuditDoc.SubmittalsLabel.ConfigurableLabelDesc</label> @Html.ValidationMessageFor(x => x.AuditDoc.SubmittalId) @Html.DropDownListFor(x => x.AuditDoc.SubmittalId, new SelectList(Model.AuditDoc.ListOfSubmittals, "Id", "Name"))

ビュー#2:

 <label>@Model.AuditDoc.SubmittalsLabel.ConfigurableLabelDesc</label> @Html.DropDownListFor(x => x.AuditDoc.SubmittalId, new SelectList(Model.AuditDoc.ListOfSubmittals, "Id", "Name"))

ご覧のとおり、ビュー#2ではそのバリデーターデータアノテーションを無効にし、ビュー#1ではオンのままにしておきます。

4

3 に答える 3

2

私は別のアプローチを使用してこの問題を解決しました。

秘訣は、検証自体を無効にすることではなく、コントローラーのアクションが呼び出される前に不適切な検証エラーをクリアすることです(したがって、ModelState.IsValidはtrueを返します)。

ICustomValidationModel(またはViewModel)オブジェクトにカスタム検証が必要な場合は、次のように呼ばれる、私が定義したインターフェイスを実装します。

public interface ICustomValidation {
    void PerformValidation(ModelStateDictionary modelState);
}

BaseControllerのクラス(すべてのコントローラーサブクラス)には、次のメソッドオーバーライドがあります。

protected override void OnActionExecuting(ActionExecutingContext filterContext) {
    base.OnActionExecuting(filterContext);

    // Unfortunately it seems this is the only way to get the Model object
    if( filterContext.ActionParameters.ContainsKey("model") ) {

        Object                    model = filterContext.ActionParameters["model"];
        ModelStateDictionary modelState = filterContext.Controller.ViewData.ModelState; // ViewData.Model always returns null at this point.

        ICustomValidation modelValidation = model as ICustomValidation;
        if( modelValidation != null ) {
            modelValidation.PerformValidation( modelState );
        }
    }

}

したがって、ViewModelクラスの例では、特定の検証エラーを無効にする(または無視する)場合は、次のようにする必要があります。

public class SomeModel : ICustomValidation {

    [Required]
    public Boolean NamePresent { get; set; }

    [Required]
    public String Name { get; set; }

    public void PerformValidation(ModelStateDictionary modelState) {
        if( !NamePresent ) dict.Remove("Name");
    }
}

私の実際のコードには、Model-recursiveおよびby-prefixメソッドでModelStateDictionaryをクリアするロジックがもう少しあり、堅牢性を維持しています。

私の解決策はあなたの問題と正確には一致しませんが、同様のアプローチを使用すると、あなたはそれをあなたのために働かせることができるはずです。

于 2012-08-08T22:57:11.013 に答える
2

これは、デフォルトのデータアノテーションのセットでは不可能です。ただし、2つの個別のビューモデルを使用するか、独自のvalidationAttributeを作成するかを選択できます。

私はこれを一度書いた..私はそれを使うのが嫌だったが..

public class RequiredOnAttribute : ValidationAttribute
{
    public string[] URLs { get; set; }

    public override bool IsValid(object value)
    {
        if (URLs.Contains(System.Web.HttpContext.Current.Request.Url.AbsolutePath))
        {
            if (string.IsNullOrEmpty(value as string))
            {
                return false;
            }
        }
        return true;
    }
}

使用法:

[RequiredOn(URLs = new string[] { "/create", "/edit" })]
public string MyModelField { get; set; }

Range、RegExなどでも同じことができます。

于 2012-08-08T22:27:24.130 に答える
0

私も別のビューモデルオブジェクトを使用することをお勧めします。この記事には、それをきれいに実装する方法の良い例がありますhttp://lostechies.com/jimmybogard/2009/06/30/how-we-do-mvc-view-models/

または、コントローラーでModelState.IsValidを呼び出すこともできません。

于 2012-08-08T22:39:00.947 に答える