Learn how to validate the incoming paging options, and use the ASP.NET Core configuration and dependency injection system to add paging defaults to collections.
- [Instructor] The client should be able to omit the offset or limit parameters when they retrieve a collection. Right now, though, if those parameters are omitted, the API will throw an exception. We can add some default values to fall back on if one or both of these parameters is missing. To add some paging defaults, let's jump over to Appsettings.json. We'll add a new element called DefaultPagingOptions, and inside we'll just have a limit parameter, and a default offset.
You can adjust these to the values that make sense for your API. In Startup.cs we'll need to load these values from configuration. In the configure services method we can say, services.Configure, PagingOptions, and load that from Configuration.GetSection, DefaultPagingOptions. Now in the RoomsController, we can inject an instance of PagingOptions from the service container. We can declare it here as a local variable.
Call it defaultPagingOptions. And then in the constructor, we'll accept an Ioptions from the Options name space, of PagingOptions. This will inject the object we just added in Startup.cs. We'll call this defaultPagingOptions as well. And then, in the body of the constructor, we'll set the local default paging options to defaultPagingOptions.Value. Now let's scroll down to the GetAllRoomOpeningsAsync method. Before we call the service, we'll say pagingOptions.Offset = pagingOptions.Offset, or if null, defaultPagingOptions.Offset.
And the same for Limit. Set this to the default as well if it's missing. This will guarantee that those values are either provided by the client, or fall back to the defaults. There's one more thing we can do. In the pagingOptions class, we use some attributes to define the error messages and the valid ranges for these options. We can use the model validation functionality built into ASP.netcore to validate these automatically. If we switch back to the RoomsController, at the very top of the method, we can check to make sure that the model state is valid.
We can say if not ModelState.IsValid, return BadRequest, which will return 400 back to the client, and as the body of the error message, we'll say new ApiError, and pass in the model state. We'll need to add this overload to the ApiError class, switch over to the ApiError class, and add another overload to the constructor that takes a model state dictionary.
This, you'll have to import from the model binding name space. We'll set the default error message to "Invalid parameters." and the detail message to modelState.FirstOrDefault, we need to import link, where the value has an error, and we'll get that error message, and call FirstOrDefault on that as well. This line gets a little long, but what it'll do is pull the first error message out of the model state, and return it back to the client.
Alright, let's test this with Postman. If we make a request with no parameters, we should get the default paging options of offset 0, limit 25. And that's what we have. The first 25 items in a 27 item collection. Additionally, we can check the validation rules as well. If we send an invalid limit value such as limit=0, we should get an error message back, and the error message is created for us automatically. The detail message comes straight out of the attribute that we added to the model class. Now that we've taken care of the paging options, let's add navigation links to the page collection response.
- REST vs. RPC
- Using HTTP methods (aka verbs)
- Returning JSON
- Creating a new API project
- Building a root controller
- Routing to controllers with templates
- Requiring HTTPS for security
- Creating resources and data models
- Returning data and resources from a controller
- Representing links (HREFs)
- Representing collections
- Sorting and searching collections
- Creating forms
- Caching and compression
- Authentication and authorization for RESTful APIs