Can we use FluentValidation AND DataAnnotations working together for the same class/model?

May 12, 2010 at 7:39 AM
Edited May 12, 2010 at 7:41 AM

I ask this because i would like to use DataAnnotations for simple stuff like range/required etc with it's client-side validation and simple attribute style declarations etc, and use FluentValidation for more complex stuff like validation of multiple properties across a particular class.

Is there a way to do this (use both) for the same data model/class somehow? so we can have the best of both worlds, or not really?

 

Coordinator
May 12, 2010 at 7:49 AM

I see no reason why not - they're completely separate so you should be able to mix and match them without any issues.

May 12, 2010 at 7:55 AM

i remember trying but it didn't work out. do i just leave metadataprovider alone or still keep .current set to FV framework?

i currently have it set to... are there any mods i need to make to global.asax?

ModelMetadataProviders.Current =
		 New FluentValidation.Mvc.FluentValidationModelMetadataProvider(New FluentValidation.Attributes.AttributedValidatorFactory())
also, re buddy classing, for FV i/we use 
<Validator(GetType(tProductValidator))>
and for normal dataannotations/VS metadata buddy classing we use
<MetadataType(GetType(tProductMetaData))>
so not sure how we could move forward given this difference in declaring the buddy classing
May 12, 2010 at 8:06 AM

i enter this:

Public Class tProductValidator
	Inherits AbstractValidator(Of tProduct)

	<Required(ErrorMessage:="The Product Name is required.")>
	<DisplayName("Product NameXXX")>
	Public Property ProductName As String

where i have your rules, so this is just above the FV rule declarations, and it the above stuff doesn't persist - if i use the <MetadataType...> buddy classing with the Validator one as well, then the ProductName sample works but all the other FV rules do not work. so both never work together.


Coordinator
May 12, 2010 at 8:13 AM

MVC only supports 1 metadata provider, but multiple validator providers, so you'd probably want to use the default metadata provider, but both the dataanotations and the FV validator providers.

You shouldn't really be putting your attributes on the ProductValidator - you should be using a separate class for this.

May 12, 2010 at 8:24 AM

i could not get it to work no matter what combination i tried. it would/could be interesting to get these to work together because using FV for simple stuff can become quite verbos and difficult to read/write. just a suggesting :), FV is awesome!

 

Coordinator
May 12, 2010 at 8:32 AM

Could you elaborate on the problem? I've tried this in the past and it works fine. So long as you have both validator providers enabled, the MVC model binding infrastructure will ask both providers to perform the validation.

May 12, 2010 at 8:44 AM
Edited May 12, 2010 at 8:45 AM

both should be enabled, unless i am missing something, this is my global.asax:

	Sub Application_Start()
		AreaRegistration.RegisterAllAreas()
		RegisterRoutes(RouteTable.Routes)

		DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes = False
		ModelValidatorProviders.Providers.Add(New FluentValidation.Mvc.FluentValidationModelValidatorProvider(
											 New FluentValidation.Attributes.AttributedValidatorFactory()))

		' this is to support metadata stuff such as UIHint, DisplayName, Scaffold, HiddenInput etc...
		' you will need to import the FluentValidation.Mvc.MetadataExtensions namespace
		ModelMetadataProviders.Current =
		 New FluentValidation.Mvc.FluentValidationModelMetadataProvider(New FluentValidation.Attributes.AttributedValidatorFactory())

	End Sub
im presuming 'enabling' it is just adding the providers to the Providers collection? i'm assuming there is no other step needed to enable both. as both work independently, but never together.
Coordinator
May 12, 2010 at 11:15 AM

It depends what you want to do - do you need to use FV for metadata, or only validation? If only validation, then you need to remove the line that sets the ModelMetadataProvider.

May 12, 2010 at 12:29 PM
Edited May 12, 2010 at 12:33 PM

I want to use FV & DataAnnotations for Validation (both together). I am aware that removing the MetadataProvider line means MVC takes care of metadata vs. FV taking care of it while the line is present.

Meanwhile, i am still unable to get Validation for FV and DA (DataAnnotations) working together. I am able to get DA MetadataProvider working while FV Validation is working, however, as soon as i add a DA Validation reference to my test, FV Validation is disabled and the DA Validation works only! Here is an example of a class structure where FV Validation si auto-dsabled/doesn't work:

<Validator(GetType(tProductValidator))>
Partial Public Class tProduct
End Class

<MetadataType(GetType(tProductValidatorX))> _
Partial Public Class tProduct
End Class

Public Class tProductValidatorX
	<DisplayName("Product Name XX")>
	<Required(ErrorMessage:="haha it works")>
	Public Property ProductName As String

End Class

Public Class tProductValidator
	Inherits AbstractValidator(Of tProduct)
	
	... this is where FV rules reside...
End Class

 

Above, ONLY DA Validation works (FV Validation does not), on the ProductName Required test. Now, if you remove the <Required(ErrorMessage:="haha it works")> the FV Validation works, and the DA Validation does not! They just switch on/off depending its like one switches the other off and they never work together. I have tried several different class setup structures.

It really would be a dream to get both of these working together, don't you think? Maybe i'm just over excited but your Framework combined with inherent DA attributes for simple stuff would be a validation dream.

 



Coordinator
May 12, 2010 at 5:15 PM

Off the top of my head I cannot remember how the DefaultModelBinder deals with handling multiple ValidationProviders. Personally I've only ever used one at once - I've never seen the need to use both together. If you want to do this then may need to create your own ModelBinder subclass in order to do this (which isn't really something I'd recommend doing as the DefaultModelBinder's code is rather complex). I don't have time to investigate this at the moment, but I will take a look when I get some free time.

May 14, 2010 at 6:44 AM

if i can get FV working for simple scenarios, won't need to use both, but either way, all things considered, FV is still noticably better than DataAnnotations