ASP.NET MVC intercepting route handling - asp.net-mvc-4

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. :)

Related

ASP.NET MVC Routing catch all

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"}
);

All requests goes against the same action in Piranha

I've started using Piranha CMS and really enjoining it, but now I came into a bit of trouble.
One of my pages is a contact form where I want to post an extended page model with contact information to the controller.
I've created a page template Contact and in the manager gui and I've set the setting View to Contact
The correct view is loaded but the problem is that all the requests goes against the index action method and not the contact action method in PageController.
What am I doing wrong?
The view is used to signal the controller what view should be used to render the page, not which action should be called. This can be used when several pages has the same type of data and logic, but should be rendered differently.
The field route is used to rewrite a page to a controller/action. The default route for a page is Page which means that requests to that page is rewritten to ~/page, i.e the PageController and its Index action. If you wanted a certain type to be rewritten to the contact action of the PageController you set the route to Page/Contact which will rewrite the request to ~/page/contact.
If you have a complex structure you should add custom controllers, for examples a ProductController. The route could then be set to Product rewriting the request to ~/product.
I hope this clarifies things!
Regards
HÃ¥kan

Using custom route and not allowing default route for specific action

I'm using MVC 4 and am customizing my routes.
I have a Partners action in my About. By default MVC matches the route /About/Partners to this action. I have set up a custom route so that /Partners maps to this action. My question is how do I make it so that /About/Partners no longer works for that action. I don't think I can alter the default route in the route.config file because it is being used by other actions.
Try putting the new route BEFORE the default route

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

how to redirect one area to another area

I have two controllers in my MVC4 Project.
One controller is in default controller name called Login.
another controller is in area .area name called HR.inside controller name called AddNewHire.
inside AddNewHire i written AddNewEmployee method.
in Login controller i am having one method .that name is LoginButton
inside LoginButton method i written
return RedirectToAction("AddNewEmployee","AddNewHire",new {area="HR"});
am getting Error Like
Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
Requested URL: /AddNewHireController/AddNewEmployee
Try using RedirectToRoute instead of RedirectToAction. What you would have to do is to define a route. Have a look at this MSDN link (Walkthrough: Creating an ASP.NET MVC Areas Application Using Multiple Projects