I have an Areas on Net Core App named Admin, on MapSpaFallbackRoute setting on startup, I want to set like this,
app.UseMvc(routes =>
{
routes.MapSpaFallbackRoute(
name: "spa-fallback-admin",
defaults: new { area="Admin", controller = "Home", action = "Index" });
});
is this the correct way to define MapSpaFallbackRoute? I doubt MapSpaFallbackRoute have attributes area,
I have been try this, and my apps return 404(not found).
so, what the correct way to define MapSpaFallbackRoute, I want using HomeController on Admin area, with Index action
It is my complete code, I want to request with path admin, controller on admin areas should be handle that.
app.MapWhen(context => context.Request.Path.Value.StartsWith("/admin"), builder =>
{
builder.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{area=Admin}/{controller=Home}/{action=Index}/{id?}");
routes.MapSpaFallbackRoute(
name: "spa-fallback-admin",
defaults: new { area="Admin", controller = "Home", action = "Index" });
});
});
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
routes.MapSpaFallbackRoute(
name: "spa-fallback",
defaults: new { controller = "Home", action = "Index" });
routes.MapRoute(
name: "areas",
template: "{area:exists}/{controller=Home}/{action=Index}/{id?}");
});
thanks for your help
What MapSpaFallbackRoute does is allows defining default values for route parameters to handle 404 cases.
Now to your question: yes, MVC routing (both attribute/convention) supports {area} as route parameter and so you can write above code to define a default value.
You didn't show your routing setup, so I assume that your main problem is that you haven't specified {area} parameter in your route template.
For example, if consider convention routing, the following should work:
app.UseMvc(routes => {
routes.MapRoute("default", "{area}/{controller}/{action}/{id?}");
routes.MapSpaFallbackRoute(
name: "spa-fallback-admin",
defaults: new { area="Admin", controller = "Home", action = "Index" });
});
For updated question:
Try to use .UseWhen instead of .MapWhen:
app.UseWhen(context => context.Request.Path.Value.StartsWith("/admin"), builder =>
{
after searching for this issue I realize Dotnet core 3 doesn't support MapSpaFallbackRoute method so to fix this problem you should add the Spa package manually use this command on your terminal Dotnet
add package Microsoft.AspNetCore.SpaServices --version 3.1.16
you can check the version at this link
NuGet Gallery
Related
When i'm creating routing in asp.net core 2.2 with companyname and controller. My application shows 404 error for the following code when I hit F5.
app.UseMvc(route =>
{
route.MapRoute("Default", "MyCompany/{controller=Home}/{action=Index}/{id?}");
});
If I enter the full path it is working.
If I remove MyCompany before the controller, It works fine.
Please help me to fix this issue.
Try to configure your routing to:
app.UseMvc(routes =>
{
routes.MapRoute(
name: "startupRoute",
template: "/",
defaults: new { controller = "Home", action = "Index" }) ;
routes.MapRoute(
name: "default",
template: "MyCompany/{controller=Home}/{action=Index}/{id?}");
});
I want to have a URL path pattern like this:
http://example.com/15/232
Both first segment and the second segment are composed of integer values. In case this pattern is not met, I want routing to fallback to the default {controller=Home}/{action=Index} pattern.
How can I achieve this?
What I'd probably do is modify your startup.cs to reflect your new route like this:
app.UseMvc(routes =>
{
routes.MapRoute(
name: "segment",
template: "{segment1:int}/{segment2:int}", //<-- Matches /15/232
defaults: new { controller = "Home", action = "Segment" }
);
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}"
);
}
The new route would just point to a single controller and action, and from there, you return the appropriate View for the content based on the path.
public IActionResult Segment(int segment1, int segment2)
{
return View()
}
I have the following MapRoute definition:
routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
As you can see this exactly same as the official default. In the documentation there is an explanation about defaults:
Default and optional route parameters do not need to be present in the
URL path for a match.
So I created a very simple additional action in the HomeController to test the behavior of defaults:
public String Test()
{
return "Route found";
}
Now I trying to understand why this url is not working: '/Test'
I'm expected if I set default controller value (=Home) then the router will find the action if it was defined in the default controller.
I'm also wondering if there is any difference between this two declaration formats:
routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
routes.MapRoute("default", "{controller}/{action}/{id?}", new { controller = "Home", action = "Index" });
In previous versions of ASP.NET, and using MVC 5, I could set up a route like this in my AreaRegistraion:
context.MapRoute(
"pfrecent",
"Forums/Recent/{page}",
new { controller = ForumController.Name, action = "Recent", page = 1 },
new[] { "PopForums.Controllers" });
This would route /Forums/Recent to the forum controller and its recent action. However, I can't figure out how to make it work in ASP.Net 5/MVC 6. I've added [Area("Forums")] to the controller class, and used this route from the Startup class:
routes.MapRoute(
"pfrecent",
"Forums/Recent/{page}",
new { controller = ForumController.Name, action = "Recent", page = 1 });
routes.MapRoute(
name: "areaRoute",
template: "{area:exists}/{controller=Home}/{action=Index}/{id?}");
However, it resolves to /Forums/Forum/Recent?page=1. The intention is to continue using /Forums/Recent.
We are using this for enabling areas in MVC 6:
// Configure MVC routing
app.UseMvc(routes =>
{
// Areas support
routes.MapRoute(
name: "areaRoute",
template: "{area:exists}/{controller=Home}/{action=Index}/{id?}");
// Default routing
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
The first route is for areas, second is for main content.
On Startup.cs
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
routes.MapRoute(
name: "Business",
template: "{area:exists}/{controller=Home}/{action=Index}/{id?}");
})
on Controller
[Area("Business")]
public class DemoController : Controller
{
public IActionResult Index()
{
return View();
}
}
Place this in your Startup.cs file at the TOP of the routes list:
routes.MapRoute(
name: "forumsAreaRoute",
template: "Forums/{action}/{page?}",
defaults: new {area = "Forums", controller = "Forum", action = "Recent", page = 1});
Your Forum controller should look like this:
[Area("Forums")]
public class ForumController : Controller
{
// GET: /<controller>/
public IActionResult Recent(int? page)
{
// Do action stuff here
}
}
This solution will satisfy a url of http://somedomain.com/Forums/Recent/1 and return the first page.
I hate answering my own questions, but after getting back to this, and looking at source and experimenting, I found that you have to specify the area in the route mapping, as well as the HtmlHelpers (I'm assuming this will be true for tag helpers as well, but I haven't gone that far yet in conversion.) So the route mapping has to look like this:
routes.MapRoute(
"pfrecent",
"Forums/Recent/{page?}",
new { controller = ForumController.Name, action = "Recent", page = 1, Area = "Forums" }
);
The important part is the Area property in the route value object. The HtmlHelper has to look like this, also naming the Area:
#Html.ActionLink(PopForums.Resources.Recent, "Recent", ForumController.Name, new { page = 1, Area = "Forums" }, null)
It causes the URL for the recent page to be /Forums/Recent as expected. As best I can tell, setting routes in a derived AreaRegistration class in MVC5 set the area value on the routes for you. Having [Area("Forums")] on your controller class (which I already had) seems to assume the previous role of area registration.
I'm experimenting setting up a multi-tenant solution in asp.net mvc 4 wherein you are able to specify tenant specific overrides to certain controllers if they require different functionality.
I'd like to have routes that are like
/{Controller}/{Action}/{Id}/
/{Tenant}/{Controller}/{Action}/{Id}
If the tenant isn't specified it should just match the first route.
I have tried
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional });
routes.MapRoute(
name: "Tenant",
url: "{tenant}/{controller}/{action}/{id}",
defaults: new { tenant = "", controller = "Home", action = "Index", id = UrlParameter.Optional });
This works correctly for
/ -> detected as the first route (correct!)
/Home -> detected as
first route (correct!)
/Home/Index -> detected as first route
(correct!)
/Client1/Home/Index - Client1 is detected as controller
name (incorrect)
If I switch the routes around then the tenant route works but the base one does not.
What am I missing here, is it possible to achieve this?
Note, I'd prefer to not have to specify a dummy tenant string in the route as I'll have to translate that back later on in a few places where I need to resolve tenant specific information.
You can use the library I wrote here. This lib allows you to define an alternative route, if the routes conflict. You must define the routes as follows:
var firstRoute = routes.MapReplaceableRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional });
var secoundRoute = routes.MapRoute(
name: "Tenant",
url: "{tenant}/{controller}/{action}/{id}",
defaults: new { tenant = "", controller = "Home", action = "Index", id =
UrlParameter.Optional }, lookupParameters: new string[] {"tenant"}, lookupService: new LookupService());
firstRoute.AlternativeRoute = secondRoute;
For lookupService, you just need an empty implementation of the IRouteValueLookupService.