Add support for default response (#8028)
* Add support for default response Fixes #6828
This commit is contained in:
parent
335500ab0e
commit
d2bb674b0a
|
|
@ -29,7 +29,7 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer
|
|||
_mvcOptions = mvcOptions;
|
||||
}
|
||||
|
||||
public IList<ApiResponseType> GetApiResponseTypes(ControllerActionDescriptor action)
|
||||
public ICollection<ApiResponseType> GetApiResponseTypes(ControllerActionDescriptor action)
|
||||
{
|
||||
// We only provide response info if we can figure out a type that is a user-data type.
|
||||
// Void /Task object/IActionResult will result in no data.
|
||||
|
|
@ -38,7 +38,7 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer
|
|||
var runtimeReturnType = GetRuntimeReturnType(declaredReturnType);
|
||||
|
||||
var responseMetadataAttributes = GetResponseMetadataAttributes(action);
|
||||
if (responseMetadataAttributes.Count == 0 &&
|
||||
if (responseMetadataAttributes.Count == 0 &&
|
||||
action.Properties.TryGetValue(typeof(ApiConventionResult), out var result))
|
||||
{
|
||||
// Action does not have any conventions. Use conventions on it if present.
|
||||
|
|
@ -67,14 +67,11 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer
|
|||
.ToArray();
|
||||
}
|
||||
|
||||
private IList<ApiResponseType> GetApiResponseTypes(
|
||||
private ICollection<ApiResponseType> GetApiResponseTypes(
|
||||
IReadOnlyList<IApiResponseMetadataProvider> responseMetadataAttributes,
|
||||
Type type)
|
||||
{
|
||||
var results = new List<ApiResponseType>();
|
||||
|
||||
// Build list of all possible return types (and status codes) for an action.
|
||||
var objectTypes = new Dictionary<int, Type>();
|
||||
var results = new Dictionary<int, ApiResponseType>();
|
||||
|
||||
// Get the content type that the action explicitly set to support.
|
||||
// Walk through all 'filter' attributes in order, and allow each one to see or override
|
||||
|
|
@ -86,7 +83,17 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer
|
|||
{
|
||||
metadataAttribute.SetContentTypes(contentTypes);
|
||||
|
||||
if (metadataAttribute.Type == typeof(void) &&
|
||||
ApiResponseType apiResponseType;
|
||||
|
||||
if (metadataAttribute is IApiDefaultResponseMetadataProvider)
|
||||
{
|
||||
apiResponseType = new ApiResponseType
|
||||
{
|
||||
IsDefaultResponse = true,
|
||||
Type = metadataAttribute.Type,
|
||||
};
|
||||
}
|
||||
else if (metadataAttribute.Type == typeof(void) &&
|
||||
type != null &&
|
||||
(metadataAttribute.StatusCode == StatusCodes.Status200OK || metadataAttribute.StatusCode == StatusCodes.Status201Created))
|
||||
{
|
||||
|
|
@ -94,20 +101,38 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer
|
|||
// In this event, use the action's return type for 200 or 201 status codes. This lets you decorate an action with a
|
||||
// [ProducesResponseType(201)] instead of [ProducesResponseType(201, typeof(Person)] when typeof(Person) can be inferred
|
||||
// from the return type.
|
||||
objectTypes[metadataAttribute.StatusCode] = type;
|
||||
apiResponseType = new ApiResponseType
|
||||
{
|
||||
StatusCode = metadataAttribute.StatusCode,
|
||||
Type = type,
|
||||
};
|
||||
}
|
||||
else if (metadataAttribute.Type != null)
|
||||
{
|
||||
objectTypes[metadataAttribute.StatusCode] = metadataAttribute.Type;
|
||||
apiResponseType = new ApiResponseType
|
||||
{
|
||||
StatusCode = metadataAttribute.StatusCode,
|
||||
Type = metadataAttribute.Type,
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
results[apiResponseType.StatusCode] = apiResponseType;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Set the default status only when no status has already been set explicitly
|
||||
if (objectTypes.Count == 0 && type != null)
|
||||
if (results.Count == 0 && type != null)
|
||||
{
|
||||
objectTypes[StatusCodes.Status200OK] = type;
|
||||
results[StatusCodes.Status200OK] = new ApiResponseType
|
||||
{
|
||||
StatusCode = StatusCodes.Status200OK,
|
||||
Type = type,
|
||||
};
|
||||
}
|
||||
|
||||
if (contentTypes.Count == 0)
|
||||
|
|
@ -117,25 +142,15 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer
|
|||
|
||||
var responseTypeMetadataProviders = _mvcOptions.OutputFormatters.OfType<IApiResponseTypeMetadataProvider>();
|
||||
|
||||
foreach (var objectType in objectTypes)
|
||||
foreach (var apiResponse in results.Values)
|
||||
{
|
||||
if (objectType.Value == null || objectType.Value == typeof(void))
|
||||
var responseType = apiResponse.Type;
|
||||
if (responseType == null || responseType == typeof(void))
|
||||
{
|
||||
results.Add(new ApiResponseType()
|
||||
{
|
||||
StatusCode = objectType.Key,
|
||||
Type = objectType.Value
|
||||
});
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
var apiResponseType = new ApiResponseType()
|
||||
{
|
||||
Type = objectType.Value,
|
||||
StatusCode = objectType.Key,
|
||||
ModelMetadata = _modelMetadataProvider.GetMetadataForType(objectType.Value)
|
||||
};
|
||||
apiResponse.ModelMetadata = _modelMetadataProvider.GetMetadataForType(responseType);
|
||||
|
||||
foreach (var contentType in contentTypes)
|
||||
{
|
||||
|
|
@ -143,7 +158,7 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer
|
|||
{
|
||||
var formatterSupportedContentTypes = responseTypeMetadataProvider.GetSupportedContentTypes(
|
||||
contentType,
|
||||
objectType.Value);
|
||||
responseType);
|
||||
|
||||
if (formatterSupportedContentTypes == null)
|
||||
{
|
||||
|
|
@ -152,7 +167,7 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer
|
|||
|
||||
foreach (var formatterSupportedContentType in formatterSupportedContentTypes)
|
||||
{
|
||||
apiResponseType.ApiResponseFormats.Add(new ApiResponseFormat()
|
||||
apiResponse.ApiResponseFormats.Add(new ApiResponseFormat
|
||||
{
|
||||
Formatter = (IOutputFormatter)responseTypeMetadataProvider,
|
||||
MediaType = formatterSupportedContentType,
|
||||
|
|
@ -160,11 +175,9 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
results.Add(apiResponseType);
|
||||
}
|
||||
|
||||
return results;
|
||||
return results.Values;
|
||||
}
|
||||
|
||||
private Type GetDeclaredReturnType(ControllerActionDescriptor action)
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
var errorMessage = Resources.FormatApiConvention_UnsupportedAttributesOnConvention(
|
||||
methodDisplayName,
|
||||
Environment.NewLine + string.Join(Environment.NewLine, unsupportedAttributes) + Environment.NewLine,
|
||||
$"{nameof(ProducesResponseTypeAttribute)}, {nameof(ApiConventionNameMatchAttribute)}");
|
||||
$"{nameof(ProducesResponseTypeAttribute)}, {nameof(ProducesDefaultResponseTypeAttribute)}, {nameof(ApiConventionNameMatchAttribute)}");
|
||||
|
||||
throw new ArgumentException(errorMessage, nameof(conventionType));
|
||||
}
|
||||
|
|
@ -83,6 +83,7 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
private static bool IsAllowedAttribute(object attribute)
|
||||
{
|
||||
return attribute is ProducesResponseTypeAttribute ||
|
||||
attribute is ProducesDefaultResponseTypeAttribute ||
|
||||
attribute is ApiConventionNameMatchAttribute;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.ApiExplorer
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a return type for all HTTP status codes that are not covered by other <see cref="IApiResponseMetadataProvider"/> instances.
|
||||
/// </summary>
|
||||
public interface IApiDefaultResponseMetadataProvider : IApiResponseMetadataProvider
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -10,6 +10,7 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
{
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
[ProducesDefaultResponseType]
|
||||
[ApiConventionNameMatch(ApiConventionNameMatchBehavior.Prefix)]
|
||||
public static void Get(
|
||||
[ApiConventionNameMatch(ApiConventionNameMatchBehavior.Suffix)]
|
||||
|
|
@ -18,6 +19,7 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
|
||||
[ProducesResponseType(StatusCodes.Status201Created)]
|
||||
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||
[ProducesDefaultResponseType]
|
||||
[ApiConventionNameMatch(ApiConventionNameMatchBehavior.Prefix)]
|
||||
public static void Post(
|
||||
[ApiConventionNameMatch(ApiConventionNameMatchBehavior.Any)]
|
||||
|
|
@ -27,6 +29,7 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||
[ProducesDefaultResponseType]
|
||||
[ApiConventionNameMatch(ApiConventionNameMatchBehavior.Prefix)]
|
||||
public static void Put(
|
||||
[ApiConventionNameMatch(ApiConventionNameMatchBehavior.Suffix)]
|
||||
|
|
@ -40,6 +43,7 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||
[ProducesDefaultResponseType]
|
||||
[ApiConventionNameMatch(ApiConventionNameMatchBehavior.Prefix)]
|
||||
public static void Delete(
|
||||
[ApiConventionNameMatch(ApiConventionNameMatchBehavior.Suffix)]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Mvc.ApiExplorer;
|
||||
using Microsoft.AspNetCore.Mvc.Formatters;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc
|
||||
{
|
||||
/// <summary>
|
||||
/// A filter that specifies the <see cref="System.Type"/> for all HTTP status codes that are not covered by <see cref="ProducesResponseTypeAttribute"/>.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
|
||||
public sealed class ProducesDefaultResponseTypeAttribute : Attribute, IApiDefaultResponseMetadataProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="ProducesResponseTypeAttribute"/>.
|
||||
/// </summary>
|
||||
public ProducesDefaultResponseTypeAttribute()
|
||||
: this(typeof(void))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="ProducesResponseTypeAttribute"/>.
|
||||
/// </summary>
|
||||
/// <param name="type">The <see cref="Type"/> of object that is going to be written in the response.</param>
|
||||
public ProducesDefaultResponseTypeAttribute(Type type)
|
||||
{
|
||||
Type = type ?? throw new ArgumentNullException(nameof(type));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type of the value returned by an action.
|
||||
/// </summary>
|
||||
public Type Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the HTTP status code of the response.
|
||||
/// </summary>
|
||||
public int StatusCode { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
void IApiResponseMetadataProvider.SetContentTypes(MediaTypeCollection contentTypes)
|
||||
{
|
||||
// Users are supposed to use the 'Produces' attribute to set the content types that an action can support.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -72,6 +72,60 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer
|
|||
public Task<ActionResult<BaseModel>> Get(int id) => null;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetApiResponseTypes_CombinesFilters()
|
||||
{
|
||||
// Arrange
|
||||
var filterDescriptors = new[]
|
||||
{
|
||||
new FilterDescriptor(new ProducesResponseTypeAttribute(400), FilterScope.Global),
|
||||
new FilterDescriptor(new ProducesResponseTypeAttribute(typeof(object), 201), FilterScope.Controller),
|
||||
new FilterDescriptor(new ProducesResponseTypeAttribute(typeof(ProblemDetails), 400), FilterScope.Controller),
|
||||
new FilterDescriptor(new ProducesResponseTypeAttribute(typeof(BaseModel), 201), FilterScope.Action),
|
||||
new FilterDescriptor(new ProducesResponseTypeAttribute(404), FilterScope.Action),
|
||||
};
|
||||
|
||||
var actionDescriptor = new ControllerActionDescriptor
|
||||
{
|
||||
FilterDescriptors = filterDescriptors,
|
||||
MethodInfo = typeof(GetApiResponseTypes_ReturnsResponseTypesFromActionIfPresentController).GetMethod(nameof(GetApiResponseTypes_ReturnsResponseTypesFromActionIfPresentController.Get)),
|
||||
};
|
||||
|
||||
var provider = GetProvider();
|
||||
|
||||
// Act
|
||||
var result = provider.GetApiResponseTypes(actionDescriptor);
|
||||
|
||||
// Assert
|
||||
Assert.Collection(
|
||||
result.OrderBy(r => r.StatusCode),
|
||||
responseType =>
|
||||
{
|
||||
Assert.Equal(201, responseType.StatusCode);
|
||||
Assert.Equal(typeof(BaseModel), responseType.Type);
|
||||
Assert.False(responseType.IsDefaultResponse);
|
||||
Assert.Collection(
|
||||
responseType.ApiResponseFormats,
|
||||
format => Assert.Equal("application/json", format.MediaType));
|
||||
},
|
||||
responseType =>
|
||||
{
|
||||
Assert.Equal(400, responseType.StatusCode);
|
||||
Assert.Equal(typeof(ProblemDetails), responseType.Type);
|
||||
Assert.False(responseType.IsDefaultResponse);
|
||||
Assert.Collection(
|
||||
responseType.ApiResponseFormats,
|
||||
format => Assert.Equal("application/json", format.MediaType));
|
||||
},
|
||||
responseType =>
|
||||
{
|
||||
Assert.Equal(404, responseType.StatusCode);
|
||||
Assert.Equal(typeof(void), responseType.Type);
|
||||
Assert.False(responseType.IsDefaultResponse);
|
||||
Assert.Empty(responseType.ApiResponseFormats);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetApiResponseTypes_ReturnsResponseTypesFromApiConventionItem()
|
||||
{
|
||||
|
|
@ -159,6 +213,54 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer
|
|||
public Task<ActionResult<BaseModel>> PostModel(int id, BaseModel model) => null;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetApiResponseTypes_ReturnsDefaultProblemResponse()
|
||||
{
|
||||
// Arrange
|
||||
var actionDescriptor = GetControllerActionDescriptor(
|
||||
typeof(GetApiResponseTypes_ReturnsResponseTypesFromDefaultConventionsController),
|
||||
nameof(GetApiResponseTypes_ReturnsResponseTypesFromDefaultConventionsController.DeleteBase));
|
||||
actionDescriptor.Properties[typeof(ApiConventionResult)] = new ApiConventionResult(new IApiResponseMetadataProvider[]
|
||||
{
|
||||
new ProducesResponseTypeAttribute(201),
|
||||
new ProducesResponseTypeAttribute(404),
|
||||
new ProducesDefaultResponseTypeAttribute(typeof(SerializableError)),
|
||||
});
|
||||
|
||||
var provider = GetProvider();
|
||||
|
||||
// Act
|
||||
var result = provider.GetApiResponseTypes(actionDescriptor);
|
||||
|
||||
// Assert
|
||||
Assert.Collection(
|
||||
result.OrderBy(r => r.StatusCode),
|
||||
responseType =>
|
||||
{
|
||||
Assert.True(responseType.IsDefaultResponse);
|
||||
Assert.Equal(typeof(SerializableError), responseType.Type);
|
||||
Assert.Collection(
|
||||
responseType.ApiResponseFormats,
|
||||
format => Assert.Equal("application/json", format.MediaType));
|
||||
},
|
||||
responseType =>
|
||||
{
|
||||
Assert.Equal(201, responseType.StatusCode);
|
||||
Assert.Equal(typeof(BaseModel), responseType.Type);
|
||||
Assert.False(responseType.IsDefaultResponse);
|
||||
Assert.Collection(
|
||||
responseType.ApiResponseFormats,
|
||||
format => Assert.Equal("application/json", format.MediaType));
|
||||
},
|
||||
responseType =>
|
||||
{
|
||||
Assert.Equal(404, responseType.StatusCode);
|
||||
Assert.Equal(typeof(void), responseType.Type);
|
||||
Assert.False(responseType.IsDefaultResponse);
|
||||
Assert.Empty(responseType.ApiResponseFormats);
|
||||
});
|
||||
}
|
||||
|
||||
private static ApiResponseTypeProvider GetProvider()
|
||||
{
|
||||
var mvcOptions = new MvcOptions
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// 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.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc.ApiExplorer;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
|
|
@ -15,11 +16,10 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
public void Constructor_ThrowsIfConventionMethodIsAnnotatedWithProducesAttribute()
|
||||
{
|
||||
// Arrange
|
||||
var expected = $"Method {typeof(ConventionWithProducesAttribute).FullName + ".Get"} is decorated with the following attributes that are not allowed on an API convention method:" +
|
||||
Environment.NewLine +
|
||||
typeof(ProducesAttribute).FullName +
|
||||
Environment.NewLine +
|
||||
$"The following attributes are allowed on API convention methods: {nameof(ProducesResponseTypeAttribute)}, {nameof(ApiConventionNameMatchAttribute)}";
|
||||
var methodName = typeof(ConventionWithProducesAttribute).FullName + '.' + nameof(ConventionWithProducesAttribute.Get);
|
||||
var attribute = typeof(ProducesAttribute);
|
||||
|
||||
var expected = GetErrorMessage(methodName, attribute);
|
||||
|
||||
// Act & Assert
|
||||
ExceptionAssert.ThrowsArgument(
|
||||
|
|
@ -38,11 +38,9 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
public void Constructor_ThrowsIfConventionMethodHasRouteAttribute()
|
||||
{
|
||||
// Arrange
|
||||
var expected = $"Method {typeof(ConventionWithRouteAttribute).FullName + ".Get"} is decorated with the following attributes that are not allowed on an API convention method:" +
|
||||
Environment.NewLine +
|
||||
typeof(HttpGetAttribute).FullName +
|
||||
Environment.NewLine +
|
||||
$"The following attributes are allowed on API convention methods: {nameof(ProducesResponseTypeAttribute)}, {nameof(ApiConventionNameMatchAttribute)}";
|
||||
var methodName = typeof(ConventionWithRouteAttribute).FullName + '.' + nameof(ConventionWithRouteAttribute.Get);
|
||||
var attribute = typeof(HttpGetAttribute);
|
||||
var expected = GetErrorMessage(methodName, attribute);
|
||||
|
||||
// Act & Assert
|
||||
ExceptionAssert.ThrowsArgument(
|
||||
|
|
@ -61,11 +59,9 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
public void Constructor_ThrowsIfMultipleUnsupportedAttributesArePresentOnConvention()
|
||||
{
|
||||
// Arrange
|
||||
var expected = $"Method {typeof(ConventionWitUnsupportedAttributes).FullName + ".Get"} is decorated with the following attributes that are not allowed on an API convention method:" +
|
||||
Environment.NewLine +
|
||||
string.Join(Environment.NewLine, typeof(ProducesAttribute).FullName, typeof(ServiceFilterAttribute).FullName, typeof(AuthorizeAttribute).FullName) +
|
||||
Environment.NewLine +
|
||||
$"The following attributes are allowed on API convention methods: {nameof(ProducesResponseTypeAttribute)}, {nameof(ApiConventionNameMatchAttribute)}";
|
||||
var methodName = typeof(ConventionWitUnsupportedAttributes).FullName + '.' + nameof(ConventionWitUnsupportedAttributes.Get);
|
||||
var attributes = new[] { typeof(ProducesAttribute), typeof(ServiceFilterAttribute), typeof(AuthorizeAttribute) };
|
||||
var expected = GetErrorMessage(methodName, attributes);
|
||||
|
||||
// Act & Assert
|
||||
ExceptionAssert.ThrowsArgument(
|
||||
|
|
@ -82,5 +78,14 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
[Authorize]
|
||||
public static void Get() { }
|
||||
}
|
||||
|
||||
private static string GetErrorMessage(string methodName, params Type[] attributes)
|
||||
{
|
||||
return $"Method {methodName} is decorated with the following attributes that are not allowed on an API convention method:" +
|
||||
Environment.NewLine +
|
||||
string.Join(Environment.NewLine, attributes.Select(a => a.FullName)) +
|
||||
Environment.NewLine +
|
||||
$"The following attributes are allowed on API convention methods: {nameof(ProducesResponseTypeAttribute)}, {nameof(ProducesDefaultResponseTypeAttribute)}, {nameof(ApiConventionNameMatchAttribute)}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -111,6 +111,7 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer
|
|||
Assert.True(result);
|
||||
Assert.Collection(
|
||||
conventionResult.ResponseMetadataProviders.OrderBy(o => o.StatusCode),
|
||||
r => Assert.IsAssignableFrom<IApiDefaultResponseMetadataProvider>(r),
|
||||
r => Assert.Equal(200, r.StatusCode),
|
||||
r => Assert.Equal(404, r.StatusCode));
|
||||
}
|
||||
|
|
@ -130,6 +131,7 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer
|
|||
Assert.True(result);
|
||||
Assert.Collection(
|
||||
conventionResult.ResponseMetadataProviders.OrderBy(o => o.StatusCode),
|
||||
r => Assert.IsAssignableFrom<IApiDefaultResponseMetadataProvider>(r),
|
||||
r => Assert.Equal(201, r.StatusCode),
|
||||
r => Assert.Equal(400, r.StatusCode));
|
||||
}
|
||||
|
|
@ -152,6 +154,7 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer
|
|||
Assert.True(result);
|
||||
Assert.Collection(
|
||||
conventionResult.ResponseMetadataProviders.OrderBy(o => o.StatusCode),
|
||||
r => Assert.IsAssignableFrom<IApiDefaultResponseMetadataProvider>(r),
|
||||
r => Assert.Equal(204, r.StatusCode),
|
||||
r => Assert.Equal(400, r.StatusCode),
|
||||
r => Assert.Equal(404, r.StatusCode));
|
||||
|
|
@ -175,6 +178,7 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer
|
|||
Assert.True(result);
|
||||
Assert.Collection(
|
||||
conventionResult.ResponseMetadataProviders.OrderBy(o => o.StatusCode),
|
||||
r => Assert.IsAssignableFrom<IApiDefaultResponseMetadataProvider>(r),
|
||||
r => Assert.Equal(200, r.StatusCode),
|
||||
r => Assert.Equal(400, r.StatusCode),
|
||||
r => Assert.Equal(404, r.StatusCode));
|
||||
|
|
|
|||
|
|
@ -711,7 +711,6 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
|
||||
// Assert
|
||||
var description = Assert.Single(result);
|
||||
Assert.Equal(2, description.SupportedResponseTypes.Count);
|
||||
|
||||
Assert.Collection(
|
||||
description.SupportedResponseTypes.OrderBy(responseType => responseType.StatusCode),
|
||||
|
|
@ -749,7 +748,6 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
|
||||
// Assert
|
||||
var description = Assert.Single(result);
|
||||
Assert.Equal(2, description.SupportedResponseTypes.Count);
|
||||
|
||||
Assert.Collection(
|
||||
description.SupportedResponseTypes.OrderBy(responseType => responseType.StatusCode),
|
||||
|
|
@ -1171,6 +1169,10 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
Assert.Collection(
|
||||
description.SupportedResponseTypes.OrderBy(r => r.StatusCode),
|
||||
responseType =>
|
||||
{
|
||||
Assert.True(responseType.IsDefaultResponse);
|
||||
},
|
||||
responseType =>
|
||||
{
|
||||
Assert.Equal(typeof(Product).FullName, responseType.ResponseType);
|
||||
Assert.Equal(200, responseType.StatusCode);
|
||||
|
|
@ -1255,6 +1257,10 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
Assert.Collection(
|
||||
description.SupportedResponseTypes.OrderBy(r => r.StatusCode),
|
||||
responseType =>
|
||||
{
|
||||
Assert.True(responseType.IsDefaultResponse);
|
||||
},
|
||||
responseType =>
|
||||
{
|
||||
Assert.Equal(typeof(void).FullName, responseType.ResponseType);
|
||||
Assert.Equal(201, responseType.StatusCode);
|
||||
|
|
@ -1283,6 +1289,10 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
Assert.Collection(
|
||||
description.SupportedResponseTypes.OrderBy(r => r.StatusCode),
|
||||
responseType =>
|
||||
{
|
||||
Assert.True(responseType.IsDefaultResponse);
|
||||
},
|
||||
responseType =>
|
||||
{
|
||||
Assert.Equal(typeof(void).FullName, responseType.ResponseType);
|
||||
Assert.Equal(204, responseType.StatusCode);
|
||||
|
|
@ -1316,6 +1326,10 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
Assert.Collection(
|
||||
description.SupportedResponseTypes.OrderBy(r => r.StatusCode),
|
||||
responseType =>
|
||||
{
|
||||
Assert.True(responseType.IsDefaultResponse);
|
||||
},
|
||||
responseType =>
|
||||
{
|
||||
Assert.Equal(typeof(void).FullName, responseType.ResponseType);
|
||||
Assert.Equal(200, responseType.StatusCode);
|
||||
|
|
|
|||
Loading…
Reference in New Issue