FluentValidation validator not being called - asp.net-mvc-3

I have a MVC 3 site but am using the non-MVC FluentValidation dll. I've created a validator class and in the constructor put all my RuleFors and then set an attribute on my model class thus
[FluentValidation.Attributes.Validator(typeof(MyValidator))]
The problem is that the constructor on the validator class never gets called. I think it might be because I am not using the MVC version of the dll, but then I could not get that version to work for me either.
Any help would be appreciated.
Thanks,
Sachin

In your Application_Start make sure that you have initialized the custom fluent validation model validator provider otherwise nothing will happen:
FluentValidation.Mvc.FluentValidationModelValidatorProvider.Configure();
The FluentValidationModelValidatorProvider class is defined inside the FluentValidation.Mvc assembly. Please take a look at the documentation for integrating FluentValidation into an ASP.NET MVC site.
The validator will be triggered when you invoke a controller action taking a model decorated with the [Validator] attribute as argument:
[HttpPost]
public ActionResult Process(MyViewModel model)
{
...
}

Another reason your validation might not be called is if you have more than one constructor. I did this by accident and it was mystifying. I am so used to having a service constructor just pass in required services from dependency injection, that I did this by mistake:
public MyValidator(IJsonService jsonService)
{
_jsonService = jsonService;
}
public MyValidator()
{
RuleFor(x => x.ProductTechnologyId).GreaterThan(0).NotEmpty();
}
Only one constructor can be called! Oops!

Related

WebApi action parameters validation by ValidationAttribute

Does WebAPI can handle ValidationAttribute on action parameter?
For instance:
public class SampleController : ApiController
{
public string Get([RegularExpression("sampleExpression")]string id)
{
return "result";
}
}
In this sample WebAPI doesn't invoke any methods of RegularExpressionAttribute (or any other data annotation attribute) to validate input parameter. But in case if we passing an object as parameter, for instance a class then WebAPI can validate properties.
Is it a bug? Or I'm doing something wrong?
UPD: It's an open issue:
http://aspnetwebstack.codeplex.com/workitem/24?PendingVoteId=24
Does anyone can suggest a workaround?
This is a genuine question, I'm curious why not just do something like :
public class SampleController : ApiController
{
public string Get(string id)
{
RegularExpressionHelper.ValidateWith("sampleExpression",id);
return "result";
}
}
To me this seems to be equivalently concise. It is obvious when the validation occurs. I can safely assume that if the validation fails then an exception will be thrown. I can easily add additional validation and be confident of the order in which they occur.
Regarding the attribute method, I don't know if the validation is used as part of the route matching, I have no idea what happens if it fails. I don't know what filters run before or after the validation. I'm sure if I knew MVC better I would know the answer to these questions, but I don't see the advantage of using an attribute that makes my code's behaviour dependent on some framework controlled infrastructure.
Am I missing some significant benefit?
I had the same doubt. My workaround consists in creating a class just for encapsulating the parameter, so I can decorate it with the validation attribute I want. I could use the workaround proposed by Darrel in his answer, but I have a filter that checks if ModelState.IsValid before entering the action, so I need to validate before the action gets executed.
[ModelBinder]
public class Item
{
[RegularExpression("sampleExpression")]
public string Id { get; set; }
}
The class must be annotated with [ModelBinder], otherwise the parameter binding mechanism will try to extract the id field from the body of the request. Read this article for more info.
Also, note that Id is now in PascalCase instead of camelCase. Read this article to understand how the conversion is made.
The action signature is:
public string Get(Item item)

MVC Controller - Inject 2 repositories in controller

I'm trying to inject a second repository into my asp.net mvc 3 controller. And I cant get it to work, not sure where to "add another" using Ninject.
I have a void function in global.asa.cs
kernel.Bind<INewsRepository>().To<NewsRepository>();
And in my controller I have:
private INewsRepository _newsRepository;
private IContentRepository _contentRepository;
public NewsController(INewsRepository newsRepository, IContentRepository contentRepository)
{
this._newsRepository = newsRepository;
this._contentRepository = contentRepository;
}
How can I register IContentRepository for the NewsController as well?
I use autofac instead of Ninject but the basics stay the same.
If you got your first dependency injection working then you should be able to bind others as well. You just have to add a new binding in Application_Start() in your Global.asax.
So under your first binding do this as well:
kernel.Bind<IContentRepository>().To<ContentRepository>();
You can have as many bindings as you like.
First off it's a good practice to move the bootstrapping of your application into a separate location. This keeps your Global.asax clean.
You should also be using convention based registration. It will end up saving you lots of time for the bindings you don't need to customize.
So for you I'd probably suggest the following
public static class Bootstrapper()
{
public static void Bootstrap()
{
kernel.Scan( k =>
{
k.FromAssemblyContaining<INewsRepository>();
k.BindWithDefaultConventions();
});
}
}
And in your Global.asax you add this..
Bootstrapper.Bootstrap();
Then I would suggest you spend some time on Google reading about ninject conventions.

ASP.NET MVC 3: Validating model when information external to the model is required

What's a good way to validate a model when information external to the model is required in order for the validation to take place? For example, consider the following model:
public class Rating {
public string Comment { get; set; }
public int RatingLevel { get; set; }
}
The system administrator can then set the RatingLevels for which a comment is required. These settings are available through a settings service.
So, in order to fully validate the model I need information external to it, in this case the settings service.
I've considered the following so far:
Inject the service into the model. The DefaultModelBinder uses System.Activator to create the object so it doesn't go through the normal dependency resolver and I can't inject the service into the model without creating a new model binder (besides which, that doesn't feel like the correct way to go about it).
Inject the service into an annotation. I'm not yet sure this is possible but will investigate further soon. It still feels clumsy.
Use a custom model binder. Apparently I can implement OnPropertyValidating to do custom property validation. This seems the most preferable so far though I'm not yet sure how to do it.
Which method, above or not, is best suited to this type of validation problem?
Option 1 doesn't fit. The only way it would work would be to pull in the dependency via the service locator anti-pattern.
Option 2 doesn't work. Although I couldn't see how this was possible because of the C# attribute requirements, it is possible. See the following for references:
Resolving IoC Container Services for Validation Attributes in ASP.NET MVC
NInjectDataAnnotationsModelValidatorProvider
Option 3: I didn't know about this earlier, but what appears to be a very powerful way to write validators is to use the ModelValidator class and a corresponding ModelValidatorProvider.
First, you create your custom ModelValidatorProvider:
public class CustomModelValidatorProvider : ModelValidatorProvider
{
public CustomModelValidatorProvider(/* Your dependencies */) {}
public override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context)
{
if (metadata.ModelType == typeof(YourModel))
{
yield return new YourModelValidator(...);
}
}
}
ASP.NET MVC's IDependencyResolver will attempt to resolve the above provider, so as long as it's registered with your IoC container you won't need to do anything else. And then the ModelValidator:
public class EntryRatingViewModelValidatorMvcAdapter : ModelValidator
{
public EntryRatingViewModelValidatorMvcAdapter(
ModelMetadata argMetadata,
ControllerContext argContext)
: base(argMetadata, argContext)
{
_validator = validator;
}
public override IEnumerable<ModelValidationResult> Validate(object container)
{
if (/* error condition */)
{
yield return new ModelValidationResult
{
MemberName = "Model.Member",
Message = "Rating is required."
};
}
}
}
As the provider is retrieved through the IDependencyResolver and the provider has full control over the returned ModelValidators I was easily able to inject the dependencies and perform necessary validation.
You could try fluent validation. It supports asp.net mvc and DI so you can inject external services into your validators.
Assuming that you want both client and server-side validation of the model based upon the values returned from the service, I would opt for 2., Inject the service into an annotation.
I give some sample code in my response to this question about adding validators to a model. The only additional step in your case is that you will need to inject your service into your class inheriting from DataAnnotationsModelValidatorProvider.
What about just simply using IValidateableObject and in that method determine if validation is appropriate or not and setting the errors there?
How do I use IValidatableObject?

StructureMap Beginner | Property Injection

Part of this question was already asked here : structuremap Property Injection but the answer was never given.
With StructureMap, is it possible to do Property Injection such that
class SomeController : Controller
{
public IService Service
{
get;
set;
}
}
gets injected properly? I am a
StructureMap supports setter/property injection. So you could do the following:
public class SomeController : Controller
{
[SetterProperty]
public IService Service { get; set; }
}
and then:
ObjectFactory.Initialize(x =>
{
x.For<IService>()
.Use<ServiceImpl>();
});
or if you don't like the idea of cluttering your controllers with StructureMap specific attributes you could configure it like this:
ObjectFactory.Initialize(x =>
{
x.For<IService>()
.Use<ServiceImpl>();
x.ForConcreteType<SomeController>()
.Configure
.Setter<IService>(c => c.Service)
.IsTheDefault();
});
Also note that property injection is suitable in scenarios where the presence of this property is not compulsory for the correct functioning of the controller. For example think of a logger. If the consumer of the controller doesn't inject any specific implementation of a logger into the property the controller still works it's just that it doesn't log. In your case you are using a service and I would use constructor injection if your controller actions depend on this service. So the question you should ask yourself is: will my controller crash when I call some its action if this property is null? If the answer to this question is yes then I would recommend constructor injection. Also when you use a constructor injection you force the consumer of this controller to specify an implementation because he cannot obtain an instance of the controller without passing a proper service in the constructor.
To inject dependencies for all properties of a certain type, use the SetAllProperties method as part of the initialization of your ObjectFactory:
ObjectFactory.Initialize(x =>
{
x.SetAllProperties(x => x.OfType<IService>());
});
It is also possible to define policies for setter injection, see this post.

Why is my Spring 3 Validator Validating Everything on the Model?

I have a spring 3 controller with a validator for one of the methods. It insists on validating every object on the model. Would anyone be able to explain to me why it does this or if I'm doing something wrong?
According to the docs, 5.7.4.3 Configuring a JSR-303 Validator for use by Spring MVC (http://static.springsource.org/spring/docs/3.0.0.RC3/spring-framework-reference/html/ch05s07.html)
With JSR-303, a single javax.validation.Validator instance typically validates all model objects that declare validation constraints. To configure a JSR-303-backed Validator with Spring MVC, simply add a JSR-303 Provider, such as Hibernate Validator, to your classpath. Spring MVC will detect it and automatically enable JSR-303 support across all Controllers.
Example:
#Controller
public class WhaleController {
#Autowired
private Validator myValidator;
#Autowired
private WhaleService whaleService;
#InitBinder
protected void initBinder(WebDataBinder binder) {
binder.setValidator(this.myValidator);
}
#RequestMapping(value="/save-the-whales")
#Transactional
public void saveTheWhales(#Valid WhaleFormData formData, BindingResult errors, Model model) {
if (!errors.hasFieldErrors()) {
Whale whale = new Whale();
whale.setBreed( formData.getBreed() );
this.whaleService.saveWhale( whale );
model.addAttribute("whale", whale);
}
model.addAttribute("errors", errors.getFieldErrors());
}
}
When run it will complain that Whale is an invalid target for myValidator (which is set to validate WhaleFormData, and does so fine). Whale is a POJO with no validation constraints, annotation and no config anywhere. Through trial and error I've found that ANY object placed on the model will attempt to be validated and fail if the validator is not setup to handle it. Primitives are just fine.
Can anyone tell me why this is, point me to the appropriate documentation and/or tell me the best way to put something on the model without having it validated?
In the case above I would like to place "whale" on the model as it will now have a unique whaleId() that it received from my persistence layer.
Thanks!
I guess this behaviour is not covered in the documentation well.
The problem is caused by the following:
By default, #InitBinder-annotated method is called for each non-primitive model attribute, both incoming and outcoming (the purpose of calling it for outcoming attibutes is to allow you to register custom PropertyEditors, which are used by form tags when rendering a form).
DataBinder.setValidator() contains a defensive check that call Validator.supports() and throws an exception if false is returned. So, there is no attempt to perform a validation, just an early check.
The solution is to restrict the scope of #InitBinder to particular attribute:
#InitBinder("whaleFormData")
protected void initBinder(WebDataBinder binder) { ... }

Resources