In my MVC 4 web appication if I access the Home page I call the following url:
sitename/Home
I now added a subfolder called Mobile to the Controllers folder.How can I configure routing to be able to call the Home controller in the Mobile folder like this
sitename/Mobile/Home
Here's my RegisterRoutes method:
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 },
namespaces: new string[] { "Test.Controllers" }
);
routes.MapRoute(
name: "Mobile",
url: "Mobile/{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new string[] { "Test.Controllers.Mobile" }
);
}
ASP.NET MVC routes are order dependant and should go in order of most specific to most generic.
At the moment, if you type the url Mobile/Home/Index the routing will try and map that to:
controller: Mobile
action: Home
id: Index
using the default route and never get to your intended route map.
If you swap the MapRoute declarations around, then MVC will see that it starts with "Mobile" and use that route as intended.
#dav_i is 100% correct in that the route needs to be before the other one. The URL for mobile has Mobile in the URL, so you would have to have Mobile in any action links or redirects... So ideally, in your global.asax, you'd try to detect whether the browser is mobile, and redirect within there... But you still have to manage having Mobile in the URL. That's because functions like Url.Action and Html.ActionLink expect the controller and action to be the full URL, and this:
#Url.Action("Action", "Control")
produces:
/Control/Action
And as such, you'd have to handle this. Alternatively, you could use mobile views without having to worry about this. See this tutorial.
Related
I have an existing Web application that was developed in ASP.NET 4.0. I want to add MVC functionality to the app, so I've integrated MVC into the app as per Scott Hanselman's article Integrating ASP.NET MVC 3 into existing upgraded ASP.NET 4 Web Forms applications. Because MVC routing is greedy, I added the following code to my Global.asa so that an empty URL will go to my Default.aspx:
routes.MapPageRoute("WebFormsDefault", "", "~/Default.aspx");
The problem now is that ActionLinks and RouteLinks don't form correctly. If I try to create an action link using:
#Html.ActionLink("Item List Page", "List", "Item")
the following URL is created:
"/SiteName/?action=List&controller=Item
I've found several posts from others with this same problem, but none of them have any answer. Is this just a bug? Is integrating MVC into a WebForms app just a bad idea in general? Or is there a way to fix this so that my Default.aspx page will be displayed when a user first enters the site and ActionLinks and RouteLinks will work correctly?
Coming to this a bit late, but I figure better late than never. I was having this exact same issue and I solved it by grouping my MapPageRoute code and my MapRoute code and then always calling the MapRoute code first. Example:
Originally my routing looked like this -
routes.MapPageRoute("401", "401/", "~/Views/Error/401.aspx");
routes.MapPageRoute("404", "404/", "~/Views/Error/404.aspx");
routes.MapPageRoute("500", "500/", "~/Views/Error/500.aspx");
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" }
);
etc etc
This was causing all of my form actions to direct to a url formatted as so:
/mysite/401?action=x&controller=y
Clearly that was not useful. By making sure that I always setup all of my MVC routes first, the problem resolved itself. I ended up making two seperate methods, one for configuring MVC routes and one for configuring Webform routes as so:
RouteConfig.RegisterMvcRoutes(RouteTable.Routes); // contains only MapRoute
RouteConfig.RegisterWFRoutes(RouteTable.Routes); // contains only MapPageRoute
(these calls go into the Global.asax file as usual and replace RouteConfig.RegisterRoutes)
I would not advise mixing webforms with MVC, but I did manage to get this working by using this helpful posting:
http://bartwullems.blogspot.com/2011/04/combining-aspnet-webforms-and-aspnet.html
I also had to be rather careful about the ordering of the routes so that my most generic route went after the aspx page I wanted to be served up as a default.
Here is my complete RouteConfig:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute({resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "SignUp",
url: "SignUp",
defaults: new { controller = "Profile", action = "SignUp", shortUrl = UrlParameter.Optional });
routes.MapRoute(
name: "Admin",
url: "Admin",
defaults: new { controller = "Admin", action = "Index", shortUrl = UrlParameter.Optional });
//used to get aspx page to render
routes.MapPageRoute("WebForms", "", "~/WebForms/Default.aspx", false, null, new RouteValueDictionary(new { controller = new IncomingRequestConstraint() }));
//this generic route must go last
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" }
);
}
public class IncomingRequestConstraint : IRouteConstraint
{
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
return routeDirection == RouteDirection.IncomingRequest;
}
}
i have url called http://0.00.000.000:0000/ics/Account/Login but i want to show the fixed url like "http:abc.com" in all pages. what ever it may the action and view i require fixed url for my app. can we use files in mvc or routing to achieve this?
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
I built an web application where the RouteConfig.cs was the default one.
Now I received a task where I need to append a customer tracking ID in the beginning of the URL but keeping the same functionality it has when it is not present too.
http://localhost:60202/Home/Index //Generic customer
http://localhost:60202/Location/123/Home/Index //URL with the customer tracking id
This code 123 is a tracking ID where my customer knows the location he originates the call to my page. I have no power to ask them to change this since they use across the globe.
I tried to achieve this with this custom route:
routes.MapRoute(
name: "Route",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "Location/{trackingId}/{controller}/{action}",
defaults: new { trackingId = 0, controller = "Home", action = "Index" }
);
In this case I can access my application with both URL schema I provided above but I couldn't manage to make ActionLink and BeginForm take this into account.
#Html.ActionLink("InĂcio", "Index", "Home") //this should have full URL info
Is there a way to achieve this without the need to change every ActionLink, Url.Content and BeginForm and surround them with if in every case?
How could I use both URL schema without change every navigation code?
Our currently implemented approach is to duplicated the folders in IIS since there is only 4 as of today but in near future it can be a pain to maintain.
I don't know why but based on this question it should work out of the box.
Edit 1
Looks like changing position of these two MapRoute are making the ActionLink work as I expected. Unfortunately Url.Content still is buggy.
Well, it's embarrassing but looks like the order you add routes make difference. So I changed to this:
routes.MapRoute(
name: "Default",
url: "Location/{trackingId}/{controller}/{action}",
defaults: new { trackingId = 0, controller = "Home", action = "Index" }
);
routes.MapRoute(
name: "Route",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
With this change every ActionLink started to work as I expected. I still had the problem with Url.Content I was using in Ajax calls.
In this case I figured out that I should use Ulr.Action for this instead.
Referenced js and css still used the second MapRoute (or don't even care about the route at all) but this is not a problem.
I don't know what happened to my website. From today the default action "Index" in only one controller doesn't work anymore.
If I call http://website.com/Valuation i get 403 error page because the webserver doesn't route my request and try to browse the folder. If I write http://website.com/Valuation/Index everything works.
I search in all the code but i can't find the problem, everything seems fine like other controllers.
How can i find the problem? Do you know if there are a known issue that cause that problem or you know if there is a trace\log\debugger of routing requests?
Thanks
Mic
Most probably the issue is you have a folder by name Valuation in your website root. Thats why the valuation index action is not working. Instead of routing to the Controller Action the url http://website.com/Valuation is routing to the Folder Valuation.
Delete this folder Valuation from your root or rename it then this url http://website.com/Valuation will work.
Also check if the ValuationController has the public ActionResult Index() ([HttpGet] method.
Check ~\App_Start\RouteConfig.cs file
public class RouteConfig
{
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}
);
}
}
Am building a CMS using MVC4. My experience with MVC is limited and trying to create a MapRoute that can handle the page structured created by the CMS. URLs for the pages would be along the lines of website.com/About
To handle this I have come up with the following
routes.MapRoute(
name: "Default",
url: "{p}",
defaults: new { controller = "Home", action = "Index", p = UrlParameter.Optional }
);
This works fine for root level pages but if I want sub pages like website.com/About/OurTeam
I get a 404. Ideally what I would like is just be able pass either the whole url after the .com bit as a string and sort it out in the controller or to split the levels up as an array of parameters and pass that through as 'p'.
Hope that makes sense. Any ideas?
You can use:
routes.MapRoute(
name: "Default",
url: "{*p}",
defaults: new { controller = "Home", action = "Index", p = UrlParameter.Optional }
);
The asterisk indicates that it's a catch-all route. Keep in mind that these routes are extremely greedy, make sure that this stays below any specific routes.
You could also add a route constraint to this route which can determine whether the page exists in the database or something. See this post for more info.