I'm creating a ASP.NET Core (.NET Core 3.1) API that accepts requests with JSON content.
If I POST to my endpoint non-JSON request content (while running in debug in VS with IIS Express) I get the response similar to:
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.13",
"title": "Unsupported Media Type",
"status": 415,
"traceId": "|a53c33b7-43fa646efa5c6ab9."
}
Instead of this being sent out in the response I would like to create my own response for this scenario. I would like to do this by changing the pipeline if possible.
Within my Startup.cs
I added:
public void Configure(IApplicationBuilder app)
{
app.Use(async (context, next) =>
{
await next.Invoke();
if (context.Response.StatusCode == StatusCodes.Status415UnsupportedMediaType)
{
await context.Response.WriteAsync("Unsupported media type handled");
}
});
// other calls on app
}
However, upon running the app and hitting my endpoint I now get:
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.13",
"title": "Unsupported Media Type",
"status": 415,
"traceId": "|3ec437d7-4b20f64c28d04f16."
}Unsupported media type handled
I've tried calling context.Response.Clear();
before I write my new text, but this just outputs the JSON above without my custom text. Which seems even stranger.
What is going on here? It feels like something is handling and creating the 415 response before my pipeline even starts. Or what might I be doing wrong?
CodePudding user response:
from here
Another option you can evaluate is option 1: suppressing the default client error handling done by ASP.NET core and take full control of the response in case of a 415 response status code.
This is an example:
public void ConfigureServices(IServiceCollection services)
{
services
.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
options.SuppressMapClientErrors = true;
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.Use(async (context, next) =>
{
await next();
// Handle the 415 response
if (context.Response.StatusCode == 415)
{
context.Response.ContentType = "application/json";
var json = JsonSerializer.Serialize(new { message = "You need to add a request body!" });
await context.Response.WriteAsync(json);
}
});
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
The response payaload you will get (for an invalid request, a request with no content for example) is the following:
Notice that here I'm able to take full control of the response content because, by disabling the default client error mapping done by ASP.NET core (options.SuppressMapClientErrors = true;
), the response you get when sending an invalid POST request is a plain 415 status code, with no response content at all. So, when writing to the response stream (await context.Response.WriteAsync(json);
), you are writing inside an empty response stream, so only our custom JSON is sent to the client as the response content.
In your first attempt you forgot to disable the automatic response created by ASP.NET core in case of 415 response status code, so the code await context.Response.WriteAsync("Unsupported media type handled");
is appending content to the response stream, after the response content already written by the ASP.NET core framework automatically.