dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
34.95k stars 9.87k forks source link

Can't use custom parsers with [SupplyParameterFromQuery] #56662

Open giovinazzo-kevin opened 4 weeks ago

giovinazzo-kevin commented 4 weeks ago

Is there an existing issue for this?

Describe the bug

One nice property of the [FromQuery] attribute in the context of API routes is that it allows custom deserialization by way of implementing a static TryParse method on the receiving type.

So if I have a class Foo and I define:

public class Foo {
    public static bool TryParse(string queryString, out Foo parsed) 
    {
        // ...
    }
}

Then I will be able to declare any parameter used by my controllers and minimal API routes as being of type Foo:

public async Task<Baz> Bar([FromQuery] Foo? foo = default) 
{
    // ...
}

This, however, does not seem to be the case for Blazor. If I do the same by using [SupplyParameterFromQuery], then I will be met with the following error:

Querystring values cannot be parsed as type 'Foo'.

According to the official documentation:

Component parameters supplied from the query string support the following types:

bool, DateTime, decimal, double, float, Guid, int, long, string. Nullable variants of the preceding types. Arrays of the preceding types, whether they're nullable or not nullable.

I wonder why there is such a difference between implementations, and if there is a recommended work-around that maintains type safety and handles parsing failures gracefully -- short of defining the parameters as string properties and handling the parsing logic in their set method.

As far as a controller is concerned, parsing failures are treated as 400 errors. I imagine that there would be some additional considerations when it comes to component parameters which might shed some light on why the implementations diverge.

Expected Behavior

The parameters supplied by the query string are parsed by convention depending on their declared type, with parsing failures that don't throw either being handled as errors or simply ignored, maybe depending on a property on the attribute itself.

Steps To Reproduce

  1. Create a custom type that implements the aforementioned TryParse.
  2. Use it in conjunction with [FromQuery] in a controller or minimal API route: it works.
  3. Use it in conjunction with [SupplyParameterFromQuery] in a Blazor component or page: it doesn't work.

Exceptions (if any)

InvalidOperationException: Querystring values cannot be parsed as type 'Foo'.

.NET Version

8.0.300

Anything else?

https://learn.microsoft.com/en-us/aspnet/core/blazor/fundamentals/routing?view=aspnetcore-8.0

javiercn commented 4 weeks ago

@giovinazzo-kevin thanks for contacting us.

This is not a feature that Blazor has. We might in the future implement support for IParsable<T> if we see enough demand for it.