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
35.46k stars 10.03k forks source link

Blazor Custom Route Constraints #28938

Open GravlLift opened 3 years ago

GravlLift commented 3 years ago

I am trying to use custom route constraint in Blazor, similar to how it currently works for both razor pages and MVC routes:

services.AddRouting(options =>
{
    options.ConstraintMap.Add("customName", typeof(MyCustomConstraint));
});

... but it appears that blazor route constraints do not consider any custom constraints that have been registered:

https://github.com/dotnet/aspnetcore/blob/af7c0cc2a2f944811041b55f9b4e0ae6cc948fd7/src/Components/Components/src/Routing/RouteConstraint.cs#L57-L85

So I instead encounter the ArgumentException, "Unsupported constraint '{constraint}' in route '{template}'.".

It would be ideal if RouteConstraint could be modified to reference RouteOptions.ContraintMap as the other routing engines do. Alternatively, needing to use some Blazor-specific registration method to register constraints only for Blazor would also be acceptable.

ghost commented 3 years ago

We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.

javiercampos commented 3 years ago

Extensible route constraints should be a must (and I thought that was already solved in asp.net ~12/13 years ago). The SetParametersAsync parsing "hack" might work for some very contrived scenarios... but it completely disallows generalization, and even forbids doing certain scenarios without many more hacks...

Just imagine some route like: /users/{id}/{action:createOrEditConstraint} where you want one page to resolve both /create and /edit, but you want other different page to resolve /list (or others). Since you can't have user-defined constraints, /users/{id}/{action} matches both pages and you'll get an error.

Yes, it could be solved by creating -yet another component- and either redirect or include the create/edit component and list component in it, but that's yet another hack, and a ton more of boilerplate (one more component, with all its initialization and parsing per "CRUD" entity in a project).

One more scenario (which I used in razor pages/webapi/MVC a lot) is having short guids as parameters (while internally using Guid). Yes, you can just have a string and parse it on SetParametersAsync, but you can't generalize that (on a base class, for example), because you wouldn't have access to the inherited class parameter, so you basically need to specify the SetParameterAsync method and parse specifically on every single routable view with a short guid parameter (and again, since you can't constraint it -with a regex or something-, you can't distinguish it from other string routes).

Again, nothing that can't be "hacked away", but this is basic, and I'm sure many people (even those not on this thread) would miss this, so I believe affected-few doesn't look like a correct label here, to me.

Tragen commented 3 years ago

After 2 hours of debugging why my ulong constraint isn't working, I stumbled upon this bug. For me it looks like a very basic feature. Please fix this soon. Also ulong and uint should be added to the default constraints.

Alerinos commented 3 years ago

I believe this should be introduced in ASP.NET Core 7

Alerinos commented 2 years ago

@pranavkm I would like to remind you of this, it is quite an important and useful thing.

kyletinsley commented 2 years ago

Regex route constraints would be wonderful. Trying to constrain a string route parameter to a finite list of string values and want to 404 otherwise.

TehGM commented 1 year ago

It'd be super useful if you depend on enum in routes, too. It's a case in my project https://stalcraftclan.com - and currently I have to work it around by grabbing string and manually trying to parse the value. It results in a lot of boilerplate code and is also quite error-prone.

It's supported in other ASP.NET Core areas, I don't see why it couldn't be in Blazor.

haefele commented 1 year ago

This would be really really useful to have, for example when I want to allow just a couple string values (a enum basically). Right now it's very tedious and annoying code to write.

ghost commented 1 year ago

We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.

kcabral817 commented 1 year ago

It appears that folks are tone deaf. This is a requested requirement and now it appears not even 'short' is supported. I fail to understand why foundational issues like this keep getting put to the back burner.

akhozov commented 1 year ago

Hello, I've faced with the same situation. I need to customize routing constraint and have no ways to do this. Is it possible to up priority of this feature request?

Tragen commented 1 year ago

This ticket is nearly 3 years old and a very basic feature. I wouldn't bet they will fix this anytime soon.

ghost commented 10 months ago

We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.

StephenWBertrand commented 9 months ago

yep for sure would like this feature. Looking to be able to have locale codes embedded into urls as way to support direct links for desired languages etc.

domain.com/{locale?}/myPage domain.com/myPage
domain.com/en-US/myPage domain.com/es-US/myPage

ax-meyer commented 7 months ago

I just spent a few hours trying to figure out why my constraint doesn't work... at least now I know.

But please, support such a basic feature. I am very suprised it is not supported for blazor.

AndreyZ1 commented 4 months ago

here is working solution for ulong data type, works fine:

Route constraint:

public class UlongRouteConstraint : IRouteConstraint
{
    public static string UlongRouteConstraintName = "ulong";

    public bool Match(HttpContext? httpContext, IRouter? route, string routeKey, RouteValueDictionary values,
        RouteDirection routeDirection)
    {
        if (routeKey == null)
        {
            throw new ArgumentNullException(nameof(routeKey));
        }

        if (values == null)
        {
            throw new ArgumentNullException(nameof(values));
        }

        if (!values.TryGetValue(routeKey, out var routeValue) || routeValue == null)
        {
            return false;
        }
        if (routeValue is ulong)
        {
            return true;
        }

        var valueString = Convert.ToString(routeValue, CultureInfo.InvariantCulture);
        var parsed = ulong.TryParse(valueString, out var value);
        if (parsed)
        {
            values[routeKey] = value;
        }

        return parsed;
    }
}

Register:

builder.Services.Configure<RouteOptions>(options =>
{
    options.ConstraintMap.Add(UlongRouteConstraint.UlongRouteConstraintName, typeof(UlongRouteConstraint));
});

Use:

@page "/user/servers/{ServerId:ulong}/{ProductId:ulong}/details"

...

[Parameter, EditorRequired]
public ulong ServerId { get; set; }

[Parameter, EditorRequired]
public ulong ProductId { get; set; }