2011-11-10 53 views
2

我有一個模型,其中包含一個地址和人員兩次,一次爲「主要」聯繫人,一次爲「發票」聯繫人,和一個名爲InvoiceContactSameAsMain的布爾值 - 一個笨拙的名字,但描述性的。屬性的getter會檢查「main」和「invoice」的Address和Contact對象是否相同,如果是,則返回true。設置人員檢查該值是否爲真,如果是,則將主要人員複製到發票人員上,並將主要地址複製到發票地址上。有沒有辦法強制模型在MVC3控制器中重新驗證?

在我的視圖中,布爾值由複選框表示(如您所期望的)。附加的是一個小的JS函數,如果選中該複選框,則隱藏發票字段,並通過將data-val HTML屬性設置爲false並強制重新分析不顯眼驗證屬性的形式。取消選中該框自然顯示字段並重新打開驗證。

所有這些工作正常,直到我到我的控制器。

儘管模型是「有效的」幷包含正確的字段(感謝我的InvoiceContactSameAsMain setter),但ModelState.IsValid仍然堅決不實,並且我似乎無法找到任何方法來重新驗證模型。如果我清除模型狀態,任何和所有的錯誤消失。我非常想避免在名稱中挖掘ModelState中的字段,因爲Person和Address對象在整個項目中都會使用,並且可能需要在某個時間點更改或擴展。

有沒有什麼明顯的我在這裏錯過了,這將允許我重新驗證ModelState?我試過TryUpdateModel和TryValidateModel,但它們都顯示使用緩存的ModelState值。我甚至嘗試遞歸調用我的Action,傳入「固定」模型。我幾乎感謝一個人沒有工作。

請讓我知道,如果有任何更多的細節或例子將有所幫助。

編輯:顯然,如果這是完全錯誤的方式來解決問題,請讓我知道。

編輯2:根據Ron Sijm的建議添加代碼示例。

該模型如下: public class詳細信息 { public int? UserID {get;組; }

public Company Company { get; set; } 

    public Address CompanyAddress { get; set; } 
    public Person MainPerson { get; set; } 

    public Address InvoiceAddress { get; set; } 
    public Person InvoiceContact { get; set; } 

    [Display(Name = "Promotional code")] 
    [StringLength(20, ErrorMessage = "Promotional code should not exceed 20 characters")] 
    public string PromotionalCode { get; set; } 

    [Display(Name = "Invoice contact same as main")] 
    public bool InvoiceContactSameasMain 
    { 
     get { return InvoiceContact.Equals(MainPerson); } 
     set 
     { 
      if (value) 
      { 
       InvoiceContact = MainPerson.Copy(); 
       InvoiceAddress = CompanyAddress.Copy(); 
      } 
     } 
    } 

    [_Common.MustAccept] 
    [Display(Name = "I agree with the Privacy Policy")] 
    public bool PrivacyFlag { get; set; } 

    [Display(Name = "Please subscribe to Sodexo News Letter")] 
    public bool MarketingOption { get; set; } 

    [Display(Name = "Contract number")] 
    public int? ContractNumber { get; set; } 

    public Details() 
    { 
     Company = new Company(); 
     CompanyAddress = new Address(); 
     MainPerson = new Person(); 
     InvoiceAddress = new Address(); 
     InvoiceContact = new Person(); 
    } 
} 

這是包裹在一個視圖模型因爲有一些參與的頁面SelectLists的:

public class DetailsViewModel 
{ 
    public Details Details    { get; set; } 
    public SelectList MainContactTitles { get; set; } 
    public SelectList InvoiceContactTitles { get; set; } 
    public SelectList SICCodes    { get; set; } 
    public SelectList TypesOfBusiness  { get; set; } 
    public SelectList NumbersOfEmployees { get; set; } 

    public DetailsViewModel() 
    { 
    } 
} 

該控制器的兩個相關的操作如下:

public class DetailsController : _ClientController 
{ 
    [Authorize] 
    public ActionResult Index() 
    { 
     DetailsViewModel viewModel = new DetailsViewModel(); 
     if (Client == null) 
     { 
      viewModel.Details = DetailsFunctions.GetClient((int)UserId, null); 
     } 
     else 
     { 
      viewModel.Details = DetailsFunctions.GetClient((int)UserId, Client.ContractNumber); 
     } 
     viewModel.MainContactTitles = DetailsFunctions.GetTitles((int)UserId, viewModel.Details.MainPerson.title); 
     viewModel.InvoiceContactTitles = DetailsFunctions.GetTitles((int)UserId, viewModel.Details.InvoiceContact.title); 
     viewModel.SICCodes = DetailsFunctions.GetSICCodes(viewModel.Details.Company.sic_code); 
     viewModel.NumbersOfEmployees = DetailsFunctions.GetNumbersOfEmployees(viewModel.Details.Company.number_of_employees); 
     viewModel.TypesOfBusiness = DetailsFunctions.GetTypesOfBusiness(viewModel.Details.Company.public_private); 
     return View(viewModel); 
    } 

    [Authorize] 
    [HttpPost] 
    public ActionResult Index(DetailsViewModel ViewModel) 
    { 
     if (ModelState.IsValid) 
     { 
      //go to main page for now 
      DetailsFunctions.SetClient((int)UserId, ViewModel.Details); 
      return RedirectToAction("Index", "Home"); 
     } 
     else 
     { 
      ViewModel.MainContactTitles = DetailsFunctions.GetTitles((int)UserId, ViewModel.Details.MainPerson.title); 
      ViewModel.InvoiceContactTitles = DetailsFunctions.GetTitles((int)UserId, ViewModel.Details.InvoiceContact.title); 
      ViewModel.SICCodes = DetailsFunctions.GetSICCodes(ViewModel.Details.Company.sic_code); 
      ViewModel.NumbersOfEmployees = DetailsFunctions.GetNumbersOfEmployees(ViewModel.Details.Company.number_of_employees); 
      ViewModel.TypesOfBusiness = DetailsFunctions.GetTypesOfBusiness(ViewModel.Details.Company.public_private); 
      return View(ViewModel); 
     } 
    } 
} 

我可以提供視圖和JS,如果需要的話,但作爲模型綁定都工作得很好,我不知道這是多少幫助。

+1

我認爲你的代碼示例有幫助 –

+0

你可以在調試時看到爲什麼'ModelState.IsValid'是錯誤的。如果展開一些節點,您將看到哪些規則失敗。 – Darcy

+0

@Darcy:失敗的規則是複製的發票地址和個人中的規則。驗證器仍然將它們視爲空白,儘管我可以在模型中正確地看到它們。 –

回答

3

這是一個適度廢話破解,但是我已經結束了檢查ModelState.IsValid之前剛剛掃清了控制器相關領域的ModelState錯誤:

if(ViewModel.Details.InvoiceContactSameasMain) 
     { 
      //iterate all ModelState values, grabbing the keys we want to clear errors from 
      foreach (string Key in ModelState.Keys) 
      { 
       if (Key.StartsWith("Details.InvoiceContact") || Key.Startwith("Details.InvoiceAddress")) 
       { 
        ModelState[Key].Errors.Clear(); 
       } 
      } 
     } 

唯一的好處是,如果人或地址對象改變,這個代碼不需要改變。

+0

+1這是唯一類似於我找到的工作解決方案非常類似的問題。似乎應該有更好的方法,但我不知道它是什麼。 – Corin

相關問題