[Fixes #1331] Register object for dispose in ObjectResult and
FileStreamResult
This commit is contained in:
parent
1c00cfe7aa
commit
fc9e1caf43
|
|
@ -376,6 +376,12 @@ namespace Microsoft.AspNet.Mvc
|
||||||
[NonAction]
|
[NonAction]
|
||||||
public virtual JsonResult Json(object data)
|
public virtual JsonResult Json(object data)
|
||||||
{
|
{
|
||||||
|
var disposableValue = data as IDisposable;
|
||||||
|
if (disposableValue != null)
|
||||||
|
{
|
||||||
|
Response.OnResponseCompleted(_ => disposableValue.Dispose(), state: null);
|
||||||
|
}
|
||||||
|
|
||||||
return new JsonResult(data);
|
return new JsonResult(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -659,6 +665,11 @@ namespace Microsoft.AspNet.Mvc
|
||||||
[NonAction]
|
[NonAction]
|
||||||
public virtual FileStreamResult File(Stream fileStream, string contentType, string fileDownloadName)
|
public virtual FileStreamResult File(Stream fileStream, string contentType, string fileDownloadName)
|
||||||
{
|
{
|
||||||
|
if (fileStream != null)
|
||||||
|
{
|
||||||
|
Response.OnResponseCompleted(_ => fileStream.Dispose(), state: null);
|
||||||
|
}
|
||||||
|
|
||||||
return new FileStreamResult(fileStream, contentType) { FileDownloadName = fileDownloadName };
|
return new FileStreamResult(fileStream, contentType) { FileDownloadName = fileDownloadName };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -717,6 +728,12 @@ namespace Microsoft.AspNet.Mvc
|
||||||
[NonAction]
|
[NonAction]
|
||||||
public virtual HttpNotFoundObjectResult HttpNotFound(object value)
|
public virtual HttpNotFoundObjectResult HttpNotFound(object value)
|
||||||
{
|
{
|
||||||
|
var disposableValue = value as IDisposable;
|
||||||
|
if (disposableValue != null)
|
||||||
|
{
|
||||||
|
Response.OnResponseCompleted(_ => disposableValue.Dispose(), state: null);
|
||||||
|
}
|
||||||
|
|
||||||
return new HttpNotFoundObjectResult(value);
|
return new HttpNotFoundObjectResult(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -737,6 +754,12 @@ namespace Microsoft.AspNet.Mvc
|
||||||
[NonAction]
|
[NonAction]
|
||||||
public virtual BadRequestObjectResult HttpBadRequest(object error)
|
public virtual BadRequestObjectResult HttpBadRequest(object error)
|
||||||
{
|
{
|
||||||
|
var disposableValue = error as IDisposable;
|
||||||
|
if (disposableValue != null)
|
||||||
|
{
|
||||||
|
Response.OnResponseCompleted(_ => disposableValue.Dispose(), state: null);
|
||||||
|
}
|
||||||
|
|
||||||
return new BadRequestObjectResult(error);
|
return new BadRequestObjectResult(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -759,6 +782,12 @@ namespace Microsoft.AspNet.Mvc
|
||||||
[NonAction]
|
[NonAction]
|
||||||
public virtual CreatedResult Created([NotNull] string uri, object value)
|
public virtual CreatedResult Created([NotNull] string uri, object value)
|
||||||
{
|
{
|
||||||
|
var disposableValue = value as IDisposable;
|
||||||
|
if (disposableValue != null)
|
||||||
|
{
|
||||||
|
Response.OnResponseCompleted(_ => disposableValue.Dispose(), state: null);
|
||||||
|
}
|
||||||
|
|
||||||
return new CreatedResult(uri, value);
|
return new CreatedResult(uri, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -780,7 +809,8 @@ namespace Microsoft.AspNet.Mvc
|
||||||
{
|
{
|
||||||
location = uri.GetComponents(UriComponents.SerializationInfoString, UriFormat.UriEscaped);
|
location = uri.GetComponents(UriComponents.SerializationInfoString, UriFormat.UriEscaped);
|
||||||
}
|
}
|
||||||
return new CreatedResult(location, value);
|
|
||||||
|
return Created(location, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -822,6 +852,12 @@ namespace Microsoft.AspNet.Mvc
|
||||||
object routeValues,
|
object routeValues,
|
||||||
object value)
|
object value)
|
||||||
{
|
{
|
||||||
|
var disposableValue = value as IDisposable;
|
||||||
|
if (disposableValue != null)
|
||||||
|
{
|
||||||
|
Response.OnResponseCompleted(_ => disposableValue.Dispose(), state: null);
|
||||||
|
}
|
||||||
|
|
||||||
return new CreatedAtActionResult(actionName, controllerName, routeValues, value);
|
return new CreatedAtActionResult(actionName, controllerName, routeValues, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -859,6 +895,12 @@ namespace Microsoft.AspNet.Mvc
|
||||||
[NonAction]
|
[NonAction]
|
||||||
public virtual CreatedAtRouteResult CreatedAtRoute(string routeName, object routeValues, object value)
|
public virtual CreatedAtRouteResult CreatedAtRoute(string routeName, object routeValues, object value)
|
||||||
{
|
{
|
||||||
|
var disposableValue = value as IDisposable;
|
||||||
|
if (disposableValue != null)
|
||||||
|
{
|
||||||
|
Response.OnResponseCompleted(_ => disposableValue.Dispose(), state: null);
|
||||||
|
}
|
||||||
|
|
||||||
return new CreatedAtRouteResult(routeName, routeValues, value);
|
return new CreatedAtRouteResult(routeName, routeValues, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -423,6 +423,33 @@ namespace Microsoft.AspNet.Mvc.Test
|
||||||
Assert.Equal(uri.OriginalString, result.Location);
|
Assert.Equal(uri.OriginalString, result.Location);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Created_IDisposableObject_RegistersForDispose()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var mockHttpContext = new Mock<DefaultHttpContext>();
|
||||||
|
mockHttpContext.Setup(x => x.Response.OnResponseCompleted(It.IsAny<Action<object>>(), It.IsAny<object>()));
|
||||||
|
var uri = new Uri("/test/url", UriKind.Relative);
|
||||||
|
|
||||||
|
var controller = new TestableController()
|
||||||
|
{
|
||||||
|
ActionContext = new ActionContext(mockHttpContext.Object, new RouteData(), new ActionDescriptor())
|
||||||
|
};
|
||||||
|
var input = new DisposableObject();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = controller.Created(uri, input);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.IsType<CreatedResult>(result);
|
||||||
|
Assert.Equal(StatusCodes.Status201Created, result.StatusCode);
|
||||||
|
Assert.Equal(uri.OriginalString, result.Location);
|
||||||
|
Assert.Same(input, result.Value);
|
||||||
|
mockHttpContext.Verify(
|
||||||
|
x => x.Response.OnResponseCompleted(It.IsAny<Action<object>>(), It.IsAny<object>()),
|
||||||
|
Times.Once());
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void CreatedAtAction_WithParameterActionName_SetsResultActionName()
|
public void CreatedAtAction_WithParameterActionName_SetsResultActionName()
|
||||||
{
|
{
|
||||||
|
|
@ -483,6 +510,32 @@ namespace Microsoft.AspNet.Mvc.Test
|
||||||
Assert.Equal(expected, result.RouteValues);
|
Assert.Equal(expected, result.RouteValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CreatedAtAction_IDisposableObject_RegistersForDispose()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var mockHttpContext = new Mock<DefaultHttpContext>();
|
||||||
|
mockHttpContext.Setup(x => x.Response.OnResponseCompleted(It.IsAny<Action<object>>(), It.IsAny<object>()));
|
||||||
|
|
||||||
|
var controller = new TestableController()
|
||||||
|
{
|
||||||
|
ActionContext = new ActionContext(mockHttpContext.Object, new RouteData(), new ActionDescriptor())
|
||||||
|
};
|
||||||
|
var input = new DisposableObject();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = controller.CreatedAtAction("SampleAction", input);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.IsType<CreatedAtActionResult>(result);
|
||||||
|
Assert.Equal(StatusCodes.Status201Created, result.StatusCode);
|
||||||
|
Assert.Equal("SampleAction", result.ActionName);
|
||||||
|
Assert.Same(input, result.Value);
|
||||||
|
mockHttpContext.Verify(
|
||||||
|
x => x.Response.OnResponseCompleted(It.IsAny<Action<object>>(), It.IsAny<object>()),
|
||||||
|
Times.Once());
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void CreatedAtRoute_WithParameterRouteName_SetsResultSameRouteName()
|
public void CreatedAtRoute_WithParameterRouteName_SetsResultSameRouteName()
|
||||||
{
|
{
|
||||||
|
|
@ -540,6 +593,32 @@ namespace Microsoft.AspNet.Mvc.Test
|
||||||
Assert.Equal(expected, result.RouteValues);
|
Assert.Equal(expected, result.RouteValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CreatedAtRoute_IDisposableObject_RegistersForDispose()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var mockHttpContext = new Mock<DefaultHttpContext>();
|
||||||
|
mockHttpContext.Setup(x => x.Response.OnResponseCompleted(It.IsAny<Action<object>>(), It.IsAny<object>()));
|
||||||
|
|
||||||
|
var controller = new TestableController()
|
||||||
|
{
|
||||||
|
ActionContext = new ActionContext(mockHttpContext.Object, new RouteData(), new ActionDescriptor())
|
||||||
|
};
|
||||||
|
var input = new DisposableObject();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = controller.CreatedAtRoute("SampleRoute", input);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.IsType<CreatedAtRouteResult>(result);
|
||||||
|
Assert.Equal(StatusCodes.Status201Created, result.StatusCode);
|
||||||
|
Assert.Equal("SampleRoute", result.RouteName);
|
||||||
|
Assert.Same(input, result.Value);
|
||||||
|
mockHttpContext.Verify(
|
||||||
|
x => x.Response.OnResponseCompleted(It.IsAny<Action<object>>(), It.IsAny<object>()),
|
||||||
|
Times.Once());
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void File_WithContents()
|
public void File_WithContents()
|
||||||
{
|
{
|
||||||
|
|
@ -612,7 +691,12 @@ namespace Microsoft.AspNet.Mvc.Test
|
||||||
public void File_WithStream()
|
public void File_WithStream()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var controller = new TestableController();
|
var mockHttpContext = new Mock<DefaultHttpContext>();
|
||||||
|
mockHttpContext.Setup(x => x.Response.OnResponseCompleted(It.IsAny<Action<object>>(), It.IsAny<object>()));
|
||||||
|
var controller = new TestableController()
|
||||||
|
{
|
||||||
|
ActionContext = new ActionContext(mockHttpContext.Object, new RouteData(), new ActionDescriptor())
|
||||||
|
};
|
||||||
var fileStream = Stream.Null;
|
var fileStream = Stream.Null;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -629,7 +713,13 @@ namespace Microsoft.AspNet.Mvc.Test
|
||||||
public void File_WithStreamAndFileDownloadName()
|
public void File_WithStreamAndFileDownloadName()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var controller = new TestableController();
|
var mockHttpContext = new Mock<DefaultHttpContext>();
|
||||||
|
mockHttpContext.Setup(x => x.Response.OnResponseCompleted(It.IsAny<Action<object>>(), It.IsAny<object>()));
|
||||||
|
|
||||||
|
var controller = new TestableController()
|
||||||
|
{
|
||||||
|
ActionContext = new ActionContext(mockHttpContext.Object, new RouteData(), new ActionDescriptor())
|
||||||
|
};
|
||||||
var fileStream = Stream.Null;
|
var fileStream = Stream.Null;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -640,6 +730,9 @@ namespace Microsoft.AspNet.Mvc.Test
|
||||||
Assert.Same(fileStream, result.FileStream);
|
Assert.Same(fileStream, result.FileStream);
|
||||||
Assert.Equal("someContentType", result.ContentType);
|
Assert.Equal("someContentType", result.ContentType);
|
||||||
Assert.Equal("someDownloadName", result.FileDownloadName);
|
Assert.Equal("someDownloadName", result.FileDownloadName);
|
||||||
|
mockHttpContext.Verify(
|
||||||
|
x => x.Response.OnResponseCompleted(It.IsAny<Action<object>>(), It.IsAny<object>()),
|
||||||
|
Times.Once());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -685,6 +778,31 @@ namespace Microsoft.AspNet.Mvc.Test
|
||||||
Assert.Equal("Test Content", result.Value);
|
Assert.Equal("Test Content", result.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void HttpNotFound_IDisposableObject_RegistersForDispose()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var mockHttpContext = new Mock<DefaultHttpContext>();
|
||||||
|
mockHttpContext.Setup(x => x.Response.OnResponseCompleted(It.IsAny<Action<object>>(), It.IsAny<object>()));
|
||||||
|
|
||||||
|
var controller = new TestableController()
|
||||||
|
{
|
||||||
|
ActionContext = new ActionContext(mockHttpContext.Object, new RouteData(), new ActionDescriptor())
|
||||||
|
};
|
||||||
|
var input = new DisposableObject();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = controller.HttpNotFound(input);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.IsType<HttpNotFoundObjectResult>(result);
|
||||||
|
Assert.Equal(StatusCodes.Status404NotFound, result.StatusCode);
|
||||||
|
Assert.Same(input, result.Value);
|
||||||
|
mockHttpContext.Verify(
|
||||||
|
x => x.Response.OnResponseCompleted(It.IsAny<Action<object>>(), It.IsAny<object>()),
|
||||||
|
Times.Once());
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void BadRequest_SetsStatusCode()
|
public void BadRequest_SetsStatusCode()
|
||||||
{
|
{
|
||||||
|
|
@ -715,6 +833,31 @@ namespace Microsoft.AspNet.Mvc.Test
|
||||||
Assert.Equal(obj, result.Value);
|
Assert.Equal(obj, result.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void BadRequest_IDisposableObject_RegistersForDispose()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var mockHttpContext = new Mock<DefaultHttpContext>();
|
||||||
|
mockHttpContext.Setup(x => x.Response.OnResponseCompleted(It.IsAny<Action<object>>(), It.IsAny<object>()));
|
||||||
|
|
||||||
|
var controller = new TestableController()
|
||||||
|
{
|
||||||
|
ActionContext = new ActionContext(mockHttpContext.Object, new RouteData(), new ActionDescriptor())
|
||||||
|
};
|
||||||
|
var input = new DisposableObject();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = controller.HttpBadRequest(input);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.IsType<BadRequestObjectResult>(result);
|
||||||
|
Assert.Equal(StatusCodes.Status400BadRequest, result.StatusCode);
|
||||||
|
Assert.Same(input, result.Value);
|
||||||
|
mockHttpContext.Verify(
|
||||||
|
x => x.Response.OnResponseCompleted(It.IsAny<Action<object>>(), It.IsAny<object>()),
|
||||||
|
Times.Once());
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void BadRequest_SetsStatusCodeAndValue_ModelState()
|
public void BadRequest_SetsStatusCodeAndValue_ModelState()
|
||||||
{
|
{
|
||||||
|
|
@ -888,6 +1031,30 @@ namespace Microsoft.AspNet.Mvc.Test
|
||||||
Assert.Same(data, actualJsonResult.Value);
|
Assert.Same(data, actualJsonResult.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Controller_Json_IDisposableObject_RegistersForDispose()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var mockHttpContext = new Mock<DefaultHttpContext>();
|
||||||
|
mockHttpContext.Setup(x => x.Response.OnResponseCompleted(It.IsAny<Action<object>>(), It.IsAny<object>()));
|
||||||
|
|
||||||
|
var controller = new TestableController()
|
||||||
|
{
|
||||||
|
ActionContext = new ActionContext(mockHttpContext.Object, new RouteData(), new ActionDescriptor())
|
||||||
|
};
|
||||||
|
var input = new DisposableObject();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = controller.Json(input);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.IsType<JsonResult>(result);
|
||||||
|
Assert.Same(input, result.Value);
|
||||||
|
mockHttpContext.Verify(
|
||||||
|
x => x.Response.OnResponseCompleted(It.IsAny<Action<object>>(), It.IsAny<object>()),
|
||||||
|
Times.Once());
|
||||||
|
}
|
||||||
|
|
||||||
public static IEnumerable<object[]> RedirectTestData
|
public static IEnumerable<object[]> RedirectTestData
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
|
@ -1402,7 +1569,7 @@ namespace Microsoft.AspNet.Mvc.Test
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var model = new TryValidateModelModel();
|
var model = new TryValidateModelModel();
|
||||||
var validationResult = new []
|
var validationResult = new[]
|
||||||
{
|
{
|
||||||
new ModelValidationResult(string.Empty, "Out of range!")
|
new ModelValidationResult(string.Empty, "Out of range!")
|
||||||
};
|
};
|
||||||
|
|
@ -1569,5 +1736,13 @@ namespace Microsoft.AspNet.Mvc.Test
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class DisposableObject : IDisposable
|
||||||
|
{
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Microsoft.AspNet.Http;
|
using Microsoft.AspNet.Http;
|
||||||
|
using Microsoft.AspNet.Http.Core;
|
||||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||||
using Microsoft.AspNet.Routing;
|
using Microsoft.AspNet.Routing;
|
||||||
using Microsoft.AspNet.WebUtilities;
|
using Microsoft.AspNet.WebUtilities;
|
||||||
|
|
@ -144,7 +145,12 @@ namespace Microsoft.AspNet.Mvc
|
||||||
public void ControllerFileStream_InvokedInUnitTests(string content, string contentType, string fileName)
|
public void ControllerFileStream_InvokedInUnitTests(string content, string contentType, string fileName)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var controller = new TestabilityController();
|
var mockHttpContext = new Mock<DefaultHttpContext>();
|
||||||
|
mockHttpContext.Setup(x => x.Response.OnResponseCompleted(It.IsAny<Action<object>>(), It.IsAny<object>()));
|
||||||
|
var controller = new TestabilityController()
|
||||||
|
{
|
||||||
|
ActionContext = new ActionContext(mockHttpContext.Object, new RouteData(), new ActionDescriptor())
|
||||||
|
};
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var result = controller.FileStream_Action(content, contentType, fileName);
|
var result = controller.FileStream_Action(content, contentType, fileName);
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
|
|
@ -307,12 +308,10 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
|
||||||
// Arrange
|
// Arrange
|
||||||
var server = TestHelper.CreateServer(_app, SiteName);
|
var server = TestHelper.CreateServer(_app, SiteName);
|
||||||
var client = server.CreateClient();
|
var client = server.CreateClient();
|
||||||
var input = "{\"SampleInt\":10}";
|
|
||||||
|
|
||||||
var request = new HttpRequestMessage(
|
var request = new HttpRequestMessage(
|
||||||
HttpMethod.Post,
|
HttpMethod.Post,
|
||||||
"http://localhost/ActionResultsVerification/GetNotFoundObjectResultWithContent");
|
"http://localhost/ActionResultsVerification/GetNotFoundObjectResultWithContent");
|
||||||
request.Content = new StringContent(input, Encoding.UTF8, "application/json");
|
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var response = await client.SendAsync(request);
|
var response = await client.SendAsync(request);
|
||||||
|
|
@ -321,5 +320,37 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
|
||||||
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
|
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
|
||||||
Assert.Equal("{\"SampleInt\":10,\"SampleString\":\"Foo\"}", await response.Content.ReadAsStringAsync());
|
Assert.Equal("{\"SampleInt\":10,\"SampleString\":\"Foo\"}", await response.Content.ReadAsStringAsync());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task HttpNotFoundObjectResult_WithDisposableObject()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var server = TestHelper.CreateServer(_app, SiteName);
|
||||||
|
var client = server.CreateClient();
|
||||||
|
var nameValueCollection = new List<KeyValuePair<string, string>>
|
||||||
|
{
|
||||||
|
new KeyValuePair<string, string>("guid", Guid.NewGuid().ToString()),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response1 = await client.PostAsync(
|
||||||
|
"/ActionResultsVerification/GetDisposeCalled",
|
||||||
|
new FormUrlEncodedContent(nameValueCollection));
|
||||||
|
|
||||||
|
await client.PostAsync(
|
||||||
|
"/ActionResultsVerification/GetNotFoundObjectResultWithDisposableObject",
|
||||||
|
new FormUrlEncodedContent(nameValueCollection));
|
||||||
|
|
||||||
|
var response2 = await client.PostAsync(
|
||||||
|
"/ActionResultsVerification/GetDisposeCalled",
|
||||||
|
new FormUrlEncodedContent(nameValueCollection));
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
var isDisposed = Convert.ToBoolean(await response1.Content.ReadAsStringAsync());
|
||||||
|
Assert.False(isDisposed);
|
||||||
|
|
||||||
|
isDisposed = Convert.ToBoolean(await response2.Content.ReadAsStringAsync());
|
||||||
|
Assert.True(isDisposed);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -10,6 +10,10 @@ namespace ActionResultsWebSite
|
||||||
{
|
{
|
||||||
public class ActionResultsVerificationController : Controller
|
public class ActionResultsVerificationController : Controller
|
||||||
{
|
{
|
||||||
|
|
||||||
|
[FromServices]
|
||||||
|
public GuidLookupService Service { get; set; }
|
||||||
|
|
||||||
public IActionResult Index([FromBody]DummyClass test)
|
public IActionResult Index([FromBody]DummyClass test)
|
||||||
{
|
{
|
||||||
if (!ModelState.IsValid)
|
if (!ModelState.IsValid)
|
||||||
|
|
@ -95,6 +99,22 @@ namespace ActionResultsWebSite
|
||||||
return HttpNotFound(CreateDummy());
|
return HttpNotFound(CreateDummy());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IActionResult GetNotFoundObjectResultWithDisposableObject(string guid)
|
||||||
|
{
|
||||||
|
return HttpNotFound(CreateDisposableType(guid));
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool GetDisposeCalled(string guid)
|
||||||
|
{
|
||||||
|
bool value;
|
||||||
|
if (Service.IsDisposed.TryGetValue(guid, out value))
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public DummyClass GetDummy(int id)
|
public DummyClass GetDummy(int id)
|
||||||
{
|
{
|
||||||
return CreateDummy();
|
return CreateDummy();
|
||||||
|
|
@ -108,5 +128,28 @@ namespace ActionResultsWebSite
|
||||||
SampleString = "Foo"
|
SampleString = "Foo"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private DisposableType CreateDisposableType(string guid)
|
||||||
|
{
|
||||||
|
return new DisposableType(Service, guid);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DisposableType : IDisposable
|
||||||
|
{
|
||||||
|
private GuidLookupService _service;
|
||||||
|
private string _guid;
|
||||||
|
|
||||||
|
public DisposableType(GuidLookupService service, string guid)
|
||||||
|
{
|
||||||
|
_service = service;
|
||||||
|
_guid = guid;
|
||||||
|
_service.IsDisposed[_guid] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_service.IsDisposed[_guid] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace ActionResultsWebSite
|
||||||
|
{
|
||||||
|
public class GuidLookupService
|
||||||
|
{
|
||||||
|
public Dictionary<string, bool> IsDisposed { get; } = new Dictionary<string, bool>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -16,6 +16,7 @@ namespace ActionResultsWebSite
|
||||||
app.UseServices(services =>
|
app.UseServices(services =>
|
||||||
{
|
{
|
||||||
services.AddMvc();
|
services.AddMvc();
|
||||||
|
services.AddInstance(new GuidLookupService());
|
||||||
|
|
||||||
services.Configure<MvcOptions>(options =>
|
services.Configure<MvcOptions>(options =>
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue