(X) Hide this
    • Login
    • Join
      • Generate New Image
        By clicking 'Register' you accept the terms of use .

WCF RIA Services Part 6 - Validating Data

(4 votes)
Brian Noyes
>
Brian Noyes
Joined Jun 10, 2010
Articles:   19
Comments:   116
More Articles
24 comments   /   posted on Aug 26, 2010

This article is Part 6 of the series WCF RIA Services.

Introduction

In Part 5 I discussed metadata classes and shared code, and one of the example uses of metadata classes I showed was using a [Required] validation attribute to cause some validation on both the client and server side. In this article, I will dive into more depth on the various ways you can validate data using WCF RIA Services. I’m going to look at four ways of validating input data:

  • Using built-in validation attributes from the System.ComponentModel.DataAnnotations namespace
  • Using custom validation attributes to invoke custom logic on the server and client side for cross property validation
  • Using server side validation when changes are submitted to the back end
  • Doing asynchronous validation using a domain service invoke operation

To demonstrate these things in the application context that I have been building up over the last 5 articles, I needed to add some more functionality. That functionality included some small schema changes to the database, so a new database creation script is included with the download code to create an appropriate database schema with some minimal sample data to be able to run the application. Because I am continuing to keep the focus on WCF RIA Services capabilities and not on general Silverlight display functionality, the display of some of the validation errors in the sample is necessarily crude to keep the changes to the app to a minimum and to keep the article length digestible.

The new functionality includes the ability to add customers (and there are a couple defined in the DB script so you don’t have to add any to get started), as well as select a customer associated with a given Task. There are validations associated with the definition of a Customer, as well as for creating time entries associated with a task that has a customer, described in more detail later in the article.

The finished code for this article can be downloaded here.

Data Annotation Validation Attributes

As mentioned last time, WCF RIA Services has rich built-in support for the validation attributes in the System.ComponentModel.DataAnnotation namespace. These attributes include the ability to specify simple forms of validation on entity properties by adding an attribute to an entity property. If your entity model is one where you cannot modify the properties directly (such as the code generated entities of Entity Framework), you can place the validation attributes on the properties of your metadata class. Those validation attributes will be used for server side validation by WCF RIA Services, and they will also be used client side because the client generated entities will have those attributes on their properties.

The available validation attributes include:

  • Required
  • StringLength (added by Entity Framework for string fields and therefore generated on the client)
  • Regular Expressions
  • Range (for numeric inputs)

There are a few others in the namespace that you might want to look into that purely affect display, but I won’t go into details of those in this article.

To apply them when using an entity framework model, you again just add them to the properties of your metadata class.

The generated client code will include those defined in your metadata class, as well as any defined on the model entities themselves, such as the [StringLength] attributes added by Entity Framework for string fields in the database.

As an example of using one of these attributes, a Customer has a Phone property that is a string, but needs to follow a proper format for a phone number. A regular expression is a great way of checking this kind of thing. So the metadata class for my Customer entity type includes the following attribute on the Phone property:

 [MetadataTypeAttribute(typeof(Customer.CustomerMetadata))]
 public partial class Customer
 {
     internal sealed class CustomerMetadata
     {
         ...
         [RegularExpression(@"^\D?(\d{3})\D?\D?(\d{3})\D?(\d{4})$", ErrorMessage="...")]
         public string Phone { get; set; }
         ...
     }

You can see the only challenge in using the regular expression validation is in coming up with the right regular expression. The one I am using here allows several formatting variants of US phone numbers (3 digits, 3 digits, 4 digits with variations on delimiters in between).

Just by having that attribute on the server entity or its metadata class, it shows up on the code generated client entity. Additionally, the WCF RIA Services Entity base class that is added to the client entity has an implementation of INotifyDataErrorInfo that uses the data annotation attributes to perform validation when data bound in the UI. So just by adding these attributes with appropriate error messages, you get validation indications for the user like shown below.

8-24-2010 7-20-20 AM

The error message shown on the Phone input TextBox happens automatically when the focus leaves the control. In the sample code, I used a behavior to cause the binding to update on each keystroke to get more immediate feedback to the user. The error message shown is the one specified in the server side attribute. You can also see that I added a ValidationSummary control to the form. That is to display when there is more than one validation error on the form at a time, which will come into play in the next section.

Custom Validation Attributes

In addition to the pre-built validation attributes discussed in the last section, there is a [CustomValidation] attribute in the data annotations namespace that allows you to point to a static method you can define to perform any kind of custom logic you need to validate when a property is set. That may involve doing some calculation or conditional logic, but ultimately you are deciding whether the newly input values are valid. Keep in mind that if you put these attributes on the server side entity or its metadata class, you will need to ensure that the code defined in the custom validation will be able to execute on both the client and server side. So you would not want to put code in there that does a look up against the database for example. I’ll show examples of how to deal with that kind of validation in the next two sections.

One place custom validations come in very handy is for cross-property validations. When the validity of one property’s value depends on the value of another property on the same object, or possibly the values of some of the child objects or a parent object, you can accommodate this fairly easily using custom validation.

In the Customer class for the sample, I added a contrived property called HasPhone. The simple idea here is that if HasPhone is set to true, then a valid phone number should be supplied. If HasPhone is set to false, no phone number should be supplied. This validation should be triggered whenever either property is modified, and both properties can be displayed as having a validation error when they are out of sync. You can see this in action below. Notice that both input controls (Phone TextBox and HasPhone CheckBox) are indicating a validation error, and there are two errors shown in the ValidationSummary control.

8-24-2010 7-23-02 AM

To support this, you first define the validation method that you want to point to from the [CustomValidation] attribute. That method has to have a particular signature, specifically it must be public, return a ValidationResult, and take in a value and a ValidationContext. If you are doing two properties with different types on the properties like I am here, you can break it down into two methods with each value having the appropriate type, even if they share some validation code:

 public class CustomerPhoneValidator
 {
     public static ValidationResult CrossValidatePhoneWithHasPhone(string newPhone, ValidationContext context)
     {
         Customer customer = context.ObjectInstance as Customer;
         if (customer == null) return ValidationResult.Success;
         bool hasPhone = customer.HasPhone;
         string phone = newPhone;
  
         return ValidatePhoneAndHasPhone(hasPhone, phone);
     }
  
     public static ValidationResult CrossValidateHasPhoneWithPhone(bool newHasPhone, ValidationContext context)
     {
         Customer customer = context.ObjectInstance as Customer;
         if (customer == null) return ValidationResult.Success;
         bool hasPhone = newHasPhone;
         string phone = customer.Phone;
  
         return ValidatePhoneAndHasPhone(hasPhone, phone);
     }
  
     private static ValidationResult ValidatePhoneAndHasPhone(bool hasPhone, string phone)
     {
         if (hasPhone && string.IsNullOrWhiteSpace(phone))
         {
             return new ValidationResult(@"If the customer has a phone, the number must be specified", 
                 new string[] { "HasPhone", "Phone" });
         }
         else if (!hasPhone && !string.IsNullOrWhiteSpace(phone))
         {
             return new ValidationResult(@"If the customer does not have a phone, the number should not be specified", 
                 new string[] { "HasPhone", "Phone" });
         }
         else
         {
             return ValidationResult.Success;
         }
     }
 }

You can see that I have two validation methods, one for the boolean HasPhone property and one for the string Phone property. Other than the type of the value, the signature of the methods is the same. You can see that the ValidationContext argument that is passed to your method allows you to get a reference to the whole object that the property being validated is on, allowing you to get to other properties on that object. At the point where your validation method is being called, the target property (i.e. Phone) has not been set on the object itself yet. The value being passed in to your validation method is the proposed new value, and it is up to your method to decide whether to allow it to be set or not. If you are fine with the value being set, you just return a ValidationResult.Success value. If you do not like the value, then you can return a ValidationResult with an error string populated and optionally a string array containing all of the property names affected by the error. This is how you can address cross-property validation scenarios like the one here. If no phone or an invalid phone number is supplied, I can check to see if the HasPhone property is set to true. If so, both Phone and HasPhone are in error because they have to agree with respect to their supplied values.

To apply the custom validation to a property, you just use a [CustomValidation] attribute:

 [MetadataTypeAttribute(typeof(Customer.CustomerMetadata))]
 public partial class Customer
 {
     internal sealed class CustomerMetadata
     {
         ...
         [CustomValidation(typeof(CustomerPhoneValidator),"CrossValidatePhoneWithHasPhone")]
         [RegularExpression(@"^\D?(\d{3})\D?\D?(\d{3})\D?(\d{4})$", ErrorMessage="...")]
         public string Phone { get; set; }
         
         [CustomValidation(typeof(CustomerPhoneValidator), "CrossValidateHasPhoneWithPhone")]
         public bool HasPhone { get; set; }
         ...
     }
 }

In this case I have a separate attribute for the regular expression and the cross-property validation for demonstration purposes. That will result in two different errors at times. For a more user friendly experience, as long as you are writing custom validation logic for a property tied in with the [CustomValidation] attribute, you might want to move that format validation inside the custom validation logic so that you only return one error at a time from a single control value.

Server-Side Validation

Some kinds of validation are not appropriate to do on the client side. You may have data you need to look up on the back end that you don’t want to expose to the client that will drive the decision of whether a given chunk of data is valid or not. For the sample application, I added the ability to look up a customer status on a customer when a task is saved. If the customer status (which I don’t want exposed to the client so that it doesn’t get inadvertently displayed in the client) is marked as “DeadBeat” status, then I want to limit the number of billable hours I accrue for that customer. So at the point where I go to save a task on the back end, I need to look up the customer status and see how many hours have been added to the modified Task as child TimeEntries and decide whether to accept that task for update. If I don’t want to accept it, I can throw a ValidationException from the update method, and validation errors will be added to the entity in the client application and can be displayed in various ways.

To facilitate this scenario, it did require a change to my object model. I talked briefly about the [Composition] attribute in the last article. In order to have the TimeEntries sent down with the Task even if they have not changed themselves (such as when a customer has just been assigned to the Task), I needed to switch to having the TimeEntries collection on the Task be a [Composition] relationship. When you do that, the TimeEntries become wholly owned by their parent Task, and you don’t submit updates to individual time entries the way the application was doing in the last couple articles. Now you just get updates to tasks, and those changes might involve changes to the discrete properties of the task, the assignment of a related customer (which is not a Composition relationship because customers can be independently queried and updated) or the addition/removal/change of a time entry within the child TimeEntries collection of the Task. You can check out the UpdateTask method in the domain service to see the way this altered the coding patterns. Basically you have to do some state detection yourself and call the appropriate parts of the data access API (Entity Framework in this case) to manage the inserts/updates/deletes of your child objects in a composition relationship.

By going with a composition relationship, though, now all the child TimeEntries are sent down with a modified task and you can evaluate the package as a whole for server side validation. So the update and insert methods for Tasks call a helper method that first does the server side validation:

 private void ValidateCustomerHours(Task task)
 {
     if (task.CustomerId.HasValue)
     {
         int customerId = task.CustomerId.Value;
         bool timeAllowed = IsTotalTimeAllowed(customerId, task.TotalTime);
         if (!timeAllowed)
             throw new ValidationException(
                 "You cannot enter more than 10 hours per billing cycle for this customer.");
     }
 }
  
 [Invoke]
 public bool IsTotalTimeAllowed(int customerId, TimeSpan totalTime)
 {
     Customer relatedCustomer = ObjectContext.Customers.Where(c => c.CustomerId == customerId).FirstOrDefault();
     if (relatedCustomer != null && relatedCustomer.Status == "Deadbeat" 
         && (totalTime > TimeSpan.FromHours(10)))
     {
         return false;
     }
     return true;
 }

If I wrote the client so that it did not validate the max hours for a customer on the client side before sending the task to the back end for updating or inserting, this code would be invoked and would throw the ValidationException back to the client. On the client side, WCF RIA Services would add a ValidationError to the Task  and it could be displayed by the build in validation mechanisms of Silverlight Controls.

8-24-2010 12-55-52 PM

Async Validation through Invoke Methods

When it comes to validation, it is generally better to let the user know as early as possible when they have entered invalid data instead of waiting until a later point such as when they have tried to send that invalid data to the back end for persistence. A decent way to do this in WCF RIA Services is to use an [Invoke] method on your service. In addition to the CRUD methods you can expose on a WCF RIA Service, you can also add arbitrary methods that you mark with an [Invoke] attribute. These too will be exposed as service methods to the client and will show up on the corresponding domain context. They can pass different types than the main entities that the domain service is managing as entities, but there is a restricted set of types that you can pass as parameters and return types. The WCF RIA Services enumerates the types that can be used as parameters and return types on domain service methods.

To support more immediate feedback to the user for the case of entering too many hours for a customer with bad status, I added the IsTotalTimeAllowed method that you can see in the code snippet in the previous section. That method is being used both internally by the server side validation, and can be called directly from the client as well. In the client side view model, at the point where the user has entered a new time entry, I can make a call to that service method to check whether the new time entry will exceed the max allowed hours.

 TimeEntry entry = popup.DataContext as TimeEntry;
 ...
 if (SelectedTask.CustomerId.HasValue)
 {
     TasksDomainContext context = new TasksDomainContext();
     Action<InvokeOperation<bool>> action = delegate(InvokeOperation<bool> op)
     {
         ...
         if (entry != null) SelectedTask.TimeEntries.Add(entry);
         ...
     };
     context.IsTotalTimeAllowed(SelectedTask.CustomerId.Value, 
         SelectedTask.TotalTime + (entry.EndTime - entry.StartTime), action, null);
 }

As you can see, the invoke method shows up on the domain context as a normal async service method. You can pass a callback delegate of type InvokeOperation<T>, where T is the return type of the invoke method, and that callback will be invoked when the async call is complete. You get the same thread marshalling back to the UI thread that you do with Load and SubmitChanges operations, so you don’t have to do any thread marshaling yourself.

You can see the full implementation with some (crude) user prompting in the sample application in the download code.

Summary

The built in validation support in WCF RIA Services is one of the more compelling features that makes me want to use WCF RIA Services for most data-oriented situations in Silverlight. The ease of using data annotation attributes to express simple validation rules or custom validation attributes to tie in more complex validations covers a large number of validation scenarios nicely. Add to that the ability to invoke whatever logic you need from your domain service CRUD methods and Invoke methods on the back end and you have a nice end to end solution for handling validation. The fact that WCF RIA Services takes care of adding the validation errors to the entities on the client side and implements INotifyDataErrorInfo on those entities to participate nicely with the data binding features of Silverlight just rounds it all out into a very powerful part of WCF RIA Services.

The complete code for this article can be downloaded here.

About the Author

Brian Noyes is Chief Architect of IDesign, a Microsoft Regional Director, and Connected System MVP. He is a frequent top rated speaker at conferences worldwide including Microsoft TechEd, DevConnections, DevTeach, and others. He is the author of Developing Applications with Windows Workflow Foundation, Smart Client Deployment with ClickOnce, and Data Binding in Windows Forms 2.0. Brian got started programming as a hobby while flying F-14 Tomcats in the U.S. Navy, later turning his passion for code into his current career. You can contact Brian through his blog at http://briannoyes.net/ or on twitter @briannoyes.

 


Subscribe

Comments

  • -_-

    RE: WCF RIA Services Part 6 - Validating Data


    posted by eukal on Aug 26, 2010 13:02

    You wrote "When the validity of one property’s value depends on the value of another property on the same object, or possibly the values of some of the child objects or a parent object, you can accommodate this fairly easily using custom validation"

     

    How do you get the "parent object" (not "the same object") of a property from ValidationContext?

  • -_-

    RE: WCF RIA Services Part 6 - Validating Data


    posted by Brian Noyes on Aug 27, 2010 02:52

    Ooh, I love insightful readers! :) You caught me in some loose terminology. If it is truly a parent object, you would not be able to get to the object server side because it would not be passed down by RIA Services. However, depending on how you were using the object model and how you decorated it, you could use a Composition attribute on something that was logically a parent (i.e. a Customer property on an Task object) and then it could be passed down. But that would fundamentally modify the way you were managing that object in the domain service so you are not really treating it as a true parent, really more of a child at that point.

    From a client side though, if the validation was only being used client side (not through the server metadata class for example), that Customer object would be populated still from the domain context setting up the whole object model on the client side and populating the related entity properties, so client side you could walk to the Parent through the related property on the child.

    Hope that clears it up.

  • -_-

    RE: WCF RIA Services Part 6 - Validating Data


    posted by Anand Subramanian on Aug 31, 2010 00:39
    You just did an 9G in your tomcat
  • -_-

    RE: WCF RIA Services Part 6 - Validating Data


    posted by Janni on Sep 23, 2010 11:14

    Hi,

    I am very intrerested in your example for server side validation.
    Especially in the part were you throw a ValidationException in ValidateCustomerHours.
    Your code looks like this:

    if (!timeAllowed)
      throw new ValidationException(
      "You cannot enter more than 10 hours per billing cycle for this customer.");


    This code is called in your DomainService in the method U
    pdateTask(Task currentTask).
    Your example does not use this ValidationException so I prepared a little demo and threw
    a ValidationException at the beginning of my UpdateXXX-method in my demo DomainService.

    So far things work, I throw a ValidationException in my UpdateXXX-method in the DomainService and when the DomainContext.SubmitChanges submits an entity which triggers the ValidationException I am getting an exception on my client side.

    Now how do I translate this specific exception into something that my datagrid or any control that uses bindings can use? How do I tell the corresponding cell in my datagrid or a textbox or whatever control to change its color to red and display the exception error?

    How do I integrate this server side validation exception into something that shows up nicely on the client?

  • -_-

    RE: WCF RIA Services Part 6 - Validating Data


    posted by Brian Noyes on Sep 23, 2010 16:28

    Hi Janni,

    To a large degree, you don't have to do anything. When you throw that exception on the server, it gets associated inside the RIA Services stack with the entity it was passing to you for updates. When the update batch is completed, RIA Services returns results to the client. Those results include the validation errors that happened on the server for each entity, whether triggered by a validation attribute, or from throwing a ValidationException inside the update methods. On the client side, RIA Services implements the INotifyDataErrorInfo interface for each entity and puts those errors into the collection of errors and raises the ErrorsChanged event. Any bound properties on an entity should then requery by calling the GetErrors method and should display a validation error if the control supports it.

     That being said, unfortunately the DataGrid only shows validation errors as far as I know if you are editing a row, so it will not show that validation error in the data grid unless you go in and start editing one of the cells for a row who's object has validation errors. If you have normal input controls like TextBox, you should see the validation error immediately. I looked around briefly while writing the article to try to find a way to get the DataGrid to display the validation errors when not in edit mode, but ran out of time and had to pass on that.

    Hope that clarifies.

  • -_-

    RE: WCF RIA Services Part 6 - Validating Data


    posted by Janni on Sep 23, 2010 18:07

    adly the problems start earlier in my case. 
    This is my Update method on the server DomainService:

    public void UpdateCdGroupDescriptions(cdGroupDescriptions currentcdGroupDescriptions) 

    {
        if (currentcdGroupDescriptions.Title.ToUpper().Equals("BLABLA")) {
            ValidationResult error = new ValidationResult("BLABLA wrong!", new string[] {"Title"});
            throw new ValidationException(error, null, currentcdGroupDescriptions);
        }
        this.ObjectContext.cdGroupDescriptions.AttachAsModified   
            (currentcdGroupDescriptions,this.ChangeSet.GetOriginal(currentcdGroupDescriptions));
    }

    I am generating a ValidationError item for the property Title when it contains a specific string.
    Then I throw a ValidationException containing this specific error.

    On the client side the DomainContext SubmitChanges method looks like that (dummy code):

    DataMgr.ArticleContext.SubmitChanges(submitOp => { var b = 10; }, null);

    I am using a lambda which checks for errors in the SubmitOperation and displays the error. The problem isthat the code which handles this (ErrorHandler.DiplayError) is not called at all!

    When the server throws a ValidationException as I stated before on the client side I am getting a message box from Visual Studio Just-In-Time Debugger:
    "An unhandled exception('Unhandled Error in SIlverlight Application
    Code: 4004
    Category: ManagedRuntimeError
    Message: System.ServiceModel.DomainServices.Client.DomainOperationException:
    Submit operation failed validation. Please inspect Entity.ValidationErrors for
    each Entity in EntitiesInError for more information.
    ...
    ...

    This means that I have to somehow handle the exception before it gets rerouted my controls via their data binding? So I changed the code to this:

    DataMgr.ArticleContext.SubmitChanges(submitOp => { submitOp.MarkErrorAsHandled(); }, null);
    Now I am not getting the Exception warning dialog of my visual studio but nothing happens in my GUI. I told the system that I would handle the error by myself.
    I tested my code with a TextBox which was bound via a twoway binding and no validation error popped up in my GUI.

    I did not find a complete, working tutorial for this problem on the web.
  • -_-

    RE: WCF RIA Services Part 6 - Validating Data


    posted by Janni on Sep 23, 2010 18:26
    Sorry, I don't know what happened here, why my post is displayed three times?
  • iiordanov

    RE: WCF RIA Services Part 6 - Validating Data


    posted by iiordanov on Sep 23, 2010 18:30

    Hi Janni,

    You comment is reposted each time you refresh the page. Do not worry I will delete all repeated posts. 

  • -_-

    RE: WCF RIA Services Part 6 - Validating Data


    posted by Brian Noyes on Sep 23, 2010 19:40

    Janni, it is also getting cropped and can't follow it as a result. Besides, it is getting a little too specific to your scenario to continue here. Please contact me directly via email (brian dot noyes at idesign.net) and I'll try to help you out.

    Thanks, Brian

  • -_-

    RE: WCF RIA Services Part 6 - Validating Data


    posted by Jonathan ANTOINE aka Jmix90 on Oct 22, 2010 12:48

    Hello,

    This may interest you and/or your readers : [RIA Services] How to force the validation of my entities (and just the validation !) goo.gl/VPHV

    Thx for the article by the way !

  • -_-

    RE: WCF RIA Services Part 6 - Validating Data


    posted by Kent Zhou on Mar 16, 2011 20:04
    For async validation example, as this error is caused by property TotalTime, how to bind this validation to TotalTime, like annotation attribute bind to property in metadata class? In this way, user can see the redbox and message on TextBox for TotalTime.
  • -_-

    RE: WCF RIA Services Part 6 - Validating Data


    posted by Brian Noyes on Mar 16, 2011 23:26
    Should be able to just add a ValidationResult to the collection of ValidationErrors on the entity base class and set the parameters to the ValidationResult constructor that identifies which properties it is associated with, like the CustomValidation method samples are doing for cross field validation.
  • -_-

    RE: WCF RIA Services Part 6 - Validating Data


    posted by Robin on Mar 29, 2011 23:50

    I'm new to Silverlight (old dog on ASP.net) so I have been struggling with my overall approach.  I am now comfortable with my current project because you have helped me get a structure.  The download was perfect for me.  I am now enthused and working till 4am again - time passes so quickly doesn't it if only there was overtime? 

    Keep up the good work and if you are ever in London or in Hampshire UK I will stand you a beer or 2.

  • -_-

    RE: WCF RIA Services Part 6 - Validating Data


    posted by alman on Apr 13, 2011 15:27
     
    public class BookShelfService : LinqToEntitiesDomainService<BookClubEntities> {
        [Insert]
        public void ShareBook(Book book) {
            ...
            AmazonService amazonService = new AmazonService();
            if (amazonService.IsValidASIN(book.ASIN) == false) {
                ValidationResult error =
                    new ValidationResult("The specified Amazon ID did not resolve to an actual book.",
                                         new string[] { "ASIN" });
                throw new ValidationException(error, null, book);
            }
            ...
        }
    }
    
  • RahulMisra2000

    RE: WCF RIA Services Part 6 - Validating Data


    posted by RahulMisra2000 on May 02, 2011 20:51

    Brian,

    Are there any cross-thread access issues when code in the callback tries to access the ViewModel properties that are bound to the UI controls because only the UI thread should be manipulating, directly or indirectly, the UI controls.

     When working with WCF Data Services, I had to use the Deployment....Dispatcher to hook into the UI thread before accessing the UI controls.

     Is this not an issue with WCF RIA ?

  • -_-

    RE: WCF RIA Services Part 6 - Validating Data


    posted by Brian Noyes on May 03, 2011 02:52

    Hi Rahul,

    Not an issue with RIA Services because all callbacks and Completed handlers are automatically marshaled to the UI thread.

  • ylogico

    Re: WCF RIA Services Part 6 - Validating Data


    posted by ylogico on Aug 30, 2011 12:17

    Thanks for your post!!

    I'm using DataAnnotation in a Silverlight MVVM application for validation. My problem is that errors doesn't show up until user focus on that field and gets out of it. This can be a problem if user tries to "save" without using every required field for example.

    Do you know how to force this Validation??

    Thanks in advance!!!

  • brian.noyes

    Re: WCF RIA Services Part 6 - Validating Data


    posted by brian.noyes on Aug 30, 2011 15:55

    If you are talking about data in the data grid, I do not know how to force it to display the validation errors all the time, it only shows them when the row goes into edit mode.

  • ylogico

    Re: WCF RIA Services Part 6 - Validating Data


    posted by ylogico on Aug 30, 2011 15:56

    Yes, I was talking about that :-(.

    I'm using this to validate textboxes and I want to force a global validation.

    Thanks anyway ;-)

  • gisbing

    Re: WCF RIA Services Part 6 - Validating Data


    posted by gisbing on Dec 17, 2012 16:44

    Hi Brian,

    In my RIA service Silverlight app, I have a group of views that share same viewmodel. What is the best way to record the error on all the views so an event can be fired so other module knows that if there is error on any of the views? I'm currently using "System.Windows.Controls.ValidationError" in code behind to update the total number of errors in viewmodel but it doen't work (ValidationError never gets fired).

    Thanks!

  • brian.noyes

    Re: WCF RIA Services Part 6 - Validating Data


    posted by brian.noyes on Dec 18, 2012 17:40

    Do you have NotifyOnValidationError=true on your binding? That event won't fire unless you enable it with that property.

    That is one way. If I were doing it that way, I would dispatch that event into the view model with a Blend InvokeCommandAction behavior and then fire a Prism event that could be monitored by some central service that can tell you if any view in the has a validation error. The problem with that approach is cleaning up - getting that state refreshed when things go valid.

    Instead if I need some centralized knowledge of whether there are validation errors in the system somewhere, I would have a way to walk my object graph at the place where I need that knowledge and query each object for HasErrors through INotifyDataErrorInfo.

  • gisbing

    Re: WCF RIA Services Part 6 - Validating Data


    posted by gisbing on Dec 19, 2012 00:42

    Yes, I have "NotifyOnValidationError=true".

    Now I'm facing another issue that when a new entity (which is the object bind to my childwindow) is created, the [Required] property shows null but HasValidationError on the entity is false. If I set the required property to valid value and then to null after create that entity, HasValidationError become to true. I also tested this on the Desription property on TimeEntry object in your example.

    Does this mean that validation doesn't occur on new entiry in RIA service? If yes, does it mean that I need to force the validation on new entity?

    Thanks.

  • brian.noyes

    Re: WCF RIA Services Part 6 - Validating Data


    posted by brian.noyes on Dec 19, 2012 04:34

    I would have to check, but I think the RIA services validation does not kick in until you explicitly set a value. This is because a lot of people prefer not to be met by a barrage of red when they navigate to an empty form - they only want to see red if you have entered an invalid value. So you usually have to force validation on submit/save to check if the object(s) are valid based on their current values.

  • brian.noyes

    Re: WCF RIA Services Part 6 - Validating Data


    posted by brian.noyes on Dec 19, 2012 04:34

    I would have to check, but I think the RIA services validation does not kick in until you explicitly set a value. This is because a lot of people prefer not to be met by a barrage of red when they navigate to an empty form - they only want to see red if you have entered an invalid value. So you usually have to force validation on submit/save to check if the object(s) are valid based on their current values.

Add Comment

Login to comment:
  *      *       

From this series