Reputation: 21
I am porting an API from .NET to .NET Core. For the task every response needs to be the same. In the case where I try a "PUT" request on a "GET" only endpoint the old API returns the following in Postman with status code 405:
{
"Message": "The requested resource does not support http method 'PUT'."}
.NET Core by default returns empty body with 405.
My question is how to emulate the response body of the first example in .NET CORE.
My current attempts led me to creating a middle-ware which is added before app.UseRouting();
.
The middleware looks like this: public class MethodNotAllowedMiddleware
{
private RequestDelegate _next;
public MethodNotAllowedMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
await _next(context);
if(context.Response.StatusCode == (int)HttpStatusCode.MethodNotAllowed)
{
await context.Response.WriteAsync("The requested resource does not support http method 'PUT'.");//This will NOT be hardcoded string
}
}
}
However the response body is plain string and not in JSON format. How could I build the response with proper classes instead of hard-coding a string? I am thinking that this is a very hacky solution, and that there should be a more elegant way to solve the problem that I am missing.
Upvotes: 0
Views: 1240
Reputation: 21
I was on the right track, I was missing setting the response StatusCode, Content-Type and serialized JSON for the response Body.
After adjustments the body of the middleware looks like this: await _next(context);
if (context.Response.StatusCode == (int)HttpStatusCode.MethodNotAllowed && context.Response.HasStarted == false)
{
//Assign the error message
MiddlewareErrorMessage msg = new MiddlewareErrorMessage($"The requested resource does not support http method '{context.Request.Method}'.");
// Set the status code
context.Response.StatusCode = 405;
// Set the content type
context.Response.ContentType = "application/json; charset=utf-8";
string jsonString = JsonConvert.SerializeObject(msg);
await context.Response.WriteAsync(jsonString, Encoding.UTF8);
}
Where "MiddlewareErrorMessage" simply has the structure of the error I want to return
Upvotes: 0
Reputation: 1016
See custom error handling here: https://joonasw.net/view/custom-error-pages
You can re-route to a new path and use MVC to create any object/page you want:
app.Use(async (ctx, next) =>
{
await next();
if (ctx.Response.StatusCode == 405 && !ctx.Response.HasStarted)
{
//Re-execute the request so the user gets the error page
string originalPath = ctx.Request.Path.Value;
ctx.Items["originalPath"] = originalPath;
ctx.Request.Path = "/Home/Error405";
await next();
}
});
And you controller code:
public class HomeController : Controller
{
[AllowAnonymous]
public IActionResult Error405()
{
return new ObjectResult(new Response {
Message = "The requested resource does not support http method 'PUT'."
}) {
StatusCode = 405
};
}
public class Response
{
public string Message { get; set; }
}
}
AllowAnonymous
to disable the authorization flowUpvotes: 1