asp.net-mvc 在 Asp.Net MVC 中禁用模型验证

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3578781/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 00:26:26  来源:igfitidea点击:

Disable Model Validation in Asp.Net MVC

asp.net-mvcmodel-view-controllervalidationmodel

提问by MartinF

How do I disable Model validation for a single Action in a Controller ? Or can I do it per model by registering the model type at startup somewhere ?

如何禁用控制器中单个操作的模型验证?或者我可以通过在启动时在某处注册模型类型来为每个模型执行此操作吗?

I want the ModelBinder to bind to the model, but afterwards it should not perform the model validation.

我希望 ModelBinder 绑定到模型,但之后它不应该执行模型验证。

The reason why i dont want validation to happen is because i am trying to move the logic from the controllers to a service layer which will be responsible for validating the models as i cant assume that models being passed to a service contains valid data.

我不希望发生验证的原因是因为我试图将逻辑从控制器移动到服务层,该服务层将负责验证模型,因为我不能假设传递给服务的模型包含有效数据。

As I understand this is the recommend approach (to not have logic in the controllers), so I find it a bit strange that i cant seem to find anything about how the model validation can be disabled (per action or per model type).

据我所知,这是推荐的方法(控制器中没有逻辑),所以我觉得有点奇怪,我似乎无法找到有关如何禁用模型验证的任何信息(每个动作或每个模型类型)。

Please notice that I dont want to disable model validation for the entire webapplication (by removing the validation providers), and i dont want to disable the input validation that checks for malicious code being posted.

请注意,我不想禁用整个 Web 应用程序的模型验证(通过删除验证提供程序),并且我不想禁用检查发布的恶意代码的输入验证。



UPDATE

更新

I am using .Net 4.0 and MVC 3 Preview 1

我正在使用 .Net 4.0 和 MVC 3 Preview 1

采纳答案by MartinF

Unfortunately there seems to be no easy way to disable the model validation happening in the ModelBinder except for registering every single model type you don't want to validate (including nested complex types) with a specific ModelBinder. It can be done with the following code:

不幸的是,似乎没有简单的方法可以禁用 ModelBinder 中发生的模型验证,除了使用特定的 ModelBinder 注册您不想验证的每个模型类型(包括嵌套复杂类型)。可以使用以下代码完成:

ModelBinders.Binders[typeof(MyModelType)] = new NonValidatingModelBinder();

ModelBinders.Binders[typeof(MyModelType)] = new NonValidatingModelBinder();

Creating a SkipValidationAttribute that can be attached to action methods or action method parameters doesn't seem possible as it should be implemented in the ControllerActionInvoker, but there is no way of letting the ModelBinder know that it should do any validation in the SetProperty() and OnModelUpdated methods when calling BindModel() in the GetParameterValue() method.

创建可以附加到操作方法或操作方法参数的 SkipValidationAttribute 似乎不可能,因为它应该在 ControllerActionInvoker 中实现,但是没有办法让 ModelBinder 知道它应该在 SetProperty() 和在 GetParameterValue() 方法中调用 BindModel() 时的 OnModelUpdated 方法。

回答by Alfonso Mu?oz

Just remove the items you don′t need before checking if the model is valid

在检查模型是否有效之前,只需删除不需要的项目

ModelState.Remove("Email");
if (ModelState.IsValid)
{
   // your logic
}

回答by Francisco

I've solved this problem with this code:

我用这段代码解决了这个问题:

public ActionResult Totals(MyModel model)
{
    ModelState.Clear();
    return View(model);
}

Not sure it's the right way though.

虽然不确定这是正确的方法。

回答by kazuoua

I definitely dislike this addition in the 2.0 version, because, as you stated in your question, validation makes more sense in the Service layer. In this way you can reuse it in other non-web applications, and test it more easily without having to mock the auto-validation mechanism.

我绝对不喜欢 2.0 版本中的这一添加,因为正如您在问题中所述,验证在服务层更有意义。通过这种方式,您可以在其他非 Web 应用程序中重用它,并更轻松地对其进行测试,而无需模拟自动验证机制。

Validation in Controller layer is pointless because in this part you can only verify model data and not business rules. For example, think of a service responsible of adding new comments and a user that wants to post a new one, the data in the comment he/she is posting may be valid, but what happens if the user is banned to comment because of misbehavior in the past? You should do some validation in the Service layer to ensure this is not happening, and if it does, throwing an exception. In short, validation must be done in the Service layer.

控制器层的验证是没有意义的,因为在这部分你只能验证模型数据,不能验证业务规则。例如,考虑一个负责添加新评论的服务和一个想要发布新评论的用户,他/她发布的评论中的数据可能是有效的,但是如果用户因为不当行为而被禁止发表评论会发生什么在过去?您应该在服务层进行一些验证以确保不会发生这种情况,如果发生,则抛出异常。总之,验证必须在Service层进行。

I use xVal as my Validation framework because it's compatible with the DataAnnotationModel, allows me to place validation wherever I want and performs client-side validation without extra-effort, even remote-client side. This is how I use it at the beginning of each of my services, for example, a login service:

我使用 xVal 作为我的验证框架,因为它与 DataAnnotationModel 兼容,允许我将验证放在我想要的任何地方,并且无需额外的努力即可执行客户端验证,甚至是远程客户端。这是我在每个服务(例如登录服务)开始时使用它的方式:

public void SignIn(Login login) {
    var loginErrors = DataAnnotationsValidationRunner.GetErrors(login);

    // Model validation: Empty fields?
    if (loginErrors.Any())
        throw new RulesException(loginErrors);

    // Business validation: Does the user exist? Is the password correct?
    var user = this._userRepository.GetUserByEmail(login.Email);

    if (user == null || user.Password != login.Password)

        throw new RulesException(null, "Username or password invalids");

    // Other login stuff...
}

Simple, web-independent and easy... then, in the Controller:

简单、独立于网络且容易……然后,在控制器中:

public RedirectResult Login(Login login) {

    // Login the user

    try {

        this._authenticationRepository.SignIn(login);

    } catch (RulesException e) {

        e.AddModelStateErrors(base.ModelState, "Login");

    }

    // Redirect

    if (base.ModelState.IsValid)
        return base.Redirect(base.Url.Action("Home"));
    else return base.Redirect(base.Url.Action("Login"));
}

回答by Steve Michelotti

I would recommend you perform validation in bothplaces rather than trying to turn off validation in the UI. I understand your point that the service cannot assume that it's being passed valid data - that is a valid concern and is the reason your service should have validation. But you should alsohave validation in your UI. This is also nice because you can have client-side validation to prevent user errors and give you users a better experience.

我建议您在两个地方执行验证,而不是尝试在 UI 中关闭验证。我理解您的观点,即服务不能假设它正在传递有效数据 - 这是一个有效的问题,也是您的服务应该进行验证的原因。但是您应该在您的 UI 中进行验证。这也很好,因为您可以进行客户端验证以防止用户错误并为您提供更好的用户体验。

回答by Fabio Milheiro

I know that this already been answered but what you really needed was to extend the DataAnnotationsValidatorProviderand override the GetValidatorsmethod.

我知道这已经得到了回答,但您真正需要的是扩展DataAnnotationsValidatorProvider并覆盖该GetValidators方法。

Then, on startup, you would remove the DataAnnotationsValidatorProviderfrom ModelValidatorProviders.Providersand add your new one.

然后,在启动时,您将删除DataAnnotationsValidatorProviderfromModelValidatorProviders.Providers并添加新的。

Needless to say, if you simply don't want any validation at all, you can simply have the GetValidatorsmethod returning an empty collection.

不用说,如果您根本不需要任何验证,您可以简单地让该GetValidators方法返回一个空集合。

In my case, I need to remove validation only when submitting the forms while still keeping the client-side validation, hence the following:

就我而言,我只需要在提交表单时删除验证,同时仍保留客户端验证,因此如下:

public class DynamicModelValidatorProvider : DataAnnotationsModelValidatorProvider
{
   GetValidators(ModelMetadata metadata, ControllerContext context, IEnumerable<Attribute> attributes)
    {
        if (context.HttpContext.Request.HttpMethod == "POST")
        {
            return new ModelValidator[] { };
        }

        return base.GetValidators(metadata, context, attributes);
    }
}

回答by Bob Housedorf

I use [ ValidateInput( false )]

我使用 [ ValidateInput( false )]

Not sure if this prevents model validation, or only IIS submit validation.

不确定这是否会阻止模型验证,或者只有 IIS 提交验证。