diff --git a/src/Microsoft.AspNet.Mvc.Core/DefaultControllerFactory.cs b/src/Microsoft.AspNet.Mvc.Core/DefaultControllerFactory.cs index b7c582235a..821c7030f8 100644 --- a/src/Microsoft.AspNet.Mvc.Core/DefaultControllerFactory.cs +++ b/src/Microsoft.AspNet.Mvc.Core/DefaultControllerFactory.cs @@ -30,7 +30,6 @@ namespace Microsoft.AspNet.Mvc var controller = _activator.CreateInstance(_serviceProvider, actionDescriptor.ControllerDescriptor.ControllerTypeInfo.AsType()); - // TODO: How do we feed the controller with context (need DI improvements) InitializeController(controller, actionContext); return controller; @@ -38,6 +37,12 @@ namespace Microsoft.AspNet.Mvc public void ReleaseController(object controller) { + var disposableController = controller as IDisposable; + + if (disposableController != null) + { + disposableController.Dispose(); + } } private void InitializeController(object controller, ActionContext actionContext) diff --git a/src/Microsoft.AspNet.Mvc.Core/IControllerFactory.cs b/src/Microsoft.AspNet.Mvc.Core/IControllerFactory.cs index 949fd2dd8d..343790a19e 100644 --- a/src/Microsoft.AspNet.Mvc.Core/IControllerFactory.cs +++ b/src/Microsoft.AspNet.Mvc.Core/IControllerFactory.cs @@ -1,11 +1,8 @@ - - -namespace Microsoft.AspNet.Mvc +namespace Microsoft.AspNet.Mvc { public interface IControllerFactory { object CreateController(ActionContext actionContext); - void ReleaseController(object controller); } } diff --git a/src/Microsoft.AspNet.Mvc.Core/ReflectedActionInvoker.cs b/src/Microsoft.AspNet.Mvc.Core/ReflectedActionInvoker.cs index 515616197b..a842ee03ec 100644 --- a/src/Microsoft.AspNet.Mvc.Core/ReflectedActionInvoker.cs +++ b/src/Microsoft.AspNet.Mvc.Core/ReflectedActionInvoker.cs @@ -48,8 +48,6 @@ namespace Microsoft.AspNet.Mvc public async Task InvokeActionAsync() { - IActionResult actionResult; - var filterMetaItems = GetAndArrangeFilters(); var controller = _controllerFactory.CreateController(_actionContext); @@ -61,10 +59,17 @@ namespace Microsoft.AspNet.Mvc "controller")); } - actionResult = await RunAuthorizationFilters(filterMetaItems) ?? - await RunActionFiltersAndActions(filterMetaItems, controller); + try + { + var actionResult = await RunAuthorizationFilters(filterMetaItems) ?? + await RunActionFiltersAndActions(filterMetaItems, controller); - await RunActionResultFilters(actionResult, filterMetaItems); + await RunActionResultFilters(actionResult, filterMetaItems); + } + finally + { + _controllerFactory.ReleaseController(controller); + } } private FilterItem[] GetAndArrangeFilters() diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/DefaultControllerFactoryTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/DefaultControllerFactoryTest.cs new file mode 100644 index 0000000000..d2c5334664 --- /dev/null +++ b/test/Microsoft.AspNet.Mvc.Core.Test/DefaultControllerFactoryTest.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.AspNet.DependencyInjection; +using Moq; +using Xunit; + +namespace Microsoft.AspNet.Mvc.Core.Test +{ + public class DefaultControllerFactoryTest + { + [Fact] + public void DefaultControllerFactory_DisposesIDisposableController() + { + // Arrange + var factory = new DefaultControllerFactory( + new Mock().Object, + new Mock().Object); + + var controller = new MyController(); + + // Act + Assert + Assert.False(controller.Disposed); + + factory.ReleaseController(controller); + + Assert.True(controller.Disposed); + } + + [Fact] + public void DefaultControllerFactory_ReleasesNonIDisposableController() + { + // Arrange + var factory = new DefaultControllerFactory( + new Mock().Object, + new Mock().Object); + + var controller = new Object(); + + // Act + Assert + Assert.DoesNotThrow(() => factory.ReleaseController(controller)); + } + + private class MyController : Controller, IDisposable + { + public bool Disposed { get; set; } + public void Dispose() + { + Disposed = true; + } + } + } +}