1. Moving the HttpNotAcceptableOutputFormatter to product code.
2. Renaming the NoContentFormatter to HttpNoContentOutputFormatter. 3. Updating the test to use mock.
This commit is contained in:
parent
e884a476e9
commit
7a3dc352c9
|
|
@ -12,7 +12,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
/// <summary>
|
||||
/// Sets the status code to 204 if the content is null.
|
||||
/// </summary>
|
||||
public class NoContentFormatter : IOutputFormatter
|
||||
public class HttpNoContentOutputFormatter : IOutputFormatter
|
||||
{
|
||||
public bool CanWriteResult(OutputFormatterContext context, MediaTypeHeaderValue contentType)
|
||||
{
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
// 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.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
/// <summary>
|
||||
/// A formatter which does not have a supported content type and selects itself if no content type is passed to it.
|
||||
/// Sets the status code to 406 if selected.
|
||||
/// </summary>
|
||||
public class HttpNotAcceptableOutputFormatter : IOutputFormatter
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public bool CanWriteResult(OutputFormatterContext context, MediaTypeHeaderValue contentType)
|
||||
{
|
||||
return contentType == null;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IReadOnlyList<MediaTypeHeaderValue> GetSupportedContentTypes(Type declaredType,
|
||||
Type runtimeType,
|
||||
MediaTypeHeaderValue contentType)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task WriteAsync(OutputFormatterContext context)
|
||||
{
|
||||
var response = context.ActionContext.HttpContext.Response;
|
||||
response.StatusCode = 406;
|
||||
return Task.FromResult<bool>(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -34,7 +34,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
options.ModelBinders.Add(new ComplexModelDtoModelBinder());
|
||||
|
||||
// Set up default output formatters.
|
||||
options.OutputFormatters.Add(new NoContentFormatter());
|
||||
options.OutputFormatters.Add(new HttpNoContentOutputFormatter());
|
||||
options.OutputFormatters.Add(new TextPlainFormatter());
|
||||
options.OutputFormatters.Add(new JsonOutputFormatter(JsonOutputFormatter.CreateDefaultSettings(),
|
||||
indent: false));
|
||||
|
|
|
|||
|
|
@ -275,18 +275,23 @@ namespace Microsoft.AspNet.Mvc.Core.Test.ActionResults
|
|||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("", 2)]
|
||||
[InlineData(null, 2)]
|
||||
[InlineData("application/xml", 3)]
|
||||
[InlineData("application/custom", 3)]
|
||||
[InlineData("application/xml;q=1, application/custom;q=0.8", 4)]
|
||||
[InlineData("")]
|
||||
[InlineData(null)]
|
||||
[InlineData("application/xml")]
|
||||
[InlineData("application/custom")]
|
||||
[InlineData("application/xml;q=1, application/custom;q=0.8")]
|
||||
public void SelectFormatter_WithNoMatchingAcceptHeadersAndRequestContentType_PicksFormatterBasedOnObjectType
|
||||
(string acceptHeader, int attemptedCountForCanWrite)
|
||||
(string acceptHeader)
|
||||
{
|
||||
// For no accept headers,
|
||||
// can write is called twice once for the request media type and once for the type match pass.
|
||||
// For each additional accept header, it is called once.
|
||||
// Arrange
|
||||
var acceptHeaderCollection = string.IsNullOrEmpty(acceptHeader) ?
|
||||
null :
|
||||
acceptHeader?.Split(',')
|
||||
.Select(header => MediaTypeWithQualityHeaderValue.Parse(header))
|
||||
.ToArray();
|
||||
var stream = new MemoryStream();
|
||||
var httpResponse = new Mock<HttpResponse>();
|
||||
httpResponse.SetupProperty<string>(o => o.ContentType);
|
||||
|
|
@ -295,15 +300,10 @@ namespace Microsoft.AspNet.Mvc.Core.Test.ActionResults
|
|||
var actionContext = CreateMockActionContext(httpResponse.Object,
|
||||
requestAcceptHeader: acceptHeader,
|
||||
requestContentType: "application/xml");
|
||||
var requestContentType = MediaTypeHeaderValue.Parse("application/xml");
|
||||
var input = "testInput";
|
||||
var result = new ObjectResult(input);
|
||||
|
||||
// Set more than one formatters. The test output formatter throws on write.
|
||||
result.Formatters = new List<IOutputFormatter>
|
||||
{
|
||||
new CannotWriteFormatter(),
|
||||
new CountingFormatter(),
|
||||
};
|
||||
var mockCountingFormatter = new Mock<IOutputFormatter>();
|
||||
|
||||
var context = new OutputFormatterContext()
|
||||
{
|
||||
|
|
@ -311,13 +311,37 @@ namespace Microsoft.AspNet.Mvc.Core.Test.ActionResults
|
|||
Object = input,
|
||||
DeclaredType = typeof(string)
|
||||
};
|
||||
var mockCountingSupportedContentType = MediaTypeHeaderValue.Parse("application/text");
|
||||
mockCountingFormatter.Setup(o => o.CanWriteResult(context,
|
||||
It.IsNotIn<MediaTypeHeaderValue>(mockCountingSupportedContentType)))
|
||||
.Returns(false);
|
||||
mockCountingFormatter.Setup(o => o.CanWriteResult(context, mockCountingSupportedContentType))
|
||||
.Returns(true);
|
||||
|
||||
mockCountingFormatter.Setup(o => o.GetSupportedContentTypes(context.DeclaredType,
|
||||
input.GetType(),
|
||||
It.IsAny<MediaTypeHeaderValue>()))
|
||||
.Returns(new List<MediaTypeHeaderValue> { mockCountingSupportedContentType });
|
||||
|
||||
// Set more than one formatters. The test output formatter throws on write.
|
||||
result.Formatters = new List<IOutputFormatter>
|
||||
{
|
||||
new CannotWriteFormatter(),
|
||||
mockCountingFormatter.Object,
|
||||
};
|
||||
|
||||
// Act
|
||||
var formatter = result.SelectFormatter(context, result.Formatters);
|
||||
|
||||
// Assert
|
||||
var countingFormatter = Assert.IsType<CountingFormatter>(formatter);
|
||||
Assert.Equal(attemptedCountForCanWrite, countingFormatter.GetCanWriteCallCount());
|
||||
Assert.Equal(mockCountingFormatter.Object, formatter);
|
||||
mockCountingFormatter.Verify(v => v.CanWriteResult(context,
|
||||
mockCountingSupportedContentType),
|
||||
Times.Once());
|
||||
var callCount = (acceptHeaderCollection == null ? 0 : acceptHeaderCollection.Count()) + 1;
|
||||
mockCountingFormatter.Verify(v => v.CanWriteResult(context,
|
||||
It.IsNotIn<MediaTypeHeaderValue>(mockCountingSupportedContentType)),
|
||||
Times.Exactly(callCount));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -507,42 +531,6 @@ namespace Microsoft.AspNet.Mvc.Core.Test.ActionResults
|
|||
return serviceCollection.BuildServiceProvider();
|
||||
}
|
||||
|
||||
public class CountingFormatter : OutputFormatter
|
||||
{
|
||||
private int _canWriteCallsCount = 0;
|
||||
|
||||
public CountingFormatter()
|
||||
{
|
||||
SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("text/plain"));
|
||||
SupportedEncodings.Add(Encoding.GetEncoding("utf-8"));
|
||||
}
|
||||
|
||||
public override bool CanWriteResult(OutputFormatterContext context, MediaTypeHeaderValue contentType)
|
||||
{
|
||||
_canWriteCallsCount++;
|
||||
if (base.CanWriteResult(context, contentType))
|
||||
{
|
||||
var actionReturnString = context.Object as string;
|
||||
if (actionReturnString != null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public int GetCanWriteCallCount()
|
||||
{
|
||||
return _canWriteCallsCount;
|
||||
}
|
||||
|
||||
public override Task WriteResponseBodyAsync(OutputFormatterContext context)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public class CannotWriteFormatter : IOutputFormatter
|
||||
{
|
||||
public virtual bool CanWriteResult(OutputFormatterContext context, MediaTypeHeaderValue contentType)
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ namespace Microsoft.AspNet.Mvc.Test
|
|||
ActionContext = null,
|
||||
};
|
||||
var contetType = useNonNullContentType ? MediaTypeHeaderValue.Parse("text/plain") : null;
|
||||
var formatter = new NoContentFormatter();
|
||||
var formatter = new HttpNoContentOutputFormatter();
|
||||
|
||||
// Act
|
||||
var actualCanWriteResult = formatter.CanWriteResult(formatterContext, contetType);
|
||||
|
|
@ -71,7 +71,7 @@ namespace Microsoft.AspNet.Mvc.Test
|
|||
ActionContext = new ActionContext(defaultHttpContext, new RouteData(), new ActionDescriptor())
|
||||
};
|
||||
|
||||
var formatter = new NoContentFormatter();
|
||||
var formatter = new HttpNoContentOutputFormatter();
|
||||
|
||||
// Act
|
||||
await formatter.WriteAsync(formatterContext);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
|
||||
// Assert
|
||||
Assert.Equal(5, mvcOptions.OutputFormatters.Count);
|
||||
Assert.IsType<NoContentFormatter>(mvcOptions.OutputFormatters[0].Instance);
|
||||
Assert.IsType<HttpNoContentOutputFormatter>(mvcOptions.OutputFormatters[0].Instance);
|
||||
Assert.IsType<TextPlainFormatter>(mvcOptions.OutputFormatters[1].Instance);
|
||||
Assert.IsType<JsonOutputFormatter>(mvcOptions.OutputFormatters[2].Instance);
|
||||
Assert.IsType<XmlDataContractSerializerOutputFormatter>(mvcOptions.OutputFormatters[3].Instance);
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ namespace ConnegWebsite
|
|||
public IActionResult OverrideTheFallback_UsingCustomFormatters(int input)
|
||||
{
|
||||
var objectResult = new ObjectResult(input);
|
||||
objectResult.Formatters.Add(new StopIfNoMatchOutputFormatter());
|
||||
objectResult.Formatters.Add(new HttpNotAcceptableOutputFormatter());
|
||||
objectResult.Formatters.Add(new PlainTextFormatter());
|
||||
objectResult.Formatters.Add(new JsonOutputFormatter(JsonOutputFormatter.CreateDefaultSettings(), false));
|
||||
return objectResult;
|
||||
|
|
@ -57,7 +57,7 @@ namespace ConnegWebsite
|
|||
{
|
||||
var objectResult = new ObjectResult(input);
|
||||
var formattersProvider = ActionContext.HttpContext.RequestServices.GetService<IOutputFormattersProvider>();
|
||||
objectResult.Formatters.Add(new StopIfNoMatchOutputFormatter());
|
||||
objectResult.Formatters.Add(new HttpNotAcceptableOutputFormatter());
|
||||
foreach (var formatter in formattersProvider.OutputFormatters)
|
||||
{
|
||||
objectResult.Formatters.Add(formatter);
|
||||
|
|
@ -65,26 +65,5 @@ namespace ConnegWebsite
|
|||
|
||||
return objectResult;
|
||||
}
|
||||
|
||||
public class StopIfNoMatchOutputFormatter : IOutputFormatter
|
||||
{
|
||||
// Select if no Registered content type.
|
||||
public bool CanWriteResult(OutputFormatterContext context, MediaTypeHeaderValue contentType)
|
||||
{
|
||||
return contentType == null;
|
||||
}
|
||||
|
||||
public IReadOnlyList<MediaTypeHeaderValue> GetSupportedContentTypes(Type declaredType, Type runtimeType, MediaTypeHeaderValue contentType)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public Task WriteAsync(OutputFormatterContext context)
|
||||
{
|
||||
var response = context.ActionContext.HttpContext.Response;
|
||||
response.StatusCode = 406;
|
||||
return Task.FromResult<bool>(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue