public void GetApiResponseTypes_HandlesActionWithMultipleContentTypesAndProduces() { // Arrange var actionDescriptor = GetControllerActionDescriptor(typeof(TestController), nameof(TestController.GetUser)); actionDescriptor.FilterDescriptors.Add(new FilterDescriptor(new ProducesAttribute("text/xml") { Type = typeof(BaseModel) }, FilterScope.Action)); actionDescriptor.FilterDescriptors.Add(new FilterDescriptor(new ProducesResponseTypeAttribute(typeof(ValidationProblemDetails), 400, "application/problem+json"), FilterScope.Action)); actionDescriptor.FilterDescriptors.Add(new FilterDescriptor(new ProducesResponseTypeAttribute(typeof(ProblemDetails), 404, "application/problem+json"), FilterScope.Action)); actionDescriptor.FilterDescriptors.Add(new FilterDescriptor(new ProducesResponseTypeAttribute(409), FilterScope.Action)); var provider = new ApiResponseTypeProvider(new EmptyModelMetadataProvider(), new ActionResultTypeMapper(), new MvcOptions()); // Act var result = provider.GetApiResponseTypes(actionDescriptor); // Assert Assert.Collection( result.OrderBy(r => r.StatusCode), responseType => { Assert.Equal(typeof(BaseModel), responseType.Type); Assert.Equal(200, responseType.StatusCode); Assert.Equal(new[] { "text/xml" }, GetSortedMediaTypes(responseType)); }, responseType => { Assert.Equal(typeof(ValidationProblemDetails), responseType.Type); Assert.Equal(400, responseType.StatusCode); Assert.Equal(new[] { "application/problem+json" }, GetSortedMediaTypes(responseType)); }, responseType => { Assert.Equal(typeof(ProblemDetails), responseType.Type); Assert.Equal(404, responseType.StatusCode); Assert.Equal(new[] { "application/problem+json" }, GetSortedMediaTypes(responseType)); }, responseType => { Assert.Equal(typeof(void), responseType.Type); Assert.Equal(409, responseType.StatusCode); Assert.Empty(GetSortedMediaTypes(responseType)); }); }
private ApiDescription CreateApiDescription( ControllerActionDescriptor action, string httpMethod, string groupName) { var parsedTemplate = ParseTemplate(action); var apiDescription = new ApiDescription() { ActionDescriptor = action, GroupName = groupName, HttpMethod = httpMethod, RelativePath = GetRelativePath(parsedTemplate), }; var templateParameters = parsedTemplate?.Parameters?.ToList() ?? new List <TemplatePart>(); var parameterContext = new ApiParameterContext(_modelMetadataProvider, action, templateParameters); foreach (var parameter in GetParameters(parameterContext)) { apiDescription.ParameterDescriptions.Add(parameter); } var requestMetadataAttributes = GetRequestMetadataAttributes(action); var apiResponseTypes = _responseTypeProvider.GetApiResponseTypes(action); foreach (var apiResponseType in apiResponseTypes) { apiDescription.SupportedResponseTypes.Add(apiResponseType); } // It would be possible here to configure an action with multiple body parameters, in which case you // could end up with duplicate data. if (apiDescription.ParameterDescriptions.Count > 0) { var contentTypes = GetDeclaredContentTypes(requestMetadataAttributes); foreach (var parameter in apiDescription.ParameterDescriptions) { if (parameter.Source == BindingSource.Body) { // For request body bound parameters, determine the content types supported // by input formatters. var requestFormats = GetSupportedFormats(contentTypes, parameter.Type); foreach (var format in requestFormats) { apiDescription.SupportedRequestFormats.Add(format); } } else if (parameter.Source == BindingSource.FormFile) { // Add all declared media types since FormFiles do not get processed by formatters. foreach (var contentType in contentTypes) { apiDescription.SupportedRequestFormats.Add(new ApiRequestFormat { MediaType = contentType, }); } } } } return(apiDescription); }