Merge pull request #8200 from aspnet/release/2.2

Respect LowercaseUrls in ApiExplorer
This commit is contained in:
Pranav K 2018-08-02 15:43:39 -07:00 committed by GitHub
commit 9e5905dac0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 52 additions and 3 deletions

View File

@ -26,6 +26,7 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer
private readonly MvcOptions _mvcOptions;
private readonly IActionResultTypeMapper _mapper;
private readonly ApiResponseTypeProvider _responseTypeProvider;
private readonly RouteOptions _routeOptions;
private readonly IInlineConstraintResolver _constraintResolver;
private readonly IModelMetadataProvider _modelMetadataProvider;
@ -53,6 +54,7 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer
/// constraints.</param>
/// <param name="modelMetadataProvider">The <see cref="IModelMetadataProvider"/>.</param>
/// <param name="mapper"> The <see cref="IActionResultTypeMapper"/>.</param>
[Obsolete("This constructor is obsolete and will be removed in a future release.")]
public DefaultApiDescriptionProvider(
IOptions<MvcOptions> optionsAccessor,
IInlineConstraintResolver constraintResolver,
@ -66,6 +68,30 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer
_responseTypeProvider = new ApiResponseTypeProvider(modelMetadataProvider, mapper, _mvcOptions);
}
/// <summary>
/// Creates a new instance of <see cref="DefaultApiDescriptionProvider"/>.
/// </summary>
/// <param name="optionsAccessor">The accessor for <see cref="MvcOptions"/>.</param>
/// <param name="constraintResolver">The <see cref="IInlineConstraintResolver"/> used for resolving inline
/// constraints.</param>
/// <param name="modelMetadataProvider">The <see cref="IModelMetadataProvider"/>.</param>
/// <param name="mapper"> The <see cref="IActionResultTypeMapper"/>.</param>
/// <param name="routeOptions">The accessor for <see cref="RouteOptions"/>.</param>
public DefaultApiDescriptionProvider(
IOptions<MvcOptions> optionsAccessor,
IInlineConstraintResolver constraintResolver,
IModelMetadataProvider modelMetadataProvider,
IActionResultTypeMapper mapper,
IOptions<RouteOptions> routeOptions)
{
_mvcOptions = optionsAccessor.Value;
_constraintResolver = constraintResolver;
_modelMetadataProvider = modelMetadataProvider;
_mapper = mapper;
_responseTypeProvider = new ApiResponseTypeProvider(modelMetadataProvider, mapper, _mvcOptions);
_routeOptions = routeOptions.Value;
}
/// <inheritdoc />
public int Order => -1000;
@ -383,7 +409,9 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer
{
if (part.IsLiteral)
{
currentSegment += part.Text;
currentSegment += _routeOptions.LowercaseUrls ?
part.Text.ToLowerInvariant() :
part.Text;
}
else if (part.IsParameter)
{

View File

@ -387,6 +387,25 @@ namespace Microsoft.AspNetCore.Mvc.Description
Assert.Single(description.ParameterDescriptions, p => p.Name == "id5");
}
[Fact]
public void GetApiDescription_ProducesLowerCaseRelativePaths()
{
// Arrange
var action = CreateActionDescriptor();
action.AttributeRouteInfo = new AttributeRouteInfo
{
Template = "api/Products/UpdateProduct/{productId}"
};
var routeOptions = new RouteOptions { LowercaseUrls = true };
// Act
var descriptions = GetApiDescriptions(action, routeOptions: routeOptions);
// Assert
var description = Assert.Single(descriptions);
Assert.Equal("api/products/updateproduct/{productId}", description.RelativePath);
}
[Fact]
public void GetApiDescription_PopulatesResponseType_WithProduct()
{
@ -1797,7 +1816,8 @@ namespace Microsoft.AspNetCore.Mvc.Description
ActionDescriptor action,
List<MockInputFormatter> inputFormatters = null,
List<MockOutputFormatter> outputFormatters = null,
bool allowValidatingTopLevelNodes = true)
bool allowValidatingTopLevelNodes = true,
RouteOptions routeOptions = null)
{
var context = new ApiDescriptionProviderContext(new ActionDescriptor[] { action });
@ -1827,7 +1847,8 @@ namespace Microsoft.AspNetCore.Mvc.Description
optionsAccessor,
constraintResolver.Object,
modelMetadataProvider,
new ActionResultTypeMapper());
new ActionResultTypeMapper(),
Options.Create(routeOptions ?? new RouteOptions()));
provider.OnProvidersExecuting(context);
provider.OnProvidersExecuted(context);