Skip to main content

11 posts tagged with "asp.net mvc"

View All Tags

NgValidationFor Baby Steps

I thought as I start the NgValidationFor project I'd journal my progress. I'm writing this with someone particular in mind: me. Specifically, me in 2 years who will no doubt wonder why I made some of the choices I did. Everyone else, move along now - nothing to see. Unless the inner workings of someone else's mind are interesting to you... In which case: welcome!

Getting up and running#

I've got a project on GitHub and I'm starting to think about implementations. One thing that bit me on jVUN was being tied to a specific version of ASP.Net MVC. For each major release of ASP.Net MVC I needed separate builds / NuGet packages and the like. A pain. Particularly when it came to bug fixes for prior versions - the breaking changes with each version of MVC meant far more work was required when it came to shipping fixes for MVC 4 / MVC 3.

So with that in mind I'm going to try and limit my dependencies. I'm not saying I will never depend upon ASP.Net MVC - I may if I think it becomes useful to give the users a nicer API or if there's another compelling reason. But to start with I'm just going to focus on the translation of data annotations to Angular validation directive attributes.

To that end I'm going to begin with just a class library and an associated test project. I'm going to try and minimise the dependencies that NgValidationFor has. At least initially I may even see if I can sensibly avoid depending on System.Web (mindful of the upcoming ASP.Net 5 changes). Let's see.

A little time passes.......

So what have we got?#

My first efforts have resulted in the implementation of the <a href="https://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.requiredattribute(v=vs.110).aspx">RequiredAttribute</a>. This is the code right now. It's made up of:

  1. NgValidationFor.Core - the core part of the project which converts data annotations into AngularJS 1.x validation directive attributes.
  2. NgValidationFor.Core.UnitTests - the unit tests for the core
  3. NgValidationFor.Documentation - this is an ASP.Net MVC project which will become a documentation site for NgValidationFor. It also doubles as a way for me to try out NgValidationFor.
  4. NgValidationFor.Documentation.UnitTests - unit tests for the documentation (there's none yet as I'm still spiking - but when I'm a little clearer, they will be)

How can it be used? Well fairly easily. Take this simple model:

using System.ComponentModel.DataAnnotations;
namespace NgValidationFor.Documentation.Models
{
public class RequiredDemoModel
{
[Required]
public string RequiredField { get; set; }
}
}

When used in an MVC View for which RequiredDemoModel is the Model, NgValiditionFor can be used thusly:

@using NgValidationFor.Core
@using NgValidationFor.Documentation.Models
@model RequiredDemoModel
<input type="text"
name="userName"
ng-model="user.name"
@Html.Raw(Model.GetAttributes(x => Model.RequiredField))
>

Which results in this HTML:

<input type="text"
name="userName"
ng-model="user.name"
required="required"
>

Tada!!!! It works.

So what now?#

Yes it works, but I'm not going to pretend it's pretty. I don't like having to wrap the usage of NgValidationFor with Html.Raw(...). I'm having to do that because GetAttributes returns a string. This string is then HTML encoded by MVC. To avoid my quotation marks turning into &amp;quot; I need to actually be exposing an <a href="https://msdn.microsoft.com/en-us/library/system.web.ihtmlstring(v=vs.110).aspx">IHtmlString</a>. So I'm going to need to depend upon System.Web. That's not so bad - at least I'm not tied to a specific MVC version.

I'm not too keen on the implementation I've come up with for NgValidationFor either. It's a single static method at the minute which does everything. It breaks the Single Responsibility Priniciple and the Open/Closed Principle. I need to take a look at that - I want people to be able to extend this and I need to think about a good and simple way to achieve that.

Finally, usage. Model.GetAttributes(x =&gt; Model.RequiredField) feels wrong to me. I think I'm happy with having this used as an extension method but it needs to be clearer what's happening. Perhaps Model.NgValidationFor(x =&gt; Model.RequiredField) would be better. I need to try a few things out and come up with a nicer way to use NgValidationFor.

A tale of Angular, html5mode, ASP.Net MVC and ASP.Net Web API

So. You want to kick hash based routing to the kerb. You want real URLs. You've read the HTML5 mode section of the Angular $location docs and you're good to go. It's just a matter of dropping $locationProvider.html5Mode(true) into your app initialisation right?

Wrong.

You want your URLs to be shareable. If, when you copy the URL out of your browser and send it someone else, they do not get taken to the same position in the application as you do then I've got news for you: THAT'S NOT REALLY A URL. And just using $locationProvider.html5Mode(true) has done nothing useful for you. You want to ensure that, if the URL entered in the browser does not relate to a specific server-side end-point, the self-same HTML root page is always served up. Then Angular can load the correct resources for the URL you have entered and get you to the required state.

There are tips to be found in Angular UI's How to: Configure your server to work with html5Mode doc. However they required a little extra fiddling to get my ASP.Net back end working quite as I wanted. To save you pain, here are my cultural learnings.

ASP.Net MVC#

I had an ASP.Net MVC app which I wanted to use html5mode with. To do this is simply a matter of tweaking your RouteConfig.cs like so:

public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
// Here go the routes that you still want to be able to hit
routes.MapRoute(
name: "IAmARouteThatYouStillWantToHit",
url: "ThatsWhyIAmRegisteredFirst",
defaults: new { controller = "Hittable", action = "Index" }
);
// Everything else will hit Home/Index which serves up the root angular app page
routes.MapRoute(
name: "Default",
url: "{*anything}", // THIS IS THE MAGIC!!!!
defaults: new { controller = "Home", action = "Index" }
);
}

With this in place my existing routes work just as I would hope. Any route that doesn't fit that registered can be assumed to be html5mode related and will serve up the root angular app page as I'd hope.

ASP.Net Web API#

Later I realised that the app in question was mostly static content. Certainly the root angular app page was and so it seemed wasteful to require an ASP.Net MVC controller to serve up that static content. So I stripped out MVC from the app entirely, choosing to serve raw HTML instead. For the dynamic parts I switched to using Web API. This was "hittable" as long as I had my WebApiConfig.cs and my system.webServer section in my web.config lined up correctly, viz:

public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
// other stuff
}
}
<configuration>
<system.webServer>
<defaultDocument>
<files>
<clear />
<add value="build/index.html" /> <!-- This is the root document for the Angular app -->
</files>
</defaultDocument>
<rewrite>
<rules>
<rule name="Main Rule" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<!-- Allows "api/" prefixed URLs to still hit Web API controllers
as defined in WebApiConfig -->
<add input="{REQUEST_URI}" pattern="api/" ignoreCase="true" negate="true" />
<!-- Static files and directories can be served so partials etc can be loaded -->
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="/" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>

With this in place I can happily hit "api" prefixed URLs and still land on my Web API controllers whilst other URLs will serve up the root angular app page. Lovely.

Tonight I'll Start an Open Source Project...

Further posts on this topic#

I'm excited. Are you? I'm babysitting for a friend, I've my laptop, time to kill and (crucially) an idea...

The Idea#

You're likely aware of the various form element directives that AngularJS offers. For instance the input directive:

HTML input element control. When used together with ngModel, it provides data-binding, input state control, and validation.

You'll notice that I emphasised the word "validation" there. That's important - that's my idea. I'm using AngularJS to build SPA's and for the server side I'm using ASP.Net MVC / Web API. Crucially, my templates are actually ASP.Net MVC Partial Views. That's key.

When I send data back from my SPA back to the server it gets unmarshalled / deserialized into a C# class (view model) of some kind. When data goes the other way it's flowing back from a JSON'd view model and being used by my Angular code.

Now historically if I was building a fairly vanilla MVC app then I'd be making use of all the TextboxFor extension methods etc to generate my input elements. For example, with a view model like this:

using System.ComponentModel.DataAnnotations;
namespace App.ViewModels
{
public class RequiredModel
{
[Required]
public string RequiredField{ get; set; }
}
}

I'd have a view like this:

@model App.ViewModels.RequiredModel
@using (Html.BeginForm())
{
<div class="row">
@Html.LabelFor(x => x.TextBox, "Something must be entered:")
@Html.TextBoxFor(x => x.TextBox, true)
</div>
}

And that would generate HTML like this:

<form action="/Demo/Required" method="post">
<div class="row">
<label for="TextBox">Something must be entered:</label>
<input data-msg-required="The TextBox field is required."
data-rule-required="true"
id="TextBox" name="TextBox" type="text" value="" />
</div>
</form>

If you look at the HTML you'll see that the Required data annotations have been propogated into the HTML in the HTML in the form of data-rule-* and data-msg-* attributes. The code above is built using my jQuery.Validation.Unobtrusive.Native project which in turn was inspired by / based upon the Unobtrusive Client Validation in ASP.NET MVC. That's right - I've done this before - or at least something quite like it.

There's clearly a strong crossover between AngularJS's input directive parameters and unobtrusive client validation. I'm planning to take the principles (and maybe some of the code) that I used on that project and see if I can't make something useful with it here. Server side validation is jolly important but I can probably save a few compute cycles on the server by making use of client side validation as well. If I'm right then I should able to come up with a mechanism that saves me from manually duplicating my server validation on the client.

The Aim#

I want to be able to use HTML Helpers to propogate validation metadata from the server view models into angular form validation directive attributes. Quite a mouthful I know. What does that actually mean? Well I've got 2 ideas. Possibly I want to be able to code something like this:

@model App.ViewModels.RequiredModel
@using (Html.BeginForm())
{
<div class="row">
@Html.LabelFor(x => x.TextBox, "Something must be entered:")
@Html.NgTextBoxFor(x => x.TextBox)
</div>
}

And have HTML like this generated:

<form action="/Demo/Required" method="post">
<div class="row">
<label for="TextBox">Something must be entered:</label>
<input
ng-required="true"
id="TextBox" name="TextBox" type="text" value="" />
</div>
</form>

The reservation I have about this approach is that it rather takes you away from the HTML. Yes it works (and to your seasoned MVC-er it will feel quite natural in some ways) but it feels rather heavy handed. But I'd like what I'm building to be easy for users to plug into existing code without a ton of rework. So, the other idea I'm toying with is having HTML helpers that just return a string of attributes. So if I had an angular form that looked like this:

<div ng-controller="ExampleController">
<form>
<div class="row">
<label>Something must be entered:
<input name="RequiredField" type="text" value="" />
</label>
</div>
</form>

I could tweak it to push in the validation directive attributes like this:

@model App.ViewModels.RequiredModel
<div ng-controller="ExampleController">
<form>
<div class="row">
<label>Something must be entered:
<input name="RequiredField" type="text" value="" @Html.NgValidationFor(x => x.RequiredField) />
</label>
</div>
</form>

And end up with HTML like this:

<div ng-controller="ExampleController">
<form>
<div class="row">
<label>Something must be entered:
<input name="RequiredField" type="text" value="" ng-required="true" />
</label>
</div>
</form>

This is a simplified example of course - it's likely that any number of validation directive attributes might be returned from NgValidationFor. And crucially if these attributes were changed on the server view model then the validation changes would automatically end up in the client HTML with this approach.

The Approach#

At least to start off with I'm going to aim at creating the second of my approaches. I may come back and implement the first at some point but I think the second is a better place to start.

I'm kind of surprised no-one else has built this already actually - but I'm not aware of anything. I've had a little duckduckgo around and found no takers. The closest I've come is the excellent BreezeJS. BreezeJS does way more than I want it to - I'm planning to restrict the scope of this project to simply turning data annotations on my ASP.Net MVC server models into ng-* directive attributes in HTML. That's it.

So, general housekeeping.... I'm going to host this project on GitHub, I'm going to have Continuous Integration with AppVeyor and I'm planning to publish this via NuGet (when and if I've created something useful).

I just need a name and I'll begin. What shall I call it? Some options:

  • Angular ASP.Net MVC Extensions
  • angular-aspnet-mvc-extensions
  • Angular MVC Element Extensions
  • Angular Validation Html Helpers
  • NgValidationFor (the name of the HTML helper I made up)

Hmmmm.... None of them is particularly lighting my fire. The first four are all a bit RonSeal - which is fine.... Ug. The last one... It's a bit more pithy. Okay - I'll go with "NgValidationFor" at least for now. If something better occurs I can always change my mind.

And we're off!

PartialView.ToString()

In the name of DRY I found myself puzzling how one could take a PartialViewResult and render it as a string. Simple, right?

In fact, in my head this was already a solved problem. I mean I've written about this before already! Except I haven't. Not really - what I did back then was link to what someone else had written and say "yay! well done chap - like he said!". It turns out that was a bad move. That blog appears to be gone and so I'm back to where I was. Ug. Lesson learned.

What are we trying to do?#

So, for the second time of asking, here is how to take a PartialViewResult and turn it into a string. It's an invaluable technique to deal with certain scenarios.

In my own case I have a toolbar in my application that is first pushed into the UI in my _Layout.cshtml by means of a trusty @Html.Action("Toolbar"). I wanted to be able to re-use the PartialViewResult returned by Toolbar on my controller inside a JSON payload. And despite the title of this post, PartialView.ToString()doesn't quite cut the mustard. Obvious really, if it did then why would I be writing this and you be reading this?

The solution is actually fairly simple. And, purely for swank, I'm going to offer it you 3 ways. Whatever's your poison.

Inheritance (it's so yesterday darling)#

Yes there was a time when everything was inheritance based. You were rewarded handsomely for making sure that was the case. However, times have changed and (with good reason) people tend to favour composition over inheritance. So, perhaps just for the memories, let first offer you the inheritance based approach:

protected string ConvertPartialViewToString(PartialViewResult partialView)
{
using (var sw = new StringWriter())
{
partialView.View = ViewEngines.Engines
.FindPartialView(ControllerContext, partialView.ViewName).View;
var vc = new ViewContext(
ControllerContext, partialView.View, partialView.ViewData, partialView.TempData, sw);
partialView.View.Render(vc, sw);
var partialViewString = sw.GetStringBuilder().ToString();
return partialViewString;
}
}

The idea being that the above method is placed onto a base controller which your controllers subclass. Thus using this method inside one of the controllers is as simple as:

var toolbarHtml = ConvertPartialViewToString(partialViewResult);

Extension method (sexier syntax)#

So the next choice is implementing this as an extension method. Here's my static class which adds ConvertToString onto PartialViewResult:

using System.IO;
using System.Web.Mvc;
namespace My.Utilities.Extensions
{
public static class PartialViewResultExtensions
{
public static string ConvertToString(this PartialViewResult partialView,
ControllerContext controllerContext)
{
using (var sw = new StringWriter())
{
partialView.View = ViewEngines.Engines
.FindPartialView(controllerContext, partialView.ViewName).View;
var vc = new ViewContext(
controllerContext, partialView.View, partialView.ViewData, partialView.TempData, sw);
partialView.View.Render(vc, sw);
var partialViewString = sw.GetStringBuilder().ToString();
return partialViewString;
}
}
}
}

I don't know about you but I do love an extension method - it often makes for much more readable code. In this case we can use:

var toolbarHtml = partialViewResult.ConvertToString(ControllerContext);

Which I think we can all agree is really rather lovely. Perhaps it would be more lovely if I didn't have to pass ControllerContext - but hey! Still quite nice.

Favouring Composition over Inheritance (testable)#

Although ASP.Net MVC was designed to be testable there are times when you think "really? Can it be that hard?". In fact for a well thought through discussion on the topic I advise you read this. (I'm aware of the irony implicit in linking to another blog post in a blog post that I only wrote because I first linked to another blog which vanished.... Infinite recursion anybody?)

The conclusion of the linked blog post is twofold

  1. Don't mock HTTPContext
  2. Use the facade pattern instead

Having testable code is not a optional bauble in my view - it's a necessity. So with my final approach that's exactly what I'll do.

using System.Web.Mvc;
namespace My.Interfaces
{
public interface IMvcInternals
{
string ConvertPartialViewToString(PartialViewResult partialView, ControllerContext controllerContext);
}
}
// ....
using System.IO;
using System.Web.Mvc;
using My.Interfaces;
namespace My.Utilities
{
public class MvcInternals : IMvcInternals
{
public string ConvertPartialViewToString(PartialViewResult partialView,
ControllerContext controllerContext)
{
using (var sw = new StringWriter())
{
partialView.View = ViewEngines.Engines
.FindPartialView(controllerContext, partialView.ViewName).View;
var vc = new ViewContext(
controllerContext, partialView.View, partialView.ViewData, partialView.TempData, sw);
partialView.View.Render(vc, sw);
var partialViewString = sw.GetStringBuilder().ToString();
return partialViewString;
}
}
}
}

So here I have a simple interface with a ConvertPartialViewToString method on it. This interface can be passed into a controller and then used like this:

var toolbarHtml = _mvcInternals.ConvertPartialViewToString(partialViewResult, ControllerContext);

Ah... that's the sweet mellifluous sound of easily testable code.

How I'm Using Cassette part 1:Getting Up and Running

Backing into the light#

For a while now, I've been seeking a bulletproof way to handle the following scenarios... all at the same time in the context of an ASP.Net MVC application:

  1. How to serve full-fat JavaScript in debug mode and minified in release mode
  2. When debugging, ensure that the full-fat JS being served is definitely the latest version; and *not* from the cache. (The time I've wasted due to 304's...)
  3. How to add Javascript assets that need to be served up from any point in an ASP.Net MVC application (including views, layouts, partial views... even controllers if so desired) whilst preventing duplicate scripts from being served.
  4. How to ensure that Javascript files are served up last to any web page to ensure a speedy feel to users (don't want JS blocking rendering).
  5. And last but certainly not least the need to load Javascript files in dependency order. If myView.js depends on jQuery then clearly jQuery-latest.js needs to be served before myView.js.

Now the best, most comprehensive and solid looking solution to this problem has for some time seemed to me to be Andrew Davey'sCassette. This addresses all my issues in one way or another, as well as bringing in a raft of other features (support for Coffeescript etc).

However, up until now I've slightly shied away from using Cassette as I was under the impression it had a large number of dependencies. That doesn't appear to be the case at all. I also had some vague notion that I could quite simply build my own solution to these problems making use of Microsoft's Web Optimization which nicely handles my #1 problem above. However, looking again at the documentation Cassette was promising to handle scenarios #1 - #5 without breaking sweat. How could I ignore that? I figured I should do the sensible thing and take another look at it. And, lo and behold, when I started evaluating it again it seemed to be just what I needed.

With the minumum of fuss I was able to get an ASP.Net MVC 4 solution up and running, integrated with Cassette, which dealt with all my scenarios very nicely indeed. I thought it might be good to write this up over a short series of posts and share what my finished code looks like. If you follow the steps I go through below it'll get you started using Cassette. Or you could skip to the end of this post and look at the repo on GitHub. Here we go...

Adding Cassette to a raw MVC 4 project#

Fire up Visual Studio and create a new MVC 4 project (I used the internet template to have some content in place).

Go to the Package Manager Console and key in "Install-Package Cassette.Aspnet". Cassette will install itself.

Now you've got Cassette in place you may as well pull out usage of Web Optimization as you're not going to need it any more.Be ruthless, delete App_Start/BundleConfig.cs and delete the line of code that references it in Global.asax.cs. If you take the time to run the app now you'll see you've miraculously lost your CSS and your JavaScript. The code referencing it is still in place but there's nothing for it to serve up. Don't worry about that - we're going to come back and Cassette-ify things later on...

You'll also notice you now have a CassetteConfiguration.cs file in your project. Open it. Replace the contents with this (I've just commented out the default code and implemented my own CSS and Script bundles based on what is available in the default template of an MVC 4 app):

In the script above I've created 4 bundles, 1 stylesheet bundle and 3 JavaScript bundles - each of these is roughly equivalent to Web Optimization bundles that are part of the MVC 4 template:

~/bundles/css
Our site CSS - this includes both our own CSS and the jQuery UI CSS as well. This is the rough equivalent of the Web Optimization bundles ~/Content/css and ~/Content/themes/base/css brought together.
~/bundles/head
What scripts we want served in the head tag - Modernizr basically. Do note the setting of the PageLocation property - the purpose of this will become apparent later. This is the direct equivalent of the Web Optimization bundle: ~/bundles/modernizr.
~/bundles/core
The scripts we want served on every page. For this example project I've picked jQuery and jQuery UI. This is the rough equivalent of the Web Optimization bundles ~/bundles/jquery and ~/bundles/jqueryui brought together.
~/bundles/validate
The validation scripts (that are dependent on the core scripts). This is the rough equivalent of the Web Optimization bundle: ~/bundles/jqueryval.

At this point we've set up Cassette in our project - although we're not making use of it yet. If you want to double check that everything is working properly then you can fire up your project and browse to "Cassette.axd" in the root. You should see something a bit like this:

How Web Optimization and Cassette Differ#

If you're more familiar with the workings of Web Optimization than Cassette then it's probably worth taking a moment to appreciate an important distinction between the slightly different ways each works.

Web Optimization

  1. Create bundles as desired.
  2. Serve up bundles and / or straight JavaScript files as you like within your MVC views / partial views / layouts.

Cassette

  1. Create bundles for *all* JavaScript files you wish to serve up. You may wish to create some bundles which consist of a number of a number of JavaScript files pushed together. But for each individual file you wish to serve you also need to create an individual bundle. (Failure to do so may mean you fall prey to the "Cannot find an asset bundle containing the path "~/Scripts/somePath.js".")
  2. Reference bundles and / or individual JavaScript files in their individual bundles as you like within your MVC views / partial views / layouts / controllers / HTML helpers... the list goes on!
  3. Render the referenced scripts to the page (typically just before the closing body tag)

Making use of our Bundles#

Now we've created our bundles let's get the project serving up CSS and JavaScript using Cassette. First the layout file. Take the _Layout.cshtml file from this:

To this:

And now let's take one of the views, Login.cshtml and take it from this:

To this:

So now you should be up and running with Cassette. If you want the code behind this then take I've put it on GitHub here.

Unit testing ModelState

  • Me: "It can't be done"
  • Him: "Yes it can"
  • Me: "No it can't"
  • Him: "Yes it can, I've just done it"
  • Me: "Ooooh! Show me ..."

The above conversation (or one much like it) took place between my colleague Marc Talary and myself a couple of weeks ago. It was one of those faintly embarrassing situations where you state your case with absolute certainty only to subsequently discover that you were *completely* wrong. Ah arrogance, thy name is Reilly...

The disputed situation in this case was ModelState validation in ASP.Net MVC. How can you unit test a models validation driven by DataAnnotations? If at all. Well it can be done, and here's how.

Simple scenario#

Let's start with a simple model:

And let's have a controller which makes use of that model:

When I was first looking at unit testing this I was slightly baffled by the behaviour I witnessed. I took an invalid model (where the properties set on the model were violating the model's validation DataAnnotations):

I passed the invalid model to the Edit controller action inside a unit test. My expectation was that the ModelState.IsValid code path would *not* be followed as this was *not* a valid model. So ModelState.IsValid should evaluate to false, right? Wrong!

Contrary to my expectation the validity of ModelState is not evaluated on the fly inside the controller. Rather it is determined during the model binding that takes place *before* the actual controller action method is called. And that completely explains why during my unit test with an invalid model we find we're following the ModelState.IsValid code path.

Back to the dispute#

As this blog post started off I was slightly missing Marc's point. I thought he was saying we should be testing the ModelState.IsValid == false code path. And given that ModelState is determined before we reach the controller my view was that the only way to achieve this was through making use of ModelState.AddModelError in our unit test (you can read a good explanation of that here). And indeed we were already testing for this; we were surfacing errors via a JsonResult and so had a test in place to ensure that ModelState errors were transformed in the manner we would expect.

However, Marc's point was actually that we should have unit tests that enforced our design. That is to say, if we'd decided a certain property on a model was mandatory we should have a test that checked that this was indeed the case. If someone came along later and removed the Required data annotation then we wanted that test to fail.

It's worth saying, we didn't want a unit test to ensure that ASP.Net MVC worked as expected. Rather, where we had used DataAnnotations against our models to drive validation, we wanted to ensure the validation didn't disappear further down the track. Just to be clear: we wanted to test our code, not Microsoft's.

Now I get to learn something#

When I grasped Marc's point I thought that the the only way to write these tests would be to make use of reflection. And whilst we could certainly do that I wasn't entirely happy with that as a solution. To my mind it was kind of testing "at one remove", if you see what I mean. What I really wanted was to see that MVC was surfacing validations in the manner I might have hoped. And you can!

.... Drum roll... Ladies and gents may I present Marc's ModelStateTestController:

This class is, as you can see, incredibly simple. It is a controller, it inherits from System.Web.Mvc.Controller and establishes a mock context in the constructor using MOQ. This controller exposes a single method: TestTryValidateModel. This method internally determines the controller's ModelState given the supplied object by calling off to Mvc's (protected) TryValidateModel method (TryValidateModel evaluates ModelState).

This simple class allows us to test the validations on a model in a simple fashion that stays close to the way our models will actually be used in the wild. It's pragmatic and it's useful.

An example#

Let me wrap up with an example unit test. The test below makes use of the ModelStateTestController to check the application of the DataAnnotations on our model:

Wrapping up#

In a way I think it's a shame that TryValidateModel is a protected method. If it weren't it would be simplicity to write a unit test which tested the ModelState directly in context of the action method. It would be possible to get round this by establishing a base controller class which all our controllers would inherit from which implemented the TestTryValidateModel method from above. On the other hand maybe it's good to have clarity of the difference between testing model validations and testing controller actions. Something to ponder...

Twitter.Bootstrap.MVC4 meet Bootstrap Datepicker

Update 14/01/2013#

Since I wrote this I've taken things on a little further - to read about that go here.

Getting Responsive#

It's the new year, it's time for new things. Long on my list of "things to do" was getting up to speed with Responsive web design. No doubt like everyone else I've been hearing more and more about this over the last year (by the way there was a good article on Mashable about this last month). RWD (in case you don't already know) is pretty much about having web interfaces that format their presentation based on the device they're running to provide a good user experience. (I kind of think of it as a write once, run anywhere approach - though hopefully without the negative connotations...)

Rather than diving straight in myself I'd heard at a user group that it might be worth taking Twitter Bootstrap as a baseline. I'm a lazy

busy fellow so this sounded ideal.

I like ASP.Net MVC...#

... and this flavoured my investigations. I quickly stumbled on an article written by Eric Hexter. Eric had brought together Twitter Bootstrap and ASP.Net MVC 4 in a NuGet package. Excellent work chap!

To get up and running with Eric's work was a straightforward proposition. I...

  1. Created new MVC 4 application in Visual Studio called 鈥淏ootstrapMvcSample鈥 using the 鈥淓mpty鈥 Project Template.

  2. Executed the following commands at the NuGet Package Manager Console: - Install-Package twitter.bootstrap.mvc4

    • Install-Package twitter.bootstrap.mvc4.sample

Check out the responsive goodness I had when I ran it:

This is just 1 page, with @media queries doing the heavy lifting.

Bootstrap Datepicker#

The eagle-eyed amongst you will have noticed that the edit screen above features a date field. I've long been a fan of datepickers to allow users to enter a date in an application in an intuitive fashion. Until native browser datepickers become the norm we'll be relying on some kind of component. Up until now my datepicker of choice has been the jQuery UI one. Based on a quick Google it seemed that jQuery UI and Twitter Bootstrap were not necessarily natural bedfellows. (Though Addy Osmani's jQuery UI Bootstrap shows some promise...)

Since I feared ending up down a blind alley I found myself casting around for a Twitter Bootstrap datepicker. I quickly happened upon Stefan Petre's Bootstrap Datepicker which looked just the ticket.

Shake hands and play nice...#

Incorporating the Bootstrap Datepicker into Twitter.Bootstrap.MVC4 was actually a pretty straightforward affair. I added the following datepicker assets to the ASP.Net MVC project as follows:

  • bootstrap-datepicker.js was added to ~\Scripts.
  • datepicker.css was added to ~\Content. I renamed this file to bootstrap-datepicker.css to stay in line with the other css files.

Once this was done I amended the BootstrapBundleConfig.cs bundles to include these assets. Once this was done the bundle file looked like this:

I then created this folder:~\Views\Shared\EditorTemplates. To this folder I added the following Date.cshtml Partial to hold the datepicker EditorTemplate: (Having this in place meant that properties with the [DataType(DataType.Date)] attribute would automatically use this EditorTemplate when rendering an editor - I understand [UIHint] attributes can be used to the same end.)

And finally I amended the Create.cshtml View (which perhaps more accurately might be called the Edit View?) to include a bit of JavaScript at the bottom to initialise any datepickers on the screen.

Et voil脿 - it works!

My thanks to Eric Hexter and Stefan Petre for doing all the hard work!

Still to do#

I haven't really tested how this all fits together (if at all) with browsers running a non-English culture. There may still be a little tinkering require to get that working...

Globalize and jQuery Validation

Update 05/10/2015#

If you're after a version of this that works with Globalize 1.x then take a look here.

Update 27/08/2013#

To make it easier for people to use the approach detailed in this post I have created a repository for jquery.validate.globalize.js on GitHub here.

This is also available as a nuget package here.

To see a good demo take a look here.

Background#

I've written before about a great little library called Globalize which makes locale specific number / date formatting simple within JavaScript. And I've just stumbled upon an old post written by Scott Hanselman about the business of Globalisation / Internationalisation / Localisation within ASP.NET. It's a great post and I recommend reading it (I'm using many of the approaches he discusses).

jQuery Global is dead... Long live Globalize!#

However, there's one tweak I would make to Scotts suggestions and that's to use Globalize in place of the jQuery Global plugin. The jQuery Global plugin has now effectively been reborn as Globalize (with no dependancy on jQuery). As far as I can tell jQuery Global is now disappearing from the web - certainly the link in Scotts post is dead now at least. I've ripped off been inspired by the "Globalized jQuery Unobtrusive Validation" section of Scotts article and made jquery.validate.globalize.js.

And for what it's worth jquery.validate.globalize.js applies equally to standard jQuery Validation as well as to jQuery Unobtrusive Validation. I say that as the above JavaScript is effectively a monkey patch to the number / date / range / min / max methods of jQuery.validate.js which forces these methods to use Globalize's parsing support instead.

Here's the JavaScript:

The above script does 2 things. Firstly it monkey patches jquery.validate.js to make use of Globalize.js number and date parsing in place of the defaults. Secondly it initialises Globalize to relevant current culture driven by the html lang property. So if the html tag looked like this:

<html lang="de-DE">
...
</html>

Then Globalize would be initialised with the "de-DE" culture assuming that culture was available and had been served up to the client. (By the way, the Globalize initialisation logic has only been placed in the code above to demonstrate that Globalize needs to be initialised to the culture. It's more likely that this initialisation step would sit elsewhere in a "proper" app.)

Wait, where's html lang getting set?#

In Scott's article he created a MetaAcceptLanguage helper to generate a META tag like this: &lt;meta name="accept-language" content="en-GB" /&gt; which he used to drive Globalizes specified culture.

Rather than generating a meta tag I've chosen to use the lang attribute of the html tag to specify the culture. I've chosen to do this as it's more in line with the W3C spec. But it should be noted this is just a different way of achieving exactly the same end.

So how's it getting set? Well, it's no great shakes; in my _Layout.cshtml file my html tag looks like this:

<html lang="@System.Globalization.CultureInfo.CurrentUICulture.Name">

And in my web.config I have following setting set:

<configuration>
<system.web>
<globalization culture="auto" uiCulture="auto" />
<!--- Other stuff.... -->
</system.web>
</configuration>

With both of these set this means I get &lt;html lang="de-DE"&gt; or &lt;html lang="en-GB"&gt; etc. depending on a users culture.

Serving up the right Globalize culture files#

In order that I send the correct Globalize culture to the client I've come up with this static class which provides the user with the relevant culture URL (falling back to the en-GB culture if it can't find one based your culture):

Putting it all together#

To make use of all of this together you'll need to have the html lang attribute set as described earlier and some scripts output in your layout page like this:

<script src="@Url.Content("~/Scripts/jquery.js")" type="text/javascript"></script>
<script src="@Url.Content(GlobalizeUrls.Globalize)" type="text/javascript"></script>
<script src="@Url.Content(GlobalizeUrls.GlobalizeCulture)" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="@Url.Content("~/scripts/jquery.validate.globalize.js")" type="text/javascript"></script>
@* Only serve the following script if you need it: *@
<script src="@Url.Content("~/scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>

Which will render something like this:

<script src="/Scripts/jquery.js" type="text/javascript"></script>
<script src="/Scripts/globalize.js" type="text/javascript"></script>
<script src="/scripts/globalize/globalize.culture.en-GB.js" type="text/javascript"></script>
<script src="/Scripts/jquery.validate.js" type="text/javascript"></script>
<script src="/Scripts/jquery.validate.globalize.js" type="text/javascript"></script>
<script src="/Scripts/jquery.validate.unobtrusive.js" type="text/javascript"></script>

This will load up jQuery, Globalize, your Globalize culture, jQuery Validate, jQuery Validates unobtrusive extensions (which you don't need if you're not using them) and the jQuery Validate Globalize script which will set up culture aware validation.

Finally and just to re-iterate, it's highly worthwhile to give Scott Hanselman's original article a look. Most all the ideas in here were taken wholesale from him!

How to attribute encode a PartialView in MVC (Razor)

This post is plagiarism. But I'm plagiarising myself so I don't feel too bad.

I posted a question on StackOverflow recently asking if there was a simple way to attribute encode a PartialView in Razor / ASP.NET MVC. I ended up answering my own question and since I thought it was a useful solution it might be worth sharing.

The Question#

In the project I was working on I was using PartialViews to store the HTML that would be rendered in a tooltip in my ASP.NET MVC application. (In case you're curious I was using the jQuery Tools library for my tooltip effect.)

I had thought that Razor, clever beast that it is, would automatically attribute encode anything sat between quotes in my HTML. Unfortunately this doesn't appear to be the case. In the short term I was able to workaround this by using single quotation marks to encapsulate my PartialViews HTML. See below for an example:

<div class="tooltip"
title='@Html.Partial("_MyTooltipInAPartial")'>
Some content
</div>

Now this worked just fine but I was aware that if any PartialView needed to use single quotation marks I would have a problem. Let's say for a moment that _MyTooltipInAPartial.cshtml contained this:

<span style="color:green">fjkdsjf'lksdjdlks</span>

Well when I used my handy little single quote workaround, the following would result:

<div class="tooltip"
title='<span style="color:green">fjkdsjf'lksdjdlks</span>'>
Some content
</div>

Which although it doesn't show up so well in the code sample above is definite "does not compute, does not compute, does not compute *LOUD EXPLOSION*" territory.

The Answer#

This took me back to my original intent which was to encapsulate the HTML in double quotes like this:

<div class="tooltip"
title="@Html.Partial("_MyTooltipInAPartial")">
Some content
</div>

Though with the example discussed above we clearly had a problem whether we used single or double quotes. What to do?

Well the answer wasn't too complicated. After a little pondering I ended up scratching my own itch by writing an HTML helper method called PartialAttributeEncoded which made use of HttpUtility.HtmlAttributeEncode to HTML attribute encode a PartialView.

Here's the code:

Using the above helper is simplicity itself:

<div class="tooltip"
title="@Html.PartialAttributeEncoded("_MyTooltipInAPartial")">
Some content
</div>

And, given the example I've been going through, it would provide you with this output:

<div class="tooltip"
title="&lt;span style=&quot;color:green&quot;>fjkdsjf&#39;lksdjdlks</span>">
Some content
</div>

Now the HTML in the title attribute above might be an unreadable mess - but it's the unreadable mess you need. That's what the HTML we've been discussing looks like when it's been encoded.

Final thoughts#

I was surprised that Razor didn't handle this out of the box. I wonder if this is something that will come along with a later version? It's worth saying that I experienced this issue when working on an MVC 3 application. It's possible that this issue may actually have been solved with MVC 4 already; I haven't had chance to check yet though.

Rendering Partial View to a String

Well done that man!#

Every now and then I'm thinking to myself "wouldn't it be nice if you could do x..." And then I discover that someone else has thought the self same thoughts and better yet they have the answer! I had this situation recently and discovered the wonderful Kevin Craft had been there, done that and made the T-shirt. Here's his blog: http://craftycodeblog.com/2010/05/15/asp-net-mvc-render-partial-view-to-string/ I wanted to talk about how this simple post provided me with an elegant solution to something I've found niggling and unsatisfactory for a while now... ## How it helped

Just last week I was thinking about Partial Views. Some background. I'm working on an ASP.NET MVC 3 project which provides users with a nice web interface to manage the workflow surrounding certain types of financial asset. The user is presented with a web page which shows a kind of grid to the user. As the user hovers over a row they are presented with a context menu which allows them to perform certain workflow actions. If they perform an action then that row will need to be updated to reflect this. Back in the day this would have been achieved by doing a full postback to the server. At the server the action would be taken, the persistent storage updated and then the whole page would be served up to the user again with the relevant row of HTML updated but everything else staying as is. Now there's nothing wrong with this approach as such. I mean it works just fine. But in my case since I knew that it was only that single row of HTML that was going to be updated and so I was loath to re-render the whole page. It seemed a waste to get so much data back from the server when only a marginal amount was due to change. And also I didn't want the user to experience the screen refresh flash. Looks ugly. Now in the past when I've had a solution to this problem which from a UI perspective is good but from a development perspective slightly unsatisfactory. I would have my page call a controller method (via jQuery.ajax) to perform the action. This controller would return a JsonResult indicating success or failure and any data necessary to update the screen. Then in the success function I would manually update the HTML on the screen using the data provided. Now this solution works but there's a problem. Can you tell what it is yet? It's not very DRY. I'm repeating myself. When the page is initially rendered I have a View which renders (in this example) all the relevant HTML for the screen *including* the HTML for my rows of data. And likewise I have my JavaScript method for updating the screen too. So with this solution I have duplicated my GUI logic. If I update 1, I need to update the other. It's not a massive hardship but it is, as I say, unsatisfactory. I was recently thinking that it would be nice if I could refactor my row HTML into a Partial View which I could then use in 2 places: 1. In my standard View as I iterated through each element for display and 2. Nested inside a JsonResult...

The wonderful thing about approach 2 is that it allows me to massively simplify my success to this: ```js $("myRowSelector") .empty() .html(data.RowHTML); //Where RowHTML is the property that //contains my stringified PartialView

and if I later make changes to the `Partial View` these changes will not require me to make any changes to my JavaScript at all. Brilliant! And entirely satisfactory. On the grounds that someone else might have had the same idea I did a little googling around. Sure enough I discovered [Kevin Craft's post](<http://craftycodeblog.com/2010/05/15/asp-net-mvc-render-partial-view-to-string/>) which was just the ticket. It does exactly what I'd hoped. Besides being a nice and DRY solution this approach has a number of other advantages as well: - Given it's a `Partial View` the Visual Studio IDE provides a nice experience when coding it up with regards to intellisense / highlighting etc. Not something available when you're hand coding up a string which contains the HTML you'd like passed back...
- A wonderful debug experience. You can debug the rendering of a `Partial View` being rendered to a string in the same way as if the ASP.NET MVC framework was serving it up. I could have lived without this but it's fantastic to have it available.
- It's possible to nest \***multiple**\* `Partial Views` within your `JsonResult`. THIS IS WONDERFUL!!! This means that if several parts of your screen need to be updated (perhaps the row and a status panel as well) then as long as both are refactored into a `Partial View` you can generate them on the fly and pass them back.
<!-- -->
Excellent stuff!

Optimally Serving Up JavaScript

I have occasionally done some server-side JavaScript with Rhino and Node.js but this is the exception rather than the rule. Like most folk at the moment, almost all the JavaScript I write is in a web context.

Over time I've come to adopt a roughly standard approach to how I structure my JavaScript; both the JavaScript itself and how it is placed / rendered in the an HTML document. I wanted to write about the approach I'm using. Partly just to document the approach but also because I often find writing about something crystalises my feelings on the subject in one way or another. I think that most of what I'm doing is sensible and rational but maybe as I write about this I'll come to some firmer conclusions about my direction of travel.

What are you up to?#

Before I get started it's probably worth mentioning the sort of web development I'm generally called to do (as this has obviously influenced my decisions).

Most of my work tends to be on web applications used internally within a company. That is to say, web applications accessible on a Company intranet. Consequently, the user base for my applications tends to be smaller than the Amazons and Googles of this world. It almost invariably sits on the ASP.NET stack in some way. Either classic WebForms or MVC.

"Render first. JS second."#

I took 2 things away from Steve Souder's article:

  1. Async script loading is better than synchronous script loading
  2. Get your screen rendered and *then* execute your JavaScript

I'm not doing any async script loading as yet; although I am thinking of giving it a try at some point. In terms of choosing a loader I'll probably give RequireJS first crack of the whip (purely as it looks like most people are tending it's direction and that can't be without reason).

However - it seems that the concept of async script loading is kind of conflict with one of the other tenets of web wisdom: script bundling. Script bundling, if you're not already aware, is the idea that you should combine all your scripts into a single file and then just serve that. This prevents multiple HTTP requests as each script loads in. Async script loading is obviously okay with multiple HTTP requests, presumably because of the asynchronous non-blocking pattern of loading. So. 2 different ideas. And there's further movement on this front right now as Microsoft are baking in script bundling to .NET 4.5.

Rather than divide myself between these 2 horses I have at the moment tried to follow the "JS second" part of this advice in my own (perhaps slightly old fashioned) way...

I want to serve you...#

I have been making sure that scripts are the last thing served to the screen by using a customised version of Michael J. Ryan's HtmlHelper. This lovely helper allows you to add script references as required from a number of different sources (layout page, view, partial view etc - even the controller if you so desired). It's simple to control the ordering of scripts by allowing you to set a priority for each script which determines the render order.

Then as a final step before rendering the &lt;/body&gt; tag the scripts can be rendered in one block. By this point the web page is rendered visually and a marginal amount of blocking is, in my view, acceptable.

If anyone is curious - the class below is my own version of Michael's helper. My contribution is the go faster stripes relating to the caching suffix and the ability to specify dependancies using script references rather than using numeric priority mechanism):

Minification - I want to serve you less...#

Another tweak I made to the script helper meant that when compiling either the debug or production (minified) versions of common JS files will be included if available. This means in a production environment the users get minified JS files so faster loading. And in a development environment we get the full JS files which make debugging more straightforward.

What I haven't started doing is minifying my own JS files as yet. I know I'm being somewhat inconsistent here by sometimes serving minified files and sometimes not. I'm not proud. Part of my rationale for this that since most of my users use my apps on a daily basis they will for the most part be using cached JS files. Obviously there'll be slightly slower load times the first time they go to a page but nothing that significant I hope.

I have thought of starting to do my own minification as a build step but have held off for now. Again this is something being baked into .NET 4.5; another reason why I have held off doing this a different way for now.

Update

It now looks like this Microsofts optimisations have become this Nuget package. It's early days (well it was released on 15th August 2012 and I'm writing this on the 16th) but I think this looks not to be tied to MVC 4 or .NET 4.5 in which case I could use it in my current MVC 3 projects. I hope so...

By the way there's a nice rundown of how to use this by K. Scott Allen of Pluralsight. It's fantastic. Recommended.

Update 2

Having done a little asking around I now understand that this *can* be used with MVC 3 / .NET 4.0. Excellent!

One rather nice alternative script serving mechanism I've seen (but not yet used) is Andrew Davey's Cassette which I mean to take for a test drive soon. This looks fantastic (and is available as a Nuget package - 10 points!).

CDNs (they want to serve you)#

I've never professionally made use of CDNs at all. There are clearly good reasons why you should but most of those good reasons relate most to public facing web apps.

As I've said, the applications I tend to work on sit behind firewalls and it's not always guaranteed what my users can see from the grand old world of web beyond. (Indeed what they see can change on hour by hour basis sometimes...) Combined with that, because my apps are only accessible by a select few I don't face the pressure to reduce load on the server that public web apps can face.

So while CDN's are clearly a good thing. I don't use them at present. And that's unlikely to change in the short term.

TL:DR#

  1. I don't use CDNs - they're clearly useful but they don't suit my particular needs
  2. I serve each JavaScript file individually just before the body tag. I don't bundle.
  3. I don't minify my own scripts (though clearly it wouldn't be hard) but I do serve the minified versions of 3rd party libraries (eg jQuery) in a Production environment.
  4. I don't use async script loaders at present. I may in future; we shall see.

I expect some of the above may change (well, possibly not point #1) but this general approach is working well for me at present.

I haven't touched at all on how I'm structuring my JavaScript code itself. Perhaps next time.