2016-03-16 88 views
0

我有自定義驗證問題。我有一個視圖模型:MVC自定義驗證被標準驗證覆蓋

public class CityViewModel 
{ 
    [ForeignKey(ErrorMessageResourceName = "County")] 
    public int CountyId { get; set; } 

    public string PostCode { get; set; } 
} 

我創建了一個名爲ForeignKey一個自定義的驗證類,它包含以下代碼:

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true)] 
public class ForeignKeyAttribute : ValidationAttribute 
{ 
    protected override ValidationResult IsValid(object value, ValidationContext validationContext) 
    { 
     PropertyInfo propretyInfo = validationContext.ObjectType.GetProperty(validationContext.MemberName); 
     ResourceManager manager = Resource.ResourceManager; 

     if (propretyInfo.PropertyType.IsGenericType && propretyInfo.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>)) { 
      if (value != null && (int)value == 0) { 
       return new ValidationResult(manager.GetString(ErrorMessageResourceName)); 
      } 
      else { 
       return ValidationResult.Success; 
      } 
     } 
     else if (value == null || (int)value == 0) { 
      return new ValidationResult(manager.GetString(ErrorMessageResourceName)); 
     } 

     return ValidationResult.Success; 
    } 
} 

這種方法效果很好,並返回正確的錯誤。問題是在我的控制器動作:

[HttpPost] 
public ActionResult Create(DataSourceRequest request, CityViewModel model) 
{ 
    try { 
     if (ModelState.IsValid) { 
      // Some code 

      return Json(new[] { model }.ToDataSourceResult(request, ModelState)); 
     } 
    } 
    catch (Exception e) { 
     // Some code 
    } 

    return Json(ModelState.ToDataSourceResult()); 
} 

如果CountyId爲空(果然是0,但在進入方法Create可以爲空之前在驗證過程中)我ModelState包含,CountyId領域,這種錯誤「 CountyId字段是必需的。「而不是我的錯誤傳遞給ForeignKey自定義屬性。

如果我用這個代碼:

TryValidateModel(model); 

然後ModelState包含兩個錯誤,因此調用TryValidateModel之前,我應該使用:

ModelState["CountyId"].Errors.Clear(); 

我怎麼能對MVC說時不寫我的錯誤首先驗證?我更喜歡簡單地使用ModelState.IsValid。任何人都可以幫助我?

+0

您屬性'int'這意味着,使所需的驗證,首先執行它必須有一個值。如果你想返回你的錯誤信息,使屬性'int?'(可爲空) –

+0

@StephenMuecke謝謝你的答案。我知道我可以設置屬性爲空,但我需要它是不可空的。我可以壓制'Required'驗證嗎? – erikscandola

+0

你可以嘗試排除創建方法參數中的Id,例如: Create([Bind(Exclude =「Id」)],CityViewModel model) – ThrowingSpoon

回答

1

嘗試創建方法剔除ID參數

[HttpPost] 
public ActionResultCreate([Bind(Exclude = "Id")], CityViewModel model) 
+0

這怎麼可能解決OP的問題。通過從綁定中排除該屬性,其值將被初始化爲零,這會觸發驗證錯誤,並且'ModelState'無效,因此將返回視圖以糾正它。該視圖將顯示用戶輸入/選擇的前一個值(將得到錯誤消息的可憐用戶混淆,即使它不是),以便用戶再次發佈有效值,將其忽略並重置爲零,以及無盡的循環重演。沒有任何東西可以保存,用戶無疑不會再次使用該應用程序。 –

+0

@StephenMuecke我測試了這個解決方案,它工作。當我試圖驗證我的模型時,驗證繞過'Required'驗證但不驗證'ForeignKey'驗證。 – erikscandola

+0

是的,但有什麼意義。如果用戶輸入了一些有效的東西(比如說5),那麼當你去保存數據時,它會嘗試將值保存爲'0'(因爲值不是'5',因爲它沒有綁定)。那當然會拋出異常。如果你檢查'ModelState'並返回視圖無效 - 你最終會產生一個無限循環(並且很多憤怒的用戶在你後面) –