258 lines
9.4 KiB
C#
Raw Normal View History

// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Linq;
using System.Net.Http.Formatting.Mocks;
using System.Net.Http.Headers;
using System.Text;
using Microsoft.TestCommon;
using Newtonsoft.Json.Linq;
using Xunit;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Net.Http.Formatting
{
public class DefaultContentNegotiatorTests
{
private readonly DefaultContentNegotiator _negotiator = new DefaultContentNegotiator();
private readonly HttpRequestMessage _request = new HttpRequestMessage();
[Fact]
public void TypeIsCorrect()
{
Assert.Type.HasProperties(typeof(DefaultContentNegotiator), TypeAssert.TypeProperties.IsPublicVisibleClass);
}
[Fact]
public void Negotiate_WhenTypeParameterIsNull_ThrowsException()
{
Assert.ThrowsArgumentNull(() => _negotiator.Negotiate(null, _request, Enumerable.Empty<MediaTypeFormatter>()), "type");
}
[Fact]
public void Negotiate_WhenRequestParameterIsNull_ThrowsException()
{
Assert.ThrowsArgumentNull(() => _negotiator.Negotiate(typeof(string), null, Enumerable.Empty<MediaTypeFormatter>()), "request");
}
[Fact]
public void Negotiate_WhenFormattersParameterIsNull_ThrowsException()
{
Assert.ThrowsArgumentNull(() => _negotiator.Negotiate(typeof(string), _request, null), "formatters");
}
[Fact]
public void Negotiate_ForEmptyFormatterCollection_ReturnsNull()
{
var result = _negotiator.Negotiate(typeof(string), _request, Enumerable.Empty<MediaTypeFormatter>());
Assert.Null(result);
}
[Fact]
public void MediaTypeMappingTakesPrecedenceOverAcceptHeader()
{
// Prepare the request message
_request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));
_request.Headers.Add("Browser", "IE");
_request.Headers.Add("Cookie", "ABC");
// Prepare the formatters
List<MediaTypeFormatter> formatters = new List<MediaTypeFormatter>();
formatters.Add(new JsonMediaTypeFormatter());
formatters.Add(new XmlMediaTypeFormatter());
PlainTextFormatter frmtr = new PlainTextFormatter();
frmtr.SupportedMediaTypes.Clear();
frmtr.MediaTypeMappings.Clear();
frmtr.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/xml"));
frmtr.MediaTypeMappings.Add(new MyMediaTypeMapping(new MediaTypeHeaderValue(("application/xml"))));
formatters.Add(frmtr);
// Act
var result = _negotiator.Negotiate(typeof(string), _request, formatters);
// Assert
Assert.NotNull(result);
Assert.Equal("application/xml", result.MediaType.MediaType);
Assert.IsType<PlainTextFormatter>(result.Formatter);
}
[Fact]
public void Negotiate_ForRequestReturnsFirstMatchingFormatter()
{
MediaTypeHeaderValue mediaType = new MediaTypeHeaderValue("application/myMediaType");
MediaTypeFormatter formatter1 = new MockMediaTypeFormatter()
{
CanWriteTypeCallback = (Type t) => false
};
MediaTypeFormatter formatter2 = new MockMediaTypeFormatter()
{
CanWriteTypeCallback = (Type t) => true
};
formatter2.SupportedMediaTypes.Add(mediaType);
MediaTypeFormatterCollection collection = new MediaTypeFormatterCollection(
new MediaTypeFormatter[]
{
formatter1,
formatter2
});
_request.Content = new StringContent("test", Encoding.Default, mediaType.MediaType);
var result = _negotiator.Negotiate(typeof(string), _request, collection);
Assert.Same(formatter2, result.Formatter);
Assert.MediaType.AreEqual(mediaType, result.MediaType, "Expected the formatter's media type to be returned.");
}
[Fact]
public void Negotiate_SelectsJsonAsDefaultFormatter()
{
// Arrange
_request.Content = new StringContent("test");
// Act
var result = _negotiator.Negotiate(typeof(string), _request, new MediaTypeFormatterCollection());
// Assert
Assert.IsType<JsonMediaTypeFormatter>(result.Formatter);
Assert.Equal(MediaTypeConstants.ApplicationJsonMediaType.MediaType, result.MediaType.MediaType);
}
[Fact]
public void Negotiate_SelectsXmlFormatter_ForXhrRequestThatAcceptsXml()
{
// Arrange
_request.Content = new StringContent("test");
_request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));
_request.Headers.Add("x-requested-with", "XMLHttpRequest");
// Act
var result = _negotiator.Negotiate(typeof(string), _request, new MediaTypeFormatterCollection());
// Assert
Assert.Equal("application/xml", result.MediaType.MediaType);
Assert.IsType<XmlMediaTypeFormatter>(result.Formatter);
}
[Fact]
public void Negotiate_SelectsJsonFormatter_ForXhrRequestThatDoesNotSpecifyAcceptHeaders()
{
// Arrange
_request.Content = new StringContent("test");
_request.Headers.Add("x-requested-with", "XMLHttpRequest");
// Act
var result = _negotiator.Negotiate(typeof(string), _request, new MediaTypeFormatterCollection());
// Assert
Assert.Equal("application/json", result.MediaType.MediaType);
Assert.IsType<JsonMediaTypeFormatter>(result.Formatter);
}
[Fact]
public void Negotiate_RespectsFormatterOrdering_ForXhrRequestThatDoesNotSpecifyAcceptHeaders()
{
// Arrange
_request.Content = new StringContent("test");
_request.Headers.Add("x-requested-with", "XMLHttpRequest");
MediaTypeFormatterCollection formatters = new MediaTypeFormatterCollection(new MediaTypeFormatter[]
{
new XmlMediaTypeFormatter(),
new JsonMediaTypeFormatter(),
new FormUrlEncodedMediaTypeFormatter()
});
// Act
var result = _negotiator.Negotiate(typeof(string), _request, formatters);
// Assert
Assert.Equal("application/json", result.MediaType.MediaType);
Assert.IsType<JsonMediaTypeFormatter>(result.Formatter);
}
[Fact]
public void Negotiate_SelectsJsonFormatter_ForXHRAndJsonValueResponse()
{
// Arrange
_request.Content = new StringContent("test");
_request.Headers.Add("x-requested-with", "XMLHttpRequest");
// Act
var result = _negotiator.Negotiate(typeof(JToken), _request, new MediaTypeFormatterCollection());
Assert.Equal("application/json", result.MediaType.MediaType);
Assert.IsType<JsonMediaTypeFormatter>(result.Formatter);
}
[Fact]
public void Negotiate_SelectsJsonFormatter_ForXHRAndMatchAllAcceptHeader()
{
// Accept
_request.Content = new StringContent("test");
_request.Headers.Add("x-requested-with", "XMLHttpRequest");
_request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("*/*"));
// Act
var result = _negotiator.Negotiate(typeof(string), _request, new MediaTypeFormatterCollection());
// Assert
Assert.Equal("application/json", result.MediaType.MediaType);
Assert.IsType<JsonMediaTypeFormatter>(result.Formatter);
}
[Fact]
public void Negotiate_UsesRequestedFormatterForXHRAndMatchAllPlusOtherAcceptHeader()
{
// Arrange
_request.Content = new StringContent("test");
_request.Headers.Add("x-requested-with", "XMLHttpRequest");
_request.Headers.Accept.ParseAdd("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); // XHR header sent by Firefox 3b5
// Act
var result = _negotiator.Negotiate(typeof(string), _request, new MediaTypeFormatterCollection());
// Assert
Assert.Equal("application/xml", result.MediaType.MediaType);
Assert.IsType<XmlMediaTypeFormatter>(result.Formatter);
}
private class PlainTextFormatter : MediaTypeFormatter
{
public override bool CanReadType(Type type)
{
return true;
}
public override bool CanWriteType(Type type)
{
return true;
}
}
private class MyMediaTypeMapping : MediaTypeMapping
{
public MyMediaTypeMapping(MediaTypeHeaderValue mediaType)
: base(mediaType)
{
}
public override double TryMatchMediaType(HttpRequestMessage request)
{
if (request.Headers.Contains("Cookie"))
{
return 1.0;
}
else
{
return 0;
}
}
}
}
}