Skip to content
This repository was archived by the owner on Apr 8, 2020. It is now read-only.

Purpose of MapSpaFallbackRoute #973

Closed
im1dermike opened this issue May 24, 2017 · 11 comments
Closed

Purpose of MapSpaFallbackRoute #973

im1dermike opened this issue May 24, 2017 · 11 comments

Comments

@im1dermike
Copy link

im1dermike commented May 24, 2017

What is the purpose of the following code which is automatically loaded to the Startup class with this project:

routes.MapSpaFallbackRoute(
    name: "spa-fallback",
    defaults: new { controller = "Home", action = "Index" });

This results in a 200 being thrown when a non-existent API endpoint is hit instead of a 404.

@MarkPieszak
Copy link
Contributor

MarkPieszak commented May 24, 2017

It's for when you want to handle the 404 within your front-end application (and as noted below, let all Routes go through so your front-end can handle them)

@im1dermike
Copy link
Author

im1dermike commented May 24, 2017

@MarkPieszak My use case - which I assume is very common - is to want to handle bad angular routes in the front-end (by either sending to a "404" routes or just loading a "home" route), but throw 404s on bad API calls (that is, requests whose URL follows a certain pattern eg. "/api").

Can you give me a recommendation?

@MarkPieszak
Copy link
Contributor

You want to use a mapWhen looking for something that starts with /api, use this below and you'll be all set:

           // this part you already have
           app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });

            // here you can see we make sure it doesn't start with /api, if it does, it'll 404 within .NET if it can't be found
            app.MapWhen(x => !x.Request.Path.Value.StartsWith("/api"), builder =>
            {
                builder.UseMvc(routes =>
                {
                    routes.MapSpaFallbackRoute(
                        name: "spa-fallback",
                        defaults: new { controller = "Home", action = "Index" });
                });
            });

Hope that helps!

@SteveSandersonMS
Copy link
Member

Thanks @MarkPieszak for the answer. If this becomes a common request, we could add a further excludePrefix option onto MapSpaFallbackRoute so you can set it to api.

@SteveSandersonMS
Copy link
Member

SteveSandersonMS commented May 24, 2017

Also:

It's for when you want to handle the 404 within your front-end application.

That's not the whole story. It's mostly just so that all URLs that might be handled by your front-end application cause the front-end application to be returned. For example, a request for the URL /counter (in the default template) should cause the front-end application to be loaded, which will then display a suitable UI. If you didn't have MapSpaFallbackRoute then the server would just return a 404 for /counter since there's no matching MVC controller.

@im1dermike
Copy link
Author

@MarkPieszak Perfect. Your solution works as desired.

Fantastic responsiveness as usual.

@ADefWebserver
Copy link

If you didn't have MapSpaFallbackRoute then the server would just return a 404 for /counter since there's no matching MVC controller.

So umm yeah, this is REALLY an important point that I hope does not get lost :)

Meaning. I can send someone a url like this:

http://helloworlddata.azurewebsites.net/counter

..and it works even though there is really no /counter page. It exists only as an Angular route :)

@MarkPieszak
Copy link
Contributor

That's not the whole story. It's mostly just so that all URLs that might be handled by your front-end application cause the front-end application to be returned. For example, a request for the URL /counter (in the default template) should cause the front-end application to be loaded, which will then display a suitable UI. If you didn't have MapSpaFallbackRoute then the server would just return a 404 for /counter since there's no matching MVC controller.

Yes apologies I should of mentioned that! @SteveSandersonMS

@buvinghausen
Copy link

buvinghausen commented Sep 9, 2017

For anyone who wants to use ASP.NET Razor Pages that came out with .NET Core 2.0 I never could get map fallback route to work so I pivoted and went a different direction which implements @MarkPieszak 's solution of only routing all requests to the SPA when the route doesn't start with API.

public void ConfigureServices(IServiceCollection services) =>
  services
    .AddMvc()
    .AddRazorPagesOptions(options =>
    {
      options.Conventions.AddPageRoute("/Index", "{*url:regex(^(?!api).*$)}");
    });

@pholly
Copy link

pholly commented Oct 25, 2017

@buvinghausen That works well. Just be aware that every request that doesn't match a static file will get routed to your SPA - even requests with file extensions. MapSpaFallbackRoute does not match requests that look like filenames - that is, have an extension at the end.

Edit: I just realize you do account for periods in the request - but I'll leave my comment here just in case it helps others. Thanks!

Edit2: Just opened an issue with https://github.com/aspnet/JavaScriptServices with a suggestion: #1354

@ripasfilqadar
Copy link

 app.UseMvc(routes =>
                {
                    routes.MapSpaFallbackRoute(
                    name: "spa-fallback-admin",
                    defaults: new { area="Admin", controller = "Home", action = "Index" });
                });

is this the correct way to using controller from some areas?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants