# Wednesday, 29 October 2014

I’ve created a github project showing various examples of how to use/interact with Bootstrap 3 modal dialogues in ASP.NET MVC 5. 

I did this project many months ago when I was starting out with Bootstrap.  I was trying out various techniques and figured someone else might benefit from the samples.  I imagine this is not exhaustive nor do I purport the examples are "best practice".  Feel free to add pull requests to improve it.  I would love learning a thing or two from others.

Check out the project at https://github.com/klabranche/ASPNETMVC5Bootstrap3ModalExamples

Happy Coding! Smile

Posted 10.29.2014  #    Comments [0]  | 
# Friday, 03 May 2013

Today I wasted an hour or two chasing my tail around trying to figure out why a change to one of my ASP.NET MVC Views was not at all showing any changes in my jQuery Mobile version.  I cleared my cache, hit ctrl+F5 a billion times, redeployed to our test server and then again.  I double checked my code, then again.  I would view source and on my mobile version it hadn’t changed.  What is going on?

I noticed another oddity through all this. My page was loading up two versions of jQuery.  One being an older version I know I updated. 

<script src="/Scripts/jquery-1.8.2.js"></script>
<script src="/Scripts/jquery-1.8.3.js"></script>

Yet, it was loading. Huh? I’m confused.

What’s Happening

Then it hit me. Bundling in ASP.NET MVC looks for whatever version I have in the scripts folder to generate the tag since my syntax is:

bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
"~/Scripts/jquery-{version}.js"));
    Does this mean I have the older version along with the newer version on my test server. 

folder

Inspecting the test server revealed this to be the case.  I then went to my view folder for the mysterious view that wasn’t changing and found a very old .mobile.cshtml file that we ditched a while back once we were able to consolidate our normal and mobile view on one page.

So how did this happen.  We’re a small shop and use Web Publish built into Visual Studio to deploy to our servers.  I looked at the file publish options and the "Remove additional files at destination" was unchecked.

publishOptions

Leaving this unchecked means that any file you removed from your project if on the destination machine will not be removed. 

Delete some views, update your jQuery nuget packages and publish without this checked and the old items will remain on your deployed environment.

A simple check of the box and all is well again.

Luckily, our production server deploy settings were correct so we didn’t have to worry about some nasty little bug in production due to this. Smile

Happy Coding!

Posted 05.03.2013  #    Comments [0]  | 
# Wednesday, 01 May 2013

All of the applications I put into production use ELMAH to track unhandled exceptions.  In one our new releases of an application I noticed a semi-rare bug occurring through these logs.

Validation Failed

Validation Failed

System.Data.Entity.Validation.DbEntityValidationException: Validation failed for one or more entities.

I initially figured something extraordinary occurred for this to happen. Then it happened again and then another time. Now I felt it was time to give this error a more thorough review.  Something less then extraordinary was likely happening.

I use data annotations on my database model since I’m using Entity Framework Code First (EF CF) and in my view models.  I was a little concerned that some nefarious input was being entered that the client side unobtrusive JavaScript was missing as well as in my server side checks.

As it has almost always turned out when I suspect something like this, the true answer is something much simpler and sometimes even a bit embarrassing.

Here’s the offending view model / with the EF CF model.  Can you catch the issue?

//View Model
public class MyCourseViewModel
{
    [Display(Prompt = "Yada Yada Yada College")]
    [Required]
    public string College{ get; set; }
    [Display(Name = "Course Title", Prompt = "Intro to Psychology")]
    [Required]
    public string Name { get; set; }
    [Display(Name = "Course Prefix & Number", Prompt = "PSY 101")]
    [Required]
    public string CourseNumber{ get; set; }
//…more view model fields…. } //Database Model... public class MyDatabaseModel{ [StringLength(150)] public string College{ get; set; } [Required] [StringLength(150)] public string Name{ get; set; } [Required] [StringLength(25)] public string CourseNumber { get; set; } }

Mismatched Annotations

In my database model I set maximum lengths for my strings but I didn’t for my view model.  Enter the case where a user enters a value longer than the allowable amount and you have the client side & server side checks all pass on the view model but then an error occurs at the database model level since you’ve exceeded your length.

Takeaway

Make sure you at least have matched or created a more stringent rule in your view models as you do in your database models.  A simple oversight on my part and definitely not intentional.

Logging

Takeaway number two: Log, log, and log.  Then be sure to review those logs not just ignore them.  Take action when you begin to see a pattern.

Dealing with exceptions

Adding ELMAH to my MVC projects has been a breeze and has offered a great amount of insight into unforeseen bugs.  I often don’t react to the first new bug that ELMAH reports.  I instead look to see if it’s a pattern and when one emerges I then put it on my list to deal with.

Happy Coding! Smile

PS – I realize a better test setup would have been able to prevent this bug from ever making it into the wild. A unit test would have even missed this but not an integration test. Some extra food for thought on how testing can save your bacon…. Mmm… bacon.

Posted 05.01.2013  #    Comments [0]  | 
# Thursday, 04 October 2012

Moving an MVC4 Visual Studio 2010 project to 2012 is so far in my experience with a small application rather quick and easy. However, if that’s all you do then your app will be missing out on the nice .Net 4.5 and Entity Framework 5 features. 

Upgrading these two items, while not terribly difficult, does have a few challenges to overcome even for my relatively small application with two projects and about a dozen NuGet packages.

Hopefully my experience will help the next person get through their upgrade faster.

MVC 3 or MVC4 Release Candidate?

If you are on MVC3 or say the MVC4 Release candidate take a look at these extra steps to take.

MVC4 & VS 2010 to 2012 Steps

Open your VS 2010 solution in 2012 and let it convert your solution.

And done… Well almost.

If you happen to be using dependencies / nuget packages, there may be a chance that these are using older frameworks.  If you were already using MVC4 in 2010 chances are then you already figured out how to direct these packages to use newer versions of their dependencies using binding redirects. 

For example MVCContrib.TestHelpers references the MVC3 runtime.  My VS10 project was already using a binding redirect so all should be good. 

I am also using the MiniProfiler and in my MVC4, 2010 project I upgraded to the Entity Framework 4.4 Prerelease.  When I did this I had to add a binding redirect since the MiniProfiler at the time was using an earlier release.

If you are having issues, you’ll have to investigate if you have a dependency using an older version of a DLL that you can use a redirect to solve.

MvcContrib.TestHelpers***

In my case, my VS12 project with the TestHelpers stopped working even with the redirect.  I tried on my PC/laptop as well new and upgraded projects.  I can only assume it must be something wierd on my boxes.  I have been using the betas, previews and RC versions of MVC on both boxes so it just might be something related. 

The binding redirect *should* work.  However, if you run into my case, the atomic option is to download the MVCContrib source, change the reference for the TestHelpers project to use the MVC4 runtime, recompile and use the new DLL in your project.  This is what I ended up doing.

Done. If that’s all you want to do.

Upgrade Project(s) to 4.5

Right Click on each project and select properties.  Change the Target Framework to 4.5 in the Application section.

Update all packages to target 4.5

Perform a search and replace for the entire solution to replace targetframework=”net40” to targetframework=”net45”.  This will update all of your packages.config to use 4.5 targeted packages instead of 4.0.

targetNuget

Open your web.config and change your targetFramework=”4.0” to 4.5.  This informs IIS to also target 4.5 now.

Upgrade EF 4.4 to EF 5

Uninstall the EF package, and reinstall it via Nuget. I recommend doing this from the console/command line instead of the package GUI.  At the command line you can force an uninstall just in case you have other packages that require EF.  I originally uninstalled/reinstalled via the GUI and first removed all of my dependent projects and then added them all back in but I ran into problems with my dependent projects having issues.  I found it easier to force EF first, make sure it was all working and then investigate my other dependent packages one at a time.

You can open the console from the Tools Menu, Library Package Manager and Package Manager Console

nugetConsole

or by typing console and hitting enter in the Quick Launch which is in the upper right hand corner of VS 2012.

quicklaunch

The console opens in the lower middle of VS 2012 and allows you to type in nuget commands.

console2

Type in

uninstall-package EntityFramework –Force

and then

install-package EntityFramework

Be sure to do this for all projects using Entity Framework.  You can change this by selecting the project from the dropdrown list in the console.

If all of the above was done correctly it will install version 5.0.  If it still says 4.4 something is still pointing to the 4.0 framework.

efVersion

Build your solution.

If you get an error about the CompareAttribute being ambiguous reference…

CompareAttribute

Fix by Adding System.Web.Mvc. to the Compare Attribute.

Before:

CompareAttribute1

After:

CompareAttribute2

Rebuild.  Congratulations.  You now have a VS 2012 MVC4 project using .Net 4.5 and EF 5.

Now for the rest

From here you should now investigate all of your Nuget Packages or external references.  Since we are now pointing to 4.5 it may be that a newer version is available.  Nuget doesn’t handle updating to the new targeted version at this point.  You’ll have to look at each package and if you know it has a newer one for 4.5 you’ll want to look at uninstalling it and reinstalling as we did earlier.

One Quick way to reinstall all the packages

You could delete all of your packages and their folders and set Nuget to restore packages.

packageSettings

PackageRestore

Now the next time you recompile, Nuget will get all of the new stuff.

However, this could wreak havoc on your project.  I opted for handling my dependencies one at a time so I could deal with issues for each package one at a time. 

Happy Coding! Smile

Posted 10.04.2012  #    Comments [1]  | 
# Thursday, 19 April 2012

I’m developing an ASP.Net MVC application with Knockout 2.0/2.1rc.  I’m using modernizr (2.5.3) and css3pie (1.0 beta 5) to get CSS3 and HTML5 support on as many browsers as I can.

On a particular view I am using imageless add/delete buttons. I’m using Knockout to dynamically add and remove items from two tables.

I had to use css3pie to help make the buttons work in IE 6-8 with this line for the add button:

/* no fix currently for radial gradient in IE6-8... using linear instead.*/
-pie-background: linear-gradient(-90deg, #1b9918,#1b9918 65%,transparent 65%, transparent); 

and for the delete:

-pie-background: linear-gradient(-90deg, #da7d83, #da7d83 50%, #ca444e 50%, #ca444e);

When I apply the binding in KO (.applybinding), the buttons disappeared in IE 8.  At first I thought something was wrong in modernizr but after some testing I realized it was only IE 8 that was failing.  That got me thinking about css3Pie. After some searching around on the internet I found this post. The final response gave me my answer:

I have the same problem with a native ko templates, if I use "foreach" without a container element. Also, I was trying to use PIE.js instead of PIE.htc - but without success. For templates like data-bind="template: { name: 'itemTmpl', foreach: items }" css3pie works fine. Try to refactor templates using a container element. May be it is workaround solution.

I was using an anonymous/inline template:


    
        
+

When I changed the code to use a named template:



...
    

IE6-8 began working again.

According to the forum post, this may be an issue with KO 2.0.  I didn’t try it on an older version of KO but I did with KO 2.1rc and had the same results.

Happy Coding! Smile

Posted 04.19.2012  #    Comments [0]  | 
# Saturday, 29 October 2011

In a post about two months back I worked with Adam Anderly to update the SimpleMembershipMvc3.Sample application to include resetting/forgotten passwords and emailing verification of registration. 

Adam updated his NuGet package to include this.  He also separated the email code into a service to make it better for testing.  Go Adam!

How to get it

If you are familiar with NuGet the command is:

Install-Package SimpleMembership.Mvc3.Sample

If you aren’t familiar with NuGet yet, you need to be.  It’s a great tool!

You can also get the code via GitHub.

Happy Coding!

Posted 10.29.2011  #    Comments [0]  | 
# Thursday, 15 September 2011

At Build MVC4 was announced and shortly thereafter it became available for everyone to play with.

How Do I Get It?

You can get it three ways:

What’s In It?

MVC4 comes with many great new features including an updated face lift of the design:

face_lift

Mobile rendering baked in:

Comparison

You can see the side by side comparison of the old MVC default template and the new.  The newer template is just cleaner and easier on the eyes.

If you need more mobile then use the Mobile Project Template that uses jQuery Mobile!

Superficial?

These changes are just superficial.  True, but they do have more features such as recipes and task support for asynchronous controllers.  You can also install MVC4 side by side with MVC3 without issue.

Upgrading MVC3 to MVC4

No Problem.  At least in my case.  I did it both ways as described in the ASP.Net MVC 4 release notes.

The recommended approach is to create a new MVC4 project and move your controllers, views, etc… into the new project which works but if you have a large project that would be a pain.

The other option is to do it all manually (as described in the release notes) or use nuget to install the MVC4 bits and make a few less manual changes.

After installing the MVC4 package in your application, you will want to make all of the manual edits as outlined in Upgrading an ASP.NET MVC 3 Project to ASP.NET MVC4 section of the release notes with the folowing exceptions:

  • You don’t need to do step 3.  The Nuget package takes care of this.
  • On step 7, I had to add a binding for Razor

    <dependentAssembly>
      <assemblyIdentity name="System.Web.WebPages.Razor"
           publicKeyToken="31bf3856ad364e35" />
      <bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0"/>
    </dependentAssembly>

Should I Care?

Just the inclusion of mobile baked in is a big win and should be a good reason to watch MVC4 take shape over the next several months. 

I know this is early and I’m sure more features will make it’s way into MVC4.  At the pace that MVC has been maturing I am excited to see what’s next!

Happy Coding!

Posted 09.15.2011  #    Comments [0]  | 

On my home pc the MVC4 developer preview installed on my box but at the office I tried a few different times with no success.

WPI_Fail

Visual Studio 2010 SP1

It’s required for MVC4.  Already have it on your box?  That’s likely the reason WPI is failing to install.

Reading the log didn’t really give me much information but I was very sure that I had already installed VS 2010 SP1 on my box.  Time to go around WPI.

WPI Installer Location

Aren’t sure where WPI installers are stored?

Location

They are stored in your profile’s AppData\Local\Microsoft\Web Platform Installer\installers folder.

When I ran the MVC4VS2010 Installer by itself, outside WPI, the install worked.

Happy Coding!

Posted 09.15.2011  #    Comments [1]  | 

I updated Adam Anderly’s SimpleMembershipMvc3.Sample application available as a nuget package and on GitHub.  The sample as is only hooks up the registration and login for the Account Controller. 

What I Added

  • Require Email Verification for sign up.
  • Resetting Password
  • Forgotten Password
  • In doing so I had to add the reset and forgotten models to the AccountModels class.  If you are interested in using this code please be aware of this and take the necessary steps to backup your AccountModels and/or merge the two.

    How to get it

    In talking to Adam he is likely going to create a new sample available via NuGet for those wanting this more complete solution.

    For now you can get it via my GitHub Fork of Adam’s work.  Hopefully soon, either Adam or myself will create a nuget package for it.

    Happy Coding!

    Posted 09.15.2011  #    Comments [1]  | 
    # Thursday, 24 March 2011

    One of the awesome features in MVC is Unobtrusive JavaScript.  In MVC 3 apps you can set this in the web.config.  It’s on by default.

    I have a legacy database that has a field that is required and doesn’t allow nulls but the application allows for empty strings to be entered into the field.  I know, what’s the point of requiring a field and allowing empty strings (if empty string actually means something, OK). 

    When I set the Required Data Annotation with the AllowEmptyString=true on the field the validator was still returning an error.  On a hunch I set UnobtrusiveJavaScriptEnabled=false and then field began working as expected.

    What gives?

    MVC 3 uses jQuery validators when UnobtrusiveJavaScriptEnabled is true.  For the Required annotation it uses the jQuery required validator which doesn’t have the AllowEmptyString parameter or one like it.  Essentially, the validator ignores this parameter. Thanks to @srkirkland for pointing this out. And he would know, he runs the OSS Data Annotations Extensions project.

    Happy Coding!

    Posted 03.24.2011  #    Comments [2]  | 
    # Wednesday, 23 March 2011

    I’m working on the latest Entity Framework RC 4.1 that comes with Code First. In my quest I learned how the Data Annotations work on empty fields. Something I thought I knew but after being schooled by my simple MVC3 project I had a little help on twitter to set me straight.

    I asked on twitter – Do Data Annotation validators run when the field is empty? Required does but my experiment on others don't seem to?

    I mean, of course, duh, required would but it didn’t seem like the other validators were.  I was two validators.  The first was the String Length and I had set the Minumim and Maximum Length.  The other was the regular expression validator that wanted 4 digits.  When I emptied the fields, the validator appeared to not run because I didn’t get an error displayed.  If I entered a character then the validation appeared. 

    What’s going on? It would make sense that for the String Length validator with a Minimum Length set that when nothing is entered it should fire right?  Clearly, we are below the minimum length.  I began to assume that the validators other than the Required didn’t run if the field is empty.  I always thought they did run. 

    Well, @srkirkland to the rescue.  He set me straight.

    @klabranche When a field is empty other vals will still run, just return valid always. Convention is non-required vals return true w/ null

    …and @srkirkland would know, he runs the OSS Data Annotations Extensions project.

    Convention is non-required validators will return true with nulls

    I feel as though I should have known this but clearly I didn’t. Maybe, just maybe I had it way deep in the recesses of my mind. A lot of good that did me. :-) How about you?

    For the purpose of this post let’s fire up reflector and see for ourselves!

    regular expression annotation reflector code

    All Data Annotations wield their magic in the IsValid method.  As you can see below the Regular Expression Annotation checks to see if the string coming in is null or empty and if it is return true.

    public override bool IsValid(object value)
    {
        this.SetupRegex();
        string str = Convert.ToString(value, CultureInfo.CurrentCulture);
        if (string.IsNullOrEmpty(str))
        {
            return true;
        }
        Match match = this.Regex.Match(str);
        return ((match.Success && (match.Index == 0)) && (match.Length == str.Length));
    }

    How about one more? String Length

    string length annotation reflector code 

    public override bool IsValid(object value)
    {
        this.EnsureLegalLengths();
        int num = (value == null) ? 0 : ((string) value).Length;
        return ((value == null) || ((num >= this.MinimumLength) && (num <= this.MaximumLength)));
    }

    Again, you can see if the initial object coming in is null then return true.

    Why this convention

    I found a reference on Phil Haack’s blogs:

    http://haacked.com/archive/2009/11/19/aspnetmvc2-custom-validation.aspx

    Notice that if the value is null, we return true. This attribute is not intended to validate required fields. I’ll defer to the RequiredAttribute to validate whether the value is required or not. This allows me to place this attribute on an optional value and not have it show an error when the user leaves the field blank.

    
    

    Where I went wrong

    Back to the String Length validator. If it would fire for an empty string then we are essentially making the String Length validator a required field validator also.  This may seem logical and was my assumption. In reality, if this was true we would be making the String validator also a required validator. Having the convention on all non-required validators return true when their field is empty ensures those validators are not forcing an implicit required.  How fun would that be for a field we wanted to ensure was a certain format but could also be empty?

    So there you have it.  I was ready to blame Code First or the Entity Framework, surely not my own assumptions. :-)

    Happy Coding!

    Posted 03.23.2011  #    Comments [0]  | 
    # Saturday, 29 May 2010

    This weekend I decided to update my VS 2008 Express with MVC2.  You can do this with the Web Platform Installer (WPI). In order to install MVC2 you do need to be on SP1 for VS 2008 Express.  Your version needs to be "9.0.30729.1 SP".

    Installing with WPI is a breeze but in my case WPI stated it installed MVC2 successfully but I didn’t have the MVC2 Project as a choice in my project list.  I tried it a few times and I always received a successful install message but still only had the MVC1 project choice.

    The fix for me was pretty simple.  I just downloaded and installed MVC2 directly from the download center.

    Happy Coding!

    Posted 05.29.2010  #    Comments [0]  | 
    # Friday, 05 March 2010

    Want to learn ASP.Net MVC?  Perhaps you already started learning it.  I decided to take a side project of mine that I started in Web Forms and completely start over with .Net MVC.  I wanted to document what I did and the resources I found in the hopes that it may help you.  I still have much to learn and master with .Net MVC but so far I am impressed and am happy I decided to branch out and learn something new.  It has made me a better developer and a more well informed developer.  Both good things!

    Not sure what ASP.Net MVC is?  Check out this intro video and this overview and then hurry on back.

    How I started:

    ASP.Net MVC Tutorials and many, many blog posts from Scott Guthrie, Phil Haack, Rob Conery, Jimmy Bogard, Jeffrey Palermo, Eric Hexter, Steven Sanderson, Stephen Walther and these are just the ones I remember.

    Books:

    I started with ASP.Net MVC In Action and quickly realized that many of it’s topic were over my head.  So I put it down and read ASP.Net MVC Framework Unleashed and Pro ASP.Net MVC Framework and then went back to MVC In Action. 

    TIP #1 - When I am learning a new technology I tend to do the examples in the book from scratch.  It takes longer than just downloading their sample code but it helps me absorb it more. 

    TIP #2 – Almost all the material I read on ASP.Net MVC touch on or go into detail on Unit Testing, Test Driven Development, Dependency Injection, Inversion Of Control and many other design principles.  If you are not sure what these are you might want to research them a little bit.  The books I recommend do give overviews of these.  One of MVC’s main design goals is for giving control of the application back to the developer and ease of testing.  If you find this even the least bit interesting then keep going!

    Samples/Tutorials:

    ASP.Net MVC Tutorials – I watched these to get a feel for MVC.  They have a lot of video’s and sample code you can run through.  They did a great job of covering the basics.  Stay here a while, fire up your IDE and peck away on the keyboard with these tutorials.

    Nerd Dinner – Perhaps a cult classic or a right of passage?  I for the most part skipped it…. Oooppsss.  No wonder I struggled so hard with MVC in the beginning.  Just kidding.    It was one of the first books and sample apps out.  I skipped it only because I didn’t have it in my Safari Books Online.  I did however take advantage of their free chapter and source code.

    Rob Conery – Rob Conery published a set of video’s documenting the development of an eCommerce storefront called MVC StoreFront.  I watched these video’s carefully and read his code carefully.  He then renamed the project to Kona and added a few more screencasts.  Check these out.  I poured through his code to see some of the possibilities that MVC has.  I still don’t understand some of it but Rob’s a much smarter guy than I am. :-)

    Starter kits – Check out their Northwind MVC project, period.

    Tip #3 – Check out the ASP.Net MVC Tutorials and the MVC storefront screencasts at least! 

    Cheat sheets – Elijah Manor published several cheat sheets on MVC that are great to put on your wall or at least keep close at hand while you are learning MVC.

    50 ASP.Net MVC Tips – Stephen Walther, author of ASP.Net MVC Framework Unleashed published these nice tips on his blog.

    MVC Contrib Project – A bit more advanced but the wizards over at Headspring created this little open source gem.  The ASP.Net MVC In Action’s sample project uses MVC Contrib.  The project is great and I am still digesting a lot of what is in the project.  I especially dig the TestHelper library.  It just makes my job of testing routes a breeze.

    I mentioned I used a side project to learn ASP.Net MVC.  I know now that had I not done that I would still be sitting here thinking about learning it.  Why?  I found many things I took for granted with Web Forms were gone in ASP.Net MVC.  Viewstate for example.  I had certainly grown accustom to it.  Another gotcha for me was filling a dropdown list the right way (not directly in the controller).  I truly did have some frustrating points with ASP.Net MVC but only because I had to retrain myself to how the internet really works (Web Forms took care of this for me).  I really am better for it now.  

    Tip #4 – Take a tangible project and do it in ASP.Net MVC.  Stick with it.  It is very different from Web Forms if this is where you are coming from.  Please read my post on Confessions of a Web Form Guy Learning ASP.Net MVC if you want a little insight into some of the "aha" moments I had. 

    MVC is moving fast, as of this writing they are already on of MVC2 RC2.  A lot of new features are coming our way that make MVC that much sweeter. 

    I hope this helps you in your journey!  If you know of some other good resources for ASP.Net MVC please comment on it.

    Happy Coding!

    Posted 03.05.2010  #    Comments [0]  | 
    # Saturday, 12 December 2009

    Testing the routes in .Net MVC can be a bit tedious without some help.  MVCContrib’s TestHelper library eases the load and makes testing routes a breeze.

    To demonstrate, I created an application to manage recipes with their ingredients and directions. Below is how I wanted the routing to work.

    What I want the URL to look like What it will do
    /recipe List all recipes
    /recipe/blueberrypie Display blueberry pie recipe
    /recipe/edit/blueberrypie Edit blueberry pie recipe
    /recipe/blueberrypie/ingredients Show the ingredients for blueberry pie
    /recipe/blueberrypie/directions Show directions for blueberry pie
    /recipe/blueberrypie/ingredients/delete/1234 Delete ingredient with ID 1234 for blueberry pie & go back to the list of ingredients

    I edited the RegisterRoutes method in the Global.asax.cs file to match the table:

    // recipe/BlueberryPie/ingredients/edit/1234
    routes.MapRoute(
        "Ingredients",
        "recipe/{nameKey}/ingredients/{action}/{id}",
        new { controller = "Ingredients", action = "Index" },
        new { id = @"\d+" }
        );
    
    // recipe/BlueberryPie/ingredients/
    routes.MapRoute(
        "IngredientsForRecipe",
        "recipe/{nameKey}/ingredients/{action}",
        new { controller = "Ingredients", action = "List" }
        );
    
    // recipe/BlueberryPie/directions/edit/1234
    routes.MapRoute(
        "Directions",
        "recipe/{nameKey}/directions/{action}/{id}",
        new { controller = "directions", action = "Index" },
        new { id = @"\d+" }
        );
    
    // recipe/BlueberryPie/directions/
    routes.MapRoute(
        "DirectionsForRecipe",
        "recipe/{nameKey}/directions/{action}",
        new { controller = "directions", action = "List" }
        );
    
    // recipe/edit/BlueberryPie
    routes.MapRoute(
        null,
        "recipe/{action}/{nameKey}",
        new { controller = "Recipe", action = "List", nameKey = "" },
        new { action = "create|edit|index|list" }
        );
    
    // recipe/BlueberryPie
    routes.MapRoute(
        "recipe",
        "recipe/{nameKey}",
         new { controller = "Recipe", action = "Index" }
        );

    Now for the magic with MVCContrib’s TestHelper library and the extension ShouldMapTo:

    [TestFixture]
    public class RouteTests
    {
        [TestFixtureSetUp]
        public void SetUp()
        {
            RouteTable.Routes.Clear();
            MvcApplication.RegisterRoutes(RouteTable.Routes); 
        }
    
        [Test]
        public void RootMatchesHome()
        {
            "~/".ShouldMapTo(x => x.Index());
        }
    
        [Test]
        public void RecipeRootMatchesList()
        {
            "~/recipe".ShouldMapTo(x => x.List());
        }
    
        [Test]
        public void RecipeNameShouldDisplayIndex()
        {
            "~/recipe/BlueberryPie".ShouldMapTo(x => x.Index("BlueberryPie")); 
        }
    
        [Test]
        public void CreateRecipeShouldDisplayCreateAction()
        {
            "~/recipe/create/".ShouldMapTo(x => x.Create());
        }
    
        [Test]
        public void EditRecipeShouldDisplayEditAction()
        {
            "~/recipe/edit/BlueberryPie".ShouldMapTo(x => x.Edit("BlueberryPie"));
        }
        [Test]
        public void DeleteRecipeShouldDisplayDeleteAction()
        {
            "~/recipe/delete/1".ShouldMapTo(x => x.Delete(1));
        }
        [Test]
        public void IngredientsForRecipeShouldDisplayIngredientsListAction()
        {
            "~/recipe/BlueberryPie/ingredients".ShouldMapTo(i => i.List("BlueberryPie")); 
        }
        [Test]
        public void DirectionsForRecipeShouldDisplayIngredientsListAction()
        {
            "~/recipe/BlueberryPie/directions".ShouldMapTo(i => i.List("BlueberryPie"));
        }
        [Test]
        public void DeleteIngredientShouldDisplayDeleteAction()
        {
            "~/recipe/BlueberryPie/ingredients/delete/1".ShouldMapTo(i => i.Delete(1));
        }
        [Test]
        public void DeleteDirectionShouldDisplayDeleteAction()
        {
            "~/recipe/BlueberryPie/directions/delete/1".ShouldMapTo(i => i.Delete(1));
        }
    }

    No need to mock/fake any context, setup route data, etc.  The code is short and sweet, easy to read, understand and matches the URL that would be in the browser making it very intuitive.

    Please download the code.  The sample is using NUnit 2.5.

    MVCContribTestRoutes.zip (603.49 KB)

    Happy coding!

    Posted 12.12.2009  #    Comments [0]  | 
    # Wednesday, 25 November 2009

    I have been developing with ASP.Net since it debuted.  Before that I was doing windows form development with VB and classic ASP web development.  The advent of ASP.Net was phenomenal for me and my team.  The web forms model allowed our team to continue using the Windows event driven model over the web and allowed us to take our web development to a new level than classic ASP.  We quickly dispatched of our windows development in favor of the simple deploy / update model and gladly left the dreaded PC install / update nightmare.

    Fast forward many years and ASP.Net matured quite a bit, Windows Forms had click once and all sorts of other goodies in the framework.  Now MVC.  My experience with MVC up until this point had only been my reading in the Gang of Four book and the occasional blog entry.  While all this was going on I had (and still am) been on a mission to improve my programming skills.  The majority of this was and has been reading, reading, and more reading.  I started trying out test driven development with a side project of mine.  The project was web forms based.  I was greatly encouraged with TDD but had read all the difficulties with TDD and web forms.  I had just begun this side project and decided why not make the switch to MVC?  So I did.

    Along the way, I have had a lot of  "aha" moments.  Here’s some of them:

    Web forms code behind faked me out. I thought I had good separation of concerns. Or I really abused the code behind file but I thought I was doing right.

    For quite a while I knew large code behind files were not healthy.  I had been working as best as possible to decrease the code in them.  However, with my MVC journey I think I have come to see just how unhealthy large code behind files are and just because the code was not in the same file as my html did not mean I had a strong separation.  MVC by it’s nature encourages good separation and all the books and blog entries I have read show this by default.  In the web forms world I had to seek this out (not so much today but definitely in the early days and habits can be hard to change).

    I’m having data source withdrawals and View State withdrawals.

    I’m nearly over it now but this was a big hurdle for me.  It’s amazing how reliant I became on this but it shouldn’t be too much of a surprise since this is the magic of Web Forms. 

    I'm loving having control back of the HTML and the HTML is actually readable now.

    This is definitely has been a pleasant return to HTML for me.  With web forms I went on autopilot for much of the HTML / JavaScript that my apps produced.  I just lived with it even when I saw disgusting and bloated source.  Many took great pains to make web forms bend to their HTML will and I certainly understand why.  For me though, this is one of the reasons I like web forms so it didn’t bother me much.

    So why would I want the control back.  Simple, because I can easily have it back now and the trade off to me doesn’t really feel like a trade off.  MVC is far more bare bones by design but I still don’t feel like I am back at the classic ASP spaghetti code.  It’s this bare bones nature that I am really digging.  I have a lot more control over everything and even though I may not want to control a lot I know I have the option to.  I do miss at times the "drag and drop a control unto the canvas and go" mentality but with jQuery and HTML helpers I am missing it less and less as I become more proficient.

    Hello, JavaScript. It's been a while since we last worked together.

    With web forms, I enjoyed the luxury of not having to really getting down and dirty with JavaScript.  I used everything at my disposal to use a control and/or post backs to handle what was needed and only used JavaScript when I needed to.  Mind you, I realized this came with a price of some nice user interactions but I was willing to pay that price.  JavaScript and the DOM specifically were always giving me fits. 

    Unfortunately, this experience in the long ago past blinded me to the wonderful things going on with JavaScript over the years.  With JavaScript libraries like jQuery the capabilities that once required a JavaScript and DOM wizard are now at your fingertips.  I have fallen for JavaScript and am ashamed I had closed my mind off to it for so long. 

    MVC by it’s nature encourages JavaScript for rich UI interaction much like controls did for Web Forms but so much more.

    Testing? Ya, I did that. It's F5 right?

    MVC was not my start on considering better ways to test but everything I read and worked with on MVC had testing involved all the way.  Every book I have read, every beginning MVC blog entry has testing intertwined.  My first attempts at unit testing was with a web forms project and I was absolutely convinced it would make me a better developer, faster developer and create more maintainable code.  However, with web forms, testing for me and many I suspect was changing some code and hitting F5 to run the application and manually test.  With a little unit testing / TDD under my belt I have come to see how much more efficient it is to "F5 testing". 

    MVC permeates with the idea of unit testing and that’s by design.  I have much to learn on my testing journey but it has already paid dividends for me that has me convinced it’s an important tool in my toolset.

    I am working in harmony with the HTTP protocol now.

    I mentioned one of the reasons I liked web forms is that it allowed me a very easy transition from windows forms development.  As much as I would like to say I understood how the web really worked underneath the hood I know now that I didn’t.  Yes, I knew it was stateless and all that jazz but with web forms I was abstracted away from the way the web worked. 

    When I started learning MVC it became painfully obvious how much I had forgotten and/or didn’t really understand about how the web works.  I am still tripping over this while I continue my MVC journey but I am happy to say that the knowledge gained in understanding more deeply how the HTTP protocol really works is making me a better web developer.  “Working in harmony” is a paraphrased quote from "Pro ASP.NET MVC Framework" by Steven Sanderson.

    I am enjoying my MVC journey and look forward to becoming extremely proficient with it.  I will also admit that much of my 'aha' moments are not because of Web Forms, rather they were mainly a result of my own lack of exploration into what was possible and what was out there.  I was too busy keeping my head down and firing out widgets instead of really trying to hone my craft at all times while spitting out widgets. :-) This has changed for me now.  I have an extremely strong desire to be a real craftsman and not just someone who can bang on a keyboard.

    Web Forms is a great tool and I imagine I will continue to have it as a tool in my toolset for a long time to come along with MVC.

    Posted 11.25.2009  #    Comments [0]  |