Logo

Maarten Balliauw {blog}

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

About the author

Maarten Balliauw is currently employed as .NET Technical Consultant at RealDolmen. His interests are mainly web applications developed in ASP.NET (C#) or PHP and the Windows Azure cloud platform.
More about me More about me
Send mail E-mail me


ASP.NET MVC Quickly Pro NuGet Subscribe to my RSS feed Follow me on Twitter! View Maarten Balliauw's profile on LinkedIn
Maarten Balliauw - MVP - Most Valuable Professional
Maarten Balliauw - ASPInsider

Search

Latest Twitter

    Follow me on Twitter...

    Archive

    Disclaimer

    The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

    © Copyright Maarten Balliauw 2012


    ASP.NET MVC and the Managed Extensibility Framewok on NuGet

    imageIf you search on my blog, there’s a bunch of posts where I talk about ASP.NET MVC and MEF. And what’s cool: these posts are the ones that are actually being read quite often. I’m not sure about which bloggers actually update their posts like if it was software, but I don’t. Old posts are outdated, that’s the convention when coming to my blog. However I recently received a on of questions if I could do something with ASP.NET MVC 3 and MEF. I did, and I took things seriously.

    I’m not sure if you know MefContrib. MefContrib is a community-developed library of extensions to the Managed Extensibility Framework (MEF). I decided to wear my bad-ass shoes and finally got around installing a Windows-friendly Git client and decided to just contribute an ASP.NET MVC + MEF component to MefContrib. And while I was at it, I created some NuGet packages for all MefContrib components.

    Let’s see how easy it is to use ASP.NET MVC and MEF…

    Here’s the sample code I used: MefMvc.zip (698.58 kb)

    Obtaining MefContrib.MVC3 in an ASP.NET MVC application

    Here’s the short version of this blog post section for the insiders: Install-Package MefContrib.MVC3

    Assuming you have already heard something about NuGet, let’s get straight to business. Right-click your ASP.NET MVC project in Visual Studio and select “Add Library Package Reference…”. Search for “MefContrib.MVC3”. Once found, click the “Install” button.

    This action will download and reference the new MefContrib.Web.Mvc assembly I contributed as well as the MefContrib package.

    How to get started?

    You may notice a new file “AppStart_MefContribMVC3.cs” being added to your project. This one is executed at application start and wires all the MEF-specific components into ASP.NET MVC 3. Need something else than our defaults? Go ahead and customize this file. Are you happy with this code block? Continue reading…

    You may know that MEF is cool as ICE and thus works with Import, Compose and Export. This means that you can now start composing your application using [Import] and [Export] attributes, MefContrib will do the rest. In earlier posts I did, this also meant that you should decorate your controllers with an [Export] attribute. Having used this approach on many projects, most developers simply forget to do this at the controller model. Therefore, MefContrib.Web.Mvc  uses the ConventionCatalog from MefContrib to automatically export every controller it can find. Easy!

    To prove it works, open your FormsAuthenticationService class and add an ExportAttribute to it. Like so:

    1 [Export(typeof(IFormsAuthenticationService))] 2 public class FormsAuthenticationService : IFormsAuthenticationService 3 { 4 // ... 5 }

    Do the same for the AccountMembershipService class:

    1 [Export(typeof(IMembershipService))] 2 public class AccountMembershipService : IMembershipService 3 { 4 // ... 5 }

    Now open up the AccountController and lose the Initialize method. Yes, just delete it! We’ll tell MEF to resolve the IFormsAuthenticationService and IMembershipService. You can even choose how you do it. Option one is to add properties for both and add an ImportAttribute there:

    1 public class AccountController : Controller 2 { 3 [Import] 4 public IFormsAuthenticationService FormsService { get; set; } 5 6 [Import] 7 public IMembershipService MembershipService { get; set; } 8 9 // ... 10 }

    The other option is to use an ImportingConstructor:

    1 public class AccountController : Controller 2 { 3 public IFormsAuthenticationService FormsService { get; set; } 4 public IMembershipService MembershipService { get; set; } 5 6 [ImportingConstructor] 7 public AccountController(IFormsAuthenticationService formsService, IMembershipService membershipService) 8 { 9 FormsService = formsService; 10 MembershipService = membershipService; 11 } 12 }

    Now run your application, visit the AccountController and behold: dependencies have been automatically resolved.

    Conclusion

    There’s two conclusions to make: MEF and ASP.NET MVC3 are now easier than ever and available through NuGet. Second: MefContrib is now also available on NuGet, featuring nifty additions like the ConventionCatalog and AOP-style interception.

    Enjoy! Here’s the sample code I used: MefMvc.zip (698.58 kb)

    Need domain registration?


    Categories: ASP.NET | C# | General | ICT | MEF | MVC | Projects

    Comments (11) -

    Corey Gaudin United States |

    Tuesday, February 01, 2011 4:59 PM

    Corey Gaudin


    Maarten,

    Thank you so much for this! Thanks to all of the people that contributed to the MefContrib project also! This is really awesome! It is a much cleaner way to do this than what I had previously with MVC3 and MEF using the Dependency Resolver since I would always forget an export somewhere. This is much easier and nicer.

    Quick question: I have been playing with this reverting to this solution than what I had and it works really well. However, I noticed that by default all classes are set as NonShared Exports. This makes alot of sense, because Controllers need to be non-shared to be useful in an MVC application. It also makes alot of sense with Repository classes since having a shared context between 1000s of users would be very feasible or practical. However, there are some cases where some classes just make sense as a Shared Export. How do you accomplish this using this framework? I have tried the markup PartCreationPolicy(CreationPolicy.Shared) on the Exported Classes and the framework does not honor this. It will create a new version every time. Is there any way to do this in the existing framework released? Am I missing something? I can of course fix my problem using static members in the class instance to get around this problem, but in some cases it is far cleaner to just mark the entire class as a Shared Export. Any ideas?

    Thanks again Maarten for making my job easier. I was wondering why this wasnt a built in feature consider its MEF. But this is a better solution to have it as a NuGet package supported by cool people.

    Corey Gaudin

    Corey Gaudin United States |

    Tuesday, February 01, 2011 5:02 PM

    Corey Gaudin

    Quick Correction to above:

    It also makes alot of sense with Repository classes since having a shared context between 1000s of users *WOULDNT* be very feasible or practical.

    Sorry.

    maartenba Belgium |

    Wednesday, February 16, 2011 7:48 AM

    maartenba

    FYI: Working on master container support...

    Andy Worral United States |

    Wednesday, February 16, 2011 5:58 AM

    Andy Worral

    Maarten,

    I have to admit I am not terribly familiar with MEFContrib yet but I was wondering if you could help me out.

    I have been previously using a different implementation of MEF with MVC3 to be able to load Controllers from outside dlls via a custom ControllerFactory.  Is there any way to implement this ability just using the DependencyResolver?

    I assume I will still have to override CreateController in order to point at the other dll?

    Its all a little black boxy for me until I grab the source and read through it a bit more.

    Thanks for any pointers!

    Andy

    maartenba |

    Wednesday, February 16, 2011 7:49 AM

    maartenba

    You can do exactly the same with MEF + MefContrib, this one just gives you teh functionaility you mention out of the box without having to setup anything specific.

    Andy Worral United States |

    Wednesday, February 16, 2011 1:44 PM

    Andy Worral

    I did do a quick test using the new MEfContrib.MVC3 from nuget and it seemed that however the ControllerFactory was looking for an exported Controller that it didn't see the ones in my separate dlll.

    The base namespace in the other dll is different perhaps that is causing the issue? The controller in the other dll still has the XXXX.Areas.MyArea.DoSomethingController as the namespace just the XXXX is different.  As I was saying I haven't looked through the code to see how this implementation looks for exported Controllers and selects one.  Or if it is just using the original ControllerFactory's implementation to find the Contoller and then using MEF to instantiate it with its dependencies.

    Do you have an example at all of the MefContrib.MVC3 working with a controller from another assembly?

    Hopefully I'll get a chance to dig through the code a bit more today.

    Thanks again

    Corey Gaudin United States |

    Wednesday, March 23, 2011 10:19 PM

    Corey Gaudin

    Maarten,

    Where would you add a line to add an export without the [Export] Attribute?

    I tried adding something in the AppStart_MefContribMVC3 to do dependencyResolver.Build<ITestObject>(new TestObject()); and dependencyResolver.Container.ComposeExportedValue<ITestObject>(new TestObject) and it errored out with a Object Reference null (because the Container was still null at this point).

    I moved it to the ApplicationStart in Global.cs, and while it didnt error adding in that part, it does not import in that value to the controllers. Its as if it isnt adding that part as a export.

    maartenba |

    Thursday, March 24, 2011 9:30 AM

    maartenba

    What type of export do you want to add? Controllers? Controller exports are registered by convention over at AppStart_MefContribMVC3.Start() in the new ConventionCatalog(new MvcApplicationRegistry()). Check the MefContrib sources if you want to do something similar with other classes.

    Corey Gaudin United States |

    Thursday, March 24, 2011 12:43 PM

    Corey Gaudin

    No. I want to do just a regular object and I dont want to do it by convention. I just want to add that object in like the above. container.ComposeExportedValue<ISomeObject>(new SomeObject()); before the first controller is instantiated so that it can import in the ISomeObject. I havent found a place I can do this and it works yet.

    tom thorp United States |

    Friday, April 08, 2011 6:19 PM

    tom thorp

    First, let me say, I like the concepts and implementation of your package.  But I'm also having a problem AppStart_MefContribMVC3.

    The line -
          var dependencyResolver = new CompositionDependencyResolver(catalog);
    has an internal exception of -
      Message - Object reference not set to an instance of an object.
      Stack Trace -
            at MefContrib.Web.Mvc.Internal.WcfOperationContext.get_Current()
            at MefContrib.Web.Mvc.CurrentRequestContext.get_Items()
            at MefContrib.Web.Mvc.CompositionDependencyResolver.get_Container()

    It appears because of that, framework does not resolve any controllers.

    Can you suggestion something or point me to where I could download the source to your package.

    Jason Alban United States |

    Wednesday, April 13, 2011 7:48 AM

    Jason Alban

    I am having the same issue as tom thorp above.

    Pingbacks and trackbacks (3)+

    Comments are closed