Я использую EFCodeFirst CTP5 (хотя это не должно иметь значения) и ASP.NET MVC 3. Я создал следующие объекты:
public class Company
{
public int CompanyID { get; set; }
public int SubdomainID { get; set; }
public virtual Subdomain Subdomain { get; set; }
}
public class Subdomain : IValidatableObject
{
public int SubdomainID { get; set; }
public virtual ICollection<SubdomainActivity> Activities { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
int activitySum = Activities.Sum(x => x.Value);
if (activitySum != 100)
{
yield return new ValidationResult(string.Format("The Activity percentages must add up to 100. Current sum is {0}", activitySum), new[] { "Activities" });
}
}
}
public class SubdomainActivity
{
public int ActivityID { get; set; }
public int Value { get; set; }
}
Обратите внимание, что Company
имеет Subdomain
, а Subdomain
имеет ICollection<SubdomainActivity>
.
У меня есть контроллеры для Company
и Subdomain
. В SubdomainController
, когда я вызываю UpdateModel()
(или TryUpdateModel()
) для экземпляра Subdomain
, я получаю желаемый результат. Действия Subdomain
подтверждаются тем, что значения составляют до 100.
В CompanyController
, когда я вызываю UpdateModel()
для экземпляра Company
, он подтверждает, что Subdomain.Activities
также добавляет до 100, что мне не нужно. Пользователь не может даже редактировать Subdomain.Activites
из вида редактирования Company
, поэтому нет смысла сообщать им, что произошла ошибка с Subdomain.Activities
.
Я хотел бы иметь возможность добавить элемент в IDictionary validationContext.Items, чтобы я мог выполнять условную проверку на основе контекста или чего-то подобного, но я не смог понять, как это сделать, не написав собственный IModelBinder (что я мог бы сделать, я полагаю, но кажется излишним). В конечном счете, я нашел этот обходной путь в CompanyController
, но я уверен, что есть правильный способ справиться с этим (это обернуто в try
catch
)
var d = this.companyRepository.GetById(id);
bool good = TryUpdateModel(d);
if (!good)
{
if (ModelState.ContainsKey("Subdomain.Activities"))
ModelState.Remove("Subdomain.Activities");
if (!ModelState.IsValid)
throw new InvalidOperationException(string.Format("The model of type '{0}' could not be updated.", typeof(Company).FullName));
}
this.companyRepository.Save();
В качестве интересного примечания: если я не проверю правильность модели и не выдаю ошибку, то companyRepository.Save () работает нормально. Другими словами, EFCodeFirst, кажется, не вызывает Validate на поддомене, но MVC UpdateModel делает.
Может кто-нибудь помочь мне с лучшим / правильным / рекомендуемым способом справиться с этим?