When building a REST API, it’s recommended to annotate the controller actions with the available HTTP attributes to be precise about what your API supports.

## Why is this an issue?

- Ambiguity: Without HttpAttributes, it’s unclear which HTTP methods an action method should respond to. This can lead to confusion and make the code harder to understand and maintain.
- Unsupported HTTP Methods: If an action is not annotated at all or is annotated only with the Route attribute, it accepts all HTTP methods even if they are not supported by that action, which leads to further confusion.
- Problems with Swagger: Swagger relies on HttpAttributes to generate parts of the API documentation. These attributes are necessary for the generated documentation to be complete.
- Route path conflicts: Without HttpAttributes, it’s possible to accidentally create action methods that respond to the same route and HTTP method. This can lead to unexpected behavior and hard-to-diagnose bugs.
- Lack of routing flexibility: The HTTP attributes allow you to define multiple action methods in the same controller that respond to the same route but different HTTP methods. If you don’t use them, you might have limited flexibility when designing your API.

## How to fix it

You should annotate the controller actions with the available HttpMethod attributes. You can still use them in conjunction with the Route attribute, in case there are multiple templates for one action and you need to set the order. This allows you to clearly define the HTTP methods each action method should respond to, while still being able to customize your routes.

## Exceptions

This rule does not raise if the controller or the action is annotated with `[ApiExplorerSettings(IgnoreApi = true)]` or `AcceptsVerbs` attribute.

### Code examples

#### Noncompliant code example

    [Route("Customer")]                                                        // This route conflicts with GetCustomers action route
    public async Task<IResult> ChangeCustomer([FromBody] CustomerData data)   // Noncompliant
    {
        // ...
        return Results.Ok();
    }

    [Route("Customer")]                         // This route conflicts with ChangeCustomer action route
    public async Task<string> GetCustomers()    // Noncompliant
    {
        return _customerRepository.GetAll();
    }

#### Compliant solution

    [Route("Customer")]
    [HttpPost]
    public async Task<IResult> ChangeCustomer([FromBody] CustomerData data)    // Compliant
    {
        // ...
        return Results.Ok();
    }

    [HttpGet("Customer")]
    public async Task<string> GetCustomers()    // Compliant
    {
        return _customerRepository.GetAll();
    }

## Resources

### Documentation

- Microsoft Learn - Routing to controller actions in ASP.NET Core
- Microsoft Learn - Attribute routing with Http verb attributes
- Microsoft Learn - Get started with Swashbuckle and ASP.NET Core
- Microsoft Learn - ASP.NET Core Exception handler
- Microsoft Learn - RouteAttribute Class