Vincent
Vincent

Reputation: 1557

Custom attribute which returns http response

I'm trying to make a custom attribute in my controller methods, i want this attribute to get the HTTPContext and i want to either let it continue to the method if some condition is true or else return a BadRequest with an ErrorModel I created.

this is how my current middleware does it, but I would like something similar as an attribute above my methods (or even the entire controller class).

if (!response.Success)
{
    context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
    var errorMessageJson = JsonConvert.SerializeObject(new ErrorViewModel()
    {
        Identifier = "CPP_ERROR",
        Id = 1,
        Name = "INVALID_LOCATION",
        Description = string.IsNullOrEmpty(computerName) ? "Werkplek is onbekend." : $"Werkplek {computerName} is niet gekoppeld aan een business balie."
    });
    await context.Response.WriteAsync(errorMessageJson);
}
else
{
    context.SetWorkstation(response.Computer);
    context.SetLocation(response.Location);

    //  Call the next delegate/ middleware in the pipeline
    await _next(context);
}

Does anyone know how to achieve this? I've already looked into a custom authorization attribute but then i have no control over the HTTPResponse which is returned.

Upvotes: 0

Views: 2054

Answers (1)

Henk Mollema
Henk Mollema

Reputation: 46621

You're looking for an action filter: https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/filters?view=aspnetcore-2.2. Action filters can be applied to controller actions using attributes. For example:

public class MyActionFilterAttribute : ActionFilterAttribute
{
    public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        // Add some condition here
        if (...)
        {
            // Execute the action if the condition is true
            await next();
        }
        else
        {
            // Short-circuit the action by specifying a result
            context.Result = new BadRequestObjectResult(new ErrorViewModel
            {
                // ...
            });
        }
    }
}

You can apply this filter by using the [MyActionFilter] attribute on either a controller or action, or as a global filter. For example:

[MyActionFilter]
public class MyController : Controller
{
}

Upvotes: 2

Related Questions