Friday, February 11, 2011

Degradable cascading dropdown lists

There are several samples how to create cascading dropdown lists for ASP.NET MVC on the Web. But in my opinion they are overcomplicated. Manual generation of tags, JSON format to pass data from controller to view, using web services instead of usual action methods, all this is unnecessary.

At the same time it's important what users with disabled Javascript could still use cascading dropdown lists on your form.

I will show now how to obtain this.

At first the model. We will use a class Brand defined as:


The overriding of ToString() method allows us to do not explicitly pass dataValueField and dataTextField parameters to SelectList constructor in our views.

Class Repository which will support us with data has these two methods:



Car controller has two versions of Add action for GET and POST methods respectively:


The difference is only what a version for GET method does no validation. You can see what if input data passes validation brandName parameter is cleared and removed from ModelState dictionary to reset a dropdown list with brand names in the form. Of course in a real application new car object will be added to a database here.

Helper private methods are defined as:


And we need one more action method which will be called every time a value in the dropdown with brand names changes:


Now a view markup. Of course we need to add a reference to jquery.validate.min.js script in _Layout.cshtml file where references to other Javascript and CSS files are.

First part of a source of Add.cshtml is here:


Partial view ModelDropDownList looks like:


Both dropdown lists are of required CSS class, so jQuery validation plugin knows what user has to select some value in each of them.

And last but not least, Add.cshtml contains this Javascript code (this is promised second part of a source):


It means what after page is loaded
1) client-side form validation will be started and
2) changing value in the brands dropdown list will lead to AJAX call which refreshes DIV containing models dropdown list with correct markup.

If Javascript is disabled in user's browser it's still possible to select another brand, press submit button, and corresponding models will be rendered on the form.

The result looks like:

Wednesday, February 9, 2011

Adding a row filter to System.Web.Helpers.WebGrid

ASP.NET MVC 3 web grid doesn't have a row filter out of the box but it could be easily added in case of need.

Suppose we have such model:


Passing it to a view with the markup showed below


gives this output


We use autocomplete attribute to tell browser do not store previously used filters thus drop-down list won't hide the grid. Also we have attached onchange event handler which will submit the form every time we change the filter value.

Unfortunately if rows in the grid are sorted somehow, applying a filter resets this order. To keep sort order during form submit we should add two hidden inputs:


To obtain necessary values we make use of SortFieldName, SortColumn, SortDirectionFieldName and SortDirection properties of WebGrid class.

As these field values are passed to WebGrid automatically we need only add filter parameter to controller method and use it, for example, in Enumerable.Where() method:


The grid with applied filter looks like:


WebGrid control is smart enough to add current filter value to URLs in grid's header, so sorting doesn't reset filter!

Friday, February 4, 2011

Unobtrusive validation attributes and ViewContext.FormContext

ASP.NET MVC 3 has a new interesting feature called unobtrusive client validation. For more detailed information you may read an article by Brad Wilson. But in short it means what for an annotated model property like:


HTML helpers render such markup:


and no Javascript code is included into the page except links to external files jquery.js, jquery.validate.js and jquery.validate.unobtrusive.js.

The important thing is what all these attributes with validation rules are rendered only if ViewContext.FormContext property is initialized. It could be done with Html.BeginForm() method called in the beginning or, if you prefer using <form> tag, manually:


You should also avoid situations like the one discussed here: No unobtrusive validation if Html.BeginForm in layout template

Wednesday, February 2, 2011

Valid hash algorithm names for Crypto.Hash method

For unknown reason an algorithm parameter of System.Web.Helpers.Crypto.Hash method is a string instead of an enumeration value.

To learn which algorithms are available you can try using some unusual name and get InvalidOperationException: The hash algorithm 'md51' is not supported, valid values are: sha256, sha1, md5 message.

So, for example, the code


gives


You can check what calculated MD5 hash is the same as here.

Using this method is much simpler than using classes from System.Security.Cryptography namespace, though the latter provides such hash algorithms as AES, RC2, RSA etc.