Add 'default response' to API Response Type
Also some cleanup and unit tests.
This commit is contained in:
parent
ece5d6a690
commit
7ba167fcd8
|
|
@ -39,5 +39,15 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer
|
|||
/// Gets or sets the HTTP response status code.
|
||||
/// </summary>
|
||||
public int StatusCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the response type represents a default response.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If an <see cref="ApiDescription"/> has a default response, then the <see cref="StatusCode"/> property should be ignored. This response
|
||||
/// will be used when a more specific response format does not apply. The common use of a default response is to specify the format
|
||||
/// for communicating error conditions.
|
||||
/// </remarks>
|
||||
public bool IsDefaultResponse { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
// 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 System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc.Abstractions;
|
||||
using Microsoft.AspNetCore.Mvc.Internal;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.ApiExplorer
|
||||
{
|
||||
public class ApiBehaviorApiDescriptionProvider : IApiDescriptionProvider
|
||||
{
|
||||
private readonly IModelMetadataProvider _modelMetadaProvider;
|
||||
|
||||
public ApiBehaviorApiDescriptionProvider(IModelMetadataProvider modelMetadataProvider)
|
||||
{
|
||||
_modelMetadaProvider = modelMetadataProvider;
|
||||
}
|
||||
|
||||
/// <remarks>
|
||||
/// The order is set to execute after the default provider.
|
||||
/// </remarks>
|
||||
public int Order => -1000 + 10;
|
||||
|
||||
public void OnProvidersExecuted(ApiDescriptionProviderContext context)
|
||||
{
|
||||
}
|
||||
|
||||
public void OnProvidersExecuting(ApiDescriptionProviderContext context)
|
||||
{
|
||||
foreach (var description in context.Results)
|
||||
{
|
||||
if (!AppliesTo(description))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var responseType in CreateProblemResponseTypes(description))
|
||||
{
|
||||
description.SupportedResponseTypes.Add(responseType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool AppliesTo(ApiDescription description)
|
||||
{
|
||||
return description.ActionDescriptor.FilterDescriptors.Any(f => f.Filter is IApiBehaviorMetadata);
|
||||
}
|
||||
|
||||
// Check if the parameter is named "id" (e.g. int id) or ends in Id (e.g. personId)
|
||||
public bool IsIdParameter(ParameterDescriptor parameter)
|
||||
{
|
||||
if (parameter.Name == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (string.Equals("id", parameter.Name, StringComparison.Ordinal))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// We're looking for a name ending with Id, but preceded by a lower case letter. This should match
|
||||
// the normal PascalCase naming conventions.
|
||||
if (parameter.Name.Length >= 3 &&
|
||||
parameter.Name.EndsWith("Id", StringComparison.Ordinal) &&
|
||||
char.IsLower(parameter.Name, parameter.Name.Length - 3))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public IEnumerable<ApiResponseType> CreateProblemResponseTypes(ApiDescription description)
|
||||
{
|
||||
if (description.ActionDescriptor.Parameters.Any() || description.ActionDescriptor.BoundProperties.Any())
|
||||
{
|
||||
// For validation errors.
|
||||
yield return CreateProblemResponse(StatusCodes.Status400BadRequest);
|
||||
|
||||
if (description.ActionDescriptor.Parameters.Any(p => IsIdParameter(p)))
|
||||
{
|
||||
yield return CreateProblemResponse(StatusCodes.Status404NotFound);
|
||||
}
|
||||
}
|
||||
|
||||
yield return CreateProblemResponse(statusCode: 0, isDefaultResponse: true);
|
||||
}
|
||||
|
||||
private ApiResponseType CreateProblemResponse(int statusCode, bool isDefaultResponse = false)
|
||||
{
|
||||
return new ApiResponseType
|
||||
{
|
||||
ApiResponseFormats = new List<ApiResponseFormat>
|
||||
{
|
||||
new ApiResponseFormat
|
||||
{
|
||||
MediaType = "application/problem+json",
|
||||
},
|
||||
new ApiResponseFormat
|
||||
{
|
||||
MediaType = "application/problem+xml",
|
||||
},
|
||||
},
|
||||
IsDefaultResponse = isDefaultResponse,
|
||||
ModelMetadata = _modelMetadaProvider.GetMetadataForType(typeof(ProblemDetails)),
|
||||
StatusCode = statusCode,
|
||||
Type = typeof(ProblemDetails),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
// 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 System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc.Internal;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.ApiExplorer
|
||||
{
|
||||
public class ApiControllerApiDescriptionProvider : IApiDescriptionProvider
|
||||
{
|
||||
private readonly IModelMetadataProvider _modelMetadaProvider;
|
||||
|
||||
public ApiControllerApiDescriptionProvider(IModelMetadataProvider modelMetadataProvider)
|
||||
{
|
||||
_modelMetadaProvider = modelMetadataProvider;
|
||||
}
|
||||
|
||||
/// <remarks>
|
||||
/// The order is set to execute after the <see cref="DefaultApiDescriptionProvider"/>.
|
||||
/// </remarks>
|
||||
public int Order => -1000 + 10;
|
||||
|
||||
public void OnProvidersExecuted(ApiDescriptionProviderContext context)
|
||||
{
|
||||
}
|
||||
|
||||
public void OnProvidersExecuting(ApiDescriptionProviderContext context)
|
||||
{
|
||||
foreach (var apiDescription in context.Results)
|
||||
{
|
||||
if (!apiDescription.ActionDescriptor.FilterDescriptors.Any(f => f.Filter is IApiBehaviorMetadata))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var parameters = apiDescription.ActionDescriptor.Parameters.Concat(apiDescription.ActionDescriptor.BoundProperties);
|
||||
if (parameters.Any())
|
||||
{
|
||||
apiDescription.SupportedResponseTypes.Add(CreateProblemResponse(StatusCodes.Status400BadRequest));
|
||||
|
||||
if (parameters.Any(p => p.Name.EndsWith("id", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
apiDescription.SupportedResponseTypes.Add(CreateProblemResponse(StatusCodes.Status404NotFound));
|
||||
}
|
||||
}
|
||||
|
||||
// We don't have a good way to signal a "default" response type. We'll use 0 to indicate this until we come up
|
||||
// with something better.
|
||||
apiDescription.SupportedResponseTypes.Add(CreateProblemResponse(statusCode: 0));
|
||||
}
|
||||
}
|
||||
|
||||
private ApiResponseType CreateProblemResponse(int statusCode)
|
||||
{
|
||||
return new ApiResponseType
|
||||
{
|
||||
ApiResponseFormats = new List<ApiResponseFormat>
|
||||
{
|
||||
new ApiResponseFormat
|
||||
{
|
||||
MediaType = "application/problem+json",
|
||||
},
|
||||
new ApiResponseFormat
|
||||
{
|
||||
MediaType = "application/problem+xml",
|
||||
},
|
||||
},
|
||||
ModelMetadata = _modelMetadaProvider.GetMetadataForType(typeof(ProblemDetails)),
|
||||
StatusCode = statusCode,
|
||||
Type = typeof(ProblemDetails),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -27,7 +27,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Transient<IApiDescriptionProvider, DefaultApiDescriptionProvider>());
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Transient<IApiDescriptionProvider, ApiControllerApiDescriptionProvider>());
|
||||
ServiceDescriptor.Transient<IApiDescriptionProvider, ApiBehaviorApiDescriptionProvider>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Transient<IApplicationModelProvider, DefaultApplicationModelProvider>());
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Transient<IApplicationModelProvider, ApiControllerApplicationModelProvider>());
|
||||
ServiceDescriptor.Transient<IApplicationModelProvider, ApiBehaviorApplicationModelProvider>());
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Transient<IActionDescriptorProvider, ControllerActionDescriptorProvider>());
|
||||
|
||||
|
|
|
|||
|
|
@ -12,12 +12,12 @@ using Microsoft.Extensions.Options;
|
|||
|
||||
namespace Microsoft.AspNetCore.Mvc.Internal
|
||||
{
|
||||
public class ApiControllerApplicationModelProvider : IApplicationModelProvider
|
||||
public class ApiBehaviorApplicationModelProvider : IApplicationModelProvider
|
||||
{
|
||||
private readonly ApiBehaviorOptions _apiBehaviorOptions;
|
||||
private readonly ModelStateInvalidFilter _modelStateInvalidFilter;
|
||||
|
||||
public ApiControllerApplicationModelProvider(IOptions<ApiBehaviorOptions> apiBehaviorOptions, ILoggerFactory loggerFactory)
|
||||
public ApiBehaviorApplicationModelProvider(IOptions<ApiBehaviorOptions> apiBehaviorOptions, ILoggerFactory loggerFactory)
|
||||
{
|
||||
_apiBehaviorOptions = apiBehaviorOptions.Value;
|
||||
if (_apiBehaviorOptions.EnableModelStateInvalidFilter && _apiBehaviorOptions.InvalidModelStateResponseFactory == null)
|
||||
|
|
@ -0,0 +1,241 @@
|
|||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Mvc.Abstractions;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.AspNetCore.Mvc.Internal;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.ApiExplorer
|
||||
{
|
||||
public class ApiBehaviorApiDescriptionProviderTest
|
||||
{
|
||||
[Fact]
|
||||
public void AppliesTo_ActionWithoutApiBehavior_ReturnsFalse()
|
||||
{
|
||||
// Arrange
|
||||
var action = new ActionDescriptor()
|
||||
{
|
||||
FilterDescriptors = new List<FilterDescriptor>(),
|
||||
};
|
||||
var description = new ApiDescription()
|
||||
{
|
||||
ActionDescriptor = action,
|
||||
};
|
||||
|
||||
var provider = new ApiBehaviorApiDescriptionProvider(new EmptyModelMetadataProvider());
|
||||
|
||||
// Act
|
||||
var result = provider.AppliesTo(description);
|
||||
|
||||
// Assert
|
||||
Assert.False(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AppliesTo_ActionWithApiBehavior_ReturnsTrue()
|
||||
{
|
||||
// Arrange
|
||||
var action = new ActionDescriptor()
|
||||
{
|
||||
FilterDescriptors = new List<FilterDescriptor>()
|
||||
{
|
||||
new FilterDescriptor(Mock.Of<IApiBehaviorMetadata>(), FilterScope.Global),
|
||||
}
|
||||
};
|
||||
var description = new ApiDescription()
|
||||
{
|
||||
ActionDescriptor = action,
|
||||
};
|
||||
|
||||
var provider = new ApiBehaviorApiDescriptionProvider(new EmptyModelMetadataProvider());
|
||||
|
||||
// Act
|
||||
var result = provider.AppliesTo(description);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("id")]
|
||||
[InlineData("personId")]
|
||||
[InlineData("üId")]
|
||||
public void IsIdParameter_ParameterNameMatchesConvention_ReturnsTrue(string name)
|
||||
{
|
||||
var parameter = new ParameterDescriptor()
|
||||
{
|
||||
Name = name,
|
||||
};
|
||||
|
||||
var provider = new ApiBehaviorApiDescriptionProvider(new EmptyModelMetadataProvider());
|
||||
|
||||
// Act
|
||||
var result = provider.IsIdParameter(parameter);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData("")]
|
||||
[InlineData("i")]
|
||||
[InlineData("Id")]
|
||||
[InlineData("iD")]
|
||||
[InlineData("persoNId")]
|
||||
[InlineData("personid")]
|
||||
[InlineData("ü Id")]
|
||||
[InlineData("ÜId")]
|
||||
public void IsIdParameter_ParameterNameDoesNotMatchConvention_ReturnsFalse(string name)
|
||||
{
|
||||
var parameter = new ParameterDescriptor()
|
||||
{
|
||||
Name = name,
|
||||
};
|
||||
|
||||
var provider = new ApiBehaviorApiDescriptionProvider(new EmptyModelMetadataProvider());
|
||||
|
||||
// Act
|
||||
var result = provider.IsIdParameter(parameter);
|
||||
|
||||
// Assert
|
||||
Assert.False(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateProblemResponseTypes_NoParameters_IncludesDefaultResponse()
|
||||
{
|
||||
// Arrange
|
||||
var action = new ActionDescriptor()
|
||||
{
|
||||
FilterDescriptors = new List<FilterDescriptor>()
|
||||
{
|
||||
new FilterDescriptor(Mock.Of<IApiBehaviorMetadata>(), FilterScope.Global),
|
||||
},
|
||||
BoundProperties = new List<ParameterDescriptor>(),
|
||||
Parameters = new List<ParameterDescriptor>(),
|
||||
};
|
||||
var description = new ApiDescription()
|
||||
{
|
||||
ActionDescriptor = action,
|
||||
};
|
||||
|
||||
var provider = new ApiBehaviorApiDescriptionProvider(new EmptyModelMetadataProvider());
|
||||
|
||||
// Act
|
||||
var results = provider.CreateProblemResponseTypes(description);
|
||||
|
||||
// Assert
|
||||
Assert.Collection(
|
||||
results.OrderBy(r => r.StatusCode),
|
||||
r =>
|
||||
{
|
||||
Assert.Equal(typeof(ProblemDetails), r.Type);
|
||||
Assert.Equal(0, r.StatusCode);
|
||||
Assert.True(r.IsDefaultResponse);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateProblemResponseTypes_WithBoundProperty_Includes400Response()
|
||||
{
|
||||
// Arrange
|
||||
var action = new ActionDescriptor()
|
||||
{
|
||||
FilterDescriptors = new List<FilterDescriptor>()
|
||||
{
|
||||
new FilterDescriptor(Mock.Of<IApiBehaviorMetadata>(), FilterScope.Global),
|
||||
},
|
||||
BoundProperties = new List<ParameterDescriptor>()
|
||||
{
|
||||
new ParameterDescriptor()
|
||||
},
|
||||
Parameters = new List<ParameterDescriptor>(),
|
||||
};
|
||||
var description = new ApiDescription()
|
||||
{
|
||||
ActionDescriptor = action,
|
||||
};
|
||||
|
||||
var provider = new ApiBehaviorApiDescriptionProvider(new EmptyModelMetadataProvider());
|
||||
|
||||
// Act
|
||||
var results = provider.CreateProblemResponseTypes(description);
|
||||
|
||||
// Assert
|
||||
Assert.Collection(
|
||||
results.OrderBy(r => r.StatusCode),
|
||||
r =>
|
||||
{
|
||||
Assert.Equal(typeof(ProblemDetails), r.Type);
|
||||
Assert.Equal(0, r.StatusCode);
|
||||
Assert.True(r.IsDefaultResponse);
|
||||
},
|
||||
r =>
|
||||
{
|
||||
Assert.Equal(typeof(ProblemDetails), r.Type);
|
||||
Assert.Equal(400, r.StatusCode);
|
||||
Assert.False(r.IsDefaultResponse);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateProblemResponseTypes_WithIdParameter_Includes404Response()
|
||||
{
|
||||
// Arrange
|
||||
var action = new ActionDescriptor()
|
||||
{
|
||||
FilterDescriptors = new List<FilterDescriptor>()
|
||||
{
|
||||
new FilterDescriptor(Mock.Of<IApiBehaviorMetadata>(), FilterScope.Global),
|
||||
},
|
||||
BoundProperties = new List<ParameterDescriptor>()
|
||||
{
|
||||
},
|
||||
Parameters = new List<ParameterDescriptor>()
|
||||
{
|
||||
new ParameterDescriptor()
|
||||
{
|
||||
Name = "customerId",
|
||||
}
|
||||
},
|
||||
};
|
||||
var description = new ApiDescription()
|
||||
{
|
||||
ActionDescriptor = action,
|
||||
};
|
||||
|
||||
var provider = new ApiBehaviorApiDescriptionProvider(new EmptyModelMetadataProvider());
|
||||
|
||||
// Act
|
||||
var results = provider.CreateProblemResponseTypes(description);
|
||||
|
||||
// Assert
|
||||
Assert.Collection(
|
||||
results.OrderBy(r => r.StatusCode),
|
||||
r =>
|
||||
{
|
||||
Assert.Equal(typeof(ProblemDetails), r.Type);
|
||||
Assert.Equal(0, r.StatusCode);
|
||||
Assert.True(r.IsDefaultResponse);
|
||||
},
|
||||
r =>
|
||||
{
|
||||
Assert.Equal(typeof(ProblemDetails), r.Type);
|
||||
Assert.Equal(400, r.StatusCode);
|
||||
Assert.False(r.IsDefaultResponse);
|
||||
},
|
||||
r =>
|
||||
{
|
||||
Assert.Equal(typeof(ProblemDetails), r.Type);
|
||||
Assert.Equal(404, r.StatusCode);
|
||||
Assert.False(r.IsDefaultResponse);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -295,7 +295,7 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
new Type[]
|
||||
{
|
||||
typeof(DefaultApplicationModelProvider),
|
||||
typeof(ApiControllerApplicationModelProvider),
|
||||
typeof(ApiBehaviorApplicationModelProvider),
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ using Xunit;
|
|||
|
||||
namespace Microsoft.AspNetCore.Mvc.Internal
|
||||
{
|
||||
public class ApiControllerApplicationModelProviderTest
|
||||
public class ApiBehaviorApplicationModelProviderTest
|
||||
{
|
||||
[Fact]
|
||||
public void OnProvidersExecuting_AddsModelStateInvalidFilter_IfTypeIsAnnotatedWithAttribute()
|
||||
|
|
@ -23,7 +23,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
InvalidModelStateResponseFactory = _ => null,
|
||||
});
|
||||
|
||||
var provider = new ApiControllerApplicationModelProvider(options, NullLoggerFactory.Instance);
|
||||
var provider = new ApiBehaviorApplicationModelProvider(options, NullLoggerFactory.Instance);
|
||||
|
||||
// Act
|
||||
provider.OnProvidersExecuting(context);
|
||||
|
|
@ -43,7 +43,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
EnableModelStateInvalidFilter = false,
|
||||
});
|
||||
|
||||
var provider = new ApiControllerApplicationModelProvider(options, NullLoggerFactory.Instance);
|
||||
var provider = new ApiBehaviorApplicationModelProvider(options, NullLoggerFactory.Instance);
|
||||
|
||||
// Act
|
||||
provider.OnProvidersExecuting(context);
|
||||
|
|
@ -63,7 +63,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
InvalidModelStateResponseFactory = _ => null,
|
||||
});
|
||||
|
||||
var provider = new ApiControllerApplicationModelProvider(options, NullLoggerFactory.Instance);
|
||||
var provider = new ApiBehaviorApplicationModelProvider(options, NullLoggerFactory.Instance);
|
||||
|
||||
// Act
|
||||
provider.OnProvidersExecuting(context);
|
||||
|
|
@ -91,7 +91,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
EnableModelStateInvalidFilter = false,
|
||||
});
|
||||
|
||||
var provider = new ApiControllerApplicationModelProvider(options, NullLoggerFactory.Instance);
|
||||
var provider = new ApiBehaviorApplicationModelProvider(options, NullLoggerFactory.Instance);
|
||||
|
||||
// Act
|
||||
provider.OnProvidersExecuting(context);
|
||||
|
|
@ -119,7 +119,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
InvalidModelStateResponseFactory = _ => null,
|
||||
});
|
||||
|
||||
var provider = new ApiControllerApplicationModelProvider(options, NullLoggerFactory.Instance);
|
||||
var provider = new ApiBehaviorApplicationModelProvider(options, NullLoggerFactory.Instance);
|
||||
|
||||
// Act & Assert
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => provider.OnProvidersExecuting(context));
|
||||
|
|
@ -1079,6 +1079,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
response =>
|
||||
{
|
||||
Assert.Equal(0, response.StatusCode);
|
||||
Assert.True(response.IsDefaultResponse);
|
||||
AssertProblemDetails(response);
|
||||
});
|
||||
}
|
||||
|
|
@ -1097,12 +1098,14 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
response =>
|
||||
{
|
||||
Assert.Equal(0, response.StatusCode);
|
||||
Assert.True(response.IsDefaultResponse);
|
||||
AssertProblemDetails(response);
|
||||
},
|
||||
response => Assert.Equal(200, response.StatusCode),
|
||||
response =>
|
||||
{
|
||||
Assert.Equal(400, response.StatusCode);
|
||||
Assert.False(response.IsDefaultResponse);
|
||||
AssertProblemDetails(response);
|
||||
});
|
||||
}
|
||||
|
|
@ -1123,17 +1126,20 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
response =>
|
||||
{
|
||||
Assert.Equal(0, response.StatusCode);
|
||||
Assert.True(response.IsDefaultResponse);
|
||||
AssertProblemDetails(response);
|
||||
},
|
||||
response => Assert.Equal(200, response.StatusCode),
|
||||
response =>
|
||||
{
|
||||
Assert.Equal(400, response.StatusCode);
|
||||
Assert.False(response.IsDefaultResponse);
|
||||
AssertProblemDetails(response);
|
||||
},
|
||||
response =>
|
||||
{
|
||||
Assert.Equal(404, response.StatusCode);
|
||||
Assert.False(response.IsDefaultResponse);
|
||||
AssertProblemDetails(response);
|
||||
});
|
||||
}
|
||||
|
|
@ -1199,6 +1205,8 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
public string ResponseType { get; set; }
|
||||
|
||||
public int StatusCode { get; set; }
|
||||
|
||||
public bool IsDefaultResponse { get; set; }
|
||||
}
|
||||
|
||||
private class ApiExplorerResponseFormat
|
||||
|
|
|
|||
|
|
@ -417,7 +417,7 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
typeof(CorsApplicationModelProvider),
|
||||
typeof(AuthorizationApplicationModelProvider),
|
||||
typeof(TempDataApplicationModelProvider),
|
||||
typeof(ApiControllerApplicationModelProvider),
|
||||
typeof(ApiBehaviorApplicationModelProvider),
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -425,7 +425,7 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
new Type[]
|
||||
{
|
||||
typeof(DefaultApiDescriptionProvider),
|
||||
typeof(ApiControllerApiDescriptionProvider),
|
||||
typeof(ApiBehaviorApiDescriptionProvider),
|
||||
typeof(JsonPatchOperationsArrayProvider),
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -89,7 +89,8 @@ namespace ApiExplorerWebSite
|
|||
var responseType = new ApiExplorerResponseType()
|
||||
{
|
||||
StatusCode = response.StatusCode,
|
||||
ResponseType = response.Type?.FullName
|
||||
ResponseType = response.Type?.FullName,
|
||||
IsDefaultResponse = response.IsDefaultResponse,
|
||||
};
|
||||
|
||||
foreach(var responseFormat in response.ApiResponseFormats)
|
||||
|
|
@ -152,6 +153,8 @@ namespace ApiExplorerWebSite
|
|||
public string ResponseType { get; set; }
|
||||
|
||||
public int StatusCode { get; set; }
|
||||
|
||||
public bool IsDefaultResponse { get; set; }
|
||||
}
|
||||
|
||||
private class ApiExplorerResponseFormat
|
||||
|
|
|
|||
Loading…
Reference in New Issue