У меня есть Модель, которая содержит Адрес и Персона дважды, один раз для «основного» контакта и один раз для «счета-фактуры», а также логическое значение InvoiceContactSameAsMain - неуклюжее имя, но описательное. Получатель свойства проверяет, совпадают ли объекты Address и Contact для «main» и «invoice», и возвращает true, если они есть. Установщик проверяет, является ли значение истинным, и, если это так, копирует основного человека по лицу счета и главный адрес по адресу счета.
В моем представлении логическое значение представлено флажком (как и следовало ожидать). К этому добавлена небольшая JS-функция, которая, если установлен этот флажок, скрывает поля счета и «отключает» проверку на стороне клиента, устанавливая для атрибута HTML data-val значение false и вынуждая повторный анализ ненавязчивого Атрибуты проверки в форме. Если флажок снят, поля естественным образом отображаются и снова включается проверка.
Все это прекрасно работает, пока я не доберусь до моего контроллера.
Несмотря на то, что Модель является «действительной» и содержит правильные поля (благодаря моему установщику InvoiceContactSameAsMain), ModelState.IsValid остается абсолютно ложным, и я не могу найти какой-либо способ для повторной проверки модели. Если я очищаю ModelState, все ошибки исчезают. Я бы предпочел не копаться в полях ModelState по именам, поскольку объекты Person и Address используются в проекте и могут потребовать изменения или расширения в какой-то момент.
Есть ли что-то очевидное, что я здесь упустил, что позволит мне заново проверить ModelState? Я пробовал TryUpdateModel и TryValidateModel, но они оба используют кэшированные значения ModelState. Я даже попытался рекурсивно вызвать мой Action снова, передав «фиксированную» модель. Я почти благодарен, что один не сработал.
Пожалуйста, дайте мне знать, если какие-либо подробности или примеры помогут.
Редактировать: Очевидно, что если это совершенно неправильный подход к проблеме, просто дайте мне знать.
Редактировать 2: Добавлены примеры кода в соответствии с предложением Рона Сайма.
Модель выглядит следующим образом:
публичный класс Подробнее
{
публичный 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();
}
}
Это обернуто в ViewModel, так как на странице задействовано несколько списков выбора:
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, если это необходимо, но, поскольку привязка Model все работает просто отлично, я не уверен, какая это помощь.