Update: I have uploaded a small test project to github: link
I am creating a small web service with .Net Core 2, and would like to give the ability to clients to specify if they need navigational info in the response or not. The web api should only support xml and json, but it would be nice if clients could use Accept: application/xml+hateoas or Accept: application/json+hateoas in their request.
I tried setting up my AddMvc method like this:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options =>
{
options.RespectBrowserAcceptHeader = true;
options.ReturnHttpNotAcceptable = true;
options.FormatterMappings.SetMediaTypeMappingForFormat(
"xml", MediaTypeHeaderValue.Parse("application/xml"));
options.FormatterMappings.SetMediaTypeMappingForFormat(
"json", MediaTypeHeaderValue.Parse("application/json"));
options.FormatterMappings.SetMediaTypeMappingForFormat(
"xml+hateoas", MediaTypeHeaderValue.Parse("application/xml"));
options.FormatterMappings.SetMediaTypeMappingForFormat(
"json+hateoas", MediaTypeHeaderValue.Parse("application/json"));
})
.AddJsonOptions(options => {
// Force Camel Case to JSON
options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
})
.AddXmlSerializerFormatters()
.AddXmlDataContractSerializerFormatters()
;
And I am using the accept header in my controller methods to differentiate between normal xml/json response, and hateoas-like response, like this:
[HttpGet]
[Route("GetAllSomething")]
public async Task<IActionResult> GetAllSomething([FromHeader(Name = "Accept")]string accept)
{
...
bool generateLinks = !string.IsNullOrWhiteSpace(accept) && accept.ToLower().EndsWith("hateoas");
...
if (generateLinks)
{
AddNavigationLink(Url.Link("GetSomethingById", new { Something.Id }), "self", "GET");
}
...
}
So, in short, I do not want to create custom formatters, because the only "custom" thing is to either include or exclude navigational links in my response, but the response itself should be xml or json based on the Accept header value.
My model class looks like this (with mainly strings and basic values in it):
[DataContract]
public class SomethingResponse
{
[DataMember]
public int Id { get; private set; }
When calling my service from Fiddler, I got the following results for the different Accept values:
- Accept: application/json -> Status code 200 with only the requested data.
- Accept: application/json+hateoas -> Status code 406 (Not Acceptable).
- Accept: application/xml -> Status code 504. [Fiddler] ReadResponse() failed: The server did not return a complete response for this request. Server returned 468 bytes.
- Accept: application/xml+hateoas -> Status code 406 (Not Acceptable).
Could someone tell me which setting is wrong?