2

我正在尝试做一些自定义错误处理程序。我们有 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。

谢谢

4

3 回答 3

1

我发现了为什么这对我不起作用。像往常一样,是我傻了。因为模型有多个层/级别,即model.someobject.someotherobject.someproperty,当我调用tryValidateModel时,它会验证顶层而不是内层。

解决方案是确保它们都被调用:

            TryValidateModel(mp);
            TryValidateModel(mp.ContactInformation.PrimarySiteAddress);
            TryValidateModel(mp.ContactInformation.RegisteredOfficeAddress);

所以我的解决方案是创建一个方法来在每个对象级别上调用 try validate 或创建一个反射方法来为我做这件事。

于 2012-08-29T10:35:28.523 回答
0

在页面的发布事件中,在控制器中添加以下内容:

[HttpPost]
public ActionResult Create(TestViewModel testViewModel)
{
// If not Valid
if (!ModelState.IsValid)
{
   return this.View(testViewModel)
}
...
}

并且不要忘记将您所需的和/或其他验证添加到您的视图模型访问方法中:

[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>
于 2012-08-24T12:26:58.237 回答
0

我从这里得到这个: http ://www.unknownerror.org/opensource/aspnet/Mvc/q/stackoverflow/1352948/how-to-get-all-errors-from-asp-net-mvc-modelstate

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;
}
于 2016-06-18T02:34:27.690 回答