Sgedda
Sgedda

Reputation: 1541

Response content types in swagger, .net core api

I had some problems to render my api response as xml in swagger, finally I got it to render in the correct format, application/xml with my first action below, but it still says I can only render it as application/json.

I tried to remove application/json from Produces attribute, but still shows only application/json.

Any ideas why its behaving in this way?

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc().AddMvcOptions(o => o.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter()));
    app.UseSwagger();
    app.UseSwaggerUI(c =>
    {
        c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
        c.RoutePrefix = "";
    });
    services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1", new Info { Title = "My API", Version = "v1" });
        c.AddSecurityDefinition("Bearer", new ApiKeyScheme { In = "header", Description = "Please enter JWT with Bearer into field", Name = "Authorization", Type = "apiKey" });
        c.AddSecurityRequirement(new Dictionary<string, IEnumerable<string>> {
            { "Bearer", Enumerable.Empty<string>() },
        });
    });
}

And action:

[Produces("application/json", "application/xml")]
public ContentResult GetByAddress(string address)
{
    var addressId = GetAddressIdByAddress(address);
    string result = _soapApi.GetResultById(addressId);
    return Content(result, "application/xml", Encoding.UTF8);
}

Same result with:

[Produces("application/json", "application/xml")]
public IActionResult GetByAddress(string address)
{
    var addressId = GetAddressIdByAddress(address);
    string result = _soapApi.GetResultById(addressId);
    return Content(result, "application/xml", Encoding.UTF8);
}

Results in:

Results in this When clicking excecute I get the result in the correct XML-format though.

While this:

[Produces("application/json", "application/xml")]
public string GetByAddress(string address)
{
    var addressId = GetAddressIdByAddress(address);
    string result = _soapApi.GetResultById(addressId);
    return result;
}

Or this:

[Produces("application/json", "application/xml")]
public List<Address> GetByAddreses()
{
    string result = _soapApi.GetResults();
    return result;
}

Results in:

enter image description here

I am not able to return a list of parsed objects due to different data-structure returned for different parameters. So at this point I only receive raw soap xml-data and have to parse/deserialize it. But to actually be able to see the raw response I also need to show it as Content from string with content-type application/xml. And it gives me a nice output like (even though it still says only application/json is possible):

enter image description here

To summarize it:

I did not get it work with response content-type showing the correct content-type (in "Response Content Type" -filter) when a string was parsed to its actual format like below. Even though this results in the correct output for application/xml that was the most important (see screenshot above);

[Produces("application/json", "application/xml")]
public ContentResult GetByAddress(string address)
{
    return Content("<xml>...</xml>", "application/xml", Encoding.UTF8);
} 

Upvotes: 7

Views: 31879

Answers (4)

Pawel Cioch
Pawel Cioch

Reputation: 3202

Now days in NET6+ you can set them application wide during registration

builder.Services.AddControllers(options =>
{
    //here you can control the order and types for all responses as they will appear in swagger.json
    //technically if an endpoint returns binary image it can be changed per endpoint using either [Produces] or [SwaggerResponse] attribute
    options.Filters.Add(new ProducesAttribute("application/json", "text/json", "text/plain"));
})

Upvotes: 2

El Bayames
El Bayames

Reputation: 615

I am testing a web api application developed with asp.net core2.2.

I installed the Microsoft.AspNetCore.Mvc.Formatters.Xml nuget package.

Then I updated the ConfigureServices method within the Startup.cs by adding.

services.AddMvc().AddXmlSerializerFormatters();

And my web api swagger is working as I needed with the dropdown showing both (json and xml) and resulting the expected format. If you need more information please visit: https://learn.microsoft.com/en-us/aspnet/core/web-api/advanced/formatting?view=aspnetcore-2.1

Upvotes: 0

Miq
Miq

Reputation: 4289

It's because the return type overrides the annotations. To get it working as you wish, you need to return IActionResult and use annotations to provide what response type model it should be for particular code.
So instead returning result, return Ok(result)

I created sample code and it works for me using swagger 4.0.1

[HttpGet("Get2")]
[Produces("application/json", "application/xml", Type = typeof(List<string>))]
public IActionResult Get2()
{
   var list = new List<string>() { "value1", "value2" };
   return Ok(list);
}

swagger output

Upvotes: 7

BJ Coder
BJ Coder

Reputation: 402

[Produces("application/json", "application/xml")]
public Task<IActionResult> GetByAddreses()
{
    var result = _soapApi.GetResults();
var response = ResponceMethod<List<Address>>.SuccessResponse(StatusCodes.Status200OK, "Success", result);
    return Ok(response);
}

Upvotes: 3

Related Questions