<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>FluentValidation &#8211; Other Things</title>
	<atom:link href="https://blog.adamzolo.com/tag/fluentvalidation/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.adamzolo.com</link>
	<description>Blog about Things by Adam Zolotarev</description>
	<lastBuildDate>Sat, 20 Sep 2014 15:28:05 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.1</generator>
	<item>
		<title>Passing custom objects to FluentValidation</title>
		<link>https://blog.adamzolo.com/passing-custom-objects-fluentvalidation/</link>
					<comments>https://blog.adamzolo.com/passing-custom-objects-fluentvalidation/#respond</comments>
		
		<dc:creator><![CDATA[Adam Zolo]]></dc:creator>
		<pubDate>Sat, 20 Sep 2014 15:28:05 +0000</pubDate>
				<category><![CDATA[MVC]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[FluentValidation]]></category>
		<guid isPermaLink="false">http://eazolo.com/blog/?p=86</guid>

					<description><![CDATA[This is a guide for passing custom objects to Fluent Validators. This can be helpful for more complex validation scenarios. Here’s an example of what we want to achieve: In order to achieve this, we need to make some changes to the FluentValidationModelValidatorProvider class by overriding its CreateValidator method: Since we want FluentValidation to handle&#8230;<p><a class="more-link" href="https://blog.adamzolo.com/passing-custom-objects-fluentvalidation/" title="Continue reading &#8216;Passing custom objects to FluentValidation&#8217;">Continue reading <span class="meta-nav">&#8594;</span></a></p>]]></description>
										<content:encoded><![CDATA[<p>This is a guide for passing custom objects to Fluent Validators. This can be helpful for more complex validation scenarios.</p>
<p>Here’s an example of what we want to achieve:</p>
<pre class="brush: csharp; title: ; notranslate">
public class OurModelValidator: AbstractValidator&lt;OurMVCViewModel&gt;
{
public OurModelValidator(OurClassWeWantToPassToValidator ourClassWeWantToPassToValidator)
{
if (ourClassWeWantToPassToValidator.SomeCondition)
{
RuleFor(m =&gt; m.PropertyA).NotEmpty();
}
else
{
RuleFor(m =&gt; m.PropertyB).NotEmpty();
}
}
}
</pre>
<p>In order to achieve this, we need to make some changes to the FluentValidationModelValidatorProvider class by overriding its CreateValidator method:</p>
<pre class="brush: csharp; title: ; notranslate">
public class OurCustomFluentModelValidatorProvider : FluentValidationModelValidatorProvider
{

protected override IValidator CreateValidator(ModelMetadata metadata, ControllerContext context)
{
var type = this.IsValidatingProperty(metadata) ? metadata.ContainerType : metadata.ModelType;
return GetOurModelValidator(type) ?? this.ValidatorFactory.GetValidator(type);
}

private IValidator GetOurModelValidator(Type modelType)
{
if (modelType == typeof(OurClassWeWantToPassToValidator))
{
var ourClassWeWantToPassToValidator = new OurClassWeWantToPassToValidator();
return new OurModelValidator(ourClassWeWantToPassToValidator);
}

return null;
}
}
</pre>
<p>Since we want FluentValidation to handle all situation when OurModelValidator is not applicable, we use built-in ValidatorFactory to return default Validator when validating anything but OurMVCViewModel.</p>
<p>And the last step is to register our new provider:</p>
<pre class="brush: csharp; title: ; notranslate">
ModelValidatorProviders.Providers.Clear();
ModelValidatorProviders.Providers.Add(new DataAnnotationsModelValidatorProvider());
ModelValidatorProviders.Providers.Add(new DataErrorInfoModelValidatorProvider());
ModelValidatorProviders.Providers.Add(new ClientDataTypeModelValidatorProvider());
ModelValidatorProviders.Providers.Add(new OurCustomFluentModelValidatorProvider());
</pre>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.adamzolo.com/passing-custom-objects-fluentvalidation/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>FluentValidation Client-Side Custom Validation with MVC</title>
		<link>https://blog.adamzolo.com/fluentvalidation-client-side-custom-validation/</link>
					<comments>https://blog.adamzolo.com/fluentvalidation-client-side-custom-validation/#comments</comments>
		
		<dc:creator><![CDATA[Adam Zolo]]></dc:creator>
		<pubDate>Fri, 23 May 2014 02:51:03 +0000</pubDate>
				<category><![CDATA[MVC]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[FluentValidation]]></category>
		<guid isPermaLink="false">http://eazolo.com/blog/?p=54</guid>

					<description><![CDATA[FluentValidation is &#8220;A small validation library for .NET that uses a fluent interface and lambda expressions for building validation rules for your business objects.&#8221; It is quite awesome. However, the provided client-side validation is limited:  &#8220;any rules defined using a condition (with When/Unless), custom validators, or calls to Must will not run on the client side.&#8221; Below&#8230;<p><a class="more-link" href="https://blog.adamzolo.com/fluentvalidation-client-side-custom-validation/" title="Continue reading &#8216;FluentValidation Client-Side Custom Validation with MVC&#8217;">Continue reading <span class="meta-nav">&#8594;</span></a></p>]]></description>
										<content:encoded><![CDATA[<p>FluentValidation is &#8220;<span style="color: #253340;"><a href="http://fluentvalidation.codeplex.com/" target="_blank">A small validation library for .NET that uses a fluent interface and lambda expressions for building validation rules for your business objects.</a>&#8221; It is quite awesome. However, the provided client-side validation is limited:  &#8220;<a href="http://fluentvalidation.codeplex.com/wikipage?title=mvc&amp;referringTitle=Documentation" target="_blank">any rules defined using a condition (with When/Unless), custom validators, or calls to Must will not run on the client side.</a>&#8221; Below is some my first take on using FluentValidation on both server and client-side.</span></p>
<p>First, you need to install the nuget package. In our case, it is FluentValidation.MVC4.</p>
<p>We needed to make a certain property required, but only when some other property is true. To achieve this on client-side (server-side is trivial), we added these:</p>
<pre class="brush: csharp; title: ; notranslate">
	public class RequiredIfClientSideValidator : PropertyValidator
	{
		public string DependentProperty { get; set; }
		public object TargetValue { get; set; }

		public RequiredIfClientSideValidator(string errorMessage, string dependentProperty, object targetValue)
			: base(errorMessage)
		{
			this.DependentProperty = dependentProperty;
			this.TargetValue = targetValue;
		}

		protected override bool IsValid(PropertyValidatorContext context)
		{
			//This is not a server side validation rule. So, should not effect at the server side.  
			return true;
		}
	}
</pre>
<p>And this</p>
<pre class="brush: csharp; title: ; notranslate">
	public class RequiredIfClientSideFluentPropertyValidator : FluentValidationPropertyValidator
	{
		private RequiredIfClientSideValidator RequiredIfClientSideValidator
		{
			get { return (RequiredIfClientSideValidator)Validator; }
		}

		public RequiredIfClientSideFluentPropertyValidator(ModelMetadata metadata,
													   ControllerContext controllerContext,
													   PropertyRule propertyDescription,
													   IPropertyValidator validator)
			: base(metadata, controllerContext, propertyDescription, validator)
		{
			ShouldValidate = false;
		}

		public override IEnumerable&lt;ModelClientValidationRule&gt; GetClientValidationRules()
		{
			if (!ShouldGenerateClientSideRules()) yield break;

			var formatter = new MessageFormatter().AppendPropertyName(Rule.GetDisplayName());
			string message = formatter.BuildMessage(RequiredIfClientSideValidator.ErrorMessageSource.GetString());

			var rule = new ModelClientValidationRule()
			{
				ValidationType = &quot;requiredif&quot;,
				ErrorMessage = message
			};

			string depProp = BuildDependentPropertyId(Metadata, ControllerContext as ViewContext);
			// find the value on the control we depend on;
			// if it's a bool, format it javascript style 
			// (the default is True or False!)
			string targetValue = (RequiredIfClientSideValidator.TargetValue ?? &quot;&quot;).ToString();
			if (RequiredIfClientSideValidator.TargetValue.GetType() == typeof(bool))
				targetValue = targetValue.ToLower();

			rule.ValidationParameters.Add(&quot;dependentproperty&quot;, depProp);
			rule.ValidationParameters.Add(&quot;targetvalue&quot;, targetValue);

			yield return rule;
		}

		private string BuildDependentPropertyId(ModelMetadata metadata, ViewContext viewContext)
		{
			// build the ID of the property
			string depProp = viewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(RequiredIfClientSideValidator.DependentProperty);
			// unfortunately this will have the name of the current field appended to the beginning,
			// because the TemplateInfo's context has had this fieldname appended to it. Instead, we
			// want to get the context as though it was one level higher (i.e. outside the current property,
			// which is the containing object (our Person), and hence the same level as the dependent property.
			var thisField = metadata.PropertyName + &quot;_&quot;;
			if (depProp.StartsWith(thisField))
				// strip it off again
				depProp = depProp.Substring(thisField.Length);
			return depProp;
		}
	}
</pre>
<p>Additionally, we introduced a validator for simple client-side validation (ClientSideValidator) where you just need to pass an error message to your JavaScript validation.</p>
<pre class="brush: csharp; title: ; notranslate">
public class ClientSideValidator : PropertyValidator
	{
		public string JavascriptValidationAdapterName { get; set; }

		public ClientSideValidator(string errorMessage, string javascriptValidationFunctionName)
			: base(errorMessage)
		{
			JavascriptValidationAdapterName = javascriptValidationFunctionName;
		}

		protected override bool IsValid(PropertyValidatorContext context)
		{
			//This is not a server side validation rule. So, should not effect at the server side.  
			return true;
		}
	}
</pre>
<p>And an accompanying class: </p>
<pre class="brush: csharp; title: ; notranslate">	
	public class ClientSideFluentValidator : FluentValidationPropertyValidator
	{
		private ClientSideValidator ClientSideValidator
		{
			get { return (ClientSideValidator)Validator; }
		}

		public ClientSideFluentValidator(ModelMetadata metadata,
			ControllerContext controllerContext,
			PropertyRule propertyDescription,
			IPropertyValidator validator)
			: base(metadata, controllerContext, propertyDescription, validator)
		{
			ShouldValidate = false;
		}

		public override IEnumerable&lt;ModelClientValidationRule&gt; GetClientValidationRules()
		{
			if (!ShouldGenerateClientSideRules()) yield break;

			var formatter = new MessageFormatter().AppendPropertyName(Rule.GetDisplayName());
			string message = formatter.BuildMessage(ClientSideValidator.ErrorMessageSource.GetString());

			var rule = new ModelClientValidationRule()
			{
				ValidationType = ClientSideValidator.JavascriptValidationAdapterName,
				ErrorMessage = message
			};
			
			yield return rule;
		}
	}
</pre>
<p>Register your custom validators in Global.asax.cs:</p>
<pre class="brush: csharp; title: ; notranslate">
FluentValidationModelValidationFactory requiredIfClientSideValidationFactory =
				(metadata, context, rule, validator) =&gt;
					new RequiredIfClientSideFluentPropertyValidator(metadata, context, rule, validator);
			
			FluentValidationModelValidationFactory clientSideValidationFactory =
				(metadata, context, rule, validator) =&gt;
					new ClientSideFluentValidator(metadata, context, rule, validator);
			
			FluentValidationModelValidatorProvider.Configure(provider =&gt;
			{
				provider.Add(typeof(RequiredIfClientSideValidator), requiredIfClientSideValidationFactory);
				provider.Add(typeof(ClientSideValidator), clientSideValidationFactory);
			});
</pre>
<p>Don&#8217;t forget to add the JavaScript part:<br />
For requiredif validation:</p>
<pre class="brush: jscript; title: ; notranslate">
$.validator.addMethod('requiredif',
    function (value, element, parameters) {
    	var id = '#' + parameters&#x5B;'dependentproperty'];

    	// get the target value (as a string, 
    	// as that's what actual value will be)
    	var targetvalue = parameters&#x5B;'targetvalue'];
    	targetvalue =
          (targetvalue == null ? '' : targetvalue).toString();

    	// get the actual value of the target control
    	// note - this probably needs to cater for more 
    	// control types, e.g. radios
    	var control = $(id);
    	var controltype = control.attr('type');
    	var actualvalue =
            controltype === 'checkbox' ?
            control.attr('checked').toString() :
            control.val();

    	// if the condition is true, reuse the existing 
    	// required field validator functionality
    	if (targetvalue.toLowerCase() === actualvalue.toLowerCase())
    		return $.validator.methods.required.call(
              this, value, element, parameters);

    	return true;
    }
);

$.validator.unobtrusive.adapters.add(
    'requiredif',
    &#x5B;'dependentproperty', 'targetvalue'],
    function (options) {
    	options.rules&#x5B;'requiredif'] = {
    		dependentproperty: options.params&#x5B;'dependentproperty'],
    		targetvalue: options.params&#x5B;'targetvalue']
    	};
    	options.messages&#x5B;'requiredif'] = options.message;
    });
</pre>
<p>And for propertycvalidator:</p>
<pre class="brush: jscript; title: ; notranslate">
$.validator.addMethod('propertycvalidator', function (value, element, parameters) {
			//put your client-side validation logic here
			return true;
		});

		$.validator.unobtrusive.adapters.addBool('propertycvalidator');
</pre>
<p>And, now we are ready to create our model validator:</p>
<pre class="brush: csharp; title: ; notranslate">
		public class MyValidator()
		{
			//Make SomeProperty required. It will be validated on server and client side.
			RuleFor(m =&gt; m.SomeProperty)
				.NotEmpty().WithMessage(&quot;Some Property is required&quot;);
			//SomeOtherProperty will be validated on server side - it is required when PropertyB is true.
			//Client side validation is done by using RequiredIfClientSideValidator and passing dependent property 
			//name to unubtrusive JavaScript validation
			RuleFor(m =&gt; m.SomeOtherProperty)
				.NotNull()
				.WithMessage(&quot;Some other property is required&quot;)
				.When(model =&gt; model.PropertyB)
				.SetValidator(new RequiredIfClientSideValidator(
					&quot;Some other property is required&quot;,
					&quot;PropertyB&quot;,
					true));

			//this will get validated on client side only
			RuleFor(m =&gt; m.PropertyC)				
				.SetValidator(
					new ClientSideValidator(
						&quot;Error message&quot;,
						&quot;propertycvalidator&quot;)); // must be lower case
		}
</pre>
<p>The last part is adding the attribute to your model:<br />
[Validator(typeof(MyValidator))]<br />
public class YourModel<br />
{<br />
}</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.adamzolo.com/fluentvalidation-client-side-custom-validation/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
			</item>
	</channel>
</rss>
