26 Jul, 2010 in Programming by

Lessons from my first ASP.NET MVC 2 web application

;

image

There’s no better way to learn a new technology than to dive right in. 🙂

I recently had to rebuild a .NET 1.1 Web Forms application built back in 2005. I decided to use ASP.NET MVC to quickly re-create the application from scratch. I really like the MVC pattern because I have manually built apps using some of the same concepts naturally for many years.

These are some of the stumbling blocks I hit my first time around. I hope these can be of use to you.

 

Dynamic Drop Down List with JQuery and JSON

Here’s a good post on exposing data from your Controller and consuming it via JQuery to make a dynamic select list of options:

http://dkdevelopment.net/2010/05/04/mvc2-cascading-dropdown-lists-with-json/

 

If you’re planning on returning objects that have a relationship with another class, you’ll get this Exception:

"A circular reference was detected while serializing an object of type <type>"

 

This is a feature that ASP.NET MVC doesn’t support yet, so here’s a simple workaround to return an anonymous type:

http://mytechworld.officeacuity.com/?p=577

 

Helpers

These 2 methods keep your web application Views working after you’ve published it to the live environment. They will make sure any URLs resolve correctly and resources can be access correctly.

1. Use <%= Url.Action("Action", "Controller") %> in JavaScript to resolve the Action correctly in any JQuery/Ajax functions.

Example:

$(this).attr("href", '<%= Url.Action("YourAction", "YourController") %>');
 

2. Use <%= Url.Content(“~/Path/File.ext”) %> in your HTML when referencing an image, script or style sheet in a sub directory.

Example:

<script src="<%= Url.Content("~/Scripts/MicrosoftAjax.js") %>" type="text/javascript"></script>

 

LINQ

This isn’t specific to MVC but I really started learning both at the same time.

If you want to test for an existing record in a database, use the .SingleOrDefault() method on your .Where clause so you can test for NULL rather than an exception being thrown because the record may not exist.

Example:

if (this.repository.FindAll().Where(x => x.ID == newID).SingleOrDefault() == null)
{
  //TODO: add a record because it doesn't exist.
}

//The record should exist one way or another here.

 

Database Repositories

In order to write good unit tests against your controllers, you should look at abstracting out your data access layer. That way you can create mock table repositories in your tests rather than hitting a real database during your tests.

Then in your controller you can have at least 2 constructors, 1) without parameters that creates a concrete DAL repository class and 2) with parameters that takes a class that implements IRepository.

During normal runtime, your controller will initialize with concrete data classes. In your unit tests you can pass in your own simple repository that does enough work for the tests to pass.

Here’s my IRepository interface:

public interface IRepository<T>
{
    void Add(T entity);
    IQueryable<T> FindAll();
    T Find(int id);        
    void Update(T entity);
    void Delete(T entity);
}

Now I can have a SqlTableRepository or MockTableRepository that will both implement the same methods yet only one is safe for testing purposes.

This is a bigger concept to be explored but so far looks like a great practice for writing maintainable code.

 

IIS

If you are publishing this MVC application to a Windows 2003 / IIS 6 server, you’ll need to make a change to the web site’s settings so the dynamic routes work correctly.

You have to map all incoming requests to go through aspnet_isapi.dll and uncheck the “Verify that file exists” option.

IIS Wildcard Settings

 

 

 

 

 

 

 

 

 

 

That’s it for now.

Leave a comment if you have any questions or want any of these areas explained further.

Share on Twitter

2 Responses so far | Have Your Say!

  1. Wavatar

    Damian Karzon  |  July 27th, 2010 at 2:33 am #

    Great Post and thanks for the link.

    Talking about the return classes though, I normally create a set of classes to use as Json I found that makes it easier for when you want to send data to your controller and deserialize it.

    Also, with your linq query, you can add a query to the SingleOrDefault Function so instead of .Where(x => x.ID == newID).SingleOrDefault() you can just use .SingleOrDefault(x => x.ID == newID) or alternatively you could add a IEnumerable Find(Func exp); to your IRepository interface and that returns GetTable.Where(exp);

    LINQ is awesome once you get the hang of it! Keep up the good work.

  2. Wavatar

    Roger  |  July 27th, 2010 at 1:38 pm #

    Thanks for the LINQ tips Damian! That’ll save a few keystrokes.