bitshift
bitshift

Reputation: 6852

How to conform to REST url patterns instead of method names

Say I had a few business entities that I want to query from the Db, and do this within a Web API. Say, Customers and Orders. Each order can have exactly one customer.

Say I wanted to get
- all the orders for a given customer
- for a given order, return an object that contains some customer attributes, along with that customers 5 most recent order#'s

https://github.com/Microsoft/api-guidelines/blob/master/Guidelines.md#71-url-structure

Ive tended to use method names like these.

OrdersController:
- GetOrders
- GetordersforCustomer(int CustomerId)
- GetOrderWithCustomerInfo(int CustomerId)

CustomerController
- GetCustomer(int id)
- GetCustomerWithinZipcode

So using API controller methods like this does not follow the REST "guidelines" ive seen elsewhere, correct? If not, how could I restructure my controllers to accomodate the standard HTTP method names, especially when there are related entities?

For example, I need a call that returns an object that includes attributes from not just an order but the top 5 orders from the customer on the current order. I need a method that gets an order result, but also need a method that gets a different kind of order result - one with some attributes from a customer and/or maybe a few other entities.

example of what im talking about - using only http verbs but with related entities
https://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api#restful But how do you deal with relations? If a relation can only exist within another resource, RESTful principles provide useful guidance. Let's look at this with an example. A ticket in Enchant consists of a number of messages. These messages can be logically mapped to the /tickets endpoint as follows:

GET /tickets/12/messages - Retrieves list of messages for ticket #12
GET /tickets/12/messages/5 - Retrieves message #5 for ticket #12
POST /tickets/12/messages - Creates a new message in ticket #12
PUT /tickets/12/messages/5 - Updates message #5 for ticket #12
PATCH /tickets/12/messages/5 - Partially updates message #5 for ticket #12
DELETE /tickets/12/messages/5 - Deletes message #5 for ticket #12

Upvotes: 0

Views: 150

Answers (1)

Nkosi
Nkosi

Reputation: 247323

Question is broad and also opinion based.

That said, there is no need to restructure the controllers.

Research using attribute routing.

Reference Routing to controller actions in ASP.NET Core

Given the linked guidelines an example of potential routes could look like below suggestions.

[Route([controller])]
OrdersController:
    //Matches GET orders
    [HttpGet]
    GetOrders()

    //Matches GET customers/1234/orders
    [HttpGet(~/customers/{customerId:int}/orders)]
    GetOrdersForCustomer(int customerId)

    Matches GET orders/1324/customer/5678
    [HttpGet({orderId:int}/customer/{customerId:int})]
    GetOrderWithCustomerInfo(int orderId, int customerId)

[Route([controller])]
CustomersController
    //Matches GET customers
    [HttpGet]
    GetCustomers()

    //Matches GET customers/1234
    [HttpGet("{id:int}")]
    GetCustomer(int id)

    //Matches GET zipcodes/90210/customers
    [HttpGet("~/zipcodes/{zipCode:int}/customers")]
    GetCustomerWithinZipcode(int zipCode)

Upvotes: 0

Related Questions