ASP.Net MVC Routing issue with Html.BeginForm - asp.net-mvc

Using MVC, I have an html form helper in my view:
using (Html.BeginForm("ActionOne", "ControllerOne")) ...
Using the default route, the output for the action attribute is as expected:
<form action="/ControllerOne/ActionOne" ...
But registrering a new route with seemingly no matches affects the output.
Routing code:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.Add("testRoute", new Route("MyUrl", new MvcRouteHandler()));
routes.MapRoute("Default", "{controller}/{action}", new { controller = "Home", action = "Index"});
}
Output:
<form action="/MyUrl?action=ActionOne&controller=ControllerOne"
Is this by design or am I mising something fundamental?
Cheers!

I have experienced this exact problem. I'm not sure exactly why the System.Web.Mvc.HtmlHelper seems to just use the first non-ignore route in the routetable to generate links etc from but I have found a workaround for the "BeginForm" issue.
If you have named your "Default" route in the Global.asax.cs, for example:
routes.MapRoute("Default", "{controller}/{action}", new {controller = "Home", action = "Index" });
Then you can use the Html.BeginFormRoute method and call the name of the "Default" MVC route, then name the controller and action specifically, resulting in the correct url:
using (Html.BeginRouteForm("Default", new { controller="YourController", action = "YourFormAction" })) { }
HTH

Try this
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.Add("testRoute", new Route("MyUrl/***{action}/{controller}***", new MvcRouteHandler()));
routes.MapRoute("Default", "{controller}/{action}", new { controller = "Home", action = "Index"});
}
I think it should solve your problem.

Add this before default route
routes.MapRoute("", "ControllerOne/ActionOne", new { controller = "ControllerOne", action = "ActionOneOne"});

Related

Routing in MVC not finding the new url

I Am not understanding this concept, so after doing a manual and read a few articles I decide to ask you all.
I want to change, just for testing, from:
localhost/Home/List
To:
localhost/Custom/List
So my:
RouteConfig.cs
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute("Custom", "Custom/List/",
new
{
Controller = "Home",
Action = "List"
});
}
But is is not working. The first url still working but the second one is not finding anything.
Thanks
Routes are matched in order and your Default route matches any url with between zero to 3 segments, so ../Custom/List calls the List() method of CustomController.
You need to change the order of your routes so that the Custom is before the DefaultRoute. ../Custom/List will then match that route first and go to the List() method of HomeController

How can I get my asp.net MVC routing to use a default action within a sub-folder?

I have an ASP.Net MVC app where I need to place a certain section of code in a sub-folder named web.
I would like for the user to be able to simply type "http://www.mywebsite.com/web/mycontroller" and have it default to the action of index.
However, I can't seem to figure out how to set up my routing to default the action. From what I can tell, it's trying to use the controller = web, action = mycontroller.
My route code looks like this:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"web", "web/{controller}/{action}",
new { action = "Index" });
}
The request works fine as long as I include the /index on the end of my URL, but it doesn't seem to want to use the action = "Index" default if I exclude it.
How can I accomplish this?
Change your code as follows:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "web",
url: "web/{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
I ended up using Areas, and this has fixed my problem.

ASP.Net MVC Redirect Specific Routes to External Site

I have an nicely functioning ASP.Net MVC site using the simple standard routing scheme:
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" }
);
My client would like to redirect the static pages to a secondary site, so that they can edit them, template-style, at will. The pages that actually do something will remain on the original site.
What I need to do is set up routes for my functional views/controller-actions and redirect the remaining urls to the external site regardless of whether or not the specified url has a matching controller/action. I don't want to mess with the existing code, but use routing to execute some of the pages and redirect from others.
For example:
mysite.com/sponsors/signup would be executed
mysite.com/sponsors/information would be redirected
Even though the sponsors controller contains actions for both signup and information and there are existing views for both signup and information.
So far, I have been unable to wrap my head around a way to do this.
Any ideas?
You can use attribute routing to make it easier.
Your RouteConfig will look like below:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapMvcAttributeRoutes(); // enable attribute routing
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" }
);
}
}
Then you can add an action like below:
public class SponsorsController : Controller
{
[Route("sponsors/information")]
public ActionResult RedirectInformation()
{
return RedirectPermanent("http://yoururl.com");
}
}
EDIT ONE
If you don't want to use attribute routing, you are still going to need the action but your RouteConfig will look like below:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
//The order is important here
routes.MapRoute(
name: "redirectRoute",
url: "sponsors/information",
defaults: new { controller = "Home", action = "RedirectToInformation"}
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
In routing like this, if the match is found the rest of the routes are ignored. So, you'd want to put most specific route on top and most general in the bottom
EDIT TWO (based on the comment)
You can put a simple appsettings in Web.config like below:
<appSettings>
<add key="UseAttributeRouting" value="true" />
</appSettings>
Then in RegisterRoutes you can read it like below and make the decision.
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
if (Convert.ToBoolean(ConfigurationManager.AppSettings["UseAttributeRouting"]))
{
routes.MapMvcAttributeRoutes();
}
else
{
routes.MapRoute(
name: "redirectRoute",
url: "sponsors/information",
defaults: new {controller = "Home", action = "RedirectToInformation"}
);
}
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
The browser sometimes caches these redirects, so you may want to recommend clearing browser caches if you change these settings. Check this superuser post for clearing the cache for Chrome.
You have two options
i) This is perfect use case to write a custom mvchandler that is instatiated by a custom IRoutehandler. You can follow this example.
http://www.eworldui.net/blog/post/2008/04/aspnet-mvc---legacy-url-routing.aspx.
ii) You can write HttpHandler for these matching paths you can redirect them to the other site.
Step 1: add this to RouteConfig.cs
routes.IgnoreRoute("yourwebpage.aspx");
Step 2: create new file at root of website called "yourwebpage.aspx"
Step3: Inside yourwebpage.aspx put:
<%
Response.RedirectPermanent("http://yourwebsite.com");
%>
It is pretty simple.
Create an Action
public ActionResult ext(string s)
{
return Redirect(s);
}
And in Routeconfig file add
routes.MapRoute(name: "Default17", url: "routeyouwant", defaults: new { controller = "Home", action = "ext", s = "http://externalurl.com" });

Controller in Sub Folder

My area is below. Only the concerned part is highlighted.
Route Table
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"SubFolder", // Route name
"SubFolder/ChildController",
new { controller = "ChildController", action = "Index" },
new[] { "Practise.Areas.SOProblems.Controllers.SubFolder" });
routes.MapRoute(
"Default", // Route name
"{controller}/{action}", // URL with parameters
new { controller = "Home", action = "Index" } // Parameter defaults
);
}
This only works when the url is like this
localhost:2474/SOProblems/ChildController/index
This does not works when the url is like this
localhost:2474/SOProblems/SubFolder/ChildController/index
Can you please tell me what is missing?
This does not works when the url is like this
localhost:2474/SOProblems/SubFolder/ChildController/index
That's normal. You route pattern looks like this: SubFolder/ChildController and not SubFolder/ChildController/index. In addition to that you defined your route in the WRONG place. You defined it in your main route definitions and not in your area route definitions. So get rid of the custom route definition from your main routes and add it to the SOProblemsAreaRegistration.cs file (which is where your SOProblems routes should be registered):
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"SubFolderRoute",
"SOProblems/SubFolder/ChildController",
new { controller = "ChildController", action = "Index" },
new[] { "Practise.Areas.SOProblems.Controllers.SubFolder" }
);
context.MapRoute(
"SOProblems_default",
"SOProblems/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}
Also since your route pattern (SOProblems/SubFolder/ChildController) doesn't have the possibility to specify an action name, you can only have one action on this controller and that would be the default action that you registered (index) in this case.
If you wanted to have more actions on this controller and yet index be the default one you should include that in your route pattern:
context.MapRoute(
"SubFolder",
"SOProblems/SubFolder/ChildController/{action}",
new { controller = "ChildController", action = "Index" },
new[] { "Practise.Areas.SOProblems.Controllers.SubFolder" }
);
In both cases your main route definition could remain with their default values:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default",
"{controller}/{action}",
new { controller = "Home", action = "Index" }
);
}
Your new route "SubFolder" does not include the possibility of including an action in the route (in your case, "Index").
Your sample URL
localhost:2474/SOProblems/SubFolder/ChildController/index
Wants to try to match a route like:
"SubFolder/ChildController/{action}"
But you don't include the "{action}" in your route, so it won't match your route. It then tries the default route, which obviously fails.
Try adding "{action}" to your route:
routes.MapRoute(
"SubFolder", // Route name
"SubFolder/ChildController/{action}",
new { controller = "ChildController", action = "Index" },
new[] { "Practise.Areas.SOProblems.Controllers.SubFolder" });
or take "index" off your test URL.
For any future users looking to do this; Look into using Areas.
Here's a helpful video.
Organizing an application using Areas

Why does the order of route mapping matter when mixing MVC and webforms?

Curious why declaring a MapPageRoute before the default MVC route causes problems with UrlHelper.GenerateUrl.
I started with this in my Global.asax.cs:
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute( "MyApp", "home/my-app", new { controller = "Home", action = "MyApp" } );
routes.MapPageRoute( "MyOldWebForm", "oldform.aspx", "~/WebForms/OldForm.aspx" );
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Site", action = "Index", id = UrlParameter.Optional } );
}
Any reference in a view to a default declaration like #Html.BeginForm(), or a controller call result like RedirectToAction("Index", "Errors", new {fault = "itemMissing"} ); would yield the URL "oldform.aspx".
When I swap the order of the default MVC route with the page route, it works as expected.
This is for asp.net web forms routing.
you can see
http://msdn.microsoft.com/en-us/library/system.web.routing.routecollection.mappageroute.aspx

Resources