Posts Tagged 'Validation'

Dynamic Data and Web Forms – Part One

I’ve blogged here a few times about data annotations and validation in ASP.NET, and most recently with some sample code for a Web Forms validator that converts data annotations into client-side validation. However, while there is no data -annotation-aware standard validator, there is one way you can get your controls to validate against data annotations – and that’s by using Dynamic Data.

Dynamic Data has been around for a while. It has its own project type, and can be used to scaffold an entire web site based on an entity model. It can be extensively customized but it’s not really suitable for public facing web sites (though it’s great for quick admin-only management).

But that’s not all there is to Dynamic Data. It is also available inside other projects. There are a set of controls in Web Forms that are specifically designed to integrate with Dynamic Data AND with existing Web Form controls such as the GridView and FormView. It’s these controls that give us out-of-the-box data annotation support.

So how does it work? Let’s consider a form to send an email. There are a number of ways to go about this. We could create a form from scratch using standard controls, adding our own validation:

Or we could create an email class complete with data annotations….

…and use it to get a FormView to scaffold  the form for us.  But despite all those nice data annotations, that doesn’t add validation, so again we would have to add it ourselves, so it’s not really saved us much work:

Alternatively, we could get a FormView to scaffold it for us using Dynamic Data – and this is where we start benefiting from those data annotations.

At first glance this doesn’t look any better, as there are no validation controls in sight – but only because they’re hidden away inside those dynamic controls – as are the TextBoxes that map to the object’s properties. There’s just one problem – this is what we get if we run the page…

It turns out that Dynamic Data is not enabled by default. You have to enable it on the container control, and tell it what type it’s dealing with – and you have to do so inside the Page_Init event.

So now when we run the page with the FormView set to insert mode, we automatically get TextBoxes for the Email…

And this time the data annotations give us client side validation (though I had to add the validation summary to show the message from the From property):

The only remaining problem is that the scaffolded HTML is horrible. There are no labels, just text – so the page is inaccessible. The clever link buttons rely on JavaScript, another accessibility no-no. The button is easily fixable, but adding Labels to the TextBoxes turns out to be surprisingly fiddly – and managing that (and how to customize dynamic controls generally) will be the subject of my next blog post.

Kevin Rattan

For other related information, check out these courses from Learning Tree:

Building ASP.NET Web Applications: Hands-On

Web Forms Data Annotation Validation – Part 3

This is the third part in my look at Data Annotation validation in Web Forms in the Visual Studio 2012 Release Candidate. In the first part, I showed the server-side support for Data Annotation validation and model binding. In the second, I proposed one approach to providing client-side validation using jQuery plugins and a custom validator control that injects validation rules into the input element’s class attribute. The problem with that approach was an external dependency on the metadata plugin and the need to inject JavaScript into the page. So I got to thinking about how I might piggy-back on the unobtrusive validation support to produce a custom validator that worked in exactly the same way as the existing validators, but where the rules and messages were all derived from Data Annotations.

So the first thing to do was see how the existing validators work. I added various validators to a sample form and took a look at the underlying HTML. This is what I found:

client side unobtrusive attributes

There’s lots of interesting stuff here. The Text becomes the content of the span; the ErrorMessage is in data-val-errormessage; the validation method is in data-val-evaluation function; etc. If I can get my validator to read the Data Annotations and output the appropriate spans, that should give me the client-side validation I want.

I began in the same way as last time, by creating a new ASP.NET Web Control library and inheriting from the base validator. That code is in the previous posting, so I’m not going to repeat it here. (If you want to see the full code, I’ll put a link at the bottom of this post).

The reflection code is also the same, but one thing that is different is that this time I need to render HTML directly from the control, so I have to override the render method:

render method

The first thing I need is template for my span(s). I am going to put in {0} placeholders for the bits that need to change, and reuse the same basic string every time. Here is my template:

private static string template = “<span id=\”{0}\” data-val-evaluationfunction=\”{1}\” data-val=\”true\” data-val-errormessage=\”{2}\” data-val-controltovalidate=\”{3}\” {4} {5}>{6}</span>”;

Now, as I loop through the Data Annotations I can use string.Format() to fill in the blanks (note the += on the local spanString variable: that means I can add more spans if there are multiple annotations).

building the string

The arguments to the method are as follows:

  • this.ClientID is my current validator’s Id.
  • vat.ErrorMessage is the ErrorMessage from the Data Annotation.
  • c.ClientID is the control I am validating.
  • The string literals set up the validation for a required field
  • So where do display and message come from?

Display maps to the typical Validator display choices – static, dynamic and none. It’s initialized as style=”display: none;” data-val-display=”None” and overridden as appropriate. The message is the ErrorMessage to display in the control – as potentially overridden by the Text attribute.

message and display variables

So let’s add a reference inside our test web project and then add the new DataAnnotationValidator to the toolbox. Then we need to add a Required attribute to the Email class. (I added “DA” at the end of the message to confirm where the message was coming from).

required attribute

Then we need to set up the properties on our DataAnnotationValidator:

DataAnnotationValidator in aspx source

Now we can test it… and see that it works! We are now running client-side validation from Data Annotations, and it works and displays in exactly the same way as the other validators. And we have no additional dependencies and JavaScript injected into the page. Hurray.

working validation

Of course, we want to be able to validate other attributes as well. I went ahead and implemented several of them using the underlying RegularExpressionValidator. First I created a method to build all the regular expression spans:

regular expression builder

Then I called it from the various case statements for validation attributes:

switching attributes

Not forgetting the easiest one of all: the RegularExpressionAttribute itself:

RegularExpressionAttribute

Now I could play around with different values and messages in my Model….

Data Annotations

….and see my working Web Forms client-side Data Attribute validation:

validation working

I’ll probably refactor for robustness at some point, as well as adding support for additional attributes, but if you’re interested in the code for this version of the DataAnnotation validator, it’s online here: DataAnnotation2.txt.

Kevin Rattan

For other related information, check out these courses from Learning Tree:

Building Web Applications with ASP.NET and Ajax

Web Forms Data Annotation Validation – Part 2

In my last post I reviewed the new Web Forms support for server-side validation using Data Annotations, and ended with my frustration at not being able to find out how (or if) Microsoft had implemented the matching client-side validation. I promised to look at two different implementations that would provide client-side validation. This post is an overview of my first pass at a solution–using the jQuery validation plugin.

My hope was that since Microsoft had implemented client-side validation in MVC, all I would have to do was rip the code out of an MVC template and tweak it a bit to make it work in Web Forms. Sadly, it wasn’t going to be as easy as that. I brought over the appropriate JavaScript files, tried adding the web.config settings, but nothing happened. Still, at least I had the MVC JavaScript files and that meant I had the jquery.validate plugin – and since I’ve used that to get around issues in MVC validation, I could do so again for Web Forms. All I had to do was read the Data Annotations in a custom validator and inject the appropriate rules into the control to be validated. So… here goes:

The first thing I did was create a new ASP.NET server control so that the validator would be just another control in my toolbox:

New project dialog

Then I added a new class and inherited from the base validator:

inheriting base validator

That meant implementing the single method EvaluateIsValid():

overriding EvaluateIsValid

I simply return true here because the validator isn’t actually going to do any validation–it’s just going to inject the rules into the form element so that the validate plugin can do that for me. The validate plugin is able to read validation rules out of HTML class attributes. I’m going to translate DataAnnotations into the object literal arguments the plugin expects, so that when the validator reads the following Data Annotation…

Data Annotations

….it generates “{required:true, messages:{‘The from address is required’}}“inside the class attribute:

generated html

(In order for this to work, I’ll have to add the metadata plugin to my master page, as well as the validate and validate.unobtrusive plugins that I “borrowed” from the MVC template).

I’m not going to render this control itself, just inject content into the control it’s validating, so I override the PreRender event. I do the work inside the event handler (and inside a check to see if IsPostBack is false so that I’m only inject my code once). I even commented out the call to base.OnPreRender. Why bother? I’m not going to render it.

onprerender

The first task is to read the Data Annotations, so I need a reference to System.ComponentModel.DataAnnotations. Now I can use reflection to read the annotations, thus:

reflection

As you can see, I’m using TypeName, TypeAssembly and TypeProperty properties on my class to provide all the information I need to get hold of the object and its Data Annotations. These need to be provided by the UI developer, thus:

DataAnnotationValidator in aspx source

Now it’s just a question of checking the type of the validation attribute and creating the appropriate string. I did this by building two collections–one of rules, the other of messages. Here are the collections and a method used to populate them:

properties

And here is a switch inside the loop through the attributes that calls the AddValidation() method:

switching attributes

Once I have set up the rules and messages, all I need to do is create the literal and inject it into the control.

building the string

Then it’s time to test it… and nothing happens. That’s because although the validate plugin is there, there’s no call to .validate() on the page. So now I need to add in a scriptlet to make the plugin runs:

scriptlet

And then I need to register that script on the page.

registering script

Phew! Finally we’re done. All I have to do is add a reference to the library, add the DataAnnotationValidator to the toolbox (right-click and choose items, then browse to the library) and then add the appropriate validators to the page and give them the right property settings:

property settings

The DataAnnotation validator translates the rules into a form understood by the validate plugin, the validation runs and we have client-side validation:

working validation

Obviously, there are a lot of things that can be improved in this version. It doesn’t cover all the possible Data Annotations. It doesn’t allow for missing error messages. It only validates TextBox controls. I could improve it, but I’m not going to: I decided I didn’t like the dependency on the metadata plugin, and I hated having to inject JavaScript into the page. So I decided to go back to square one, forget about bringing in any scripts from the MVC version and work with the unobtrusive validators that come with the Web Forms template instead. And that’s what I’m going to cover in my next post.

(If you’re interested in the full code for this version of the DataAnnotation validator, it’s online here: DataAnnotation.txt.)

Kevin Rattan

For related information, check out these courses from Learning Tree:

Building Web Applications with ASP.NET and Ajax

jQuery: A Comprehensive Hands-On Introduction

Web Forms Data Annotation Validation – Part 1

This will be the first of three posts on Data Annotation validation in Web Forms in Visual Studio 2012. In the first one, I’ll talk about what I like (and what I don’t) in the new release, and in the following two I’ll show two alternative solutions to dealing with the frustration I’ve started to feel over what is either a missing feature or very-hard-to-find documentation.

First off: I love Data Annotation validation. I’ve mentioned it in a number of posts and I really like being able to annotate my classes so that the validation rules travel around with the class. I always hoped and expected that Microsoft would provide Data Annotation validation in the new release of Web Forms, given that it’s already in WPF, Silverlight and MVC. I was also hoping that Microsoft would give us unobtrusive client-side validation.

The Good News: they have.

The Bad News: they don’t seem to have done both together.

(Or at least, if they have, I can’t find any documentation on it. There are LOTS of articles out there talking about the new Data Annotation validation and also about the new unobtrusive client-side validation–but when they refer to Data Annotation validation, they are talking about server side validation, and when they talk about unobtrusive validation they’re talking about the existing property-based validators. I’ll be delighted (and grateful) if anyone out there can point me at any documentation that shows Microsoft has implemented client side Data Annotation validation in Web Forms as they did in MVC–in which case my own experiments in that direction, to be detailed over the next two posts, will have been merely a fun coding excursion and not actually necessary).

So, back to the good news.

I was playing with the new model binding functionality in Web Forms, and it’s really nice. I created an Email model which had the necessary data, a static method to return an empty Email object for the model binder and the code to send the email, thus:

Email Model class

Then I bound a Form View to my model and got rid of everything except the Insert View, thus:

FormView bound to Email model

This allows me to put the following method in the code behind and pass all the work to the business object:

code behind method

That works beautifully, and with MVC-like levels of Separation of Concerns goodness. Now if I just add some Data Annotations…

Data Annotations

I should have validation, too. And I do. But sadly, only on the server side. The page does a full round trip before showing the error messages.

server side validation

So I looked all over to see how I could turn on client side validation… and just couldn’t find it. In the end, I decided it was going to take me less time to write my own version than to find Microsoft’s implementation (if any). So I did so… twice. And in the next couple of posts I’ll look at two different ways of providing client-side Web Form validation using Data Annotations.

Kevin Rattan

For related course information, check out Learning Tree’s course, Building Web Applications with ASP.NET and Ajax.

Validation Issues with jQuery Mobile and ASP.NET MVC

I’ve written before about the peculiarities of ASP.NET MVC validation. It’s a great technology 90% of the time, but can cause issues if you do something a little out of the ordinary. I came across another one of these unusual circumstances recently when I was testing my development version of CocktailsRUs.

I was running through the site checking that upgrading to the latest version of jQuery Mobile hadn’t broken anything when I noticed something interesting – on one page, the validation ran but nothing visual happened to show that it had done so. The validation worked – the page did not submit – but there was nothing to tell the user what had happened.

It turned out there were two issues. One was a twist on the ASP.NET MVC validation issues I mentioned in that earlier post. The other was specific to jQuery Mobile.

The ASP.NET MVC validation issue

Here is a screenshot of the jQuery Mobile page AFTER the validation has run. As you can see – it is not very helpful:

screen shot of no visible validation

So I took a look at the same functionality in the normal Web view, and the result is a little different – but still not what it is supposed to be:

screenshot of partially visible validation

So I had two problems, not one: the highlighting wasn’t working in the mobile version, and the message wasn’t working in either. Time to do a little digging….

Here is the code inside the .cshtml page:

HTML and MVC code sample

The element and the validation attributes have been hard-coded to get around ASP.NET MVC’s problems with validation and repeating forms. Those problems stem from the fact that ASP.NET MVC uses IDs instead of name attributes to hook up validation. This time, however, the problem is that when it comes to displaying the result of the validation, it DOES use name attributes – and you’ll notice that in the code sample above, the “name” does not match the (case-sensitive) “Name” model property in the ValidationMessageFor() method.

So I changed the name attribute value to match the model property…

corrected code sample

And now we have a validation message:

screenshot of visible label

But it’s still not quite right – unlike the Web view, where both highlighting and text are visible:

screenshot of complete validation

The ASP.NET MVC validation and jQuery Mobile search inputs issue

So what’s going on with the search element in jQuery Mobile? We have a working label, but the input itself doesn’t have the usual CSS look and feel to highlight the error. In this case, the problem lies in the way that jQuery Mobile creates the search box.

It turns out that that the “search” input is being converted to a text input, given a wrapping div and (unsurprisingly) all sorts of CSS decoration.

generated html

The upshot is that the standard MVC CSS validation classes can’t compete and are overridden.

So how to fix it? By tweaking the CSS to make the ASP.NET MVC CSS classes more powerful. In this case, I am only using the search type with a very small number of IDs – so I added CSS rules specific to those IDS…

amended CSS

And the problem went away:

completed validation

So – back to coding… until the next interesting little niggle comes along.

Kevin Rattan

For other related information, check out these courses from Learning Tree:

jQuery: A Comprehensive Hands-On Introduction

Building Web Applications with ASP.NET MVC

How to Use ViewModels Without Sacrificing Encapsulation

I have been using ASP.NET MVC extensively over the past year, and the more I use it, the more I like it. However, there remain a couple of things that bug me. One is the fact that the built-in validation doesn’t work with repeating forms. The other is the “best practice” of placing Data Annotations on a ViewModel class.

For me, validation rules belong on the business object itself, not on the ViewModel. One of the key benefits of encapsulation is that we reduce code duplication. If we don’t encapsulate the validation rules inside the object, then we are doomed to repeat them once for every presentation layer. Data Annotations in an MVC ViewModel are not available to a WPF UI. Not only does this lead to redundancy, it increases the risk of inconsistencies cropping up between UI.

So no problem, you might think. All we have to do is add the Data Annotations to the Model itself, and then add the Model as a property of the ViewModel.

Okay, let’s try that.

Here is the Model:

BasicClass simple C# class

And here is the ViewModel:

The ViewModel class

This looks straightforward enough. But look at what happens when we ask Visual Studio to scaffold the View:

View scaffolding

What happened to our “Basic” Model property? It’s not there. The scaffolding only seems to work for simple properties.

Okay, so let’s add the details of the Model to the View. In fact, let’s cheat. We’ll get Visual Studio to scaffold the inner Model for us. First we’ll create a throwaway View. Then we copy the contents of the form and paste it into the View that’s typed to the ViewModel. All we have to do then is change the lambda expressions to point at model.Basic rather than just model:

Full scaffolding

Problem solved. The View now contains the data we need and also respects our data annotations…

This means we can pass the ViewModel through to a Controller method and pick up the Model we need via the ViewModel’s “Basic” property. There’s only one problem:  How do we use the UpdateModel() method when we’re only interested in a property on the object passed to the method, rather than the whole object? Fortunately, Microsoft anticipated the need and there’s an overload on UpdateModel() that allows us to specify a prefix. In this case, not surprisingly, the HTML helpers have inserted the prefix “Basic”:

UpdateModel() with second argument

As you can see, the Model has successfully been bound, so we now have a mechanism for taking advantage of ViewModels without sacrificing encapsulation.

Kevin Rattan

For related information, check out Building Web Applications with ASP.NET MVC from Learning Tree.

Validating That At Least One TextBox Has Content

I came across an interesting little validation problem on my current project. The site is for members only – and in order to become a member, you need to be nominated. You can provide either one or two nominators, but you must provide at least one.

So how to force users to enter text in either of two TextBoxes? RequiredFieldValidators won’t do, because either one can be left empty. Yet at least one must be completed. Clearly this is a job for CustomValidators.

The client-side and server-side code are both fairly straight-forward, but I thought someone out there might find it useful, so here it is.

First of all, the CustomValidators in the ASPX page:


<asp:CustomValidator ID=”Nomination1CustomValidator” runat=”server” Display=”None” ValidateEmptyText=”true” ClientValidationFunction=”CheckNominations” ErrorMessage=”At least one nomination must be provided” ControlToValidate=”Nominated1TextBox” OnServerValidate=”Nomination2CustomValidator_ServerValidate”></asp:CustomValidator>


<asp:CustomValidator ID=”Nomination2CustomValidator” runat=”server” Display=”None” ValidateEmptyText=”true” ClientValidationFunction=”CheckNominations” ErrorMessage=”” ControlToValidate=”Nominated2TextBox” OnServerValidate=”Nomination2CustomValidator_ServerValidate”></asp:CustomValidator>

Note the empty ErrorMessage in the second validator. Combined with display=”none’, that means our ValidationSummary control is only going to display one error message to the user, making it much less confusing. Also notice that ValidateEmptyText is set to true – otherwise, our code will never run.

Then the JavaScript. We’re validating two controls, so even though we use the standard signature the validators are expecting, we’re only interested in the args. I set the TextBoxes’ ClientIDMode to static and used jQuery to get the controls.  (I use jQuery for pretty much all my client-side code).

function CheckNominations(sender, args) {
  if ($(‘#Nominated1TextBox’).val() == “”
      && $(‘#Nominated2TextBox’).val() == “”) {
        args.IsValid = false;
  }
   else {
args.IsValid = true;

   }

}

And, of course, we also need to implement the server-side code for a complete solution:

If String.IsNullOrEmpty(Me.Nominated1TextBox.Text) And
String.IsNullOrEmpty(Me.Nominated2TextBox.Text) Then
        args.IsValid = False
Else
        args.IsValid = True
End If

So now the user must fill in one of the TextBoxes, but can pick either one.  I have been using ASP.NET MVC a lot recently, and it’s nice to go back to Web Forms and see how very easy it is to take built-in controls like the custom validator and use them to meet your specific needs.

Kevin Rattan

For related information, check out these courses from Learning Tree:

Building Web Applications with ASP.NET and Ajax

jQuery: A Comprehensive Hands-On Introduction


Learning Tree International

.NET & Visual Studio Courses

Learning Tree offers over 210 IT training and Management courses, including a full curriculum of .NET training courses.

Free White Papers

Questions on current IT or Management topics? Access our Complete Online Resource Library of over 65 White Papers, Articles and Podcasts

Enter your email address to subscribe to this blog and receive notifications of new posts by e-mail.

Join 29 other followers

Follow Learning Tree on Twitter

Archives

Do you need a customized .NET training solution delivered at your facility?

Last year Learning Tree held nearly 2,500 on-site training events worldwide. To find out more about hosting one at your location, click here for a free consultation.
Live, online training

%d bloggers like this: