Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Infer default sources for parameters in MapAction #30248

Closed
Assignees
halter73
Labels
area-minimalIncludes minimal APIs, endpoint filters, parameter binding, request delegate generator etcenhancementThis issue represents an ask for new feature or an enhancement to an existing onefeature-minimal-actionsController-like actions for endpoint routing
Milestone
@halter73

Description

@halter73

How to determine each parameter's source

The numbered and lettered rules for determining the source of a parameter should be applied in the order. The bullet points are unordered.

  1. If an attribute that implements one of the "IFrom..." interfaces inMicrosoft.AspNetCore.Http.Metadata is applied to the parameter, populate the parameter from the source specified by the attribute. Only one of these attributes can be specified per parameter, and these attributes must implement no more than one of these interfaces.
    • IFromRouteMetadata
      • Reads fromHttpRequest.RouteValues[name] wherename is specified byIFromRouteMetadata.Name or the parameter name ifIFromRouteMetadata.Name is null.
    • IFromBodyMetadata
      • Reads fromHttpRequest.Body(Reader) as JSON usingHttpRequest.ReadFromJsonAsync<{ParameterType}>().
      • Can only be used once per parameter list (there's only one body)
      • Cannot be used in the same parameter list asIFromFormMetadata
      • Will cause requests with an empty body to be rejected without calling the action unlessIFromBodyMetadata.AllowEmpty returns true. (The default interface implementation returns false.)
    • IFromFormMetadata
      • Reads fromHttpRequest.Form[name] wherename is specified byIFromFormMetadata.Name or the parameter name ifIFromFormMetadata.Name is null.
      • Can be used multiple times in a single parameter list (presumably for different names)
      • Cannot be used in the same parameter list asIFromBodyMetadata (there's only one body)
    • IFromHeaderMetadata
      • Reads fromHttpRequest.Headers[name] wherename is specified byIFromHeaderMetadata.Name or the parameter name ifIFromHeaderMetadata.Name is null.
    • IFromQueryMetadata
      • Reads fromHttpRequest.Query[name] wherename is specified byIFromQueryMetadata.Name or the parameter name ifIFromQueryMetadata.Name is null.
    • IFromServiceMetadata
      • Normally resolves viaHttpRequest.RequestServices.GetRequiredService<{ParameterType}>().
      • If the parameter is a nullable reference type (i.e. has theSystem.Runtime.CompilerServices.NullableAttribute), resolve viaHttpRequest.RequestServices.GetService<{ParameterType}>().
      • If the parameter is optional (i.e. has a default value), resolve viaHttpRequest.RequestServices.GetService<{ParameterType}>() ?? parameter.DefaultValue.
  2. If the parameter is a scalar value type that lives in the System namespace, first checkHttpRequest.RouteValues contains an entry for the parameter name. If it does, useHttpRequest.RouteValues[{ParameterName}]. Otherwise, useHttpRequest.Query[{ParameterName}].
    • TODO: Come up with actual list of scalar value types that live in the System namespace.
    • Question: Do we want to allow types to opt-in to this? Today MVC usesTypeConverter which is hard to implement.
    • Alternatives:
      • Something convention-based like the presence of abool TryParse(string, out T) method
      • The explicit implementation of an interface with that method to make it more opt in
  3. IfHttpRequest.RequestServices.GetService<{ParameterType}>() is not null, use that value.
    • TODO: Figure out how to make this work well with compile-time source generation. This might need to be determined at runtime no matter what.
  4. Otherwise, treat the parameter as if it had an attribute implementingIFromBodyMetadata whereIFromBodyMetadata.AllowEmpty is false.

How we will convert to the parameter type.

  1. For parameters bound from the body (has anIFromBodyMetadata attribute or is treated by such by convention), we will continue to assume JSON and initialize the parameter withHttpRequest.ReadFromJsonAsync<{ParameterType}>().
    • We need to figure out if we want make this configurable or force people to read they body themselves if they want configurability. If we decide on configurability, we need to decide on how much.
  2. For all other parameters bound from the request (i.e. not a service or from the body) we need to convert from a string.
    • Since there is a finite list of "scalar value who lives in the System namespace" we'll bind to by convention, we'll use their TryParse methods or equivalent until we decide on something different for those.
    • Parameters explicitly bound by attribute to a string-based source also need to be converted much like those read from theRouteValues orQuery by convention. I doubt we also want to limit these parameter types to a finite list. For now, we'll continue doing what we do today to convert from string as described below.

How we convert to the parameter type today in the "MapAction" APIs

Today, all inputs are converted to their respective parameter types as follows:

  1. For parameters bound from the body, we already callHttpRequest.ReadFromJsonAsync<{ParameterType}>().
  2. All other parameters start asstrings from the various sources listed above.
    1. If{ParameterType} isstring, we're done!
    2. If there's a{ParameterType}.Parse({ValueString}) method, use that.
      • NOTE: Going forward, prefer/requireTryParse instead.
    3. Lastly, tryConvert.ChangeType({ValueString}, typeof{ParameterType}, CultureInfo.InvariantCulture)
      • NOTE: Going forward, we should stop usingCultureInfo.InvariantCulture

Original issue:

  1. Complex type -> FromBody (Seehttps://source.dot.net/#Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelMetadata.cs,606)
  2. Name appears as a route value -> FromRoute
  3. Everything else -> FromQuery

From:#29878 (comment)

New inference rules unique to MapAction:

  1. [FromServices] should work implicitly for types that can be resolved from RequestServices.

Metadata

Metadata

Assignees

Labels

area-minimalIncludes minimal APIs, endpoint filters, parameter binding, request delegate generator etcenhancementThis issue represents an ask for new feature or an enhancement to an existing onefeature-minimal-actionsController-like actions for endpoint routing

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions


    [8]ページ先頭

    ©2009-2025 Movatter.jp