GET

GET reads data. One [HttpGet] action returns the whole collection, and an [HttpGet("{id}")] action returns one item, its id taken from the address. ASP.NET Core sends what they return as JSON, with 200 OK.

Journeyman · ASP.NET Core · REST API · Updated

After this lesson you can

  • Write GET actions that return a list, and one item by its id, as JSON

Key takeaways

  • [HttpGet] answers the controller's own route, and [HttpGet("{id}")] adds to it, so GET /api/categories/8 fills int id with 8.
  • Return a List<Category> and the client gets a JSON array; return one Category and it gets one JSON object, both with 200 OK.
  • A parameter that isn't in the route, such as string? search, comes from the query string: ?search=pro.
  • /api/categories/abc answers 400 because abc can't become an int; with {id:int} in the template, it answers 404 instead.
  • When GetById returns null for a missing category, the client gets 204 No Content, not the 404 Not Found it should get.

A client reads data with a GET request. It sends no body: the address says everything.

The whole collection

[HttpGet]
public List<Category> GetAll()
{
    return categoryDao.GetAll();
}

[HttpGet] with no template answers the controller's own route, GET /api/categories. The DAO's query is the one you'd expect:

public List<Category> GetAll()
{
    using SqlConnection connection = new SqlConnection(connectionString);
    return connection.Query<Category>(
        "SELECT CategoryId, CategoryName, Description FROM Categories ORDER BY CategoryId;").ToList();
}
GET {{HostAddress}}/api/categories
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

[
  {
    "categoryId": 1,
    "categoryName": "Beverages",
    "description": "Soft drinks, coffees, teas, beers, and ales"
  },
  {
    "categoryId": 2,
    "categoryName": "Condiments",
    "description": "Sweet and savory sauces, relishes, spreads, and seasonings"
  },
  ...
]

A List<Category> becomes a JSON array, [ ... ], of objects. You returned a list; ASP.NET Core did the rest.

One item by its id

[HttpGet("{id}")]
public Category? GetById(int id)
{
    return categoryDao.GetById(id);
}

The template "{id}" is added to the controller's route, so this action answers GET /api/categories/8, and the int id parameter gets the 8. The DAO uses QuerySingleOrDefault, which returns null when there's no such row:

public Category? GetById(int categoryId)
{
    using SqlConnection connection = new SqlConnection(connectionString);
    return connection.QuerySingleOrDefault<Category>(
        "SELECT CategoryId, CategoryName, Description FROM Categories WHERE CategoryId = @CategoryId;",
        new { CategoryId = categoryId });
}
GET {{HostAddress}}/api/categories/8
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{
  "categoryId": 8,
  "categoryName": "Seafood",
  "description": "Seaweed and fish"
}

One object becomes one JSON object, { ... }.

Two things to notice:

  • /api/categories/abc answers 400 Bad Request on its own: abc can't become an int, and [ApiController] reports it. To be stricter, write "{id:int}": then abc doesn't match the route at all, and answers 404.
  • /api/categories/300 answers 204 No Content, as HTTP Status Codes: an overview warned: the DAO returned null. Returning ActionResult<T> fixes it to a proper 404.

Filtering with the query string

A GET can take optional extras from the query string, exactly as MVC actions did. A parameter that isn't in the route is looked for there:

[HttpGet]
public List<Category> GetAll(string? search)
{
    List<Category> categories = categoryDao.GetAll();
    if (search != null)
    {
        categories = categories.Where(c => c.CategoryName.Contains(search, StringComparison.OrdinalIgnoreCase)).ToList();
    }
    return categories;
}

GET /api/categories?search=pro returns Dairy Products and Produce; GET /api/categories still returns everything. (For a big table, the DAO would filter in SQL instead, with a WHERE ... LIKE.)

Check yourself

1 question to try on the lesson page.

So what

A GET action is a DAO call and a return. The route says which item, the query string says how to filter, and ASP.NET Core turns whatever you return into JSON.

Key terms

  • GET
  • Route Template
  • Route Parameter

Cheat sheets