CSLA .NET

Vibrant discussion about CSLA .NET and using the framework to build great business applications.

Forum has moved

New location: CSLA .NET forum


CSLA .NET Resources:
  • CSLA .NET forum
  • CSLA .NET home page
  • IClientValidatable & MVC

    rated by 0 users
    Answered (Verified) This post has 1 verified answer | 11 Replies | 1 Follower

    Top 10 Contributor
    4,106 Posts
    Andy posted on Fri, Jul 12 2013 3:14 PM

    I'm trying to convert some existing validation attributes to business rules.  I have some which implement IClientValidatable (most of our validation is actually on the view models, something I'm trying to fix by bringing in Csla).  I can easily build the rule in Csla, but my question is how to keep the client side validation.  Bringing the attribute into the business layer would not work as the IClientValidatable attribute is MVC only.

    Any ideas on getting the validation client side as well? 

    Answered (Verified) Verified Answer

    Top 10 Contributor
    4,106 Posts
    Answered (Verified) Andy replied on Mon, Aug 19 2013 1:27 PM

    Just wanted to update this thread in case others are looking at something similar.

    Basically instead of writing the rule as a normal Csla BusinessRule, if you create it as a ValidationAttribute subclass instead, you can then in your MVC project implement a subclass of DataAnnotationsModelValidator<T> and override the GetClientValidationRules method.  You can then link things up using the DataAnnotationsModelValidatorProvider.RegisterAdapter(Type attributeType, Type validatorType) method in the global.asax. 

    The drawbacks are that you're no longer able to utilize the normal business rule framework and these rules are all at priority 0, but in my case it works out fine as it ends up being effectively a Required validation rule that can be turned on or off via configuration.

    The information in this blog post was very helpful, and gives more details on  how you'd implement GetClientValidationRules to tie into the jQuery validation framework.

    All Replies

    Top 10 Contributor
    9,475 Posts

    Unless I'm missing something, it looks like this interface basically duplicate the data annotations attributes. Why not just put those on your model(csla supports them), and use cslamodelbinder as shown in the 'Using CSLA 4'

    Rocky

    Top 10 Contributor
    2,279 Posts

    Hi,

    Yes, you are missing something. GetClientValidationRules is called directly from the html extensions in the view on the ValidationAttribute and does not use the modelbinder. 

    So it's like this: 

         @Html.TextBoxFor(model => model.IsSMS) @Html.LabelFor(model => model.IsSMS)
    
    

    that will call the GetClientValidationRules on the ValidationAttribute when the attribute implements IClientValidatable.

      /// <summary>
      /// Provides a way for the ASP.NET MVC validation framework to discover at run time whether a validator has support for client validation.
      /// </summary>
      public interface IClientValidatable
      {
        /// <summary>
        /// When implemented in a class, returns client validation rules for that class.
        /// </summary>
        /// 
        /// <returns>
        /// The client validation rules for this validator.
        /// </returns>
        /// <param name="metadata">The model metadata.</param><param name="context">The controller context.</param>
        IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context);
      }

    Unfortunately - this means that all your DataAnnotation ValidationRules that implements client side validation must have a reference to the System.Web.Mvc assembly and this assembly must be referenced by your BusinessLibrary in order to add the DataAnnotation rules on properties.

    Jonny Bekkum, Norway CslaContrib Coordinator

    Top 10 Contributor
    4,106 Posts
    Andy replied on Mon, Jul 15 2013 9:21 AM

    RockfordLhotka:
    Unless I'm missing something, it looks like this interface basically duplicate the data annotations attributes. Why not just put those on your model(csla supports them), and use cslamodelbinder as shown in the 'Using CSLA 4'

    The interface is defined in the MVC library, and takes instances of subclasses defined only in MVC (ModelMetadata and ControllerContext).  The full signature is this:

    IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context); 

    Top 10 Contributor
    4,106 Posts
    Andy replied on Mon, Jul 15 2013 9:31 AM

    JonnyBee:

    Hi,

    Yes, you are missing something. GetClientValidationRules is called directly from the html extensions in the view on the ValidationAttribute and does not use the modelbinder. 

    So it's like this: 

         @Html.TextBoxFor(model => model.IsSMS) @Html.LabelFor(model => model.IsSMS)
    
    

    that will call the GetClientValidationRules on the ValidationAttribute when the attribute implements IClientValidatable.

      /// <summary>   /// Provides a way for the ASP.NET MVC validation framework to discover at run time whether a validator has support for client validation.   /// </summary>   public interface IClientValidatable   {     /// <summary>     /// When implemented in a class, returns client validation rules for that class.     /// </summary>     ///      /// <returns>     /// The client validation rules for this validator.     /// </returns>     /// <param name="metadata">The model metadata.</param><param name="context">The controller context.</param>     IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context);   }
    
    

    Unfortunately - this means that all your DataAnnotation ValidationRules that implements client side validation must have a reference to the System.Web.Mvc assembly and this assembly must be referenced by your BusinessLibrary in order to add the DataAnnotation rules on properties.

    Jonny, thanks for taking the time to answer my question.  I do understand how the IClientValidatable attribute works, and I also understand that one (very bad, IMO) solution is to add a reference to the MVC library to the business layer.  As stated, I also need these classes to work in WCF, which doesn't seem to combine well with MVC.  I've looked for people trying to use both in the same project, they don't seem to play nice together.

    My question is what other options have people used to get around this?  I've been started researching to see if, for example, implementing a ModelValidator subclass could help here. I've also been thinking perhaps there is a way to detect the rule and emit some custom JS in the MVC side of things that will call the server and run the same logic the rule is enforcing.  Maybe this is a case for a view model?

    I also understand that some rules are best left for only the server to run; however in this case, it really would be best to have the rule run on the client as well.  The rule is basically "this field is required if the configuration flag in the database says it is."  We have a SaaS solution, and some fields can be required or not based on our customer's preference.

    Top 10 Contributor
    2,279 Posts
    JonnyBee replied on Mon, Jul 15 2013 10:01 AM

    Hi,

    I am curious as to why this shouldn't work with WCF. 

    Have you looked at http://wcfdataannotations.codeplex.com/ ?

    Project Description
    WCFDataAnnotations allows you to automatically validate WCF service operation arguments using the attributes and IValidatableObject interface from System.ComponentModel.DataAnnotations.

    IE: This allows you to use DataAnnotation on your WCF Data Contract objects. It plugs into the WCF Pipeline to do the validation before data reaches your service implementation. 

    Jonny Bekkum, Norway CslaContrib Coordinator

    Top 10 Contributor
    9,475 Posts

    So Microsoft changed the way the DataAnnotation attributes work so they are no longer automatic like they were in MVC 2 and 3?

    Rocky

    Top 10 Contributor
    2,279 Posts
    JonnyBee replied on Mon, Jul 15 2013 12:02 PM

    No. It's not DataAnnotation. It's the IClientValidate interface in System.Web.Mvc for client side validation that custom DataAnnotation rules may implement to say which JavaScript rule and parameters to execute on client. 

    Jonny Bekkum, Norway CslaContrib Coordinator

    Top 10 Contributor
    4,106 Posts
    Andy replied on Mon, Jul 15 2013 12:19 PM

    I think I may have found something that should work.  If I create the rule as a ValidationAttribute without the IClientValidatable interface, Csla can pick up on it fine.

    Then I can create an implementation of DataAnnotationsModelValidator<T> and use DataAnnotationsModelValidatorProvider.RegisterAdapter to tie the attribute and validator together.  Since I'm doing a simple Requires it should just work provided I emit the correct metadata in my validator adapter.

    I'm using this link as a reference (and we actually have done this before in our application, I just didn't really understand how it was working): http://www.ipreferjim.com/2011/08/dataannotations-mvc3-unobtrusive-validations/

    Now the only issue is I need to read a different property value off of the Csla object.  The property is private and I was hoping I could get to it in the attribute via the Csla PropertyInfo for it, but I can't find a way to do a ReadValue from there.  I saw a Csla interface that would help, but it's internal.

    I suppose I could just make the property public and use reflection to read it (since I'm using reflection anyway to get the PropertyInfo field I want).

    Top 10 Contributor
    9,475 Posts

    Where I am confused is that in MVC 2 and 3 it was enough to just apply a DataAnnotations attribute to a property, and MVC would automatically project the necessary js code into the browser to make those rules run client-side.

    Now they've added this new interface, and I understand that it is new and is in the Mvc namespace.

    But did they take away the prior behavior of DataAnnotations attributes, thus breaking the existing behavior?

    Rocky

    Top 10 Contributor
    2,279 Posts

    Hi,

    This is primarily for custom DataAnnotation rules to support client validation. Like for developers to create their own custom data annotation rules rather than CSLA business rules for validation and get the support of javascript based validation on the client side. 

    The developer must however create the javascript client side rule as well but it follows a defined pattern for implementation.

    To me - the programming model is flawed in the sense that a business library must have a reference to the interface in System.Web.Mvc and all the interface defines is the method GetClientValidationRules

    Jonny Bekkum, Norway CslaContrib Coordinator

    Top 10 Contributor
    4,106 Posts
    Answered (Verified) Andy replied on Mon, Aug 19 2013 1:27 PM

    Just wanted to update this thread in case others are looking at something similar.

    Basically instead of writing the rule as a normal Csla BusinessRule, if you create it as a ValidationAttribute subclass instead, you can then in your MVC project implement a subclass of DataAnnotationsModelValidator<T> and override the GetClientValidationRules method.  You can then link things up using the DataAnnotationsModelValidatorProvider.RegisterAdapter(Type attributeType, Type validatorType) method in the global.asax. 

    The drawbacks are that you're no longer able to utilize the normal business rule framework and these rules are all at priority 0, but in my case it works out fine as it ends up being effectively a Required validation rule that can be turned on or off via configuration.

    The information in this blog post was very helpful, and gives more details on  how you'd implement GetClientValidationRules to tie into the jQuery validation framework.

    Page 1 of 1 (12 items) | RSS

    Copyright (c) 2006-2014 Marimer LLC. All rights reserved.
    Email admin@lhotka.net for support.
    Powered by Community Server (Non-Commercial Edition), by Telligent Systems