[Fixes #1065] Need a way to specify "just type" with produces
This commit is contained in:
parent
45aae5956d
commit
4ecbe8c709
|
|
@ -17,6 +17,21 @@ namespace Microsoft.AspNet.Mvc
|
|||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
|
||||
public class ProducesAttribute : ResultFilterAttribute, IApiResponseMetadataProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="ProducesAttribute"/>.
|
||||
/// </summary>
|
||||
/// <param name="type">The <see cref="Type"/> of object that is going to be written in the response.</param>
|
||||
public ProducesAttribute([NotNull] Type type)
|
||||
{
|
||||
Type = type;
|
||||
ContentTypes = new List<MediaTypeHeaderValue>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="ProducesAttribute"/> with allowed content types.
|
||||
/// </summary>
|
||||
/// <param name="contentType">The allowed content type for a response.</param>
|
||||
/// <param name="additionalContentTypes">Additional allowed content types for a response.</param>
|
||||
public ProducesAttribute([NotNull] string contentType, params string[] additionalContentTypes)
|
||||
{
|
||||
ContentTypes = GetContentTypes(contentType, additionalContentTypes);
|
||||
|
|
|
|||
|
|
@ -128,6 +128,29 @@ namespace Microsoft.AspNet.Mvc.Test
|
|||
ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProducesAttribute_WithTypeOnly_SetsTypeProperty()
|
||||
{
|
||||
// Arrange
|
||||
var personType = typeof(Person);
|
||||
var producesAttribute = new ProducesAttribute(personType);
|
||||
|
||||
// Act and Assert
|
||||
Assert.NotNull(producesAttribute.Type);
|
||||
Assert.Same(personType, producesAttribute.Type);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProducesAttribute_WithTypeOnly_DoesNotSetContentTypes()
|
||||
{
|
||||
// Arrange
|
||||
var producesAttribute = new ProducesAttribute(typeof(Person));
|
||||
|
||||
// Act and Assert
|
||||
Assert.NotNull(producesAttribute.ContentTypes);
|
||||
Assert.Empty(producesAttribute.ContentTypes);
|
||||
}
|
||||
|
||||
private static void ValidateMediaType(MediaTypeHeaderValue expectedMediaType, MediaTypeHeaderValue actualMediaType)
|
||||
{
|
||||
Assert.Equal(expectedMediaType.MediaType, actualMediaType.MediaType);
|
||||
|
|
@ -160,5 +183,12 @@ namespace Microsoft.AspNet.Mvc.Test
|
|||
{
|
||||
return new ActionContext(new DefaultHttpContext(), new RouteData(), new ActionDescriptor());
|
||||
}
|
||||
|
||||
private class Person
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,14 +2,19 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
using System.Xml.Serialization;
|
||||
using ConnegWebSite;
|
||||
using Microsoft.AspNet.Builder;
|
||||
using Microsoft.AspNet.TestHost;
|
||||
using Microsoft.AspNet.Mvc.Xml;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.FunctionalTests
|
||||
|
|
@ -90,6 +95,48 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
|
|||
Assert.Equal(expectedContentType, response.Content.Headers.ContentType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ProducesAttributeWithTypeOnly_RunsRegularContentNegotiation()
|
||||
{
|
||||
// Arrange
|
||||
var server = TestServer.Create(_provider, _app);
|
||||
var client = server.CreateClient();
|
||||
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
||||
var expectedContentType = MediaTypeHeaderValue.Parse("application/json;charset=utf-8");
|
||||
var expectedOutput = "{\"Name\":\"John\",\"Address\":\"One Microsoft Way\"}";
|
||||
|
||||
// Act
|
||||
var response = await client.GetAsync("http://localhost/Home/UserInfo_ProducesWithTypeOnly");
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
Assert.Equal(expectedContentType, response.Content.Headers.ContentType);
|
||||
var actual = await response.Content.ReadAsStringAsync();
|
||||
Assert.Equal(expectedOutput, actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ProducesAttribute_WithTypeAndContentType_UsesContentType()
|
||||
{
|
||||
// Arrange
|
||||
var server = TestServer.Create(_provider, _app);
|
||||
var client = server.CreateClient();
|
||||
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));
|
||||
var expectedContentType = MediaTypeHeaderValue.Parse("application/xml;charset=utf-8");
|
||||
var expectedOutput = "<User xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\" " +
|
||||
"xmlns=\"http://schemas.datacontract.org/2004/07/ConnegWebSite\">" +
|
||||
"<Address>One Microsoft Way</Address><Name>John</Name></User>";
|
||||
|
||||
// Act
|
||||
var response = await client.GetAsync("http://localhost/Home/UserInfo_ProducesWithTypeAndContentType");
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
Assert.Equal(expectedContentType, response.Content.Headers.ContentType);
|
||||
var actual = await response.Content.ReadAsStringAsync();
|
||||
XmlAssert.Equal(expectedOutput, actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task NoMatchingFormatter_ForTheGivenContentType_Returns406()
|
||||
{
|
||||
|
|
@ -426,7 +473,7 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
|
|||
{
|
||||
// Arrange
|
||||
var server = TestServer.Create(_provider, _app);
|
||||
var client = server.CreateClient();
|
||||
var client = server.CreateClient();
|
||||
|
||||
// Act
|
||||
var response = await client.GetAsync("http://localhost/FormatFilter/MethodWithFormatFilter");
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@
|
|||
"WebApiCompatShimWebSite": "1.0.0",
|
||||
"Microsoft.AspNet.TestHost": "1.0.0-*",
|
||||
"Microsoft.AspNet.Mvc": "6.0.0-*",
|
||||
"Microsoft.AspNet.Mvc.Xml": "6.0.0-*",
|
||||
"Microsoft.AspNet.Mvc.TestConfiguration": "1.0.0",
|
||||
"MvcTagHelpersWebSite": "1.0.0",
|
||||
"Microsoft.Framework.ConfigurationModel.Json": "1.0.0-*",
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ namespace ApiExplorerWebSite
|
|||
}
|
||||
|
||||
[HttpGet("Action")]
|
||||
[ProducesType(typeof(Customer))]
|
||||
[Produces(typeof(Customer))]
|
||||
public object GetAction()
|
||||
{
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ namespace ApiExplorerWebSite
|
|||
public class ApiExplorerResponseTypeWithAttributeController : Controller
|
||||
{
|
||||
[HttpGet]
|
||||
[ProducesType(typeof(Customer))]
|
||||
[Produces(typeof(Customer))]
|
||||
public void GetVoid()
|
||||
{
|
||||
}
|
||||
|
|
@ -37,7 +37,7 @@ namespace ApiExplorerWebSite
|
|||
}
|
||||
|
||||
[HttpGet]
|
||||
[ProducesType(typeof(Customer))] // It's possible to lie about what type you return
|
||||
[Produces(typeof(Customer))] // It's possible to lie about what type you return
|
||||
public Product GetProduct()
|
||||
{
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -1,25 +0,0 @@
|
|||
// 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 Microsoft.AspNet.Mvc;
|
||||
using Microsoft.AspNet.Mvc.Description;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
|
||||
namespace ApiExplorerWebSite
|
||||
{
|
||||
public class ProducesTypeAttribute : ResultFilterAttribute, IApiResponseMetadataProvider
|
||||
{
|
||||
public ProducesTypeAttribute(Type type)
|
||||
{
|
||||
Type = type;
|
||||
}
|
||||
|
||||
public Type Type { get; private set; }
|
||||
|
||||
public void SetContentTypes(IList<MediaTypeHeaderValue> contentTypes)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -13,6 +13,23 @@ namespace ConnegWebSite
|
|||
}
|
||||
|
||||
public User UserInfo()
|
||||
{
|
||||
return CreateUser();
|
||||
}
|
||||
|
||||
[Produces(typeof(User))]
|
||||
public IActionResult UserInfo_ProducesWithTypeOnly()
|
||||
{
|
||||
return new ObjectResult(CreateUser());
|
||||
}
|
||||
|
||||
[Produces("application/xml", Type = typeof(User))]
|
||||
public IActionResult UserInfo_ProducesWithTypeAndContentType()
|
||||
{
|
||||
return new ObjectResult(CreateUser());
|
||||
}
|
||||
|
||||
private User CreateUser()
|
||||
{
|
||||
return new User() { Name = "John", Address = "One Microsoft Way" };
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue