Correct way to disable model validation in ASP.Net Core 2 MVC
Solution 1
As of aspnet core 3.1
, this is how you disable model validation as seen in docs:
First create this NullValidator class:
public class NullObjectModelValidator : IObjectModelValidator
{
public void Validate(ActionContext actionContext,
ValidationStateDictionary validationState, string prefix, object model)
{
}
}
Then use it in place of the real model validator:
services.AddSingleton<IObjectModelValidator, NullObjectModelValidator>();
Note that this only disable Model validation, you'll still get model binding errors.
Solution 2
services.Configure<ApiBehaviorOptions>(options =>
{
options.SuppressModelStateInvalidFilter = true;
});
should disable automatic model state validation.
Solution 3
Use this extension method:
public static IServiceCollection DisableDefaultModelValidation(this IServiceCollection services)
{
ServiceDescriptor serviceDescriptor = services.FirstOrDefault<ServiceDescriptor>((Func<ServiceDescriptor, bool>) (s => s.ServiceType == typeof (IObjectModelValidator)));
if (serviceDescriptor != null)
{
services.Remove(serviceDescriptor);
services.Add(new ServiceDescriptor(typeof (IObjectModelValidator), (Func<IServiceProvider, object>) (_ => (object) new EmptyModelValidator()), ServiceLifetime.Singleton));
}
return services;
}
public class EmptyModelValidator : IObjectModelValidator
{
public void Validate(ActionContext actionContext, ValidationStateDictionary validationState, string prefix, object model)
{
}
}
Ussage:
public void ConfigureServices(IServiceCollection services)
{
services.DisableDefaultModelValidation();
}
Solution 4
You should consider to use the ValidateNeverAttribute, which is nearly undocumented and well hidden by Microsoft.
[ValidateNever]
public class Entity
{
....
}
This gives you fine grained control over which entities to validate and which not.
Solution 5
Create empty model validator class.
public class EmptyModelValidator : IObjectModelValidator {
public void Validate(
ActionContext actionContext,
ValidationStateDictionary validationState,
string prefix,
object model) {
}
}
Replace DefaultModelValidator with EmptyModelValidator in configure services method.
services.Replace(
new ServiceDescriptor(typeof(IObjectModelValidator),
typeof(EmptyModelValidator),
ServiceLifetime.Singleton)
);
EmptyModelValidator not validates model so ModelState.IsValid always return false
.
Related videos on Youtube
S Waye
Updated on October 13, 2022Comments
-
S Waye over 1 year
Set up MVC with the extension method
services.AddMvc()
Then in a controller, and this may apply to GET also, create a method for the POST action with a parameter supplied in the body, e.g.
[HttpPost("save")] public Entity Save([FromBody]Entity someEntity)
When the action is called the MVC pipeline will call the ParameterBinder which in turn calls
DefaultObjectValidator
. I don't want the validation (its slow for one thing, but more importantly is looping on complex cyclical graphs), but it seems the only way to turn off validation in the pipeline is something like this:public class NonValidatingValidator : IObjectModelValidator { public void Validate(ActionContext actionContext, ValidationStateDictionary validationState, string prefix, object model) { } }
and in the StartUp/ConfigureServices:
var validator = services.FirstOrDefault(s => s.ServiceType == typeof(IObjectModelValidator)); if (validator != null) { services.Remove(validator); services.Add(new ServiceDescriptor(typeof(IObjectModelValidator), _ => new NonValidatingValidator(), ServiceLifetime.Singleton)); }
which seems like a sledgehammer. I've looked around and can't find an alternative, also tried to remove the
DataAnnotationModelValidator
without success, so would like to know if there's a better/correct way to turn off validation?-
thejman over 6 yearsI think your solution is good. You can simplify the dependency registration with just:
services.AddSingleton<IObjectModelValidator>(new NonValidatingValidator());
-
-
S Waye over 6 yearsSame unfortunately, this is part of the stack:` Microsoft.AspNetCore.Mvc.Core.dll!Microsoft.AspNetCore.Mvc.Internal.DefaultObjectValidator.Validate(Microsoft.AspNetCore.Mvc.ActionContext actionContext, Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationStateDictionary validationState, string prefix, object model) Unknown Non-user code. Skipped loading symbols. Microsoft.AspNetCore.Mvc.Core.dll!Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(Microsoft.AspNetCore.Mvc.ActionContext actionContext, Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder modelBinder`
-
ypsilo0n over 6 yearsSame what? You are getting an exception now?
-
S Waye over 6 yearsNo, I mean its still calling the DefaultObjectValidator, I suppose there exists some code along the lines of "do we have a validator, if not add DefaultObjectValidator)
-
Kamran Shahid over 4 yearsis this still valid for asp.net core 3.1? also is there any other thing which i can disable to improve my api response?
-
disklosr about 4 yearsThis answer is wrong. It only disables the handler of validation errors but doesn't disable validation itself!
-
S Waye over 3 yearsI dont think this really adds significantly more than @thejman 's comment in the question, but will accept as the answer to close things out. Thanks!
-
bramve about 3 yearsThere is a big gotcha with this solution which you should be wary of (And cost me a lot of time to find out): When you use both this solution + the [ApiController] attribute [FromHeader] parameters in controllers will always automatically give a 400 bad request without any logging making it hard to find the source of the problem.
-
Nico over 2 yearsIts name is quite tricky. I guess the filter just handles the returned result in case of validation failure. It doesn't stop the validation from happening in the first place.
-
David Keaveny over 2 yearsThis approach might be useful for a few specific classes, but if you want to disable application-wide, I wouldn't want to have to decorate all my classes (and remember to add this to future classes). Much better to do it at the middleware level and have done with it.
-
ahdung about 2 years@disklosr How about
services.AddControllers(options => options.ModelValidatorProviders.Clear());