Deciding Between ASP.NET MVC and WebForms

I am trying to create a decision flowchart for my ASP.NET MVC book and wanted to get some community feedback.  Does this diagram make sense?  What other factors should one consider that should make it into the chart?

image

Things to Note

I have tried to use the general consensus of the community for each decision.  For example, some might argue that MVC is better for prototyping but I would say the majority would disagree.

Keep in mind that these choices are not set in stone and are not mutually exclusive but are more like a guide to which platform would be better suited to satisfy a particular requirement.  For example you might want to use TDD but still end up choosing on WebForms.  (I should probably assign a weight to each question)

The "No" branch doesn’t mean exactly NO.  I mean, answering No to "Want cleaner HTML?" doesn’t mean you have something against clean HTML or you want crappy HTML – no one wants that.  Think of the question in terms of "is clean html important to you?" 

Let me hear your feedback below and I will incorporate it in version of 2 of the diagram and post it back on the blog.  Hopefully, this will help someone choose between ASP.NET MVC and WebForms on a new project.

Also, I don’t think a flowchart diagram is the best type of diagram for this type of decision tree.  Can you suggest a better format?

Use ModelBinder to Generically Bind Complex Types

[Update: Simone brought my attention to the fact that ComplexModelBinder which comes with the framework does exactly that.  You can find more info here]

ASP.NET MVC Preview 5 introduce the ModelBinder attribute that can be used to decorate a complex type in an Action.  This allows us to have actions that look like this

public ActionResult Create([ModelBinder(typeof(GenericBinder))] ContactList myList)

 

Instead of this:

public ActionResult Create(string name, string description)

 

The problem is that you have to build a Binder for every complex type you want to use as a parameter.  For example, Maarten Balliauw created a model binder on his blog and it looks like this:

public class ContactBinder : IModelBinder
{
    #region IModelBinder Members
    public object GetValue(ControllerContext controllerContext, 
                 string modelName, Type modelType, 
                 ModelStateDictionary modelState)
    {
        if (modelType == typeof(Contact))
        {
            return new Contact
            {
                Name = controllerContext.HttpContext.Request.Form["name"] ?? "",
                Email = controllerContext.HttpContext.Request.Form["email"] ?? "",
                Message = controllerContext.HttpContext.Request.Form["message"] ?? ""
            };
        }
        return null;
    }
    #endregion
}

 

Now that is a lot of typing and because I am lazy, I decided to create a generic binder that uses reflection and can work with all my complex types. 

Note: By generic I mean common – it has nothing to do with .net Generics

Also note that this will only work if you follow these conventions:

  1. The html field name must match the property name
  2. User lower case names for the html fields
  3. You don’t have to user lower case on your model properties

Here is the very rough and untested Generic Binder:

class GenericBinder : IModelBinder
{
    public object GetValue(ControllerContext controllerContext, 
                            string modelName, Type modelType, 
                            ModelStateDictionary modelState)
    {
        var instance = Activator.CreateInstance(modelType);
        foreach (var prop in modelType.GetProperties())
        {
            prop.SetValue(instance, 
                    controllerContext.HttpContext.Request
                                    .Form[prop.Name.ToLower()], 
                    null);
        }
        return instance;
    }
}

 

If you find any bugs or have a better implementation, please share.

Is this Better than Constructor Injection?

So after I finished my post on property injection I thought of something, maybe I shouldn’t use constructor injection for my classes.  Maybe, I can just use lazy properties that would call my IoC (Ninject) Kernel to instantiate the object.  So instead of defining a constructor like this:

public IAccountService Service { get; set; }

[Inject]
public AccountController(IAccountService service)
{
    Service = service;
}

I could just have a property Service do the work like this:

public IAccountService Service
{
    get
    {
        return (IAccountService) Kernel.Get(typeof (IAccountService));
    }
}

If I get rid of all my constructor parameters then I won’t need to change my ControllerFactory to use the Ninject Factory.  This keeps looking better and better.

What do you think?  I keep reading everywhere that construction injection is the way to go.  But why complicate my constructor when I can have the properties do the heavy lifting?  I would love to hear what you think.

Property Injection in ASP.NET MVC with Ninject

I got a design challenge with asp.net mvc.  I want to keep track of the currently logged in user in the session because I don’t want to hit the database every time I need to get the username or id for a query.  And I have all my controllers inherit from a base controller named BaseController.  So, I added a CurrentUser property to the BaseController and I want it to automagically work without the derived controllers having to do anything.  Here is a class diagram to help clarify:

image

The CurrentUser Property needs to look something like this:

public User CurrentUser
{
    get
    {
        var key = "currentuser";
        if (Session[key] == null)
        {
            Session[key] = /*get user from database some how*/;
        }
        return (User) Session[key] ;
    }
}

This looks simple enough but it is not.  The reason it is not simple is because to get the current user I have to call Membership.Provider.GetUser from the BaseController.  The problem with that is that it creates a dependency on the MembershipProvider class which I don’t want to have, because it will make testing very hard.

One obvious solution was to add the MembershipProvider (which is an abstract class) to the BaseController’s construct and then pass a mocked instance during testing…  The problem with this design is that now my BaseController will be forced to have a parameterized constructor which means that I have to change the code in all the derived controllers to handle that and pass the appropriate instance of MembershipProvider.  Sounds like a code smell.

My solution was to create the MembershipProvider class using my IoC container – in this case, my Ninject Kernel.  This allows me to inject a SqlMembershipProvider in development and runtime and inject a mocked provider in testing.  So the final CurrentUser property looks like this:

public User CurrentUser
{
    get
    {
        var key = "currentuser";
        if (Session[key] == null)
        {
            var Provider
                = (MembershipProvider)
                    Kernel.Get(typeof(MembershipProvider));

            Session[key] = AppHelper.CreateUserFromMembershipUser
                            (Provider.GetUser(User.Identity.Name, true));
        }
        return (User) Session[key] ;
    }
}

If you have been paying attention, you are probably wondering  what is this “Kernel” thing.  Well Kernel is an instance of the Ninject Kernel which itself was injected into the BaseController class like this:

[Inject]
public IKernel Kernel { get; set; }

I could have done this differently.  For example, I could have injected the provider itself using property injection like this:

[Inject]
public MembershipProvider Provider { get; set; }

The only problem is that the provider isn’t needed by all the derived classed and I didn’t want to have a public property in the base class that would hardly be used anywhere else.   On the other hand Kernel could be globally used to instantiate an object.

What do you think?  Is this the way to do it?  Is there a better way?

Ninject: Killer IoC

In my previous post, The Best IoC Container, I decided to go with StructureMap as the framework of choice.  I received a comment telling me to check out Ninject and then a day or two after, I saw Corey Gaudin’s post on using Ninject with MVC, so I decided to try it out.

It wasn’t too hard to get up and running in asp.net mvc.  Corey’s post was a good starting point but I was too lazy to type all his code in, I wrote my own.  It was pretty easy to get Ninject to work.

I basically created a NinjecteControllerFactory class that inherits from the DefaultControllerFactory and overrode a couple of methods.  The class looks like this:

public class NinjectControllerFactory : DefaultControllerFactory
{
    private IKernel _kernel;
    public NinjectControllerFactory(params IModule[] modules)
    {
        _kernel = new StandardKernel(modules);
    }

    protected override IController GetControllerInstance(Type controllerType)
    {
        return _kernel.Get(controllerType) as IController;
    }
}

 

Then in my Gloval.asax.cs file, I called this code to setup Ninject.

IModule[] modules = new IModule[] { new WebModule() };
ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory(modules));

 

The WebModule module has my configuration and looks like this:

public class WebModule : StandardModule
{
    public override void Load()
    {
        Bind<IAppService>().To<AspAppService>();
        Bind<IEmailService>().To<EmailService>();
        Bind<IContactService>().To<ContactService>();
        Bind<IContactRepository>().To<SqlContactRepository>();
        Bind<IFormsAuthentication>().To<FormsAuthenticationWrapper>();
        Bind<MembershipProvider>().ToConstant(Membership.Provider);
    }
}

 

Of course, you can create as many modules as you want to configure your application and pass them in the controller Factory.

This code was working fine for me and then Nate Kohari mentioned that there is a Ninject.Framework.Mvc extension that allows me to easily integrate Ninject into the MVC pipeline.  So, I decided to download the code, build it and use it.  I initially had some issues because it was referencing a different version of the core dll, so I had to rebuild that as well.

I changed my Global.asax.cs file to the following:

public class GlobalApplication : NinjectHttpApplication
{
    protected override void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            "Default",                                              // Route name
            "{controller}/{action}/{id}",                           // URL with parameters
            new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
        );
    }

    protected override IKernel CreateKernel()
    {
        IModule[] modules = new IModule[] { new AutoControllerModule(Assembly.GetExecutingAssembly()), new WebModule() };
        return new StandardKernel(modules);
    }
}

Initially I was getting errors when navigating to an injected controller, which was fixed by add the AutoControllerModule to my modules and passing it the current assembly.

So far Ninject is looking great, the API is fluent and very discoverable and the contextual binding is very slick.  So I am going to stick with it for now and see how it goes.  The documentation seems pretty good and the Nate is very responsive in the Google Group.

Yonkly: New Release 04-14-08

[update: Yonkly source code is now public]

I just released an updated version of Yonkly.

Here is a list of changes, additions and improvements:

  1. Fixed email issues
  2. Added About section under the avatar
  3. Using TinyUrl for Url shortening.
  4. Added profile Url under the avatar (so add your blog/website to your profile)
    image
  5. Added more stats and each one is linked to the appropriate view
    image
  6. Improved the message timestamp, so it is more granular (days, hours and minutes)
  7. Improved search so “tes” will match “tes*” but will only return 5 matches.
  8. Improved error handling and a generic error page.
  9. Added error logging to database
  10. Improved performance of some queries
  11. Refactored code and views

I will try to update it every couple of days, so stay tuned for more updates.

Don’t hesitate to request/suggest a feature. I am kind of winging it right now.

CMAP Code Camp 2008 Spring Edition

Yesterday, I gave a talk at CMAP Code Camp about the asp.net mvc framework and AJAX using JQuery. This is my first time speaking, so I was a little nervous. I think I did ok but I can’t really tell. Of course, the talk didn’t go as planned, because Visual Studio didn’t cooperate. Thankfully, I had a Plan B and pulled up code that I had already prepared and just walked through it and explained it. I wanted to give more details but I didn’t have enough time.

So, if you have attended the talk, I would love to hear your feedback, so please leave me a comment or send me a not through the contact page.

Previously, I posted some asp.net mvc framework resources over here. You can also see my mvc bookmarks at http://del.icio.us/eibrahim/mvc

There are also tons of JQuery resources at www.jquery.com and I found this handy JQuery 1.2 cheat sheet (remember: this is for version 1.2)

document.write(”);

var scribd_doc = new scribd.Document(2093417, ‘key-r2kryjbgk3xe6r92w2k’); scribd_doc.addParam(‘height’, 370); scribd_doc.addParam(‘width’, 450); scribd_doc.addParam(‘page’, 1); scribd_doc.addParam(‘mode’, ‘list’); scribd_doc.write(’embedded_flash_2093417_ie0ue’);

“According to most studies, people’s number one fear is public speaking. Number two is death. Death is number two. Does that sound right? This means to the average person, if you go to a funeral, you’re better off in the casket than doing the eulogy.” – Jerry Seinfeld.