Reputation: 355
I'm trying to add a CSV Output Formatter to my .NET Core 1.1 WebApi.
I've installed WebAPIContrib.Core package (https://github.com/damienbod/WebAPIContrib.Core/tree/master/src/WebApiContrib.Core.Formatter.Csv).
My Startup now look like this:
var csvFormatterOptions = new CsvFormatterOptions();
services.AddMvcCore(options =>
{
options.OutputFormatters.Add(new CsvOutputFormatter(csvFormatterOptions));
options.FormatterMappings.SetMediaTypeMappingForFormat("csv", MediaTypeHeaderValue.Parse("text/csv"));
})
.AddJsonFormatters()
.AddJsonOptions(options => new SerializationHelper().Configure(options.SerializerSettings));
My controller method is completely generic and looks like this
[HttpGet("/api/export")]
[Produces("text/csv")]
public async Task<List<Data>> GetDataAsCsv()
{
return await _someService.GetData();
}
My issue is that if i remove the produces attribute and don't send an accept header i still get a csv. How can he know to send back a CSV ? My other methods still produce JSON which is how it should be i just don't understand why this is and i'm afraid it will cause an issue down the line.
Upvotes: 3
Views: 807
Reputation: 247521
Content negotiation is part of the framework but you would need to update the action to take advantage of this.
[HttpGet("/api/export")]
public async Task<IActionResult> GetData() {
List<Data> data = await _someService.GetData();
return Ok(data); // <-- returns OkObjectResult with content negotiation baked in
}
To quote the repo linked in the original post, look at the following from its documentation
The
Get
method exports the data using the Accept header in the HTTP Request. Per default, Json will be returned. If the Accept Header is set to 'text/csv', the data will be returned as csv. TheGetDataAsCsv
method always returns csv data because the Produces attribute is used to force this.
// GET api/csvtest
[HttpGet]
public IActionResult Get() {
return Ok(DummyData());
}
[HttpGet]
[Route("data.csv")]
[Produces("text/csv")]
public IActionResult GetDataAsCsv() {
return Ok( DummyData());
}
Also as indicated in the documentation you should make sure you are configuring it properly in startup.
Out of the box, ASP.NET Core only has Json (and possibly plain text) as content types.
var csvOptions = new CsvFormatterOptions();
services.AddMvcCore(options => {
options.RespectBrowserAcceptHeader = true;
})
.AddJsonFormatters()
.AddJsonOptions(options => new SerializationHelper().Configure(options.SerializerSettings))
.AddCsvSerializerFormatters(csvOptions);
Note that the call to
RespectBrowserAcceptHeader
is false by default, so if you want content negotiation, you have to enable this.
Reference Content Negotiation in ASP.NET Core
Upvotes: 1