diff --git a/src/Microsoft.AspNetCore.Mvc.ApiExplorer/DefaultApiDescriptionProvider.cs b/src/Microsoft.AspNetCore.Mvc.ApiExplorer/DefaultApiDescriptionProvider.cs index be65b98928..e46dac2f1d 100644 --- a/src/Microsoft.AspNetCore.Mvc.ApiExplorer/DefaultApiDescriptionProvider.cs +++ b/src/Microsoft.AspNetCore.Mvc.ApiExplorer/DefaultApiDescriptionProvider.cs @@ -377,8 +377,7 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer // Set the default status only when no status has already been set explicitly if (objectTypes.Count == 0 - && type != null - && type != typeof(void)) + && type != null) { objectTypes[StatusCodes.Status200OK] = type; } diff --git a/test/Microsoft.AspNetCore.Mvc.ApiExplorer.Test/DefaultApiDescriptionProviderTest.cs b/test/Microsoft.AspNetCore.Mvc.ApiExplorer.Test/DefaultApiDescriptionProviderTest.cs index 5c5e3b9ac2..e58a76610e 100644 --- a/test/Microsoft.AspNetCore.Mvc.ApiExplorer.Test/DefaultApiDescriptionProviderTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.ApiExplorer.Test/DefaultApiDescriptionProviderTest.cs @@ -509,7 +509,7 @@ namespace Microsoft.AspNetCore.Mvc.Description new ProducesAttribute("text/json", "application/json"), FilterScope.Action), new FilterDescriptor( - new ProducesResponseTypeAttribute(typeof(void), 204), + new ProducesResponseTypeAttribute(typeof(void), 200), FilterScope.Action), new FilterDescriptor( new ProducesResponseTypeAttribute(typeof(BadData), 400), @@ -569,7 +569,7 @@ namespace Microsoft.AspNetCore.Mvc.Description responseType => { Assert.Equal(typeof(void), responseType.Type); - Assert.Equal(204, responseType.StatusCode); + Assert.Equal(200, responseType.StatusCode); Assert.Null(responseType.ModelMetadata); Assert.Empty(responseType.ApiResponseFormats); }, @@ -592,7 +592,26 @@ namespace Microsoft.AspNetCore.Mvc.Description [Theory] [InlineData(nameof(ReturnsVoid))] [InlineData(nameof(ReturnsTask))] - public void GetApiDescription_DoesNotPopulatesResponseInformation_WhenVoid(string methodName) + public void GetApiDescription_DefaultVoidStatus(string methodName) + { + // Arrange + var action = CreateActionDescriptor(methodName); + + // Act + var descriptions = GetApiDescriptions(action); + + // Assert + var description = Assert.Single(descriptions); + var responseType = Assert.Single(description.SupportedResponseTypes); + Assert.Equal(typeof(void), responseType.Type); + Assert.Equal(200, responseType.StatusCode); + Assert.Null(responseType.ModelMetadata); + } + + [Theory] + [InlineData(nameof(ReturnsVoid))] + [InlineData(nameof(ReturnsTask))] + public void GetApiDescription_VoidWithResponseTypeAttributeStatus(string methodName) { // Arrange var action = CreateActionDescriptor(methodName); diff --git a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/ApiExplorerTest.cs b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/ApiExplorerTest.cs index ece3d7e084..9836ad3a77 100644 --- a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/ApiExplorerTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/ApiExplorerTest.cs @@ -393,10 +393,30 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests Assert.Single(result, d => d.HttpMethod == "POST"); } + [Theory] + [InlineData("GetVoidWithExplicitResponseTypeStatusCode")] + [InlineData("GetTaskWithExplicitResponseTypeStatusCode")] + public async Task ApiExplorer_ResponseType_VoidWithResponseTypeAttributeStatusCode(string action) + { + // Arrange & Act + var response = await Client.GetAsync( + "http://localhost/ApiExplorerResponseTypeWithAttribute/" + action); + + var body = await response.Content.ReadAsStringAsync(); + var result = JsonConvert.DeserializeObject>(body); + + // Assert + var description = Assert.Single(result); + var responseType = Assert.Single(description.SupportedResponseTypes); + Assert.Equal(typeof(void).FullName, responseType.ResponseType); + Assert.Equal(204, responseType.StatusCode); + Assert.Empty(responseType.ResponseFormats); + } + [Theory] [InlineData("GetVoid")] [InlineData("GetTask")] - public async Task ApiExplorer_ResponseType_VoidWithoutAttribute(string action) + public async Task ApiExplorer_ResponseType_VoidWithoutAttributeDefaultStatusCode(string action) { // Arrange & Act var response = await Client.GetAsync( @@ -409,7 +429,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests var description = Assert.Single(result); var responseType = Assert.Single(description.SupportedResponseTypes); Assert.Equal(typeof(void).FullName, responseType.ResponseType); - Assert.Equal(204, responseType.StatusCode); + Assert.Equal(200, responseType.StatusCode); Assert.Empty(responseType.ResponseFormats); } diff --git a/test/WebSites/ApiExplorerWebSite/Controllers/ApiExplorerResponseTypeWithAttributeController.cs b/test/WebSites/ApiExplorerWebSite/Controllers/ApiExplorerResponseTypeWithAttributeController.cs index da08ad855e..81eca53ce2 100644 --- a/test/WebSites/ApiExplorerWebSite/Controllers/ApiExplorerResponseTypeWithAttributeController.cs +++ b/test/WebSites/ApiExplorerWebSite/Controllers/ApiExplorerResponseTypeWithAttributeController.cs @@ -10,6 +10,12 @@ namespace ApiExplorerWebSite [Route("[controller]/[Action]")] public class ApiExplorerResponseTypeWithAttributeController : Controller { + [HttpGet] + [ProducesResponseType(typeof(void), 204)] + public void GetVoidWithExplicitResponseTypeStatusCode() + { + } + [HttpGet] [Produces(typeof(Customer))] public void GetVoid() @@ -30,6 +36,13 @@ namespace ApiExplorerWebSite return new EmptyResult(); } + [HttpGet] + [ProducesResponseType(typeof(void), 204)] + public Task GetTaskWithExplicitResponseTypeStatusCode() + { + return Task.FromResult(true); + } + [HttpGet] [Produces("application/json", Type = typeof(int))] public Task GetTask() diff --git a/test/WebSites/ApiExplorerWebSite/Controllers/ApiExplorerResponseTypeWithoutAttributeController.cs b/test/WebSites/ApiExplorerWebSite/Controllers/ApiExplorerResponseTypeWithoutAttributeController.cs index 024ff2a822..dd11097d18 100644 --- a/test/WebSites/ApiExplorerWebSite/Controllers/ApiExplorerResponseTypeWithoutAttributeController.cs +++ b/test/WebSites/ApiExplorerWebSite/Controllers/ApiExplorerResponseTypeWithoutAttributeController.cs @@ -10,7 +10,6 @@ namespace ApiExplorerWebSite public class ApiExplorerResponseTypeWithoutAttributeController : Controller { [HttpGet] - [ProducesResponseType(typeof(void), 204)] public void GetVoid() { } @@ -46,7 +45,6 @@ namespace ApiExplorerWebSite } [HttpGet] - [ProducesResponseType(typeof(void), 204)] public Task GetTask() { return Task.FromResult(true);