ASP.NET MVC 3 - 选择每个提交按钮验证的模型属性

ASP.NET MVC 3 - Choose which model property each submit button validates

提问人:Eduardo 提问时间:6/18/2011 更新时间:6/19/2011 访问量:908

问:

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

asp.net asp.net-mvc-3 验证 unobtrusive-javascript

评论

0赞 Eduardo 6/18/2011
tpeczek.blogspot.com/2010/06/......Tomasz 对 MVC2 做了类似的事情
0赞 Adam Tuliper 6/18/2011
您可以有单独的表格,还是它们都采用相同的表格?

答:

0赞 Chris Marisic 6/18/2011 #1

最有可能的是大量手工卷制的使用,特别是如果您希望它不显眼。您将需要创建类似的东西,然后在单击操作上,您的 javascript 代码将验证您想要的内容。我想jQuery Verify有某种类型的规则集支持,但你必须弄清楚这一点。<input data-validationgroup="group1"...

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

要实现您想要的东西,您极不可能使用模型类上的 DataAnnotations 属性来实现这一点。

评论

0赞 Eduardo 6/18/2011
如果我不必重新创建所有现有的验证器,如 Required、Range、StringLength 等,那就太好了。
0赞 Chris Marisic 6/18/2011
这就是为什么我推荐像 FluentValidation 这样的库,这些都是内置的。
0赞 Darin Dimitrov 6/18/2011 #2

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

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

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

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

现在我们可以假设 if is clicked 是必需的,if is clicked 是必需的,if is click 是必需的,if is click 它们都不是必需的。一个虚构的场景,但非常接近您的要求。button1Field1button2Field2button3

现在,让我们为这个模型定义两个不同的 Fluent 验证器,分别对应于 和 :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" />
}