Dispose controllers after they have been utilized by the action invoker

This commit is contained in:
Yishai Galatzer 2014-04-03 09:31:06 -07:00
parent 0a62a581de
commit ebd54bfc06
4 changed files with 72 additions and 10 deletions

View File

@ -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)

View File

@ -1,11 +1,8 @@

namespace Microsoft.AspNet.Mvc
namespace Microsoft.AspNet.Mvc
{
public interface IControllerFactory
{
object CreateController(ActionContext actionContext);
void ReleaseController(object controller);
}
}

View File

@ -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()

View File

@ -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<IServiceProvider>().Object,
new Mock<ITypeActivator>().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<IServiceProvider>().Object,
new Mock<ITypeActivator>().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;
}
}
}
}