I am trying to get a dependency injection working in an ASP.NET MVC 3 application using Microsoft Unity. First, I implemented my own IDependencyResolver and activated it in the Global.asax file as follows:
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
I found that I do not need to do anything else to get the controller injection (via the constructor attribute and [Dependency]). With the default view engine, I also found that I could make the [Dependency] attribute work in standard views, but not in layout views. Can this be made to work for layouts as well?
However, I implemented my own view engine, which inherits VirtualPathProviderViewEngine, which overrides the CreateView / CreatePartialView methods and returns my own custom view (implements IView). See the Render Method for a custom view below:
public void Render(ViewContext viewContext, TextWriter writer) { var webViewPage = DependencyResolver.Current.GetService(_type) as WebViewPage; //var webViewPage = Activator.CreateInstance(_type) as WebViewPage; if (webViewPage == null) throw new InvalidOperationException("Invalid view type"); webViewPage.VirtualPath = _virtualPath; webViewPage.ViewContext = viewContext; webViewPage.ViewData = viewContext.ViewData; webViewPage.InitHelpers(); WebPageRenderingBase startPage = null; if (_runViewStartPages) startPage = StartPage.GetStartPage(webViewPage, "_ViewStart", _viewStartFileExtensions); var pageContext = new WebPageContext(viewContext.HttpContext, webViewPage, null); webViewPage.ExecutePageHierarchy(pageContext, writer, startPage); }
With the commented line, I completely lost the dependency injection in my views, so I changed it to a line above which works fine again for standard views, but not for layout views. I would appreciate it if you could show me how this can be changed to work with Layout views?
Finally, I try to start an action filter injection. I found two different cases:
Apply filter to action using attribute.
Defining it as a global filter, for example:
GlobalFilters.Filters.Add (new TestAttribute ());
None of them use the dependency converter. Therefore, I need to do extra work. Please correct me if there is a better way. To include the first scenario, I did the following:
public class UnityFilterAttributeFilterProvider : FilterAttributeFilterProvider { private IUnityContainer _container; protected override IEnumerable<FilterAttribute> GetControllerAttributes(ControllerContext controllerContext, ActionDescriptor actionDescriptor) { var attributes = base.GetControllerAttributes(controllerContext, actionDescriptor); foreach (var attribute in attributes) { _container.BuildUp(attribute.GetType(), attribute); } return attributes; } protected override IEnumerable<FilterAttribute> GetActionAttributes(ControllerContext controllerContext, ActionDescriptor actionDescriptor) { var attributes = base.GetActionAttributes(controllerContext, actionDescriptor); foreach (var attribute in attributes) { _container.BuildUp(attribute.GetType(), attribute); } return attributes; } }
And then defined it in my Global.asax file as follows:
FilterProviders.Providers.Remove(FilterProviders.Providers.Single(f => f is FilterAttributeFilterProvider)); FilterProviders.Providers.Add(new UnityFilterAttributeFilterProvider(container));
This works great, but I was wondering if this is the right thing to do? To resolve the second case, I simply changed where I defined my global filter as follows:
GlobalFilters.Filters.Add(DependencyResolver.Current.GetService<TestAttribute>());
This works again, but is this the right way to do it?
I would be grateful for the help. Thanks