Johan Driessen

Testing DataAnnotation-based validation in ASP.NET MVC

UPDATE: *Aaron Jensen pointed out that this only works for .NET 4. The DataAnnotation.Validator class mentioned in the post does not exist in .NET 3.5, so this method does not work.*

With .NET Framework 3.5 SP1 came DataAnnotations, and with ASP.NET MVC 2 Preview 1 came built-in support for DataAnnotation validation. This makes basic validation, like required fields, number intervals and so on, very simple. In order to be able to test this validation, though, you have to mimic some of the work that the ASP.NET MVC model binder does. This post will describe both how you get the validation working and how you can test it.

Decorating the properties

The first thing you have to do, is add the metadata to you data classes. You can either do this in the actual class, or you can add a partial class to hold your metadata. Either way has it’s advantages, here I’ll show the simplest on, just adding the attributes to the class.

1
2
3
4
5
6
7
8
9
10
using System.ComponentModel.DataAnnotations;

public class User
{
[Required(ErrorMessage = "Username is required")]
[StringLength(25)]
public string Username { get; set; }

public string Alias { get; set; }
}

All the attributes can be found in System.ComponentModel.DataAnnotations.

Adding validation to the view

Now, we add some validation code to our view, so we can show the error message. Actually, in ASP.NET MVC2 Preview 2 (or later), this code is already present.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<%= Html.ValidationSummary("Create was unsuccessful. Please correct the errors and try again.") %>

<% using (Html.BeginForm()) {%>
<fieldset>
<legend>Fields</legend>
<p>
<label for="Username">Username:</label>
<%= Html.TextBox("Username") %>
<%= Html.ValidationMessage("Username", "*") %>
</p>
<p>
<label for="Alias">Alias:</label>
<%= Html.TextBox("Alias") %>
<%= Html.ValidationMessage("Alias", "*") %>
</p>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>

<% } %>

Basically, what we do is add placeholders for the individual validationmessages and a validationsummary. These are already built-in in the HtmlHelper.

Checking the ModelState

Next, you have to make sure that your controller actually validates your model. Since we’re doing this TDD-style, first we’ll write a test for this.

1
2
3
4
5
6
7
8
9
10
11
[TestMethod]
public void Create_Will_Not_Accept_Empty_Username()
{
var controller = new UserController();

var user = new User();
var result = controller.Create(user);

Assert.IsFalse(controller.ModelState.IsValid);
Assert.AreEqual(1, controller.ModelState.Count);
}

What we do here is just sending in an empty User into the Create method, and assert that the ModelState of the controller is invalid, which it should be since the User did not have a Username. We also check that there is exactly one model error, since the empty Alias property should not cause an error.

Now we have to implement the Create method in the UserController to satisfy this test.

1
2
3
4
5
6
7
8
9
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(User user)
{if (!ModelState.IsValid)
{
return View();
}
//Create logic goes here
return RedirectToAction("Index");
}

Thanks to our DataAnnotations, validating the User object is really simple. The model binder will check the data annotations, and update the ModelState of the controller. So all we have to do is check if the modelstate is valid, and if not return the create form view again. So now we run our test, and see if things work:

U R FAIL!!

Oops, guess not. Now why is this? Well, as I mentioned in the previous paragraph, the model binder will check the data annotations and update the modelstate. But when we call the Create method from our test, the model binder is never invoked, so no validation takes place. So in order to be sure that our Create method won’t accept any users without names, we need to mimic the behaviour of the model binder.

In order to to this, we need to create a ValidationContext (found in System.ComponentModel.DataAnnotations) for our model (the User), and user the DataAnnotations.Validator class to validate the model. And finally add the errors to the modelstate of the controller. This somewhat cumbersome syntax turns out like this:

1
2
3
4
5
6
7
var validationContext = new ValidationContext(user, null, null);
var validationResults = new List<ValidationResult>();
Validator.TryValidateObject(user, validationContext, validationResults);
foreach (var validationResult in validationResults)
{
controller.ModelState.AddModelError(validationResult.MemberNames.First(), validationResult.ErrorMessage);
}

So, we add this code after we create the user object, but before we call the create method. And then we run the test again.

I love green tests!

Yay, it works! And if try our code in the browser, we get this nice validation message:

image

Now, in an actual application, of course we won’t keep the model validation code in the test, but rather extract a method to a base class. But this should give you the idea of how it’s done. And if you want to make it even fancier, just add a few lines in the view, and you will get Ajax validation as well!

Persistance in WF4 beta 2

Ok, this is my follow-up post to .Net Framework Profiles, where I very naïvely though I persistence in WF4 was all about using the correct target framework. As it turned out, they changed the persistence model between beta 1 and beta 2, and the tutorial was apparently written for beta 1.

So here’s my changes to the Microsoft tutorial How to: Create and Run a Long Running Workflow in order to This works on my machine. It might not work on your machine.make it work for Windows Workflow Foundation 4 beta 2.

The persistence database

First of all, since they have replaced the SqlPersistanceProvider with SqlWorkflowInstanceStore, you have to generate a different persistence database. Instead of the scripts mentioned in the tutorial, you should use SqlWorkflowInstanceStoreSchema.sql and SqlWorkflowInstanceStoreLogic.sql to generate your database. They are still found in C:\Windows\Microsoft.NET\Framework<current version>\sql\en.

Enable persistence in the workflow application

  1. Add the correct references. Disregard the references mentioned in the tutorial. Instead add references to System.Runtime and System.Activities.DurableInstancing. These are both included in the Client Profile, rendering my previous post completely obsolete (and it was only a couple of hours old).

  2. Yep, you should still add a connection string to your persistence database.

  3. Add a using statement for System.Activities.DurableInstancing instead of System.ServiceModel.Persistence.

  4. Next, add a SqlWorkflowInstanceStore to the workflow application

    1
    wfApp.InstanceStore = new SqlWorkflowInstanceStore(connectionString);
  5. In order to tell the workflow to persist when it goes idle, replace the Idle action with a PersistableIdle action.

1
2
3
4
5
6
7
8
9
10
11
12
//Remove this from the previous step
wfApp.Idle = delegate(WorkflowApplicationIdleEventArgs e)
{
idleEvent.Set();
};

//And replace it with this
wfApp.PersistableIdle = delegate(WorkflowApplicationIdleEventArgs e)
{
idleEvent.Set();
return PersistableIdleAction.Persist;
};
  1. Yeah, same, same
  2. Since the database schema is different, instead of looking in the Instances table, look in the **[System.Activities.DurableInstancing].[InstancesTable] **table (yeah, redundancy is fun, always suffix your tables with table and your databases with database!).

Now, it should work. At least it did for me. But just to be safe, I’ll decorate this post with the official Works On My Machine seal of awesomeness.

.Net Framework Profiles

UPDATE 2: I have now written a post describing how I got persistence working in WF4 beta 2.

UPDATE: Seems that they have changed just about everything concerning persistence from WF4 beta 1 to beta 2. So the forth part of the tutorial I’m referring to doesn’t seem to work at all for beta 2. I’ll have to do a follow-up on how it works once I’ve figured it out. /J

Since we are going to use Windows Workflow Foundation 4 in our new project, I though I’d better learn the basics of it. So I found Microsoft’s Getting Started Tutorial, and started following it. The first three parts went well, although I suddenly remembered how much I hate drag-and-drop-programming. But when I came to the fourth part (the most interesting one, I might add), How to Create and Run a Long Running Workflow, I ran in to a small problem.

The tutorial told me to add references to System.WorkflowServiceModel and System.WorkflowServices. Problem is, when I opened the Add References dialog, those assemblies do not exist!

“How can this be?”, you might cry. Well, it turns out that Microsoft in their infinite wisdom* have introcuded something called profiles in the target framework of the project. In .NET 4 there are two profiles: .NET Framework 4 and .NET Framework 4 Client Profile, the client profile being the default (in .NET 3.5 there is also a Server Core Profile). And the client profile does not include System.WorkflowServiceModel and System.WorkflowServices!

So, in the end the solution is simple, just change the target framework to the full .NET Framework 4, and everything will work fine. You could argue that they should have added this in the tutorial, though. :-)

On a completely unrelated note, I just heard that I have been nominated for IT consultant of the year at the 2009 IT Business Awards, and even made it to the final three. Not sure what to make of that…

* I don’t mean this as a mockery, I actually think it’s a good idea.

Bleeding edge

Starting a new project at work today. For once this project will have to use the latest and greatest technology. We want to use the new Windows Workflow Foundation, which means that we have to use .NET 4 and Visual Studio 2010. We will also use ASP.NET MVC, and since we are using VS2010 beta 2, that means ASP.NET MVC 2 Preview 2. Nice!

There are some difficulties, though. For example, we are planning to use StructureMap as for dependency injection, and since MvcContrib has a built-in Controller Factory for StructureMap, we wanted to use that too (it also has a lot of other neat features). Well, turns out that the release versions of MvcContrib don’t support ASP.NET MVC 2. So, I hade to pull the latest nightly from source control. That solved the StructureMap problem, but will it yield new problems? Time will tell.

It’s always interesting to work on the bleeding edge of technology. My new motto is that anything out of beta is too old to be worth running! :-)

Almost equal

Had another interesting problem today. A test that really should have worked started failing most of the time. The test was designed to make sure that a certain DateTime value did not change on update under a special circumstance. It was designed something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[TestMethod]
public void Updating_Foo_Will_Not_Update_ChangeDate()
{
//Create a Foo to work with
Foo foo = new Foo()
{
Name = "Update test foo",
};

foo = repository.SaveFoo( foo );
DateTime lastChanged = foo.Changed.Value;

foo.Bar = new Bar { Id = 1 };
repository.SaveFoo( foo );

var updatedFoo = repository.GetAllFoo().WithId( foo.Id );

Assert.AreEqual( lastChanged, updatedFoo.Changed.Value );
}

This assertion, as you might imagine, was not fulfilled. Stepping through the code showed that the SaveFoo method in the repository did not change the value of foo.Changed, as is was not supposed do. It did, however save the foo to the database. On a first inspection, the two dates also seemed to be exactly the same, so the assertion should have been correct.

Or so I thought. When I looked closer at the dates, it turned out they weren’t exactly the same. Close, but not exactly. More specifically, the Ticks value of them differed. The value of lastChanged was 633922004866809617, while the value of updatedFoo.Changed.Value (that had made a round trip to the database) was 633922004866800000. Not a huge difference, less than 1 ms, but enough to make the test fail. How stupid I was, assuming that the precision of DateTime in .NET, and DateTime in SQL Server was the same! Further reading revealed that SQL Server has a DateTime precision of about 3.33 ms, while .NET has a precision of 100 ns. So everytime I saved the time to the database, it would change it!

The solution? Well, since I didn’t really care about differences of a few milliseconds, I decided to extend the DateTime struct with a brilliant new comparison method:

1
2
3
4
5
public static bool IsAlmostEqualTo( this DateTime dateTime1, DateTime dateTime2 )
{
var diff = dateTime1 - dateTime2;
return Math.Abs( diff.TotalMilliseconds ) <= 5;
}

Because, hey, if I can’t feel the difference, there is no difference! This also made the Assert a little prettier:

1
Assert.IsTrue( lastChanged.IsAlmostEqualTo( updatedFoo.Changed.Value );

Problem solved! :-)

Lifting an ASP.NET MVC 1.0 project to Visual Studio 2010

I have a pet project (several actually, but let’s stick to one of them). It’s called Önskelistemaskinen, and is a web application for keeping track of the wish lists of my family members. It’s build in ASP.NET MVC with a Linq-to-SQL backend (loosely modelled after Rob Conery’s Storefront project), and naturally grossly overdesigned for an application with a target audience of about 10 people.

Anyway, I started working on this when the first beta of ASP.NET MVC came out about a year ago, and with every new release I have had to rework lots of it. So when both Visual Studio 2010 beta 2 and ASP.NET MVC 2 preview 2 came out almost simultaneously I figured, what the hell, time for another rewrite!

My first approach was to just open the project in Visual Studio 2010. It seemed very helpful, offering to convert the project to VS2010. But on closer inspection, I found that it had converted all of the projects except for the actual web project. So no luck.

I had read a blog post by Scott Hanselman about converting a ASP.NET MVC 1.0 project to 2.0 (for Visual Studio 2008, though), and also thought I had seen something pass by about an application doing that for you. I figured that might be the way to go. Just to be sure I threw the question out on Twitter, and within minutes I got an answer pointing to the conversion application.

I used the application and converted my 1.0 project to 2.0. Then I opened the project in VS2010 again, and this time the conversion wizard gladly converted my web project to VS2010! Now, I had a few other problems, since I hade used a few features in MVC Futures library, which didn’t seem to work anymore. But after fixing these, everything seems to work fine (by the way, I noticed while writing this post that MVC Futures also has a new release, so a better idea might have been to use that one. I’ll check it out tonight).

In conclusion, to get your VS2008/ASP.NET MVC 1.0 project to work in Visual Studio 2010, follow these steps:

  1. Upgrade the project to ASP.NET MVC 2, preferably using Eilon Lipton’s migration tool.
  2. Open the project in Visual Studio 2010, and let the conversion wizard work its magic.
  3. ??
  4. Profit!

Update: Turns out that Phil Haack wrote a post describing this sometime between my attempts to get it working yesterday evening and my writing of this post this morning.

In SQL, null is not != 1

Had an interesting error today. An database query that should have returned thousands of lines returned nothing. Turned out it was due to how the inequality operator works in SQL. In most programming languages, like C# or java the inequality operator handles null, so for example the following code (although extremely stupid) will work.

1
2
3
4
5
6
bool? nullValue = null;
bool? trueValue = true;
bool? falseValue = false;
Console.WriteLine((true != nullValue) );
Console.WriteLine((true != trueValue) );
Console.WriteLine((true != falseValue) );

This will produce the result True, False, True, since true really isn’t equal to null.
In SQL, however, this is not the case. Consider the following SQL query:

1
2
3
4
5
6
7
8
-- TestTable data
-- id name isTrue
-- 1 test 1
-- 2 test 0
-- 3 test NULL

select * from TestTable
where isTrue != 0

If you’re not familiar with SQL, you might think that this would return two rows, the one where isTrue is 1 and the one where isTrue is NULL. This is obviously not so, otherwise I wouldn’t have written this post. You only get the one where isTrue is 1. This is due to the fact that in SQL, the inequality operator (!= or <>) does not work on null values. So in order to get both lines, you would have to modify the query like this:

1
2
select * from TestTable
where isTrue != 0 or isTrue is null

Of course, in this case, this is not the correct solution. A column that is obviously Boolean should not allow null values at all! This was also the case in the non-working query I came across. So the moral of the story is:

Never allow null values in for boolean columns!

Mime type for Android apps

I recently got an Android phone (a HTC Hero, to be specific), and of course I felt the need to develop applications for it. I have a few in mind, and I’m sure I will dwell on that in upcoming blog posts. One thing, however, I learned immediately: In order to get the phone to install your app from a web server, you need to have the correct mime type for it.

It turns out that the correct mime type for an .apk file is

application/vnd.android.package-archive

You also need to change the settings to allow installation of programs that doesn’t come from Android Market. This setting is found in* Settings > Program, and is probably called “Unknown sources*” in English (it is definitely called “Okända källor” in Swedish).

New place, new look, same me

I started blogging on the Dropit Labs blog about a year ago, and I have kind of gotten used to it. But since I no longer work at Dropit, and thus am unable to keep writing there, I felt the need to create another place to write my posts about web development. The simple solution was obviously to start my own blog, and this is the result! Since I didn’t want to start all empty, I have copied most of my posts on the labs blog (except for a few that was only about Dropit stuff).

I have decided to run this blog on Subtext, but the choice was not easy, I can tell you! I knew that I wanted to host the blog myself, and not use a hosted blog engine like Wordpress or Blogger, since I want to be able to tweak the blog. I also made the pragmatic decision that the engine had to be written in C#, to lower my bar for actually modifying the code. I definitely did not want it to be written in PHP, because that really makes my skin crawl.

So basically, I had to look for a good .net blog platform, that was also open source. Some research (let’s call it research, but it was really just googling) yielded four candidates: BlogEngine.NET, dasBlog, AtomSite and Subtext. Initially, I though AtomSite looked very promising, especially as it is written in ASP.NET MVC, which I really like. Unfortunately I found it still lacking a bit too many features. BlogEngine.NET was the platform we used for the labs blog, and although that worked out ok, I thought it would be more fun to try something else. I wasn’t 100% happy with it anyway. So basically it came down to dasBlog or Subtext, and in the end, I just felt that Subtext had a little more umpf than dasBlog.

Finally, I just realised that I have mentioned my previous employer no less than 3 times in this post. In the name of fairness I feel compelled to mention my current employer an equal amount of times now. Active Solution. Active Solution. Active Solution.

So, there.

Until next time, I remain your humble servant.

Subtle differences

This post was originally published on *http://labs.dropit.se/blogs.*

Today I hade the dubious pleasure of having to work with an old EPiServer 4 site, and having to deploy it to IIS7 on a Windows 2008 Server.

In order to make everything work in EPiServer 4, you need to make sure that all 404-request are redirected to /Util/NotFound.aspx. On my development machine, which runs Windows 7, I accomplished this by adding the following code to web.config:

1
2
3
4
5
6
<system.webServer>
<httpErrors>
<remove statusCode="404" subStatusCode="-1" />
<error statusCode="404" prefixLanguageFilePath="" path="/Util/NotFound.aspx" responseMode="ExecuteURL" />
</httpErrors>
</system.webServer>

Since both Windows 7 and Windows 2008 Server runs IIS7, you would think that this should work on the server as well. But when I ran a particular URL that needed the redirection to NotFound, I only got the following error message:

The page cannot be displayed because an internal server error has occurred.

Nothing else. Nothing in the log files, nothing in the event log. Hmmm.

After fiddling around for a while and trying to figure out what was wrong, I tried going into the Error Pages feature in IIS Manager on the server, and suddenly got the error message saying:

This configuration section cannot be used at this path. This happens when the section is locked at a parent level. Locking is either by default (overrideModeDefault=”Deny”), or set explicitly by a location tag with overrideMode=”Deny” or the legacy allowOverride=”false”.

What this basically means is that I can’t use the <httpErrors>-section in web.config, because the machine settings says that I can’t. Now, the settings for IIS7 can be found in the file applicationHost.config, located in C:\Windows\System32\inetsrv\config. A look in this file on both the server and on my machine showed a subtle difference:

1
2
3
4
5
<!-- Windows 7 -->
<section name="httpErrors" overrideModeDefault="Allow" />

<!-- Windows 2008 Server -->
<section name="httpErrors" overrideModeDefault="Deny" />

For some reason, the default configuration on Windows 2008 Server doesn’t let you override the httpErrors-configuration in web.config, while the default configuration on Windows 7 does. I’m not saying that either one is more correct that the other, but if it had been the same on both it would have saved me a couple of hours of work today. Sometimes subtle differences can cause a lot of work…