unosquare / embedio

A tiny, cross-platform, module based web server for .NET
http://unosquare.github.io/embedio
Other
1.47k stars 176 forks source link

Use base routes with route handlers (was: Wildcards are not working?) #432

Open Temtaime opened 4 years ago

Temtaime commented 4 years ago

I have a WebApiController with [Route(HttpVerbs.Any, "/*")] registered as .WithWebApi("/someurl", m =>m .WithController<MainController>()).

The problem that it never gets called.

The server returns 404.

Any solution? How can i register an endpoint that is called when no route is found? I have an undetermined url and it cannot be processed with built-in Route attribute. I cannot catch 404 exceptions because they're costly and it is not a right way to handle this case.

Currently i'm forced to have OnGet and catch all the requests.

Also is there a way to pass custom regex as route?

geoperez commented 4 years ago

The wildcard support was dropped in v3, you can set only Regex routes.

What kind of URLs are you expecting?

/someurl /someurl/1 /someurl/1/2 ... and so on?

Temtaime commented 4 years ago

Hello. Thanks for a reply. Yes, this kind.

k3z0 commented 4 years ago

Hi @rdeago

Regarding this issue, it would be a good option to have some sort of wildcards for routing or allow custom regex routes. I tried using a custom regex string but the parsing code escapes the characters or segments the routes in an unexpected way (because of the '/' char).

rdeago commented 4 years ago

"Regex routes" is a somewhat misleading definition. EmbedIO uses regular expressions to match routes (which is an implementation detail), not to define them.

@Temtaime's use case is a nice example of 99.9% of the use cases for wildcards in routes. It is also something that the current routing code already does pretty well...

...except it doesn't. Not until we have a BaseRouteAttribute alongside RouteAttribute, and RouteResolverBase<TData> can also resolve base routes. Then a WEB Api controller method may look like this:

[BaseRoute(HttpVerbs.Get, "/someurl/")] // A base route must end in '/'
public async string SomeMethod()
    => Route.SubPath switch
    {
        "/1" => "one", // /path_to_webapimodule/someurl/1
        "/2" => "two", // /path_to_webapimodule/someurl/2
        _ => "Unknown"
    };

[BaseRoute(HttpVerbs.Get, "/otherurl/{id}/")]
public async string SomeMethod(int id)
    => Route.SubPath switch
    {
        "/1" => $"one: {id}", // /path_to_webapimodule/otherurl/{id}/1
        "/2" => $"two: {id}", // /path_to_webapimodule/otherurl/{id}/2
        _ => "Unknown"
    };

(The WebApiController.Route property already exists, but its SubPath property is currently of no use.)

As you can see, route parameters can still be used. (An oft-forgotten fact is that even module base routes are parametric: you can find the parsed parameter values, as well as the matched and remaining parts of the URL path, in an HTTP context's Route property.)

@geoperez @k3z0 if the above makes sense to you there can be a PR ready in a couple days, adding base route support inside routing modules.

geoperez commented 4 years ago

That is a really nice approach, I like it!