MVC 3 custom routes - Redirects, Action, ActionLink have incorrect url - asp.net-mvc-3

I have a certain folder structure I have to follow (/countrycode/language/) so I have my routes set up like below
routes.MapRoute(
"en-us",
"us/en/{action}/{id}",
new { Controller = "XXX", action = "Index", cc = "us", ll = "en", id = UrlParameter.Optional }
);
routes.MapRoute(
"fr-fr",
"fr/fr/{action}/{id}",
new { Controller = "XXX", action = "Index", cc = "fr", ll = "fr", id = UrlParameter.Optional }
);
routes.MapRoute(
"de-de",
"de/de/{action}/{id}",
new { Controller = "XXX", action = "Index", cc = "de", ll = "de", id = UrlParameter.Optional }
);
I've a single controller and multiple actions in that controller. When I try to redirect to an action, or link to an action within a view, the URL always starts with /us/en/ even if I was currently in /fr/fr/.
e.g. If the current route is /fr/fr/
#Html.ActionLink("fooText", "fooAction")
#Url.Action("barAction")
return RedirectToRoute("Index");
All end up as
/us/en/fooAction
/us/en/barAction
/us/en/
How can I make these methods link to the correct URL?

OK instead of:
#Html.ActionLink("fooText", "fooAction")
I need to use:
#Html.RouteLink("fooText", "fr-fr", new { controller = "XXX", action = "fooAction" })

Related

multiple parameter to Url.Action does not generate proper routing path even after defining routes in Asp.net Mvc 4

I have following code
#(Url.Action("Files","Folder", new RouteValueDictionary(new {fileGroup = group,fileName= name, ticket = nodeId})))
I have routes defined
routes.MapRoute(
name: "FolderFiles",
url: "Folder/Files/{fileGroup}/{fileName}/{ticket}/{path}",
defaults:
new
{
controller = "Folder",
action = "Files",
fileGroup = UrlParameter.Optional,
fileName = UrlParameter.Optional,
ticket= UrlParameter.Optional,
path = UrlParameter.Optional
}
);
which generates
http://mydomain.com/Folder/Files?fileGroup=Temp&fileName=Test2&ticket=461c9a67aa94
but i want following url generated
http://mydomain.com/Folder/Files/Temp/Test2/461c9a67aa94/
is it possible to get the above desired url formation?
thanks.
In your case the default route should be handled first.
Try to put your route definition after the default one.
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "FolderFiles",
url: "Folder/Files/{fileGroup}/{fileName}/{ticket}/{path}",
defaults:
new
{
controller = "Folder",
action = "Files",
fileGroup = UrlParameter.Optional,
fileName = UrlParameter.Optional,
ticket = UrlParameter.Optional,
path = UrlParameter.Optional
}
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
To link your action :
#Html.ActionLink("My link", "Files", "Folder", new {fileGroup ="Group1", fileName = "file1", ticket = "ticke1", path ="path1"}, null)
Or execute it :
#(Html.Action("Files","Folder", new {fileGroup = "Group1",fileName= "file1", ticket = "ticke1", path ="path1"}))

MVC route issue

I have this route registered:
context.MapRoute(
"Book",
"book/{id}",
new { action = "index", controller = "book" },
new string[] { "Web.Areas.Books.Controllers" }
);
This serves url like this:
http:///book/4f6be481e8f6ae0a9063afe7
Now I have a url which is either of the following:
http://<domain>/book/4f6be481e8f6ae0a9063afe7/GetFullDescription?app=3
OR
http://<domain>/book/GetFullDescription?app=3&id=4f6be481e8f6ae0a9063afe7
I prefer the first route. I just can't make it work.
I have an action GetFullDescription defined in the book controller.
If I register a route like this, it gets to the GetFullDescription action.
context.MapRoute(
"BookFullDesc",
"book/{action}/{id}",
new { action = "index", controller = "book", id = UrlParameter.Optional },
new string[] { "Web.Areas.Books.Controllers" }
);
But the http://<domain>/book/4f6be481e8f6ae0a9063afe7 url breaks
unless I change it to
http://<domain>/book/index/4f6be481e8f6ae0a9063afe7 <-- Note index after index
EDIT:
ALL I WANT IS A SINGLE ROUTE TO SERVE BOTH OF THESE 2 URLS:
http://<domain>/book/4f6be481e8f6ae0a9063afe7
http://<domain>/book/4f6be481e8f6ae0a9063afe7/GetFullDescription
Thanks
context.MapRoute(
"Book",
"book/{id}/{action}",
new { action = "index", controller = "book", app = 3 },
new string[] { "Web.Areas.Books.Controllers" }
);

ASP MVC 3 switching language with ActionLink

In an ASP MVC 3 project i want to enable language switching.
The routing is defined like this:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"DefaultWithLanguage", // Route name
"{language}/{controller}/{id}/{slug}", // URL with parameters
new { language = "en", controller = "Front", action = "Details", id = UrlParameter.Optional, slug = UrlParameter.Optional } // Parameter defaults
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
Trying to switch languages (in _Layout.cshtml) works like this:
<li>#Html.ActionLink("Spanish", ViewContext.RouteData.Values["action"].ToString(), ViewContext.RouteData.Values["controller"].ToString(), new { language = "es" })</li>
Instead of getting a URL like the following (after having selected Spanish)
.../es/ControllerName/ActionName
i 'm getting this:
.../ControllerName/ActionName?Length=11
If i set the ActionLink to the following (notice the last null parameter):
<li>#Html.ActionLink("Spanish", ViewContext.RouteData.Values["action"].ToString(), ViewContext.RouteData.Values["controller"].ToString(), new { language = "es" }, null)</li>
i get this:
.../ControllerName/ActionName?language=es
What am i missing?
Thanks in advance!
There are some issues with your routes registration DefaultWithLanguage route registration. It doesn't allow you to specify the {action}. This means that this route will only match a Details action (since you have specified it in the default values). Another issue is that you made the {id} parameter optional. But that's impossible. Only the last parameter of a route can be optional. In your case it is followed by a {slug} parameter.
So one possibility is the following:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"DefaultWithLanguage",
"{language}/{controller}/{action}/{id}",
new
{
language = "en",
controller = "Front",
action = "Details",
id = UrlParameter.Optional
}
);
}
and then:
#Html.ActionLink(
"Spanish",
ViewContext.RouteData.GetRequiredString("action"),
ViewContext.RouteData.GetRequiredString("controller"),
new { language = "es" },
null
)
If you wanted to add a {slug} parameter then your {id} can no longer be optional:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"DefaultWithLanguage",
"{language}/{controller}/{action}/{id}/{slug}",
new
{
language = "en",
controller = "Front",
action = "Details",
slug = UrlParameter.Optional
}
);
}
and then:
#Html.ActionLink(
"Spanish",
ViewContext.RouteData.GetRequiredString("action"),
ViewContext.RouteData.GetRequiredString("controller"),
new {
language = "es",
id = ViewContext.RouteData.GetRequiredString("id")
},
null
)
This is a follow up to Darin's answer.
I want to have routes like this:
.../en/ControllerName/Id
.../en/ControllerName/Id/Slug
.../en/ControllerName
This last route causes the problem (see the answer of Darin). The "hack" to keep getting this routes is to define also another route (the second named DefaultWithLanguageWithoutId) :
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"DefaultWithLanguage", // Route name
"{language}/{controller}/{id}/{slug}", // URL with parameters
new { language = "en", controller = "Front", action = "Details", id = UrlParameter.Optional, slug = UrlParameter.Optional } // Parameter defaults
);
routes.MapRoute(
"DefaultWithLanguageWithoutId", // Route name
"{language}/{controller}", // URL with parameters
new { language = "en", controller = "Front", action = "Details"} // Parameter defaults
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
This is causing the code to be adjusted in the master page to the following
<li>#Html.ActionLink("Deutsch", ViewContext.RouteData.Values["action"].ToString()
, ViewContext.RouteData.Values["controller"].ToString(), new { language = "de"
, id = ViewContext.RouteData.Values["id"]!=null ? ViewContext.RouteData.Values["id"].ToString():null }, null)</li>
<li>#Html.ActionLink("English", ViewContext.RouteData.Values["action"].ToString()
, ViewContext.RouteData.Values["controller"].ToString(), new { language = "en"
, id = ViewContext.RouteData.Values["id"] != null ? ViewContext.RouteData.Values["id"].ToString() : null }, null)</li>
Works perfect!
The only "drawback" is the fact that there is some code involved (i would have liked to avoid) in the view, but i think it is worth since it is very simple!

ASP.NET MVC 3.0 Routing behaviour

I have controller BlogController with a couple of actions:
1)Index(string id) - show all posts/show single post if parameter id specified
2)New() - add new post
3)Delete() - delete post
4)And some more another actions
So if i type in browser mysite/blog i could see all posts if i type mysite/blog/postnameid i want to see single post.
the problem is when i type mysite/blog/postnameid it is not working (The resource cannot be found.), but if i type mysite/blog/index/postnameid this way it is working. How could i make mysite/blog/postnameidto work as well.
Here is my blog route in global.ascx
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRouteLowercase(
"Blog", // Route name
"Blog/{action}/{id}", // URL with parameters
new { controller = "Blog", action = "Index" } // Parameter defaults
);
routes.MapRouteLowercase(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Than if i change it like that
routes.MapRouteLowercase(
"Blog", // Route name
"Blog/{id}", // URL with parameters
new { controller = "Blog", action = "Index" } // Parameter defaults
);
the mysite/blog/postnameid working but all another actions like New(), Delete() stop working after that (The resource cannot be found. )
UPDATE:
I forgot to mention that id is sting, not int. so from #Darin answer i changed new { id = #"\w+" } to new { id = #"\d+" } and all seams to be working but now when i typed blog/new for example, it is routing to show/new insteard blog/new
It is a bad idea and against RESTful conventions to have a single controller action that do 2 things and of course violating the single responsibility principle (list all posts if no id is specified and show a given post if an id is specified). The correct way would be to have the following:
/blog => BlogController/Index => list all posts
/blog/123 => BlogController/Show(id = 123) => show details of a given post
/blog/new => BlogController/New() => start writing a new post
/blog/delete/123 => BlogController/Delete(id = 123) => delete given post
which would be achieved with the following routes:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Blog",
"blog/{id}",
new { controller = "Blog", action = "Show" },
new { id = #"\d+" }
);
routes.MapRoute(
"Default",
"blog/{action}/{id}",
new { controller = "Blog", action = "Index", id = UrlParameter.Optional }
);
}
Notice the required route constraint on the first definition which indicates what form all ids must be so that the routing engine could disambiguate between an id and an action name.
This being said if you want to violate the 2 principles I mentioned earlier and have the routes you want a slight adaptation would be required:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Blog",
"blog/{id}",
new { controller = "Blog", action = "Index" },
new { id = #"\d+" }
);
routes.MapRoute(
"Default",
"blog/{action}/{id}",
new { controller = "Blog", action = "Index", id = UrlParameter.Optional }
);
}
Now:
/blog => BlogController/Index(id = null) => list all posts
/blog/123 => BlogController/Index(id = 123) => show details of a given post
/blog/new => BlogController/New() => start writing a new post
/blog/delete/123 => BlogController/Delete(id = 123) => delete given post

Configure asp.net mvc hocalhost/Home/Products to hocalhost/Products

How to configure asp.net mvc routing to get
hocalhost/Products and hocalhost/Search
instead of
hocalhost/Home/Products and hocalhost/Home/Search
i.e. to remove Controller name from the route?
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Products", id = UrlParameter.Optional } // Parameter defaults
);
routes.MapRoute(
"Default",
"{action}/{id}",
new { controller = "Home", action = "Products", id = UrlParameter.Optional }
);
Thus:
http://example.com/ => controller=Home, action=Products
http://example.com/Products => contoller=Home, action=Products
http://example.com/Search => contoller=Home, action=Search

Resources