Skip to content

Minimal API : Converting empty string to Nullable (ex: int?) with [FromForm] binding #55202

Closed
@JimmyLahaie

Description

@JimmyLahaie

Is there an existing issue for this?

  • I have searched the existing issues

Is your feature request related to a problem? Please describe the problem.

From a Minimal API project

With the HTML form

<form method="post" action="/SomeUrl">
<input type="text" name="someProp" />
<button type="submit">OK</button>
</form>

And Mapping
app.MapPost("/SomeUrl", ([FromForm] SomeModel theInputModel) => Results.Ok());

And Model

public class SomeModel
{
    public int? SomeProp { get; set; }
}

If I enter a number in "SomeProp" input field, it works ok.
But if I leave "SomeProp" input field empty and the submit the form, I get the exception:

Microsoft.AspNetCore.Http.BadHttpRequestException: The value '' is not valid for 'SomeProp'.

 ---> Microsoft.AspNetCore.Components.Endpoints.FormMapping.FormDataMappingException: An error occurred while trying to map a value from form data. For more details, see the 'Error' property and the 'InnerException' property.

        at Microsoft.AspNetCore.Components.Endpoints.FormMapping.FormDataReader.AddMappingError(Exception exception, String attemptedValue)

        at Microsoft.AspNetCore.Components.Endpoints.FormMapping.CompiledComplexTypeConverter`1.TryRead(FormDataReader& context, Type type, FormDataMapperOptions options, T& result, Boolean& found)

        at Microsoft.AspNetCore.Components.Endpoints.FormMapping.FormDataMapper.Map[T](FormDataReader reader, FormDataMapperOptions options)

        at lambda_method280(Closure, Object, HttpContext, Object)

        --- End of inner exception stack trace ---

        at Microsoft.AspNetCore.Http.RequestDelegateFactory.Log.FormDataMappingFailed(HttpContext httpContext, String parameterTypeName, String parameterName, FormDataMappingException exception, Boolean shouldThrow)

        at lambda_method280(Closure, Object, HttpContext, Object)

        at Microsoft.AspNetCore.Http.RequestDelegateFactory.<>c__DisplayClass104_2.<<HandleRequestBodyAndCompileRequestDelegateForForm>b__2>d.MoveNext()

     --- End of stack trace from previous location ---

That is because the request sent to the server when posting the form is a POST with content :
someProp=

The only workaroung I found is using a string instead of int? and then convert string to int? by myself which is not the best solution.

Describe the solution you'd like

When binding [FromForm], I beleive that Minimal API should convert empty string to null when converting to a Nullable type (ex int?).
Or at least give any option to do so.

Additional context

No response

Activity

ghost added
needs-area-labelUsed by the dotnet-issue-labeler to label those issues which couldn't be triaged automatically
on Apr 18, 2024
KennethHoff

KennethHoff commented on Apr 18, 2024

@KennethHoff

I've also experienced this issue. I "fixed" it by updating my frontend to delete all empty fields before sending it to the backend.

added
area-minimalIncludes minimal APIs, endpoint filters, parameter binding, request delegate generator etc
and removed
needs-area-labelUsed by the dotnet-issue-labeler to label those issues which couldn't be triaged automatically
on Apr 18, 2024
captainsafia

captainsafia commented on Apr 26, 2024

@captainsafia
Member

The form binding behavior that minimal APIs uses is shared with Blazor. I'm open to changing this behavior to be more inline with how empty strings are handled elsewhere in minimal APIs (and in forms in MVC).

@javiercn Any objections to modifying the form binding behavior for empty strings here?

added this to the Backlog milestone on Apr 30, 2024
removed their assignment
on Apr 30, 2024
dimenus

dimenus commented on Aug 6, 2024

@dimenus

@captainsafia I have this same issue with [FromQuery] as well with e.g. Nullable<long>. It works just fine when the parameter is omitted, but if the clients sends the query parameter with an empty value, the validation fails.

curl 'http://localhost:5209/proui/field?uiCodeTypeId='

Microsoft.AspNetCore.Http.BadHttpRequestException: Failed to bind parameter "Nullable<long> uiCodeTypeId" from "".
   at lambda_method34(Closure, Object, HttpContext)
   at Microsoft.AspNetCore.HttpsPolicy.HttpsRedirectionMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
   at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
   at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)
dcernach

dcernach commented on Aug 6, 2024

@dcernach

@captainsafia I'm also experiencing issues with [AsParameters] and all Nullable primitive types. This is causing significant problems. As a workaround, I've implemented an Axios interceptor to remove empty, null, and undefined values, but some of our customers are unhappy with this solution. I've tried other approaches, including custom JSON converters, without success. Is there a plan to improve Minimal API model binding to match the behavior of MVC Model Binder?

If anyone's interested, here's my Axios interceptor:

const $http = axios.create({
    baseURL: '/your-endpoint'
}); 

function cleanObject(obj) {
    for (let propName in obj) {
        if (Object.prototype.hasOwnProperty.call(obj, propName)) {
            if (obj[propName] === null || obj[propName] === undefined || obj[propName] === '') {
                delete obj[propName];
            }
        }
    }
    return obj;
}

$http.interceptors.request.use((req) => {
    if (req.data) req.data = cleanObject(req.data);
    if (req.params) req.params = cleanObject(req.params);
    return req;
});
dcernach

dcernach commented on Aug 6, 2024

@dcernach

The form binding behavior that minimal APIs uses is shared with Blazor. I'm open to changing this behavior to be more inline with how empty strings are handled elsewhere in minimal APIs (and in forms in MVC).

@javiercn Any objections to modifying the form binding behavior for empty strings here?

Please do it :)

SebastianToet

SebastianToet commented on Sep 26, 2024

@SebastianToet

This is still a big issue in Blazor SSR in the current .NET 9 preview: When a [SupplyParameterFromForm] model contains a nullable int (or double, etc.), an empty input value results in a form-binding validation error (and not in a null value without an error, as you would expect).

xxnickles

xxnickles commented on Dec 7, 2024

@xxnickles

Unfortunatelly it seems few people are using minimal api and form binding as this issue is not getting traction. I just found out this behavior also impacts nullable enumeration bidding, which fails with the same error. I will assume the workaround is going to be not include the fields from the front end, but the behavior should match other areas of aspnet, in concrete I am talking about SupplyParameterFromForm from Blazor SSR, which this scenario works fine (at least with enumerations)

added
Priority:2Work that is important, but not critical for the release
on Jan 13, 2025
jamie-nzfunds

jamie-nzfunds commented on Jan 13, 2025

@jamie-nzfunds

Just ran into this issue too. It would be great to have a fix for this.

captainsafia

captainsafia commented on Jan 14, 2025

@captainsafia
Member

There's been some recent action on a PR to fix this over at #52499.

ndjonbor

ndjonbor commented on Jan 22, 2025

@ndjonbor

@captainsafia The PR you referenced seems to be specific to binding from forms. Are there any plans on the similar issue when binding from queries? I'm facing the same problem as mentioned by dimenus:

@captainsafia I have this same issue with [FromQuery] as well with e.g. Nullable<long>. It works just fine when the parameter is omitted, but if the clients sends the query parameter with an empty value, the validation fails.

curl 'http://localhost:5209/proui/field?uiCodeTypeId='

Microsoft.AspNetCore.Http.BadHttpRequestException: Failed to bind parameter "Nullable<long> uiCodeTypeId" from "".
   at lambda_method34(Closure, Object, HttpContext)
   at Microsoft.AspNetCore.HttpsPolicy.HttpsRedirectionMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
   at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
   at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)

In my case the parameter is a strongly typed ID which implements IParsable, and the parameter is nullable. I've had no luck with handling this particular scenario

javiercn

javiercn commented on Feb 12, 2025

@javiercn
Member

We merged a community contribution for this:
#52499

But we still want to limit the change to a well-known subset of types.

removed
Priority:2Work that is important, but not critical for the release
on Feb 19, 2025
lewing

lewing commented on Feb 20, 2025

@lewing
Member

fixed in #60498

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area-blazorIncludes: Blazor, Razor Componentsarea-minimalIncludes minimal APIs, endpoint filters, parameter binding, request delegate generator etcfeature-blazor-form-validationThis issue is related to forms validation in Blazor

Type

Projects

No projects

Relationships

None yet

    Development

    No branches or pull requests

      Participants

      @lewing@halter73@JimmyLahaie@captainsafia@danroth27

      Issue actions

        Minimal API : Converting empty string to Nullable (ex: int?) with [FromForm] binding · Issue #55202 · dotnet/aspnetcore