Parsing
Body parsing is the second step in the request flow. It occurs after routing and before authentication. Multiple parsers may be attached to a single route, they will be executed in the order they were added. If one parser fails, the next parser will be used. If all parsers fail, an exception of type ParsingFailedException will be thrown. Body parsers are optional and if none are specified this step is skipped, and the Parsed property of the request's IApiContext<TModel, TUser> will be null
.
Api Context
See Also: IApiContext<TModel, TUser>
This step will set the Parsed property on the request's IApiContext<TModel, TUser> to an array of ParseResult<TModel> objects. Even if the parser doesn't accept arrays, the property will still be set to an array containing a single element. Every parse result object contains the parsed model and a list of the properties actually present in the request body.
ParsingOptions
Every body parser accepts a ParserOptions object, which specifies the properties that should be ignored when parsing, defaults for properties, required properties, and whether the parser should accept arrays. Methods for controlling this object are listed below in Parsing Options.
Builder Methods
Low-Level Methods
These methods are primarily used when you've implemented your own IBodyParser<TModel> and want to attach it to a route.
High-Level Methods
These are the methods that you will most commonly use with your routes.
Parsing
Builder Prefix: Parse
- ParseJson()
- ParseJson(JsonSerializerOptions)
- ParseJsonArrays()
- ParseJsonArrays(JsonSerializerOptions)
- ParseXml()
- ParseXmlAndJson(Boolean)
- ParseXmlAndJsonArrays()
- ParseXmlArrays()
Parsing Options
- AcceptArrays(Boolean)
- Default<TProperty>(Expression<Func<TModel, TProperty>>, TProperty)
- Default<TProperty>(Expression<Func<TModel, TProperty>>, Func<TProperty>)
- Default<TProperty>(PropertyInfo, Func<TProperty>)
- Ignore(Expression<Func<TModel, Object>>)
- Ignore(PropertyInfo)
- IgnoreAll()
- OptionalAllProperties()
- OptionalProperty(Expression<Func<TModel, Object>>)
- OptionalProperty(PropertyInfo)
- RequireAllProperties()
- RequireProperty(Expression<Func<TModel, Object>>)
- RequireProperty(PropertyInfo)
Extension Methods:
- IgnorePrimaryKey<TModel, TUser>(SeltzrOptionsBuilder<TModel, TUser>)
- RequirePrimaryKeyProperties<TModel, TUser>(SeltzrOptionsBuilder<TModel, TUser>)
- OptionalPrimaryKeyProperties<TModel, TUser>(SeltzrOptionsBuilder<TModel, TUser>)
Important
Don't confuse Require
, Ignore
, and Optional
with Omit
and Include
. The former methods work with request bodies, the latter with response bodies.
Note
Methods in bold are only available with an ORM-backed version of Seltzr, e.g Seltzr.EntityFrameworkCore
Examples
Parsing
Accept JSON request bodies containing a single element
app.UseSeltzr<MyModel>(api => {
api.ParseJson();
});
Subsequent API routes will accept requests in the format:
{
"Property1": ...,
"Property2": ...
}
Accept JSON request bodies containing a single element
app.UseSeltzr<MyModel>(api => {
api.ParseJsonArrays();
});
Note
The preceding code is equivalent to:
app.UseSeltzr<MyModel>(api => {
api.ParseJson().AcceptArrays();
});
Subsequent API routes will accept requests as a single object
{
"Property1": ...,
"Property2": ...
}
or as an array of objects
[
{
"Property1": ...,
"Property2": ...
},
{
"Property1": ...,
"Property2": ...
}
]
Accept JSON or XML request bodies
app.UseSeltzr<MyModel>(api => {
api.ParseXmlAndJson();
});
Note
The preceding code is equivalent to:
app.UseSeltzr<MyModel>(api => {
api.ParseJson().ParseXml();
});
Note
For performance reasons, all of the parsers built-in to Seltzr require the appropriate Content-Type
header to be set on the request. If you would like to change this behavior, you must inherit from a body parser and override the CanParse
method.
Modifying Parsing Options
Set a default value for a property
app.UseSeltzr<MyModel>(api => {
api.Default(model => model.Token, () => Guid.NewGuid);
});
Note
The Default
method has an overload that accepts an object
instead of a lambda. Use that overload if you want the default value to be the same for every model.
An HTTP request that provides the following models:
[
{ "Value": "Value1" },
{ "Value": "Value2" },
{ "Value": "Value3", "Token": "608..." },
]
Will be parsed into three models, with the default value for Token
having been specified for models that didn't provide one:
[
{ "Value": "Value1", "Token": "ad4..." },
{ "Value": "Value2", "Token": "0db..." },
{ "Value": "Value3", "Token": "608..." },
]
Setting a property regardless of its presence on the parsed model
app.UseSeltzr<MyModel>(api => {
api
.Default(model => model.Token, () => Guid.NewGuid)
.Ignore(model => model.Token);
});
Regardless of whether the Token
property is present in a request body, the property will always be set to a new generated Guid
.
An HTTP request that provides the following models:
[
{ "Value": "Value1" },
{ "Value": "Value2", "Token": "608..." },
]
Will be parsed into two models with new Guid
Tokens:
[
{ "Value": "Value1", "Token": "ad4..." },
{ "Value": "Value2", "Token": "0db..." }
]