Added ValueTask support to API Explorer response types. (#13739)
(cherry picked from commit 24b051de5ee386521f8b286c7c7d4f69ac1f2244) Fixes https://github.com/aspnet/AspNetCore/issues/4883
This commit is contained in:
parent
f9c15caa7a
commit
f1f615282d
|
|
@ -214,7 +214,8 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer
|
||||||
{
|
{
|
||||||
var declaredReturnType = action.MethodInfo.ReturnType;
|
var declaredReturnType = action.MethodInfo.ReturnType;
|
||||||
if (declaredReturnType == typeof(void) ||
|
if (declaredReturnType == typeof(void) ||
|
||||||
declaredReturnType == typeof(Task))
|
declaredReturnType == typeof(Task) ||
|
||||||
|
declaredReturnType == typeof(ValueTask))
|
||||||
{
|
{
|
||||||
return typeof(void);
|
return typeof(void);
|
||||||
}
|
}
|
||||||
|
|
@ -222,7 +223,7 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer
|
||||||
// Unwrap the type if it's a Task<T>. The Task (non-generic) case was already handled.
|
// Unwrap the type if it's a Task<T>. The Task (non-generic) case was already handled.
|
||||||
var unwrappedType = declaredReturnType;
|
var unwrappedType = declaredReturnType;
|
||||||
if (declaredReturnType.IsGenericType &&
|
if (declaredReturnType.IsGenericType &&
|
||||||
declaredReturnType.GetGenericTypeDefinition() == typeof(Task<>))
|
(declaredReturnType.GetGenericTypeDefinition() == typeof(Task<>) || declaredReturnType.GetGenericTypeDefinition() == typeof(ValueTask<>)))
|
||||||
{
|
{
|
||||||
unwrappedType = declaredReturnType.GetGenericArguments()[0];
|
unwrappedType = declaredReturnType.GetGenericArguments()[0];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -472,6 +472,22 @@ namespace Microsoft.AspNetCore.Mvc.Description
|
||||||
Assert.NotNull(responseType.ModelMetadata);
|
Assert.NotNull(responseType.ModelMetadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GetApiDescription_PopulatesResponseType_WithValueTaskOfProduct()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var action = CreateActionDescriptor(nameof(ReturnsValueTaskOfProduct));
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var descriptions = GetApiDescriptions(action);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
var description = Assert.Single(descriptions);
|
||||||
|
var responseType = Assert.Single(description.SupportedResponseTypes);
|
||||||
|
Assert.Equal(typeof(Product), responseType.Type);
|
||||||
|
Assert.NotNull(responseType.ModelMetadata);
|
||||||
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData(nameof(ReturnsObject))]
|
[InlineData(nameof(ReturnsObject))]
|
||||||
[InlineData(nameof(ReturnsActionResult))]
|
[InlineData(nameof(ReturnsActionResult))]
|
||||||
|
|
@ -479,6 +495,9 @@ namespace Microsoft.AspNetCore.Mvc.Description
|
||||||
[InlineData(nameof(ReturnsTaskOfObject))]
|
[InlineData(nameof(ReturnsTaskOfObject))]
|
||||||
[InlineData(nameof(ReturnsTaskOfActionResult))]
|
[InlineData(nameof(ReturnsTaskOfActionResult))]
|
||||||
[InlineData(nameof(ReturnsTaskOfJsonResult))]
|
[InlineData(nameof(ReturnsTaskOfJsonResult))]
|
||||||
|
[InlineData(nameof(ReturnsValueTaskOfObject))]
|
||||||
|
[InlineData(nameof(ReturnsValueTaskOfActionResult))]
|
||||||
|
[InlineData(nameof(ReturnsValueTaskOfJsonResult))]
|
||||||
public void GetApiDescription_DoesNotPopulatesResponseInformation_WhenUnknown(string methodName)
|
public void GetApiDescription_DoesNotPopulatesResponseInformation_WhenUnknown(string methodName)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
|
|
@ -521,7 +540,7 @@ namespace Microsoft.AspNetCore.Mvc.Description
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
typeof(DefaultApiDescriptionProviderTest),
|
typeof(DefaultApiDescriptionProviderTest),
|
||||||
nameof(DefaultApiDescriptionProviderTest.ReturnsActionResult),
|
nameof(DefaultApiDescriptionProviderTest.ReturnsValueTaskOfActionResult),
|
||||||
filterDescriptors
|
filterDescriptors
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -624,6 +643,11 @@ namespace Microsoft.AspNetCore.Mvc.Description
|
||||||
nameof(DefaultApiDescriptionProviderTest.ReturnsTask),
|
nameof(DefaultApiDescriptionProviderTest.ReturnsTask),
|
||||||
filterDescriptors
|
filterDescriptors
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
typeof(DefaultApiDescriptionProviderTest),
|
||||||
|
nameof(DefaultApiDescriptionProviderTest.ReturnsValueTask),
|
||||||
|
filterDescriptors
|
||||||
|
},
|
||||||
{
|
{
|
||||||
typeof(DerivedProducesController),
|
typeof(DerivedProducesController),
|
||||||
nameof(DerivedProducesController.ReturnsVoid),
|
nameof(DerivedProducesController.ReturnsVoid),
|
||||||
|
|
@ -634,6 +658,11 @@ namespace Microsoft.AspNetCore.Mvc.Description
|
||||||
nameof(DerivedProducesController.ReturnsTask),
|
nameof(DerivedProducesController.ReturnsTask),
|
||||||
filterDescriptors
|
filterDescriptors
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
typeof(DerivedProducesController),
|
||||||
|
nameof(DerivedProducesController.ReturnsValueTask),
|
||||||
|
filterDescriptors
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -895,6 +924,7 @@ namespace Microsoft.AspNetCore.Mvc.Description
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData(nameof(ReturnsVoid))]
|
[InlineData(nameof(ReturnsVoid))]
|
||||||
[InlineData(nameof(ReturnsTask))]
|
[InlineData(nameof(ReturnsTask))]
|
||||||
|
[InlineData(nameof(ReturnsValueTask))]
|
||||||
public void GetApiDescription_DefaultVoidStatus(string methodName)
|
public void GetApiDescription_DefaultVoidStatus(string methodName)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
|
|
@ -914,6 +944,7 @@ namespace Microsoft.AspNetCore.Mvc.Description
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData(nameof(ReturnsVoid))]
|
[InlineData(nameof(ReturnsVoid))]
|
||||||
[InlineData(nameof(ReturnsTask))]
|
[InlineData(nameof(ReturnsTask))]
|
||||||
|
[InlineData(nameof(ReturnsValueTask))]
|
||||||
public void GetApiDescription_VoidWithResponseTypeAttributeStatus(string methodName)
|
public void GetApiDescription_VoidWithResponseTypeAttributeStatus(string methodName)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
|
|
@ -944,6 +975,10 @@ namespace Microsoft.AspNetCore.Mvc.Description
|
||||||
[InlineData(nameof(ReturnsTask))]
|
[InlineData(nameof(ReturnsTask))]
|
||||||
[InlineData(nameof(ReturnsTaskOfActionResult))]
|
[InlineData(nameof(ReturnsTaskOfActionResult))]
|
||||||
[InlineData(nameof(ReturnsTaskOfJsonResult))]
|
[InlineData(nameof(ReturnsTaskOfJsonResult))]
|
||||||
|
[InlineData(nameof(ReturnsValueTask))]
|
||||||
|
[InlineData(nameof(ReturnsValueTaskOfObject))]
|
||||||
|
[InlineData(nameof(ReturnsValueTaskOfActionResult))]
|
||||||
|
[InlineData(nameof(ReturnsValueTaskOfJsonResult))]
|
||||||
public void GetApiDescription_PopulatesResponseInformation_WhenSetByFilter(string methodName)
|
public void GetApiDescription_PopulatesResponseInformation_WhenSetByFilter(string methodName)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
|
|
@ -2026,6 +2061,31 @@ namespace Microsoft.AspNetCore.Mvc.Description
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ValueTask<Product> ReturnsValueTaskOfProduct()
|
||||||
|
{
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ValueTask<object> ReturnsValueTaskOfObject()
|
||||||
|
{
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ValueTask ReturnsValueTask()
|
||||||
|
{
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ValueTask<IActionResult> ReturnsValueTaskOfActionResult()
|
||||||
|
{
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ValueTask<JsonResult> ReturnsValueTaskOfJsonResult()
|
||||||
|
{
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
private Product ReturnsProduct()
|
private Product ReturnsProduct()
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -2196,6 +2256,11 @@ namespace Microsoft.AspNetCore.Mvc.Description
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ValueTask ReturnsValueTask()
|
||||||
|
{
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
public void ReturnsVoid()
|
public void ReturnsVoid()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue