我正在尝试做一些自定义错误处理程序。我们有4个选项卡(使用JQuery选项卡),它们都是从一个大型模型构建的。简单地说,模型看起来像:
myModel.HomeInfo
myModel.PhoneNumbers
myModel.Addresses
myModel.PersonalDetails
每个部分都是具有各种信息的对象。它们都具有属性并验证消息。
在页面顶部(选项卡上方)我想显示一些顶级错误,我的意思是“myModel”对象上的属性错误。这可以在我执行以下操作时使用:
foreach (ModelState state in viewData.ModelState.Values)
当我这样做时:
@Html.ValidationSummary(false)
在我的观点中,我从四个对象及其所有孩子中获得了所有错误(超过10个)。但是当我经历错误时我自己(上面的代码),我只得到2个错误,(仅“myModel”的错误,而不是它的子属性)。
我尝试使用ILSPY来查看验证摘要正在执行的操作并进行复制。相信我的代码几乎与行相符,但它仍然只有两个错误。
我不知道使用@ Html.ValidationSummary()时会发生什么魔法。
我想知道的是我如何能够获得整个对象的所有错误,以便能够在每个标签上显示一些错误。
澄清这里是我的基本模型:
public class MemberProfileModel
{
[CompanyTabValid]
public CompanyInformationModel CompanyInformation { get; set; }
[ContactTabValid]
public ContactInformationModel ContactInformation { get; set; }
[InvoiceTabValid]
public InvoiceInformationModel InvoiceInformation { get; set; }
[TabProductIdentificationMarkValid]
public ProductIdentificationMarkModel ProductIdentificationMark { get; set; }
}
public class CompanyTabValid : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext context)
{
var model = value as CompanyInformationModel;
if(model == null) throw new ArgumentNullException("value");
var failed = new ValidationResult("Company information incomplete.");
return model.IsValid ? ValidationResult.Success : failed;
}
}
public class ContactInformationModel : BaseModel
{
public ContactInformationModel()
{
PrimarySiteAddress = new AddressInformation();
PrimarySiteContact = new ContactInformation();
RegisteredOfficeAddress = new AddressInformation();
RegisteredOfficeContact = new ContactInformation();
}
public override void Validate()
{
IsValid = PrimarySiteAddress.IsValid &&
PrimarySiteContact.IsValid &&
RegisteredOfficeAddress.IsValid &&
RegisteredOfficeContact.IsValid;
}
public AddressInformation PrimarySiteAddress { get; set; }
public ContactInformation PrimarySiteContact { get; set; }
public AddressInformation RegisteredOfficeAddress { get; set; }
public ContactInformation RegisteredOfficeContact { get; set; }
}
public class AddressInformation : BaseModel
{
public int Id { get; set; }
public Guid MemberId { get; set; }
/// <summary>
/// This property is only here to make EF happy, do not use
/// </summary>
public int LocationTypeValue { get; set; }
public LocationType LocationType { get { return (LocationType) LocationTypeValue; } set { LocationTypeValue = (int) value; } }
[Required(AllowEmptyStrings = false, ErrorMessage = "Address Line 1 required.")]
[Display(Name = "Address Line 1 *")]
public string AddressLine1 { get; set; }
[Display(Name = "Address Line 2")]
public string AddressLine2 { get; set; }
[Display(Name = "Address Line 3")]
public string AddressLine3 { get; set; }
[Required(AllowEmptyStrings = false, ErrorMessage = "Town required.")]
[Display(Name = "Town *")]
public string Town { get; set; }
[Required(AllowEmptyStrings = false, ErrorMessage = "County required.")]
[Display(Name = "County *")]
public string County { get; set; }
[Display(Name = "Country *")]
public string Country { get; set; }
[RequiredOneOfTwo("InterationalPostCode", ErrorMessage="PostCode or international PostCode are required.")]
[Display(Name = "Post Code *")]
public string PostCode { get; set; }
[RequiredOneOfTwo("PostCode", ErrorMessage = "International PostCode or PostCode are required.")]
[Display(Name = "International Post Code *")]
public string InterationalPostCode { get; set; }
public override void Validate()
{
if (string.IsNullOrEmpty(AddressLine1))
{
this.IsValid = false;
return;
}
else if (string.IsNullOrEmpty(Town))
{
this.IsValid = false;
return;
}
else if (string.IsNullOrEmpty(County))
{
this.IsValid = false;
return;
}
else if (string.IsNullOrEmpty(Country))
{
this.IsValid = false;
return;
}
else if (string.IsNullOrEmpty(PostCode) && string.IsNullOrEmpty(InterationalPostCode))
{
this.IsValid = false;
return;
}
this.IsValid = true;
return;
}
}
我已经展示了一个验证属性的示例(我们的一些是自定义的,一些是正常的),本例中的顶级MemberProfileModel = myModel,而ContactInformationModel是其子节点之一,而子节点又有自己的对象,如AddressInformation。
由于
答案 0 :(得分:1)
我发现为什么这不适合我。像往常一样,我是愚蠢的。因为模型有多个图层/级别,即I.e。 model.someobject.someotherobject.someproperty,当我调用tryValidateModel时,它将验证顶层但不验证内层。
解决这个问题的方法是确保他们都被称为:
TryValidateModel(mp);
TryValidateModel(mp.ContactInformation.PrimarySiteAddress);
TryValidateModel(mp.ContactInformation.RegisteredOfficeAddress);
所以我的解决方案是创建一个方法来调用每个对象级别的try validate,或者为我创建一个refelctive方法。
答案 1 :(得分:0)
在页面的发布事件中,在控制器中添加以下内容:
[HttpPost]
public ActionResult Create(TestViewModel testViewModel)
{
// If not Valid
if (!ModelState.IsValid)
{
return this.View(testViewModel)
}
...
}
不要忘记将您的必需和/或其他验证添加到您的viewmodel访问方法:
[Required(ErrorMessageResourceType = typeof(Resources.MyProject), ErrorMessageResourceName = "validation_Test")]
public virtual string HomeInfo { get; set; }
在你看来:
<div class="editor-row">
<div class="editor-label">
@Html.LabelFor(model => model.HomeInfo)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.HomeInfo)
@Html.ValidationMessageFor(model => model.HomeInfo)
</div>
</div>
答案 2 :(得分:0)
public static List<string> GetErrorListFromModelState
(ModelStateDictionary modelState)
{
var query = from state in modelState.Values
from error in state.Errors
select error.ErrorMessage;
var errorList = query.ToList();
return errorList;
}