i'm new to routing in aspnet mvc.. i have following code:
Action Controller
public ActionResult SchoolIndex()
{
return View(SchoolRepository.GetAllSchools());
}
here is the routing
routes.MapRoute(
"School", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "School", action = "SchoolIndex", id = "" } ); // Parameter defaults
when i enter "localhost/school" in addressbar, it is giving 404 error instead it should route to my "schoolIndex" action
i have given route-name as "School" where it is used ?
You can't specify a route name in a URI, ever.
Route names are for, e.g., Html.RouteLink(). RouteLink allows you to specify exactly the route you want, even if it's not the first matching route for the arguments you pass.
URIs are matched in order. The first matching route wins.
Read my post on routing for much more detail.
Related
By default if url is 'mydomain' it go to controller home; action = index.
But when index action has params the url have to be:
mydomain/home/index?name=John
want to get:
mydomain?name=John
What should be define for create such url?
Thanks,
Yosef
The correct url is the following:
http://mydomain.com/?name=John
Given default route setup this will invoke the Index action on Home controller and pass the name parameter.
As far as your request about the mydomain?name=John url is considered, well, this doesn't look quite a well formed url.
Are you sure you want mydomain/home/index?name=John and mydomain?name=John as your urls in your site?
If you corrected your routing engine, your routes could be, mydomain/home/index/john and mydomain/john, which to me would be more correct.
Is that what you're going for?
If so, assuming you have a Index action, accepting a string parameter of name in your home controller, you could modify your global.asax, and change the default route, and add a route below the standard default route like this:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", name= UrlParameter.Optional } // Parameter defaults
);
routes.MapRoute(
"NameOnly", // Route name
"{name}", // URL with parameters
new { controller = "Home", action = "Index" } // Parameter defaults
);
Be sure you put the name only route at the bottom, as a string based parameter will match everything, so you need to match the more explicit ones first.
In a default application ASP.NET MVC 3.0 app I have a controller with Index() and Details(string id) methods. These map to /orders/ and orders/details/ORDER_ID_HERE. How do I change the routing so that Details maps to orders/ORDER_ID_HERE, and continue to have Index() serve up a default index page?
If you would add a new route to you route collection like:
routes.MapRoute(
"Detailed", // Route name
"{contoller}/{id}", // URL with parameters
new { controller = "Orders", action = "Details", id = UrlParameter.Optional } // Parameter defaults
);
It would work, but you break a lot of things, a url like [site]/Home/Search for instance would result in a:
System.ArgumentException: The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Int32' for method 'System.Web.Mvc.ActionResult Details(Int32)' in 'MvcApplication3.Controllers.OrdersController'.
The reason for this is that /Home/Search matches the route {controller}/{id}.
An other, similar way to solve it would be:
routes.MapRoute(
"Detailed", // Route name
"order/{id}", // URL with parameters
new { controller = "Orders", action = "Details", id = UrlParameter.Optional } // Parameter defaults
);
Make sure that the static part in the route, order, does not match the name of your actual orders controller, otherwise you'll have the same problem, rendering [url]/orders unreachable with an System.ArgumentException instead of calling the Index() method (the default route)
The negative side of this approach is that you'll need to do this for every controller where you would like to have such functionality.
Try adding this route before the default route:
routes.MapRoute("SomeName", "{controller}/{id}", new { controller = "Orders", action = "Details" });
Notice how the {action} has been removed from the URL parameter.
I need to create a custom routing for this url:
/par1/par2/par3/par99/11
The url must redirect to
home/index/11
11 is the Id
I need only this parameter, the other parameter (par1/par2/...) are only for SEO purpose and could be any word.
par1, par2, etc.. are created dynamically , so the Url could be:
/par1/par2/11
or
/par1/par2/par3/111
or
/par1/3
you could just turn it around and go with
routes.MapRoute(
"Route",
"{id}/{*seostuff}",
new {controller = "Home", action="Index", seo = UrlParameter.Optional});
that will allow you to map urls such as http://www.somesite.com/11/whatever/goes-here/will-be-whatever-you/want
Maybe you'll start with this and adjust to your needs:
routes.MapRoute(
"Def0", // Route name
"{controller}/{action}/{seo1}/{seo2}/{seo3}/{id}"
);
routes.MapRoute(
"Def1", // Route name
"{controller}/{action}/{seo1}/{seo2}/{id}"
);
routes.MapRoute(
"Def2", // Route name
"{controller}/{action}/{seo1}/{id}"
);
routes.MapRoute(
"Def3", // Route name
"{controller}/{action}/{id}"
);
Since your id is at the end, you would need to make 99 routes to handle all the stuff in between in order for the id route to the controller (easily).
I would stick the id to the left of the "SEO stuff" if possible, so it can be thrown away easier, exactly like #Morder described. The {*seostuff} parameter catches forward slashes ('/'), whereas thee {seo1}, {seo2} parameters do not.
look at the way stackoverflow does urls; after the id everything is thrown away.
I know this has already been accepted but I've written a route class that allows greedy segment to be anywhere in the URL definition.
In this case URL definition would be
{*seo}/{id}
Read all details about the custom route class and use it if you like:
Custom Asp.net MVC route class with catch-all segment anywhere in the URL
I'd like to have URLs that are even shorter than /{Controller}/{Action}/{Id}.
For example, I'd like {Controller}/{Id}, where {Id} is a string.
This would allow for simple paths, e.g. Users/Username, Pages/Pagename, News/Newsname. I like this better than requiring the /Details action in the URL (Users/Details/Username), which is less elegant for the end-user.
I can easily make this work by setting up custom routes for any controller that I want this level of simplicity for. However, this causes headaches when it comes to implementing other actions, such as {Controller}/{Action}, where {Action} = 'Create', since, in this case the string {Action} conflicts with the string {Id}.
My question: how can I have 'reserved' words, so that if the URL is /News/Create, it is treated as an action, but if the URL is anything else, e.g. /News/A-gorilla-ate-my-thesis, then it is treated as an Id.
I'm hoping I can define this when setting up my routes?
Update:
Using Ben Griswold's answer, I have updated the default ASP.NET MVC routes to be:
routes.MapRoute(
"CreateRoute", // route name
"{controller}/Create", // url with parameters
new { action = "Create" } // parameter defaults
);
routes.MapRoute(
"DetailsRoute", // route name
"{controller}/{id}", // url with parameters
new { action = "Details" } // parameter defaults
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
);
This works a charm and means, by default, the details pages will use the simplified URL, but I will still be able to target a specific action if I want to (update/delete/details).
Of course, you will need to disallow the reserved "Create" word as an Id, otherwise a user may try to create an article, for example, with the name "Create", which can never be accessed.
This is really nice. If anyone sees that there is something wrong with this approach, chime in, but I like it so far.
I think you're left with creating a route for each reserved word. For example,
routes.MapRoute("CreateRoute",
"{controller}/Create",
new { action = "Create" }
);
would handle /News/Create, /Users/Create, etc. As long as this route is listed before your other custom route, I think you're covered.
I imagine you will need addition routes for various CRUD operations which will follow a similar pattern.
I tried to use the solution explained at http://weblogs.asp.net/paulomorgado/archive/2010/01/31/web-site-globalization-with-asp-net-routing.aspx to localize my application using the language parameter in my routes.
Here's the code I have in my Global.asax:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.Add("en", new Route("en/{*path}", new GlobalizationRouteHandler(CultureInfo.GetCultureInfo("en-US"))));
routes.Add("fa", new Route("fa/{*path}", new GlobalizationRouteHandler(CultureInfo.GetCultureInfo("fa-IR"))));
routes.MapRoute(
"AdminHome",
"{language}/admin",
new { controller = "Admin", action = "Index" }
);
}
But when I point my browser to /en/admin or /fa/admin I receive a 404 error message.
I tried this one too:
routes.MapRoute(
"AdminHome",
"admin",
new { controller = "Admin", action = "Index" }
);
But still a 404 error for /en/admin - (in this case "/admin" works.)
Any idea?
I have a very similar route pattern in my own MVC site.
routes.MapRoute(
"BlogSpecific", // Route name
"{blogSubFolder}/{controller}/{action}", // URL with parameters
new { blogSubFolder = "", controller = "", action = "Index" } // Parameter defaults
);
The two main differences that I can see are that I specify the {action} in my route, and I also call out the first route param as a parameter in my object ("blogSubFolder = "",").
Now I just did some testing, and I found the same behavior that you are seeing, I take out the {action} out of my route and I get a 404. But if I specify the action everything works out.
Ok, so I created a new project, with the default route, and I don't have to specify the action, it defaults to Index just like I'd expect it to. I then add a new route where I specify the controller {language}/Foo/{action}, and I continue to get errors if I don't include the index in my url. Long story short, As near as I can tell if your route has a variable that precedes the controller you have to specify the action in your url.