Skip to content

Commit 6fcf274

Browse files
committed
Set the description to the final one encountered and add tests
1 parent 917bacc commit 6fcf274

File tree

2 files changed

+40
-2
lines changed

2 files changed

+40
-2
lines changed

src/Mvc/Mvc.ApiExplorer/src/EndpointMetadataApiDescriptionProvider.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -375,8 +375,8 @@ private static void AddSupportedResponseTypes(
375375
apiResponseType.ApiResponseFormats.Add(defaultResponseFormat);
376376
}
377377

378-
// We set the Description to the first non-null value we find that matches the status code.
379-
apiResponseType.Description ??= responseMetadataTypes.FirstOrDefault(x => x.StatusCode == apiResponseType.StatusCode && x.Description is not null)?.Description;
378+
// We set the Description to the LAST non-null value we find that matches the status code.
379+
apiResponseType.Description ??= responseMetadataTypes.LastOrDefault(x => x.StatusCode == apiResponseType.StatusCode && x.Type == apiResponseType.Type && x.Description is not null)?.Description;
380380

381381
if (!supportedResponseTypes.Any(existingResponseType => existingResponseType.StatusCode == apiResponseType.StatusCode))
382382
{

src/Mvc/Mvc.ApiExplorer/test/EndpointMetadataApiDescriptionProviderTest.cs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,44 @@ public void WithEmptyMethodBody_AddsResponseDescription()
375375
Assert.Equal("application/json", badRequestResponseFormat.MediaType);
376376
}
377377

378+
/// <summary>
379+
/// Setting the description grabs the LAST description.
380+
// To validate this, we add multiple ProducesResponseType to validate that it only grabs the LAST ONE.
381+
/// </summary>
382+
[Fact]
383+
public void AddsResponseDescription_UsesLastOne()
384+
{
385+
const string expectedCreatedDescription = "A new item was created";
386+
const string expectedBadRequestDescription = "Validation failed for the request";
387+
388+
var apiDescription = GetApiDescription(
389+
[ProducesResponseType(typeof(int), StatusCodes.Status201Created, Description = "First description")] // The first item is an int, not a timespan, shouldn't match
390+
[ProducesResponseType(typeof(int), StatusCodes.Status201Created, Description = "Second description")] // Not a timespan AND not the final item, shouldn't match
391+
[ProducesResponseType(typeof(TimeSpan), StatusCodes.Status201Created, Description = expectedCreatedDescription)] // This is the last item, which should match
392+
[ProducesResponseType(StatusCodes.Status400BadRequest, Description = "First description")]
393+
[ProducesResponseType(StatusCodes.Status400BadRequest, Description = expectedBadRequestDescription)]
394+
() => TypedResults.Created("https://example.com", new TimeSpan()));
395+
396+
Assert.Equal(2, apiDescription.SupportedResponseTypes.Count);
397+
398+
var createdResponseType = apiDescription.SupportedResponseTypes[0];
399+
400+
Assert.Equal(201, createdResponseType.StatusCode);
401+
Assert.Equal(typeof(TimeSpan), createdResponseType.Type);
402+
Assert.Equal(typeof(TimeSpan), createdResponseType.ModelMetadata?.ModelType);
403+
Assert.Equal(expectedCreatedDescription, createdResponseType.Description);
404+
405+
var createdResponseFormat = Assert.Single(createdResponseType.ApiResponseFormats);
406+
Assert.Equal("application/json", createdResponseFormat.MediaType);
407+
408+
var badRequestResponseType = apiDescription.SupportedResponseTypes[1];
409+
410+
Assert.Equal(400, badRequestResponseType.StatusCode);
411+
Assert.Equal(typeof(void), badRequestResponseType.Type);
412+
Assert.Equal(typeof(void), badRequestResponseType.ModelMetadata?.ModelType);
413+
Assert.Equal(expectedBadRequestDescription, badRequestResponseType.Description);
414+
}
415+
378416
[Fact]
379417
public void AddsResponseFormatsForTypedResultWithoutReturnType()
380418
{

0 commit comments

Comments
 (0)