Comments (1)
Content pulled from https://blog.safia.rocks/minimal-apis-optionality.html
In .NET 6 RC1, we shipped support for a new feature in Minimal APIs that allows developers to set the optionality of request parameters by using nullable annotations and default parameters to indicate which values are required and which aren't. For example, let's say you had an endpoint that generated a random number based on a seed, like so:
var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.MapGet("/random", (int seed, int max) => { var random = new Random(seed); return random.Next(0, max); }); app.Run();By default, in the scenario above, the
seed
parameter will be treated as required. That means if the user sends the following request to the endpoint:$ http "http://localhost:5184/random" HTTP/1.1 400 Bad Request Content-Length: 0 Date: Sun, 22 Aug 2021 21:52:51 GMT Server: Kestrel
They'll be meet with a 400 Bad Request response. However, everything is all fine and dandy if both values are provided, though.
$ http "http://localhost:5184/random?seed=5&max=100" HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 Date: Sun, 22 Aug 2021 22:06:56 GMT Server: Kestrel Transfer-Encoding: chunked 33As it turns out, we can generate a
Random
object without providing a seed. By annotatingseed
as a nullable property, we can permit users to send requests to the endpoint without providing aseed
property to the query.app.MapGet("/random", (int? seed, int max) => { var random = seed.HasValue ? new Random(seed.Value) : new Random(); return random.Next(0, max); });In this case, both requests below are valid.
$ http "http://localhost:5184/random?max=100" HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 Date: Sun, 22 Aug 2021 22:08:16 GMT Server: Kestrel Transfer-Encoding: chunked 17 $ http "http://localhost:5184/random?seed=5&max=100" HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 Date: Sun, 22 Aug 2021 22:08:35 GMT Server: Kestrel Transfer-Encoding: chunked 33However, since the
max
attribute is still required, omitting that from the request will result in the 400 Bad Request error.$ http "http://localhost:5184/random?seed=5" HTTP/1.1 400 Bad Request Content-Length: 0 Date: Sun, 22 Aug 2021 22:09:22 GMT Server: Kestrel
In addition to nullable annotations, we can indicate that a parameter is optional by specifying a default value for the parameter.
int GetRandom(int? seed, int max = 5) { var random = seed.HasValue ? new Random(seed.Value) : new Random(); return random.Next(0, max); } app.MapGet("/random", GetRandom);
⚠️ Note: In the code above, the endpoint logic has been moved to a separate function since default parameters in inline lambdas are not currently supported in C#.The change above permits the user to provide the
seed
andmax
parameters as optional within requests. All the following requests will be processed by the endpoint.$ http "http://localhost:5184/random?seed=5&max=100" HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 Date: Sun, 22 Aug 2021 22:12:58 GMT Server: Kestrel Transfer-Encoding: chunked 33 $ http "http://localhost:5184/random?seed=5" HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 Date: Sun, 22 Aug 2021 22:15:11 GMT Server: Kestrel Transfer-Encoding: chunked 1 $ http "http://localhost:5184/random" HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 Date: Sun, 22 Aug 2021 22:15:24 GMT Server: Kestrel Transfer-Encoding: chunked 4 $ http "http://localhost:5184/random?max=100" HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 Date: Sun, 22 Aug 2021 22:15:51 GMT Server: Kestrel Transfer-Encoding: chunked 95In the above scenario, we were able to mark a query parameter as optional but the same principles apply to parameters in the body as well as services injected to the endpoint. So for example, let's say that we took the configuration for our random number generator as a set of arguments provided in the body of the request.
app.MapPost("/random", (ConfigOptions? options) => { var random = options is not null ? new Random(options.Seed) : new Random(); return random.Next(0, options?.Max ?? 100); }); app.Run(); class ConfigOptions { public int Seed { get; } public int Max { get; } }The above will appropriately handle requests where the the body parameters are provided and those where it isn't.
One thing to note is that the behavior is different for service parameter. For one, instead of returning a 400 status code, the endpoint will return a 500 status code depending on whether or not the service was provided. Also, due to some nuances in the parameter parsing logic, optionality is only support for services that are injected into the endpoint via an explicit reference (using the
FromService
attribute) and not those that are implicit referenced.🗒️ The nuance here is that there is some subtlety around discerning whether the
SomeType
inapp.MapPost("/foo", (SomeType st) => ...)
is referring to a serviceSomeType
or a body param that deserializes toSomeType
.Finally, depending on the nullability context the parameter exists in the, the behavior of this feature will differ slightly.
- Unannotated value types are always required regardless of nullability context.
- Unannotated reference types are always optional if they exist in an unknown nullability context.
- Regardless of nullability context, you can use default values to indicate that a reference or value type parameter is optional.
One final note, by default, no message will be sent in the response when a parameter fails a requiredness check. For more information on this, including current solutions, check out this GitHub issue.
from minimal-apis.github.io.
Related Issues (20)
- Troubleshooting when things go wrong.
- DI
- Testing
- Error handling
- Middleware
- Razor
- Templating
- Add a section that shows how concepts in other frameworks apply using minimal APIs HOT 7
- Routing HOT 3
- Proof read the minimal apis docs
- Feature dump of minimal APIs HOT 10
- Advanced Parameter binding HOT 1
- Table of Contents- Perhaps in ReadMe HOT 3
- HTTP Methods Overview in Quick Start HOT 11
- 404 for logo.png HOT 2
- Returning HTML- Quick Start HOT 3
- Tutorial- Let's Build- Update and Item HOT 2
- Remove icon from the site
- Rename Quick Start to a more meaningful name
- Tutorial Three: Cannot do first migration with EF Core migration tool
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from minimal-apis.github.io.