Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET MVC 4.0 Controllers and MEF, how to bring these two together?

I'm trying to create ASP.NET MVC module by using MEF. While I have no problems so far by using MEF without MVC, when it comes to exporting Controllers I have some difficulties.

I used this approach as example http://kennytordeur.blogspot.de/2012/08/mef-in-aspnet-mvc-4-and-webapi.html I made it more complex by introducing an external dll, which contained a controller. But if I follow the idea of Kenny, then I need to have a common interface (like IMyTest in his example), however, as I plan to have a number of controllers, it would mean that I will need too many interfaces. And in the end, it looks like I reuse inner methods of controllers, instead of whole controllers.

I found a question here How to integrate MEF with ASP.NET MVC 4 and ASP.NET Web API, which contained some code examples, where I see the similar picture - _contactRepository of an interface IContactRepository is imported and then reused inside a view.

That is why my question is, is it normal to export the whole controller, without using interfaces? And how to do so?

I found the connection between MEF and ASP.NET quite confusing, at first it seams that there are a number of examples in the Internet, but when I look deeper, most of them are outdated and not practical or too primitive to see how it can be applied to bigger projects.

Thanks!

like image 865
Anelook Avatar asked Jul 10 '13 19:07

Anelook


People also ask

Can you have more than one controller in MVC?

In Spring MVC, we can create multiple controllers at a time. It is required to map each controller class with @Controller annotation.

Can two different Controllers access a single view in MVC?

Yes. Mention the view full path in the View method. If the name of your Views are same in both the controllers, You can keep the Common view under the Views/Shared directory and simply call the View method without any parameter. The View name should be same as the Action method name.

How model view and controller interact with each other?

First, the browser sends a request to the Controller. Then, the Controller interacts with the Model to send and receive data. The Controller then interacts with the View to render the data. The View is only concerned about how to present the information and not the final presentation.


1 Answers

I've used MefContrib along with MEF in MVC 4, and am using the following to wire everything up. You need to invoke the Configure method from Application_Start in Global.asax so that everything is ready when MVC needs to process a request.

using System.ComponentModel.Composition.Hosting;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MefContrib.Hosting.Conventions;
using MefContrib.Web.Mvc;

[assembly: PreApplicationStartMethod( typeof(Core.Web.Initialization.DependencyInjection.RegisterDependencyResolver), "RegisterHttpModule" )]

namespace Core.Web.Initialization.DependencyInjection
{
    public class RegisterDependencyResolver
    {
        public static void RegisterHttpModule()
        {
            // Register the CompositionContainerLifetimeHttpModule HttpModule.
            // This makes sure everything is cleaned up correctly after each request.
            CompositionContainerLifetimeHttpModule.Register();      
        }

        public void Configure()
        {
            // Create MEF catalog based on the contents of ~/bin.
            //
            // Note that any class in the referenced assemblies implementing in "IController"
            // is automatically exported to MEF. There is no need for explicit [Export] attributes
            // on ASP.NET MVC controllers. When implementing multiple constructors ensure that
            // there is one constructor marked with the [ImportingConstructor] attribute.
            var catalog = new AggregateCatalog(
                new DirectoryCatalog( "bin" ),
                new ConventionCatalog( new MvcApplicationRegistry() ) );

            // Tell MVC3 to use MEF as its dependency resolver.
            var dependencyResolver = new CompositionDependencyResolver( catalog );
            DependencyResolver.SetResolver( dependencyResolver );

            // Tell MVC3 to resolve dependencies in controllers
            ControllerBuilder.Current.SetControllerFactory( new DefaultControllerFactory( new CompositionControllerActivator( dependencyResolver ) ) );

            // Tell MVC3 to resolve dependencies in filters
            FilterProviders.Providers.Remove( FilterProviders.Providers.Single( f => f is FilterAttributeFilterProvider ) );
            FilterProviders.Providers.Add( new CompositionFilterAttributeFilterProvider( dependencyResolver ) );

            // Tell MVC3 to resolve dependencies in model validators
            ModelValidatorProviders.Providers.Remove( ModelValidatorProviders.Providers.OfType<DataAnnotationsModelValidatorProvider>().Single() );
            ModelValidatorProviders.Providers.Add( new CompositionDataAnnotationsModelValidatorProvider( dependencyResolver ) );

            // Tell MVC3 to resolve model binders through MEF. Model binders must be decorated with [ModelBinderExport].
            ModelBinderProviders.BinderProviders.Add( new CompositionModelBinderProvider( dependencyResolver ) );
        }
    }
}

Additionally, you need to export your controllers to MVC. Here's an example of how I do that:

[Export]
[PartCreationPolicy( CreationPolicy.NonShared )]
public partial class HomeController : ControllerCore
{
    [ImportingConstructor]
    public HomeController( DataContext context, ILogFactory logFactory, ServiceFactory serviceFactory ) : base( context, logFactory, serviceFactory )
    {
    }

    public virtual ActionResult Index()
    {
        return View();
    }
}

Hope this helps!

like image 166
Morten Mertner Avatar answered Nov 18 '22 17:11

Morten Mertner