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, soGET /api/categories/8fillsint idwith 8.- Return a
List<Category>and the client gets a JSON array; return oneCategoryand it gets one JSON object, both with200 OK. - A parameter that isn't in the route, such as
string? search, comes from the query string:?search=pro. /api/categories/abcanswers400becauseabccan't become anint; with{id:int}in the template, it answers404instead.- When
GetByIdreturnsnullfor a missing category, the client gets204 No Content, not the404 Not Foundit 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/abcanswers400 Bad Requeston its own:abccan't become anint, and[ApiController]reports it. To be stricter, write"{id:int}": thenabcdoesn't match the route at all, and answers404./api/categories/300answers204 No Content, as HTTP Status Codes: an overview warned: the DAO returnednull. Returning ActionResult<T> fixes it to a proper404.
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