Adding Outputformatter in resource filters.

This commit is contained in:
Harsh Gupta 2015-04-07 21:21:17 -07:00
parent f60896bd90
commit 58a5ad2279
20 changed files with 320 additions and 22 deletions

View File

@ -273,12 +273,27 @@ namespace Microsoft.AspNet.Mvc
IEnumerable<IOutputFormatter> formatters = null;
if (Formatters == null || Formatters.Count == 0)
{
formatters = context
var actionBindingContext = context
.HttpContext
.RequestServices
.GetRequiredService<IOptions<MvcOptions>>()
.Options
.OutputFormatters;
.GetRequiredService<IScopedInstance<ActionBindingContext>>()
.Value;
// In scenarios where there is a resource filter which directly shortcircuits using an ObjectResult.
// actionBindingContext is not setup yet and is null.
if (actionBindingContext == null)
{
var options = context
.HttpContext
.RequestServices
.GetRequiredService<IOptions<MvcOptions>>()
.Options;
formatters = options.OutputFormatters;
}
else
{
formatters = actionBindingContext.OutputFormatters ?? new List<IOutputFormatter>();
}
}
else
{

View File

@ -24,6 +24,7 @@ namespace Microsoft.AspNet.Mvc.Core
[NotNull] IControllerFactory controllerFactory,
[NotNull] ControllerActionDescriptor descriptor,
[NotNull] IReadOnlyList<IInputFormatter> inputFormatters,
[NotNull] IReadOnlyList<IOutputFormatter> outputFormatters,
[NotNull] IControllerActionArgumentBinder controllerActionArgumentBinder,
[NotNull] IReadOnlyList<IModelBinder> modelBinders,
[NotNull] IReadOnlyList<IModelValidatorProvider> modelValidatorProviders,
@ -31,9 +32,10 @@ namespace Microsoft.AspNet.Mvc.Core
[NotNull] IScopedInstance<ActionBindingContext> actionBindingContextAccessor,
[NotNull] ITempDataDictionary tempData)
: base(
actionContext,
actionContext,
filterProviders,
inputFormatters,
inputFormatters,
outputFormatters,
modelBinders,
modelValidatorProviders,
valueProviderFactories,

View File

@ -17,6 +17,7 @@ namespace Microsoft.AspNet.Mvc.Core
private readonly IFilterProvider[] _filterProviders;
private readonly IReadOnlyList<IInputFormatter> _inputFormatters;
private readonly IReadOnlyList<IModelBinder> _modelBinders;
private readonly IReadOnlyList<IOutputFormatter> _outputFormatters;
private readonly IReadOnlyList<IModelValidatorProvider> _modelValidatorProviders;
private readonly IReadOnlyList<IValueProviderFactory> _valueProviderFactories;
private readonly IScopedInstance<ActionBindingContext> _actionBindingContextAccessor;
@ -34,6 +35,7 @@ namespace Microsoft.AspNet.Mvc.Core
_filterProviders = filterProviders.OrderBy(item => item.Order).ToArray();
_argumentBinder = argumentBinder;
_inputFormatters = optionsAccessor.Options.InputFormatters.ToArray();
_outputFormatters = optionsAccessor.Options.OutputFormatters.ToArray();
_modelBinders = optionsAccessor.Options.ModelBinders.ToArray();
_modelValidatorProviders = optionsAccessor.Options.ModelValidatorProviders.ToArray();
_valueProviderFactories = optionsAccessor.Options.ValueProviderFactories.ToArray();
@ -59,6 +61,7 @@ namespace Microsoft.AspNet.Mvc.Core
_controllerFactory,
actionDescriptor,
_inputFormatters,
_outputFormatters,
_argumentBinder,
_modelBinders,
_modelValidatorProviders,

View File

@ -18,6 +18,7 @@ namespace Microsoft.AspNet.Mvc.Core
private readonly IReadOnlyList<IFilterProvider> _filterProviders;
private readonly IReadOnlyList<IInputFormatter> _inputFormatters;
private readonly IReadOnlyList<IModelBinder> _modelBinders;
private readonly IReadOnlyList<IOutputFormatter> _outputFormatters;
private readonly IReadOnlyList<IModelValidatorProvider> _modelValidatorProviders;
private readonly IReadOnlyList<IValueProviderFactory> _valueProviderFactories;
@ -43,6 +44,7 @@ namespace Microsoft.AspNet.Mvc.Core
[NotNull] ActionContext actionContext,
[NotNull] IReadOnlyList<IFilterProvider> filterProviders,
[NotNull] IReadOnlyList<IInputFormatter> inputFormatters,
[NotNull] IReadOnlyList<IOutputFormatter> outputFormatters,
[NotNull] IReadOnlyList<IModelBinder> modelBinders,
[NotNull] IReadOnlyList<IModelValidatorProvider> modelValidatorProviders,
[NotNull] IReadOnlyList<IValueProviderFactory> valueProviderFactories,
@ -52,6 +54,7 @@ namespace Microsoft.AspNet.Mvc.Core
_filterProviders = filterProviders;
_inputFormatters = inputFormatters;
_outputFormatters = outputFormatters;
_modelBinders = modelBinders;
_modelValidatorProviders = modelValidatorProviders;
_valueProviderFactories = valueProviderFactories;
@ -208,6 +211,7 @@ namespace Microsoft.AspNet.Mvc.Core
var context = new ResourceExecutingContext(ActionContext, _filters);
context.InputFormatters = new List<IInputFormatter>(_inputFormatters);
context.OutputFormatters = new List<IOutputFormatter>(_outputFormatters);
context.ModelBinders = new List<IModelBinder>(_modelBinders);
context.ValidatorProviders = new List<IModelValidatorProvider>(_modelValidatorProviders);
context.ValueProviderFactories = new List<IValueProviderFactory>(_valueProviderFactories);
@ -417,6 +421,7 @@ namespace Microsoft.AspNet.Mvc.Core
ActionBindingContext = new ActionBindingContext();
ActionBindingContext.InputFormatters = _resourceExecutingContext.InputFormatters;
ActionBindingContext.OutputFormatters = _resourceExecutingContext.OutputFormatters;
ActionBindingContext.ModelBinder = new CompositeModelBinder(_resourceExecutingContext.ModelBinders);
ActionBindingContext.ValidatorProvider = new CompositeModelValidatorProvider(
_resourceExecutingContext.ValidatorProviders);

View File

@ -28,6 +28,11 @@ namespace Microsoft.AspNet.Mvc
/// </summary>
public virtual IList<IInputFormatter> InputFormatters { get; set; }
/// <summary>
/// Gets or sets the list of <see cref="IOutputFormatter"/> instances used to format the response.
/// </summary>
public virtual IList<IOutputFormatter> OutputFormatters { get; set; }
/// <summary>
/// Gets or sets the list of <see cref="IModelBinder"/> instances used by model binding.
/// </summary>

View File

@ -15,6 +15,8 @@ namespace Microsoft.AspNet.Mvc
public IList<IInputFormatter> InputFormatters { get; set; }
public IList<IOutputFormatter> OutputFormatters { get; set; }
public IModelValidatorProvider ValidatorProvider { get; set; }
}
}

View File

@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Http.Core;
@ -91,6 +92,7 @@ namespace Microsoft.AspNet.Mvc
var httpContext = new DefaultHttpContext();
httpContext.Request.PathBase = new PathString("");
httpContext.Response.Body = new MemoryStream();
var services = new Mock<IServiceProvider>();
httpContext.RequestServices = services.Object;
@ -100,6 +102,14 @@ namespace Microsoft.AspNet.Mvc
services.Setup(p => p.GetService(typeof(IOptions<MvcOptions>)))
.Returns(optionsAccessor);
var mockContextAccessor = new Mock<IScopedInstance<ActionBindingContext>>();
mockContextAccessor
.SetupGet(o => o.Value)
.Returns(new ActionBindingContext() { OutputFormatters = optionsAccessor.Options.OutputFormatters });
services.Setup(o => o.GetService(typeof(IScopedInstance<ActionBindingContext>)))
.Returns(mockContextAccessor.Object);
return httpContext;
}

View File

@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Http.Core;
@ -107,6 +108,15 @@ namespace Microsoft.AspNet.Mvc
httpContext.Setup(o => o.Response)
.Returns(response);
var mockContextAccessor = new Mock<IScopedInstance<ActionBindingContext>>();
mockContextAccessor
.SetupGet(o => o.Value)
.Returns((ActionBindingContext)null);
httpContext.Setup(o => o.RequestServices.GetService(typeof(IScopedInstance<ActionBindingContext>)))
.Returns(mockContextAccessor.Object);
return httpContext.Object;
}

View File

@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Http.Core;
@ -90,8 +91,18 @@ namespace Microsoft.AspNet.Mvc
var optionsAccessor = new MockMvcOptionsAccessor();
optionsAccessor.Options.OutputFormatters.Add(new StringOutputFormatter());
optionsAccessor.Options.OutputFormatters.Add(new JsonOutputFormatter());
httpContext.Setup(p => p.RequestServices.GetService(typeof(IOptions<MvcOptions>)))
httpContext
.Setup(p => p.RequestServices.GetService(typeof(IOptions<MvcOptions>)))
.Returns(optionsAccessor);
var mockActionBindingContext = new Mock<IScopedInstance<ActionBindingContext>>();
mockActionBindingContext
.SetupGet(o=> o.Value)
.Returns(new ActionBindingContext() { OutputFormatters = optionsAccessor.Options.OutputFormatters });
httpContext
.Setup(o => o.RequestServices.GetService(typeof(IScopedInstance<ActionBindingContext>)))
.Returns(mockActionBindingContext.Object);
return httpContext.Object;
}
}

View File

@ -92,6 +92,16 @@ namespace Microsoft.AspNet.Mvc
optionsAccessor.Options.OutputFormatters.Add(new StringOutputFormatter());
optionsAccessor.Options.OutputFormatters.Add(new JsonOutputFormatter());
optionsAccessor.Options.RespectBrowserAcceptHeader = respectBrowserAcceptHeader;
var mockContextAccessor = new Mock<IScopedInstance<ActionBindingContext>>();
mockContextAccessor
.SetupGet(o => o.Value)
.Returns(new ActionBindingContext()
{
OutputFormatters = optionsAccessor.Options.OutputFormatters
});
httpContext.Setup(o => o.RequestServices.GetService(typeof(IScopedInstance<ActionBindingContext>)))
.Returns(mockContextAccessor.Object);
httpContext.Setup(o => o.RequestServices.GetService(typeof(IOptions<MvcOptions>)))
.Returns(optionsAccessor);

View File

@ -162,6 +162,25 @@ namespace Microsoft.AspNet.Mvc.Core.Test.ActionResults
Assert.Equal(expectedContentType, httpResponse.ContentType);
}
[Fact]
public async Task ObjectResult_FallsBackOn_FormattersInOptions()
{
// Arrange
var formatter = GetMockFormatter();
var actionContext = CreateMockActionContext(
new[] { formatter.Object },
setupActionBindingContext: false);
// Set the content type property explicitly to a single value.
var result = new ObjectResult("someValue");
// Act
await result.ExecuteResultAsync(actionContext);
// Assert
formatter.Verify(o => o.WriteAsync(It.IsAny<OutputFormatterContext>()));
}
[Fact]
public async Task ObjectResult_WithSingleContentType_TheContentTypeIsIgnoredIfTheTypeIsString()
{
@ -824,11 +843,11 @@ namespace Microsoft.AspNet.Mvc.Core.Test.ActionResults
}
private static ActionContext CreateMockActionContext(
HttpResponse response = null,
string requestAcceptHeader = "application/*",
string requestContentType = "application/json",
string requestAcceptCharsetHeader = "",
bool respectBrowserAcceptHeader = false)
HttpResponse response = null,
string requestAcceptHeader = "application/*",
string requestContentType = "application/json",
string requestAcceptCharsetHeader = "",
bool respectBrowserAcceptHeader = false)
{
var formatters = new IOutputFormatter[] { new StringOutputFormatter(), new JsonOutputFormatter() };
@ -842,12 +861,13 @@ namespace Microsoft.AspNet.Mvc.Core.Test.ActionResults
}
private static ActionContext CreateMockActionContext(
IEnumerable<IOutputFormatter> outputFormatters,
HttpResponse response = null,
string requestAcceptHeader = "application/*",
string requestContentType = "application/json",
string requestAcceptCharsetHeader = "",
bool respectBrowserAcceptHeader = false)
IEnumerable<IOutputFormatter> outputFormatters,
HttpResponse response = null,
string requestAcceptHeader = "application/*",
string requestContentType = "application/json",
string requestAcceptCharsetHeader = "",
bool respectBrowserAcceptHeader = false,
bool setupActionBindingContext = true)
{
var httpContext = new Mock<HttpContext>();
if (response != null)
@ -872,10 +892,26 @@ namespace Microsoft.AspNet.Mvc.Core.Test.ActionResults
{
optionsAccessor.Options.OutputFormatters.Add(formatter);
}
optionsAccessor.Options.RespectBrowserAcceptHeader = respectBrowserAcceptHeader;
httpContext.Setup(o => o.RequestServices.GetService(typeof(IOptions<MvcOptions>)))
.Returns(optionsAccessor);
var mockActionBindingContext = new Mock<IScopedInstance<ActionBindingContext>>();
ActionBindingContext bindingContext = null;
if (setupActionBindingContext)
{
bindingContext = new ActionBindingContext { OutputFormatters = outputFormatters.ToList() };
}
mockActionBindingContext
.SetupGet(o => o.Value)
.Returns(bindingContext);
httpContext.Setup(o => o.RequestServices.GetService(typeof(IScopedInstance<ActionBindingContext>)))
.Returns(mockActionBindingContext.Object);
return new ActionContext(httpContext.Object, new RouteData(), new ActionDescriptor());
}

View File

@ -11,7 +11,6 @@ using Microsoft.AspNet.Http;
using Microsoft.AspNet.Http.Core;
using Microsoft.AspNet.Mvc.Core;
using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.ModelBinding.Metadata;
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
using Microsoft.AspNet.Routing;
using Microsoft.AspNet.Testing;
@ -2030,13 +2029,13 @@ namespace Microsoft.AspNet.Mvc
filterProvider.SetupGet(fp => fp.Order)
.Returns(DefaultOrder.DefaultFrameworkSortOrder);
var invoker = new TestControllerActionInvoker(
actionContext,
new[] { filterProvider.Object },
new MockControllerFactory(this),
actionDescriptor,
new InputFormatter[0],
new IOutputFormatter[0],
Mock.Of<IControllerActionArgumentBinder>(),
new IModelBinder[0],
new IModelValidatorProvider[0],
@ -2085,6 +2084,7 @@ namespace Microsoft.AspNet.Mvc
var controllerFactory = new Mock<IControllerFactory>();
controllerFactory.Setup(c => c.CreateController(It.IsAny<ActionContext>()))
.Returns(new TestController());
var metadataProvider = new EmptyModelMetadataProvider();
var invoker = new ControllerActionInvoker(
actionContext,
@ -2092,6 +2092,7 @@ namespace Microsoft.AspNet.Mvc
controllerFactory.Object,
actionDescriptor,
new IInputFormatter[0],
new IOutputFormatter[0],
new DefaultControllerActionArgumentBinder(
metadataProvider,
new DefaultObjectValidator(new IExcludeTypeValidationFilter[0], metadataProvider),
@ -2193,6 +2194,7 @@ namespace Microsoft.AspNet.Mvc
MockControllerFactory controllerFactory,
ControllerActionDescriptor descriptor,
IReadOnlyList<IInputFormatter> inputFormatters,
IReadOnlyList<IOutputFormatter> outputFormatters,
IControllerActionArgumentBinder controllerActionArgumentBinder,
IReadOnlyList<IModelBinder> modelBinders,
IReadOnlyList<IModelValidatorProvider> modelValidatorProviders,
@ -2205,6 +2207,7 @@ namespace Microsoft.AspNet.Mvc
controllerFactory,
descriptor,
inputFormatters,
outputFormatters,
controllerActionArgumentBinder,
modelBinders,
modelValidatorProviders,

View File

@ -588,6 +588,71 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
Assert.Equal("Throwing Exception Filter", await response.Content.ReadAsStringAsync());
}
[Fact]
public async Task ResourceFilter_ShortCircuitsUsingObjectResult_UsesOptions()
{
// Arrange
var input = "{ sampleInt: 10 }";
var server = TestHelper.CreateServer(_app, SiteName, _configureServices);
var client = server.CreateClient();
var request = new HttpRequestMessage(HttpMethod.Post, "http://localhost/ResourceFilter/Post");
request.Content = new StringContent(input, Encoding.UTF8, "application/json");
// Act
var response = await client.SendAsync(request);
// Assert
// Uses formatters from options.
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
// Notice this has been formatted using StringOutputFormatter and not JsonOutputFormatter.
Assert.Equal("someValue", await response.Content.ReadAsStringAsync());
}
[Fact]
public async Task ResourceFilter_ShortCircuitsUsingObjectResult_WithJsonFormatter_ReturnsResponse()
{
// Arrange
var input = "{ sampleInt: 10 }";
var server = TestHelper.CreateServer(_app, SiteName, _configureServices);
var client = server.CreateClient();
var request = new HttpRequestMessage(HttpMethod.Post, "http://localhost/ResourceFilter/Get");
request.Content = new StringContent(input, Encoding.UTF8, "application/json");
// Act
var response = await client.SendAsync(request);
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("application/json", response.Content.Headers.ContentType.MediaType);
Assert.Equal("\"someValue\"", await response.Content.ReadAsStringAsync());
}
[Fact]
public async Task ResourceFilter_ChangesOutputFormatters_JsonReturned()
{
// Arrange
var input = "{ sampleInt: 10 }";
var server = TestHelper.CreateServer(_app, SiteName, _configureServices);
var client = server.CreateClient();
var request = new HttpRequestMessage(HttpMethod.Post, "http://localhost/Json");
request.Content = new StringContent(input, Encoding.UTF8, "application/json");
// Act
var response = await client.SendAsync(request);
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("application/json", response.Content.Headers.ContentType.MediaType);
Assert.Equal("\"10\"", await response.Content.ReadAsStringAsync());
}
[Fact]
public async Task ResourceFilter_ChangesInputFormatters_JsonAccepted()
{
@ -605,7 +670,7 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("10", await response.Content.ReadAsStringAsync());
Assert.Equal("\"10\"", await response.Content.ReadAsStringAsync());
}
[Fact]
@ -630,7 +695,7 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("0", await response.Content.ReadAsStringAsync());
Assert.Equal("\"0\"", await response.Content.ReadAsStringAsync());
}
}
}

View File

@ -9,6 +9,7 @@ using Microsoft.AspNet.Http.Core;
using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Routing;
using Microsoft.AspNet.WebUtilities;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.OptionsModel;
using Moq;
using Xunit;
@ -72,6 +73,15 @@ namespace System.Web.Http
var optionsAccessor = new Mock<IOptions<MvcOptions>>();
optionsAccessor.SetupGet(o => o.Options)
.Returns(options);
var mockActionBindingContext = new Mock<IScopedInstance<ActionBindingContext>>();
var bindingContext = new ActionBindingContext { OutputFormatters = options.OutputFormatters };
mockActionBindingContext
.SetupGet(o => o.Value)
.Returns(bindingContext);
services.Setup(o => o.GetService(typeof(IScopedInstance<ActionBindingContext>)))
.Returns(mockActionBindingContext.Object);
services.Setup(s => s.GetService(typeof(IOptions<MvcOptions>)))
.Returns(optionsAccessor.Object);

View File

@ -9,6 +9,7 @@ using Microsoft.AspNet.Http.Core;
using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Routing;
using Microsoft.AspNet.WebUtilities;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.OptionsModel;
using Moq;
using Xunit;
@ -73,6 +74,15 @@ namespace System.Web.Http
optionsAccessor.SetupGet(o => o.Options)
.Returns(options);
var mockActionBindingContext = new Mock<IScopedInstance<ActionBindingContext>>();
var bindingContext = new ActionBindingContext { OutputFormatters = options.OutputFormatters };
mockActionBindingContext
.SetupGet(o => o.Value)
.Returns(bindingContext);
services.Setup(o => o.GetService(typeof(IScopedInstance<ActionBindingContext>)))
.Returns(mockActionBindingContext.Object);
services.Setup(s => s.GetService(typeof(IOptions<MvcOptions>)))
.Returns(optionsAccessor.Object);

View File

@ -10,6 +10,7 @@ using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Routing;
using Microsoft.AspNet.WebUtilities;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.OptionsModel;
using Moq;
using Xunit;
@ -86,6 +87,16 @@ namespace System.Web.Http
optionsAccessor.SetupGet(o => o.Options)
.Returns(options);
var mockActionBindingContext = new Mock<IScopedInstance<ActionBindingContext>>();
var bindingContext = new ActionBindingContext { OutputFormatters = options.OutputFormatters };
mockActionBindingContext
.SetupGet(o => o.Value)
.Returns(bindingContext);
services.Setup(o => o.GetService(typeof(IScopedInstance<ActionBindingContext>)))
.Returns(mockActionBindingContext.Object);
services.Setup(s => s.GetService(typeof(IOptions<MvcOptions>)))
.Returns(optionsAccessor.Object);

View File

@ -9,6 +9,7 @@ using System.Threading.Tasks;
using Microsoft.AspNet.Http.Core;
using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Routing;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.OptionsModel;
using Moq;
using Xunit;
@ -74,6 +75,15 @@ namespace System.Web.Http
optionsAccessor.SetupGet(o => o.Options)
.Returns(options);
var mockActionBindingContext = new Mock<IScopedInstance<ActionBindingContext>>();
var bindingContext = new ActionBindingContext { OutputFormatters = options.OutputFormatters };
mockActionBindingContext
.SetupGet(o => o.Value)
.Returns(bindingContext);
services.Setup(o => o.GetService(typeof(IScopedInstance<ActionBindingContext>)))
.Returns(mockActionBindingContext.Object);
services.Setup(s => s.GetService(typeof(IOptions<MvcOptions>)))
.Returns(optionsAccessor.Object);

View File

@ -8,6 +8,7 @@ using Microsoft.AspNet.Http.Core;
using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Routing;
using Microsoft.AspNet.WebUtilities;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.OptionsModel;
using Moq;
using Xunit;
@ -47,6 +48,15 @@ namespace System.Web.Http
optionsAccessor.SetupGet(o => o.Options)
.Returns(options);
var mockActionBindingContext = new Mock<IScopedInstance<ActionBindingContext>>();
var bindingContext = new ActionBindingContext { OutputFormatters = options.OutputFormatters };
mockActionBindingContext
.SetupGet(o => o.Value)
.Returns(bindingContext);
services.Setup(o => o.GetService(typeof(IScopedInstance<ActionBindingContext>)))
.Returns(mockActionBindingContext.Object);
services.Setup(s => s.GetService(typeof(IOptions<MvcOptions>)))
.Returns(optionsAccessor.Object);

View File

@ -32,6 +32,11 @@ namespace FiltersWebSite.Controllers
context.InputFormatters.Clear();
context.InputFormatters.Add(jsonFormatter);
// Update the output formatter collection to only return JSON.
var jsonOutputFormatter = context.OutputFormatters.OfType<JsonOutputFormatter>().Single();
context.OutputFormatters.Clear();
context.OutputFormatters.Add(jsonOutputFormatter);
}
}
}

View File

@ -0,0 +1,65 @@
// 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;
using System.Linq;
using Microsoft.AspNet.Mvc;
namespace FiltersWebSite.Controllers
{
[Route("ResourceFilter/[action]")]
public class ResourceFilterController : Controller
{
[HttpPost]
[ShortCircuitWithFormatter]
public string Get()
{
return "NeverGetsExecuted";
}
[HttpPost]
[ShortCircuit]
public string Post()
{
return "NeverGetsExecuted";
}
private class ShortCircuitWithFormatterAttribute : Attribute, IResourceFilter
{
private IOutputFormatter[] _formatters;
public ShortCircuitWithFormatterAttribute()
{
_formatters = new IOutputFormatter[] { new JsonOutputFormatter() };
}
public void OnResourceExecuted(ResourceExecutedContext context)
{
}
public void OnResourceExecuting(ResourceExecutingContext context)
{
var result = new ObjectResult("someValue");
foreach (var formatter in _formatters)
{
result.Formatters.Add(formatter);
}
context.Result = result;
}
}
private class ShortCircuitAttribute : Attribute, IResourceFilter
{
public void OnResourceExecuted(ResourceExecutedContext context)
{
}
public void OnResourceExecuting(ResourceExecutingContext context)
{
// ShortCircuit.
context.Result = new ObjectResult("someValue");
}
}
}
}