Class ValueObjectMvcExtensions
Namespace: AdCodicem.ValueObjects.AspNetCore
Assembly: AdCodicem.ValueObjects.AspNetCore.dll
Wires value object support into an ASP.NET Core application.
public static class ValueObjectMvcExtensions
Inheritance
object ← ValueObjectMvcExtensions
Inherited Members
object.Equals(object?), object.Equals(object?, object?), object.GetHashCode(), object.GetType(), object.MemberwiseClone(), object.ReferenceEquals(object?, object?), object.ToString()
Methods
AddValueObjectProblemDetails(ApiBehaviorOptions)
Adds the stable error codes of the rejected value objects to the automatic 400 response.
public static ApiBehaviorOptions AddValueObjectProblemDetails(this ApiBehaviorOptions options)
Parameters
options ApiBehaviorOptions
API behaviour options.
Returns
The same options, so calls can be chained.
Remarks
The framework's own ValidationProblemDetails response is kept as is, with an errorCodes
extension added next to errors: the human-readable messages stay where clients expect them, and a
client that wants to branch on a rule now has something stable to branch on.
AddValueObjects(MvcOptions)
Binds value objects from the underlying value everywhere MVC reads text.
public static MvcOptions AddValueObjects(this MvcOptions options)
Parameters
options MvcOptions
MVC options.
Returns
The same options, so calls can be chained.
Remarks
The provider is inserted first so that it wins over the built-in simple-type and complex-type binders,
which would otherwise try to bind a value object as an object with a Value property. It declines a
greedy binding source, which MVC's own providers bind: a header, through this binder again, the body, through
the input formatter, the services, and a binder named by [ModelBinder(typeof(…))].
This adds the binder alone.
The options hold one provider: calling this again, or
AddValueObjects(MvcOptions, Action<ValueObjectMessageOptions>)
Binds value objects from the underlying value everywhere MVC reads text, giving a refusal the message the application's resource holds for its code.
public static MvcOptions AddValueObjects(this MvcOptions options, Action<ValueObjectMessageOptions> configure)
Parameters
options MvcOptions
MVC options.
configure Action<ValueObjectMessageOptions>
Names the resource the messages are read from, through
Returns
The same options, so calls can be chained.
Remarks
The binder is added as ValueObject.value_object.too_short, looked up after ValueObject.value_object.out_of_range.minimum or
.maximum for a type declaring one bound alone. It is formatted with the display name of the member as
{0}, and the arguments the type's rules supply from {1}: a length, both bounds, the known values.
The code under errorCodes is the same in every language, and a key the resource lacks keeps the English
message. Blank text keeps the framework's message, which MVC's own message provider localises.
The resource is read through the request's IStringLocalizerFactory: register
builder.Services.AddLocalization(), without which a refusal throws an app.UseRequestLocalization(), so that the request chooses the culture. The current UI culture
chooses the template and the current culture formats the arguments. A template quoting an argument its code does
not supply throws its
A request body is read by the input formatter, which
Exceptions
options or configure is null.
AddValueObjects(IMvcBuilder)
Registers value object model binding and JSON serialization on an MVC builder.
public static IMvcBuilder AddValueObjects(this IMvcBuilder builder)
Parameters
builder IMvcBuilder
MVC builder.
Returns
The same builder, so calls can be chained.
Remarks
It also puts a formatter of its own in place of MVC's System.Text.Json input formatter, at its index: one
deriving from it, which reads with the very serializer options the framework's formatter read with, and records
the code of a value object a request body refuses, so that
The swap is a post-configuration of InputFormatters.RemoveType<SystemTextJsonInputFormatter>() still works in AddMvcOptions, in
Configure<MvcOptions> or in a post-configuration registered before this call; in one registered
after it, that finds this formatter in its place, which is not of that exact type: remove there every formatter
that is a
Once Newtonsoft.Json reads the body, through AddNewtonsoftJson(), there is no such formatter to replace,
and a body records no code; AddValueObjectsNewtonsoftJson(), from
AdCodicem.ValueObjects.AspNetCore.NewtonsoftJson, replaces Newtonsoft.Json's formatter instead.
AddValueObjects(IMvcBuilder, Action<ValueObjectMessageOptions>)
Registers value object model binding and JSON serialization on an MVC builder, giving a refusal, in a route, query, header or form value or in a JSON body, the message the application's resource holds for its code.
public static IMvcBuilder AddValueObjects(this IMvcBuilder builder, Action<ValueObjectMessageOptions> configure)
Parameters
builder IMvcBuilder
MVC builder.
configure Action<ValueObjectMessageOptions>
Names the resource the messages are read from, through
Returns
The same builder, so calls can be chained.
Remarks
Everything {0}, since the
path may hold a refused dictionary key, the refused value itself. A type the registry cannot describe, such as
AnyEntityId, has the key of the code alone and no argument.
A body's message is translated only where MVC answers with it, under
AdCodicem.ValueObjects.AspNetCore.NewtonsoftJson, keeps its English message.
Exceptions
builder or configure is null.