1

我有 UI,我在其中显示 3 个复选框,每个复选框都引用模型类的不同属性。我只是通过 mvc 数据注释使用 jquery 不显眼的验证。我希望当用户提交表单时,用户必须选择一个复选框,否则将显示客户端错误消息并且不会提交表单。

我可以通过 jquery 来完成,但我想通过 mvc 数据注释来完成。

看我的模型课

public class Customer
{
    [Required]
    [Display(Name = "First Name")]
    public string FirstName { get; set; }

    [Required]
    [Display(Name = "Last Name")]
    public string LastName { get; set; }

    [Display(Name = "Mail to me")]
    public bool SelfSend { get; set; }

    [Display(Name = "3rd party")]
    public bool thirdParty { get; set; }

    [Display(Name = "Others")]
    public bool Others { get; set; }
}

控制器

[ValidateAntiForgeryToken()]
[HttpPost]
public ActionResult Index(Customer customer)
{
    if (customer.Others == false || customer.SelfSend == false || customer.thirdParty == false)
        ModelState.AddModelError("Error", "Must select one option");

    return View();
}

使用下面的代码,我可以验证是否从服务器端代码中选择了任何复选框,并添加在客户端显示错误的模型错误。

但我想使用普通数据注释在客户端进行验证。

看我的剃须刀代码

<div class="row">
    <div class="col-md-8">
        <section id="testform">
            @using (Html.BeginForm("Index", "Customers", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
            {
                @Html.AntiForgeryToken()
                <h4>Enter customer info.</h4>
                <hr />
                @Html.ValidationSummary(true, "", new { @class = "text-danger" })
                <div class="form-group">
                    @Html.LabelFor(m => m.FirstName, new { @class = "col-md-2 control-label" })
                    <div class="col-md-10">
                        @Html.TextBoxFor(m => m.FirstName, new { @class = "form-control" })
                        @Html.ValidationMessageFor(m => m.FirstName, "", new { @class = "text-danger" })
                    </div>
                </div>
                <div class="form-group">
                    @Html.LabelFor(m => m.LastName, new { @class = "col-md-2 control-label" })
                    <div class="col-md-10">
                        @Html.TextBoxFor(m => m.LastName, new { @class = "form-control" })
                        @Html.ValidationMessageFor(m => m.LastName, "", new { @class = "text-danger" })
                    </div>
                </div>
                <div class="form-group">
                    <div class="col-md-offset-2 col-md-10">
                        <div class="checkbox">
                            @Html.CheckBoxFor(m => m.SelfSend)
                            @Html.LabelFor(m => m.SelfSend)
                        </div>
                    </div>

                    <div class="col-md-offset-2 col-md-10">
                        <div class="checkbox">
                            @Html.CheckBoxFor(m => m.thirdParty)
                            @Html.LabelFor(m => m.thirdParty)
                        </div>
                    </div>

                    <div class="col-md-offset-2 col-md-10">
                        <div class="checkbox">
                            @Html.CheckBoxFor(m => m.Others)
                            @Html.LabelFor(m => m.Others)
                        </div>
                    </div>
                    <div class="col-md-offset-2 col-md-10">
                        @Html.ValidationMessage("Error", "", new { @class = "text-danger" })
                    </div>
                    </div>
                <div class="form-group">
                    <div class="col-md-offset-2 col-md-10">
                        <input type="submit" value="Save" class="btn btn-default" />
                    </div>
                </div>

            }
        </section>
    </div>
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}
4

2 回答 2

2

您可以尝试编写客户模型验证属性。

添加CheckBoxAuthAttribute您的三个验证属性之一。

ValidationAttributeprotected virtual ValidationResult IsValid(object value, ValidationContext validationContext)中有一个方法。override in

public class CheckBoxAuthAttribute : ValidationAttribute
{
    public CheckBoxAuthAttribute(params string[] propertyNames)
    {
        this.PropertyNames = propertyNames;
    }

    public string[] PropertyNames { get; private set; }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var properties = this.PropertyNames.Select(validationContext.ObjectType.GetProperty);
        var values = properties
                .Select(p => p.GetValue(validationContext.ObjectInstance, null))
                .OfType<bool>();

        if (values.Contains(true) || (bool)value == true)
        {
            return null;
        }
        return new ValidationResult(this.FormatErrorMessage(validationContext.DisplayName));
    }
}
public class Customer
{
    [Required]
    [Display(Name = "First Name")]
    public string FirstName { get; set; }

    [Required]
    [Display(Name = "Last Name")]
    public string LastName { get; set; }

    [Display(Name = "Mail to me")]
    [CheckBoxAuth("thirdParty", "Others", ErrorMessage = "Must select one option"))]
    public bool SelfSend { get; set; }

    [Display(Name = "3rd party")]
    public bool thirdParty { get; set; }

    [Display(Name = "Others")]
    public bool Others { get; set; }
}
于 2018-07-21T20:13:46.557 回答
2

由于您希望选择 3 个可能选项之一,因此请使用单选按钮并绑定到具有必需属性的属性。

首先定义一个视图模型

public class CustomerVM
{
    [Required]
    [Display(Name = "First Name")]
    public string FirstName { get; set; }
    [Required]
    [Display(Name = "Last Name")]
    public string LastName { get; set; }
    [Required]
    public int? Mailing { get; set; } // see notes below
}

并且在视图中

@model CustomerVM
....
@using (Html.BeginForm())
{
    ....
    <label>
        @Html.RadioButtonFor(m => m.Mailing, 1, new { id = ""})
        <span>Mail to me</span>
    </label>
    <label>
        @Html.RadioButtonFor(m => m.Mailing, 2, new { id = ""})
        <span>3rd party</span>
    </label>
    .... // ditto for "Others"
    @Html.ValidationMessageFor(m => m.Mailing)
    ....
}

并且 POST 方法将是

[HttpPost]
public ActionResult Index(CustomerVM model)
{
    if(!ModelState.IsValid)
    {
        return View(model);
    }
    .... // map to instance of data model, save and redirect
}

请注意,如果这些选项不太可能更改,则将属性设置为 aenum而不是 a会更合适int,例如

public enum Mailing
{
    [Display(Name = "Mail to me")]
    SelfSend = 1,
    [Display(Name = "3rd party")]
    ThirdParty = 2,
    [Display(Name = "Others")]
    Others = 3
}

public class CustomerVM
{
    ....
    [Required]
    public Mailing? Mailing { get; set; }
}

并且查看代码将是

@Html.RadioButtonFor(m => m.Mailing, Mailing.SelfSend, new { id = ""})
于 2018-07-22T09:47:13.727 回答