1

I am currently developing a web api in .NET Core 3. I currently have the following model for my error response object:

public class ErrorRo
{
    public string Message { get; set; }
    public int StatusCode { get; set; }
    public string Endpoint { get; set; }
    public string Parameters { get; set; }
    public string IpAddress { get; set; }
}

This is a mandated response I need to implement, management has pushed this. It allows more verbose error messages for people hitting our API so that they know what went wrong.

At the moment I am currently populating this object manually in the methods themselves. Is there a way where I can overwrite the response methods. I.e. can I override the BadRequest of IActionResult to automatically populate these fields?

Thanks!

2
  • There are lots of possible ways to implement this. A custom middleware, Action Filters, a simple static method manually called on responses... Commented May 15, 2020 at 9:16
  • You should look at ActionFilters/ResultFilters. It probably depends one what information you are using to populate said dto. Though it may be easier to make a new controller subclass that has a new OurBadRequest method it and calling that instead Commented May 15, 2020 at 9:20

2 Answers 2

1

You can use result filters for this purpose. Add a filter which repalces result before sending it back

Model

public class CustomErroModel
{
    public string Message { get; set; }
    public int StatusCode { get; set; }
    public string Endpoint { get; set; }
    public string Parameters { get; set; }
    public string IpAddress { get; set; }
}

Filter

public class BadRequestCustomErrorFilterAttribute : ResultFilterAttribute
{
    public override void OnResultExecuting(ResultExecutingContext context)
    {
        //todo: check for BadRequestObjectResult if anything is returned for bad request
        if (context.Result is BadRequestResult) 
        {
            var result = new CustomErroModel
            {
                StatusCode = 200, //you status code
                Endpoint = context.HttpContext.Request.GetDisplayUrl(),
                Message = "some message",
                IpAddress = context.HttpContext.Connection.RemoteIpAddress.ToString(), //find better implementation in case of proxy
                //this returns only parameters that controller expects but not those are not defined in model
                Parameters = string.Join(", ", context.ModelState.Select(v => $"{v.Key}={v.Value.AttemptedValue}"))
            };
            
            context.Result = new OkObjectResult(result); // or any other ObjectResult
        }
    }
}

Then apply filter per action or globally

[BadRequestCustomErrorFilter]
public IActionResult SomeAction(SomeModel model)

or

services
    .AddMvc(options =>
    {
        options.Filters.Add<BadRequestCustomErrorFilterAttribute>();
        //...
    }
Sign up to request clarification or add additional context in comments.

Comments

0

Well it depends on the scenario, but one possible approach could be to use a middleware using a similar strategy like the one described in this question, so that you complete the response with extra information.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.