ASP.NET MVC Routing catch all - asp.net-core

I'm using ASP.NET Core MVC and using attribute routing in my controllers.
In my Configure method in Startup.cs I currently call app.UseMvc() to start my MVC application.
Everything works as expected.
Now I'm trying to get a catchall going, but the 404 always gets the best of the situation.
I changed my app.UseMvc to the following:
app.UseMvc(routes =>
{
routes.MapRoute("Default",
"{*catchall}",
new { controller = "Index", action = "Index" },
new { catchall = #"^(.*)?$" });
});
but no dice.
I even tried to remove the catchall regular express as well, but I still get forwarded to my 404 page.
Any help is appreciated!

For anyone having the same problem, Tom Droste pushed me into the right direction
Adding a conventional route and using attribute routing has subtle side effects
The catch-all route was added first in the route dictionary and the attribute routes are added afterwards.
The AttributeRouting class just creates an instance of AttributeRoute which is an IRouter responsible for building the attribute routes. This is done on the first time AttributeRoute is invoked
Having that, the catchall was thus never called because it's not the last route.
putting everything back into conventional routing fixed the problem.
I suggest reading https://luisfsgoncalves.wordpress.com/2015/08/18/asp-net-5-routing-part-ii/ to understand how attribute routing works

Have you tried this?
routes.MapRoute(
"Default",
"{*.}",
new { controller = "Home", action = "Index" }
);

In your Startup.cs file, place this line of code just above app.UseMvc() in the Configure() Method. Obviously you can redirect to whatever page you want.
app.UseStatusCodePagesWithRedirects("~/Home/Index");
EDIT:
Per you comment, as far as I know, you'd have to write your own middleware to redirect and keep the original url/query parameters. If you're not familiar with developing middleware, I posted a demo project on GitHub that demonstrates how to develop middleware in three easy steps. You can download the project here.

So if I understand you correctly you just want a route that will be the one when the rest isn't matched. In my knowledge there are atm two ways to fix this. The correct one would be to write some routing middleware, however the dirty solution is to create a route with all nullable arguments that will be matched as last.
routes.MapRoute(
"DirtyRoutingSolution",
"{notUsed?}/{notUsedTwo?}/{notUsedThree?}/{notUsedFour?}",
new { controller = "Home", action = "Index"}
);

Related

Route Override not working in asp.net core 3.1 razor pages

I'm using Asp.Net Core 3.1 Razor pages. I need to override the the route for one of the page in my area.
I have Home page in my Area - Blog and the current route is localhost/blog/home. I need to change this to localhost/blog. I have an Index page in the same blog area but it has an route parameter. So it will be localhost/blog/my-blog-name. And this will not interfere with localhost/blog
I added the setting in ConfigureServices in startup.cs
services
.AddRazorPagesOptions(options =>
{
options.Conventions.AddAreaPageRoute("Blog", "/", "/blog/home");
});
Here is my folder structure,
But when i navigate to localhost/blog I get an 404 not found. Please assist on where I'm wrong.
I have Home page in my Area - Blog and the current route is localhost/blog/home. I need to change this to localhost/blog. I have an Index page in the same blog area but it has an route parameter.
when i navigate to localhost/blog I get an 404 not found.
If you check the definition of AddAreaPageRoute method, you can find it takes the name of the area, the name of the page, and the route template, like below.
.AddAreaPageRoute("{area_name_here}", "{page_name_here}", "{route_here}")
Based on your requirement and code, we can find you do not configure the specified route to the page correctly, and if your Index page of Blog area accepts a required (not optional) route parameter, which would cause 404 error while you browse localhost/blog.
To fix the issue and achieve the requirement, you can try modify the code like below.
services.AddRazorPages()
.AddRazorPagesOptions(
options =>
{
options.Conventions.AddAreaPageRoute("Blog", "/home", "/blog");
}
);
Test Result

Hook up Auth0AccountController in Umbraco 7

Has anyone successfully integrated Auth0 with Umbraco 7 for member (front-end public users, not CMS back-end users) authentication?
I've successfully integrated with owin startup and dealing with signin-auth0 response. However I'm stuck on hooking up the Auth0AccountController to work with Umbraco (I'm getting a 404). Any suggestions?
I've tried adding ~/Auth0Account to the "umbracoReservedPaths" appSetting, but I just get a slightly different looking 404 (not controlled by Umbraco by looks of it).
I've also tried mapping the route in Startup.cs using
RouteTable.Routes.MapRoute(
"Auth0Account",
"Auth0Account/{action}",
new
{
controller = "Auth0Account"
}
);
but that results in a "No route in the route table matches the supplied values" error.
Any ideas?
Mapping the Auth0Account route in Startup.cs was correct:
RouteTable.Routes.MapRoute(
"Auth0Account",
"Auth0Account/{action}",
new
{
controller = "Auth0Account"
}
);
Turns out my problem was with the default redirect RedirectToLocal method in the Auth0AccountController controller. It was doing a
return RedirectToAction("Index", "Home");
which I didn't have a controller hooked up for. I replaced this with an Umbraco compatible redirect instead.
Also, instead of Auth0AccountController inheriting from Controller it might be useful to inherit from Umbraco.Web.Mvc.SurfaceController or Umbraco.Web.Mvc.RenderMvcController to expose useful Umbraco methods to the code.

ASP.NET MVC 4 - Is there a way to shorten URLs?

Is there a way using routes in mvc to shorten the url? I'm fairly new to MVC, and I guess I don't quite yet understand what routes.IgnoreRoute()does fully.
So for the sake of example, using routes could I make this,
site.com/webFolder/controller/action
look like,
site.com/controller?
Also if it helps we're currently using IIS7. Thx all.
Yes you can create custom routes. Take a look at this:
http://www.asp.net/mvc/overview/older-versions-1/controllers-and-routing/creating-custom-routes-cs
In the example given a route of /Archive/{entryDate} was created using
routes.MapRoute(
"Blog", // Route name
"Archive/{entryDate}", // URL with parameters
new { controller = "Archive", action = "Entry" } // Parameter defaults
);

ASP.NET MVC intercepting route handling

So I am facing this little problem. In my route config I have configured two routes. One default route, which handles controller/action request and one custom route which is basically website.com/my_route where my_route is received by some controller's action as an argument. the problem is that whenever I want to give that action a parameter which contains a '/' in it, the route handler resolves request to controller/action route config, so if looks like this website.com/my_route/my_subroute, you get what happens. the my_routeController is searched and of course it does not exist, now the number of '/' in url can be more than one as you see and I want to do such thing. if the appropriate controller with appropriate action does not exist I want this request to be handled but that one controller which's action will recieve my_route/my_subroute as an argument. What is the best practice in this situation. If need I can provide the route config.
Try following way in your route.config
routes.MapRoute(
"my_route",
"my_subroute/x/y/z",
new { controller = "controllername", action = "actionname" }
);
Let me know if this fixed your issue. :)

How do I set push-state in durandaljs 2.0 the works on refresh?

I'm using durandaljs 2.0. I've installed the durandal starter-kit as suggested and explained here. In the shell I'm returning router.activate({ pushState: true } ); as explained in the relevant documentation (see the bottom of the page).
Happily, the URL is indeed in a 'push state' format, e.g. http://localhost:61285/flickr - the problem is that when I refresh the page I get a 404 error telling me "the resource cannot be found". If I set push-state to false ({pushState: false} above) I get a hashed URL, e.g. http://localhost:61285/#flickr - and now a refresh does work. So, how do I set up a push state mode in durandaljs 2.0 that will work with refresh?
Thanks,
Elior
Maybe to late...but
just change the routes config.
simple as this :
routes.MapRoute(
name: "Default",
url: "{*url}",
defaults: new { controller = "Home", action = "Index" }
);
When you refresh the page, the browser will make a request to the server with that URL http://localhost:61285/flickr.
What's probably happening is that if you are using ASP.NET MVC, the server is trying to locate a Controller called flickr and it throws an exception because obviously there isn't any resource with that name.
In order to get rid of this exception you should configure the server to serve the same HTML of the APP but for unknown URL's. This can be achieved using IIS URL Rewrite in ASP.NET.
So after setting up properly the server, by requesting an unknown URL it would return the initial view for the app plus whatever you pass in the query string parameters so the router can do its job at client side.
In this blog post you will find more information about how to configure ASP.NET to handle this scenarios. In the article the author uses AngularJS, however it will be the same for Durandal.
RainerAtSpirit and margabit, you're both right, thank you. Here is how I implemented the server side:
First I should note that all the interaction with the server is done via WebApi controllers.
so, for example, if the URL is:
http://localhost:61285/home/category2/subCategory22 (for a localhost), the server tries to look for a controller called 'home' and an action in it called 'category2'. Since there's no such action, I get a 404 error.
What I wanted is that the server WILL call the 'home' controller, but send the rest of the URL as parameters to the client. My solution was to add a hash after the controller's name, so that the URL will look like this: http://localhost:61285/home/#/category2/subCategory22. If this would happen then the client will take care of the hashed part with no 404 error.
For this to happen:
I added the following to 'web.config':
<customErrors mode="On" defaultRedirect="Error">
<error statusCode="404" redirect="Error" />
</customErrors>
Then I create a controller named 'ErrorController' with the following class in it:
public class ErrorController : ApiController
{
[HttpGet, HttpPost, HttpPut, HttpDelete, HttpHead, HttpOptions, AcceptVerbs("PATCH"), AllowAnonymous]
public HttpResponseMessage Handle404()
{
string [] parts = Request.RequestUri.OriginalString.Split(new[] { '?' }, StringSplitOptions.RemoveEmptyEntries);
string parameters = parts[ 1 ].Replace("aspxerrorpath=","");
var response = Request.CreateResponse(HttpStatusCode.Redirect);
response.Headers.Location = new Uri(parts[0].Replace("Error","") + string.Format("#{0}", parameters));
return response;
}
}
what happens is that when the server get a URL with no relevant action as I mentioned above, it redirects it to this controller in the following format: http://localhost:61285/Error?aspxerrorpath=home/category2/subCategory22
as you can see, I manipulate this to add the hash and remove the unnecessary info: http://localhost:61285/home/#/category2/subCategory22 and the redirect the server to the 'home' controller.
You might wonder why I do all of this - the reason is that Durandal, a wonderful platform, enables me to use push state, but in order for that to happen I have to work-around the server getting a non-hashed URL and pass it to the client despite the fact there's no relevant controller/action; Durandal get's a hashed URL but removes the hash automatically and the user eventually sees a hash-less URL while Durandal provides all the necessary push state functionality.
Elior