Maarten Balliauw {blog}

ASP.NET, ASP.NET MVC, Windows Azure, PHP, ...

NAVIGATION - SEARCH

ASP.NET MVC 3 and MEF sitting in a tree...

As I stated in a previous blog post: ASP.NET MVC 3 preview 1 has been released! I talked about some of the new features and promised to do a blog post in the dependency injection part. In this post, I'll show you how to use that together with MEF.

Download my sample code: Mvc3WithMEF.zip (256.21 kb)

kick it on DotNetKicks.com

Dependency injection in ASP.NET MVC 3

First of all, there’s 4 new hooks for injecting dependencies:

  • When creating controller factories
  • When creating controllers
  • When creating views (might be interesting!)
  • When using action filters

In ASP.NET MVC 2, only one of these hooks was used for dependency injection: a controller factory was implemented, using a dependency injection framework under the covers. I did this once, creating a controller factory that wired up MEF and made sure everything in the application was composed through a MEF container. That is, everything that is a controller or part thereof. No easy options for DI-ing things like action filters or views…

ASP.NET MVC 3 shuffled the cards a bit. ASP.NET MVC 3 now contains and uses the Common Service Locator’s IServiceLocator interface, which is used for resolving services required by the ASP.NET MVC framework. The IServiceLocator implementation should be registered in Global.asax using just one line of code:

[code:c#]

MvcServiceLocator.SetCurrent(new SomeServiceLocator());

[/code]

This is, since ASP.NET MVC 3 preview 1, the only thing required to make DI work. In controllers, in action filters and in views. Cool, eh?

Leveraging MEF with ASP.NET MVC 3

First of all: a disclaimer. I already did posts on MEF and ASP.NET MVC before, and in all these posts, I required you to explicitly export your controller types for composition. In this example, again, I will require that, just for keeping code a bit easier to understand. Do note that are some variants of a convention based registration model available.

As stated before, the only thing to build here is a MefServiceLocator that is suited for web (which means: an application-wide catalog and a per-request container). I’ll still have to create my own controller factory as well, because otherwise I would not be able to dynamically compose my controllers. Here goes…

Implementing ServiceLocatorControllerFactory

Starting in reverse, but this thing is the simple part :-)

[code:c#]

[Export(typeof(IControllerFactory))]
[PartCreationPolicy(CreationPolicy.Shared)]
public class ServiceLocatorControllerFactory
    : DefaultControllerFactory
{
    private IMvcServiceLocator serviceLocator;

    [ImportingConstructor]
    public ServiceLocatorControllerFactory(IMvcServiceLocator serviceLocator)
    {
        this.serviceLocator = serviceLocator;
    }

    public override IController CreateController(RequestContext requestContext, string controllerName)
    {
        var controllerType = GetControllerType(requestContext, controllerName);
        if (controllerType != null)
        {
            return this.serviceLocator.GetInstance(controllerType) as IController;
        }

        return base.CreateController(requestContext, controllerName);
    }

    public override void ReleaseController(IController controller)
    {
        this.serviceLocator.Release(controller);
    }
}

[/code]

Did you see that? A simple, MEF enabled controller factory that uses an IMvcServiceLocator. This thing can be used with other service locators as well.

Implementing MefServiceLocator

Like I said, this is the most important part, allowing us to use MEF for resolving almost any component in the ASP.NET MVC pipeline. Here’s my take on that:

[code:c#]

[Export(typeof(IMvcServiceLocator))]
[PartCreationPolicy(CreationPolicy.Shared)]
public class MefServiceLocator
    : IMvcServiceLocator
{
    const string HttpContextKey = "__MefServiceLocator_Container";

    private ComposablePartCatalog catalog;
    private IMvcServiceLocator defaultLocator;

    [ImportingConstructor]
    public MefServiceLocator()
    {
        // Get the catalog from the MvcServiceLocator.
        // This is a bit dirty, but currently
        // the only way to ensure one application-wide catalog
        // and a per-request container.
        MefServiceLocator mefServiceLocator = MvcServiceLocator.Current as MefServiceLocator;
        if (mefServiceLocator != null)
        {
            this.catalog = mefServiceLocator.catalog;
        }

        // And the fallback locator...
        this.defaultLocator = MvcServiceLocator.Default;
    }

    public MefServiceLocator(ComposablePartCatalog catalog)
        : this(catalog, MvcServiceLocator.Default)
    {
    }

    public MefServiceLocator(ComposablePartCatalog catalog, IMvcServiceLocator defaultLocator)
    {
        this.catalog = catalog;
        this.defaultLocator = defaultLocator;
    }

    protected CompositionContainer Container
    {
        get
        {
            if (!HttpContext.Current.Items.Contains(HttpContextKey))
            {
                HttpContext.Current.Items.Add(HttpContextKey, new CompositionContainer(catalog));
            }

            return (CompositionContainer)HttpContext.Current.Items[HttpContextKey];
        }
    }

    private object Resolve(Type serviceType, string key = null)
    {
        var exports = this.Container.GetExports(serviceType, null, null);
        if (exports.Any())
        {
            return exports.First().Value;
        }

        var instance = defaultLocator.GetInstance(serviceType, key);
        if (instance != null)
        {
            return instance;
        }

        throw new ActivationException(string.Format("Could not resolve service type {0}.", serviceType.FullName));
    }

    private IEnumerable<object> ResolveAll(Type serviceType)
    {
        var exports = this.Container.GetExports(serviceType, null, null);
        if (exports.Any())
        {
            return exports.Select(e => e.Value).AsEnumerable();
        }

        var instances = defaultLocator.GetAllInstances(serviceType);
        if (instances != null)
        {
            return instances;
        }

        throw new ActivationException(string.Format("Could not resolve service type {0}.", serviceType.FullName));
    }

    #region IMvcServiceLocator Members

    public void Release(object instance)
    {
        var export = instance as Lazy<object>;
        if (export != null)
        {
            this.Container.ReleaseExport(export);
        }

        defaultLocator.Release(export);
    }

    #endregion

    #region IServiceLocator Members

    public IEnumerable<object> GetAllInstances(Type serviceType)
    {
        return ResolveAll(serviceType);
    }

    public IEnumerable<TService> GetAllInstances<TService>()
    {
        var instances = ResolveAll(typeof(TService));
        foreach (TService instance in instances)
        {
            yield return (TService)instance;
        }
    }

    public TService GetInstance<TService>(string key)
    {
        return (TService)Resolve(typeof(TService), key);
    }

    public object GetInstance(Type serviceType)
    {
        return Resolve(serviceType);
    }

    public object GetInstance(Type serviceType, string key)
    {
        return Resolve(serviceType, key);
    }

    public TService GetInstance<TService>()
    {
        return (TService)Resolve(typeof(TService));
    }

    #endregion

    #region IServiceProvider Members

    public object GetService(Type serviceType)
    {
        return Resolve(serviceType);
    }

    #endregion
}

[/code]

HOLY SCHMOLEY! That is a lot of code. Let’s break it down…

First of all, I have 3 constructors. 2 for convenience, one for MEF. Since the MefServiceLocator will be instantiated in Global.asax and I only want one instance of it to live in the application, I have to do a dirty trick: whenever MEF wants to create a new MefServiceLocator for some reason (should in theory only happen once per request, but I want this thing to live application-wide), I’m giving it indeed a new instance which at least shares the part catalog with the one I originally created. Don’t shoot me for doing this…

Next, you will also notice that I’m using a “fallback” locator, which in theory will be the instance stored in MvcServiceLocator.Default, which is ASP.NET MVC 3’s default MvcServiceLocator. I’m doing this for a reason though… read my disclaimer again: I stated that everything should be decorated with the [Export] attribute when I’m relying on MEF. Now since the services exposed by ASP.NET MVC 3, like the IFilterProvider, are not decorated with this attribute, MEF will not be able to find those. When I find myself in that situation, the MefServiceLocator is simply asking the default service locator for it. Not a beauty, but it works and makes my life easy.

Wiring things

To wire this thing, all it takes is adding 3 lines of code to my Global.asax. For clarity, I’m giving you my entire Global.asax Application_Start method:

[code:c#]

protected void Application_Start()
{
    // Register areas

    AreaRegistration.RegisterAllAreas();

    // Register filters and routes

    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);

    // Register MEF catalogs

    var catalog = new DirectoryCatalog(
        Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin"));
    MvcServiceLocator.SetCurrent(new MefServiceLocator(catalog, MvcServiceLocator.Default));
}

[/code]

Can you spot the 3 lines of code? This is really all it takes to make the complete application use MEF where appropriate. (Ok, that is a bit of a lie since you would still have to implement a very small IFilterProvider if you want MEF in your action filters, but still.)

Hooks

The cool thing is: a lot of things are now requested in the service locator we just created. When browsing to my site index, here’s all the things that are requested:

  • Resolve called for serviceType: System.Web.Mvc.IControllerFactory
  • Resolve called for serviceType: Mvc3WithMEF.Controllers.HomeController
  • Resolve called for serviceType: System.Web.Mvc.IFilterProvider
  • Resolve called for serviceType: System.Web.Mvc.IFilterProvider
  • Resolve called for serviceType: System.Web.Mvc.IFilterProvider
  • Resolve called for serviceType: System.Web.Mvc.IFilterProvider
  • Resolve called for serviceType: System.Web.Mvc.IViewEngine
  • Resolve called for serviceType: System.Web.Mvc.IViewEngine
  • Resolve called for serviceType: ASP.Index_cshtml
  • Resolve called for serviceType: System.Web.Mvc.IViewEngine
  • Resolve called for serviceType: System.Web.Mvc.IViewEngine
  • Resolve called for serviceType: ASP._LogOnPartial_cshtml

Which means that you can now even inject stuff into views or compose their parts dynamically.

Conclusion

I have a strong sense of a power in here… ASP.NET MVC 3 will support DI natively if you want to use it, and I’ll be one of the users happily making use of it. There’s use cases for injecting/composing something in all of the above components, and ASP.NET MVC 3 made this just simpler and more straightforward.

Here’s my sample code with some more examples in it: Mvc3WithMEF.zip (256.21 kb)

ASP.NET MVC 3 preview 1 is out! Quick review...

I just noticed a very interesting download: ASP.NET MVC 3 preview 1. Yes, you are reading this correctly, the first bits for v3.0 are there! Let’s have a quick look around and see what’s new...

kick it on DotNetKicks.com

Razor Syntax View Engine

ScottGu blogged about Razor before. ASP.NET MVC has always supported the concept of “view engines”, pluggable modules that allow you to have your views rendered by different engines like for example the WebForms engine, Spark, NHAML, …

Razor is a new view engine, focused on less code clutter and shorter code-expressions for generating HTML dynamically. As an example, have a look at the following view:

[code:c#]

<ul>
  <% foreach (var c in Model.Customers) { %>
    <li><%:c.DisplayName%></li>
  <% } %>
</ul>

[/code]

In Razor syntax, this becomes:

[code:c#]

<ul>
  @foreach (var c in Model.Customers) {
    <li>@c.DisplayName</li>
  }
</ul>

[/code]

Perhaps not the best example to show the strengths of this new engine, but do bear in mind that Razor simply puts code literally in your HTML, making it develop faster (did I mention perfect IntelliSense support in the Razor view editor?).

Also, there’s a nice addition to the “Add View” dialog in Visual Studio: you can now choose for which view engine you want to generate a view.

Razor view engine - Add view dialog

ViewData dictionary “dynamic” support

.NET 4 introduced the “dynamic” keyword, which is abstracting away a lot of reflection code you’d normally have to write yourself. The fun thing is, that the MVC guys abused this thing in a very nice way.

Controller action method, ASP.NET MVC 2:

[code:c#]

public ActionResult Index()
{
    ViewModel["Message"] = "Welcome to ASP.NET MVC!";

    return View();
}

[/code]

Controller action method, ASP.NET MVC 3:

[code:c#]

public ActionResult Index()
{
    ViewModel.Message = "Welcome to ASP.NET MVC!";

    return View();
}

[/code]

“Isn’t that the same?” – Yes, in essence it is exactly the same concept at work. However, by using the dynamic keyword, there’s less “string pollution” in my code. Do note that in most situations, you would create a custom “View Model” and pass that to the view instead of using this ugly dictionary or dynamic object. Nevertheless: I do prefer reading code that uses less dictionaries.

So far for the controller side, there’s also the view side. Have a look at this:

[code:c#]

@inherits System.Web.Mvc.WebViewPage

@{
    View.Title = "Home Page";
    LayoutPage = "~/Views/Shared/_Layout.cshtml";
}

<h2>@View.Message</h2>
<p>
    To learn more about ASP.NET MVC visit <a href="http://asp.net/mvc" title="ASP.NET MVC Website">http://asp.net/mvc</a>.
</p>

[/code]

A lot of new stuff there, right? First of all the Razor syntax, but secondly… There’s just something like @View.Message in this view, and this is rendering something from the ViewData dictionary/dynamic object. Again: very readable and understandable.

It’s a small change on the surface, but I do like it. In my opinion, it’s more readable than using the ViewData dictionary when you are not using a custom view model.

Global action filters

Imagine you have a team of developers, all writing controllers. Imagine that they have to add the [HandleError] action filter to every controller, and they sometimes tend to forget… That’s where global action filters come to the rescue! Add this line to Global.asax:

[code:c#]

GlobalFilters.Filters.Add(new HandleErrorAttribute());

[/code]

This will automatically register that action filter attribute for every controller and action method.

Fun fact: I blogged about exactly this feature about a year ago: Application-wide action filters in ASP.NET MVC. Want it in ASP.NET MVC 2? Go and get it :-)

Cool, eh? Well… I do have mixed feelings about this… I can imagine there are situations where you want to do this more selectively. Here’s my call-out to the ASP.NET MVC team:

  • At least allow to specify action filters on a per-area level, so I can have my “Administration” area have other filters than my default area.
  • In an ideal world, I’d prefer something where I can specify global action filters even more granularly. This can be done using some customizing, but it would be useful to have it out-of-the-box. Here's an example of the ideal world:

[code:c#]

GlobalFilters.Filters.AddTo<HomeController>(new HandleErrorAttribute()) 
                     .AddTo<AccountController>(c => c.ChangePassword(), new AuthorizeAttribute());

[/code]

Dependency injection support

I’m going to be short on this one: there’s 4 new hooks for injecting dependencies:

  • When creating controller factories
  • When creating controllers
  • When creating views (might be interesting!)
  • When using action filters

More on that in my next post on ASP.NET MVC 3, as I think it deserves a full post rather than jut some smaller paragraphs.

Update: Here's that next post on ASP.NET MVC 3 and dependency injection / MEF

New action result types

Not very ground-skaing news, but there's a new set of ActionResult variants available which will make your life easier:

  • HttpNotFoundResult - Speaks for itself, right :-)
  • HttpStatusCodeResult - How about new HttpStatusCodeResult(418, "I'm a teapot");
  • RedirectPermanent, RedirectToRoutePermanent, RedirectToActionPermanent - Writes a permanent redirect header

Conclusion

I only touched the tip of the iceberg. There’s more to ASP.NET MVC 3 preview 1, described in the release notes.

In short, I’m very positive about the amount of progress being made in this framework! Very pleased with the DI portion of it, on which I’ll do a blog post later.

Update: Here's that next post on ASP.NET MVC 3 and dependency injection / MEF

Manage your SQL Azure database from your browser

Yesterday, I noticed on Twitter that the SQL Azure - Project “Houston” CTP 1 has been released online. For those who do not know Houston, this is a lightweight and easy to use database management tool for SQL Azure databases built in Silverlight. Translation: you can now easily manage your SQL Azure database using any browser. It’s not a replacement for SSMS, but it’s a viable, quick solution into connecting to your cloudy database.

kick it on DotNetKicks.com

A quick look around

After connecting to your SQL Azure database through http://manage.sqlazurelabs.com, you’ll see a quick overview of your database elements (tables, views, stored procedures) as well as a fancy, three-dimensional cube displaying your database details.

image

Let’s create a new table… After clicking the “New table” toolbar item on top, a simple table designer pops up:

image

You can now easily design a table (in a limited fashion), click the “Save” button and go enter some data:

image

Stored procedures? Those are also supported:

image

Even running stored procedures:

image

Conclusion

As you can probably see from the screenshots, project “Houston” is currently quite limited. Basic operations are supported, but for example dropping a table should be done using a custom, hand-crafted query instead of a simple box.

What I would love to see is that the tool gets a bit more of the basic database operations and a Windows Phone 7 port? That would allow me to quickly do some trivial SQL Azure tasks both from my browser as well as from my (future :-)) smartphone.

Renewed MVP ASP.NET for 2010!

Just got the best e-mail a Microsoft community member can receive in his mailbox:MVPLogo

Dear Maarten Balliauw,

Congratulations! We are pleased to present you with the 2010 Microsoft® MVP Award! This award is given to exceptional technical community leaders who actively share their high quality, real world expertise with others. We appreciate your outstanding contributions in ASP/ASP.NET technical communities during the past year.

(...)

Toby Richards
General Manager
Community Support Services

I wish to thank everyone who has been supporting me, encouraging me, challenging me and thus bringing me to a second year of MVP duty. I will try to achieve the same for next year: do a lot of sessions, work on open-source, do blog posts, …

With that: if you are not yet at lest challenging me, please do start doing this. It only helps me to learn from your problems which will in turn help the whole community to learn from it.

I can almost copy my blog post from last year on the next part: I will leave the community for the next weeks to enjoy a nice vacation in Austria. No, not traveling for work this time. My next two weeks community will be a community of mountains, sun, große Bier and rest (not REST!). See you!