【问题标题】:ASP.NET MVC 3 - Choose which model property each submit button validatesASP.NET MVC 3 - 选择每个提交按钮验证的模型属性
【发布时间】:2011-09-17 08:04:36
【问题描述】:

我有一个带有三个提交按钮的视图。第一个按钮必须验证某些字段,第二个按钮必须验证其他字段,第三个按钮不验证任何内容。 如何在客户端(不显眼)和服务器端都做到这一点?

【问题讨论】:

标签: asp.net asp.net-mvc-3 validation form-submit unobtrusive-javascript


【解决方案1】:

最有可能大量使用手卷,特别是如果您希望它不引人注目。您将需要创建类似<input data-validationgroup="group1"... 的内容,然后单击您的javascript 代码将验证您想要的内容。我想 jQuery Validate 有某种类型的规则集支持,但你必须弄清楚。

您将不得不在服务器端执行类似的序列,并创建规则集类型验证类/块/方法,以将提交操作解释为相关规则集。这部分我会看一个像 FluentValidation 这样的库。

要实现您想要的,您几乎不可能使用模型类上的 DataAnnotations 属性来实现。

【讨论】:

  • 如果我不必重新创建所有现有的验证器,如Required、Range、StringLength 等,那就太好了。
  • 这就是为什么我推荐一个像 FluentValidation 这样的库,这些都是内置的。
【解决方案2】:

就我个人而言,我一直喜欢并在我的所有项目中使用FluentValidation.NET 库。它不仅在表达验证规则方面非常强大,而且这个库与 ASP.NET MVC 有很好的集成。所以我会尝试使用它来提供这个问题的示例解决方案(目前只有服务器端验证,如果你愿意,稍后我们可以讨论不显眼的客户端验证)。

所以使用默认模板启动一个新的 ASP.NET MVC 3 项目并安装FluentValidation.MVC3 NuGet 包(当前稳定版本为 2.0.0.0)。

然后我们定义一个视图模型:

public class MyViewModel
{
    public string Field1 { get; set; }
    public string Field2 { get; set; }
}

现在我们可以假设如果单击button1,则需要Field1,如果单击button2,则需要Field2,如果单击button3,则不需要它们。一个虚构的场景,但非常接近您的要求。

现在让我们为这个模型定义两个不同的流式验证器,分别对应button1button2

public class MyModelValidator1 : AbstractValidator<MyViewModel>
{
    public MyModelValidator1()
    {
        RuleFor(x => x.Field1)
            .NotEmpty();
    }
}

public class MyModelValidator2 : AbstractValidator<MyViewModel>
{
    public MyModelValidator2()
    {
        RuleFor(x => x.Field2)
            .NotEmpty();
    }
}

现在因为只有在运行时我们才知道点击了哪个按钮,所以我们需要根据请求中的值应用正确的验证器。因此,让我们编写一个自定义验证器提供程序工厂:

public class MyFactory : IValidatorFactory
{
    private readonly Func<HttpContextBase> _contextProvider;
    public MyFactory(Func<HttpContextBase> contextProvider)
    {
        _contextProvider = contextProvider;
    }

    public IValidator GetValidator(Type type)
    {
        if (type == typeof(MyViewModel))
        {
            var context = _contextProvider();
            if (!string.IsNullOrEmpty(context.Request["button1"]))
            {
                return new MyModelValidator1();
            }
            if (!string.IsNullOrEmpty(context.Request["button2"]))
            {
                return new MyModelValidator2();
            }
        }
        return null;
    }

    public IValidator<T> GetValidator<T>()
    {
        return (IValidator<T>)GetValidator(typeof(T));
    }
}

并在Application_Start注册:

ModelValidatorProviders.Providers.Add(
    new FluentValidationModelValidatorProvider(
        new MyFactory(() => new HttpContextWrapper(HttpContext.Current))
    )
);

差不多就是这样。现在剩下的都是微不足道的。

控制器:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        var model = new MyViewModel();
        return View(model);
    }

    [HttpPost]
    public ActionResult Index(MyViewModel model)
    {
        if (!ModelState.IsValid)
        {
            return View(model);
        }
        return Content("Thanks for submitting", "text/plain");
    }
}

还有一个观点:

@model MyViewModel

@using (Html.BeginForm())
{
    <div>
        @Html.LabelFor(x => x.Field1)
        @Html.EditorFor(x => x.Field1)
        @Html.ValidationMessageFor(x => x.Field1)
    </div>

    <div>
        @Html.LabelFor(x => x.Field2)
        @Html.EditorFor(x => x.Field2)
        @Html.ValidationMessageFor(x => x.Field2)
    </div>

    <input type="submit" value="Submit with button 1" name="button1" />
    <input type="submit" value="Submit with button 2" name="button2" />
    <input type="submit" value="Submit with button 3" name="button3" />
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-24
    • 1970-01-01
    • 1970-01-01
    • 2012-01-24
    • 2011-08-05
    • 2012-05-15
    • 1970-01-01
    相关资源
    最近更新 更多