I'm trying to create a new Route in MVC3 to achieve the link http://localhost/Product/1/abcxyz:
routes.MapRoute(
"ProductIndex", // Route name
"{controller}/{id}/{name}", // URL with parameters
new { controller = "Product", action = "Index", id = UrlParameter.Optional, name = UrlParameter.Optional } // Parameter defaults
);
And I used Route Link like this:
<li>#Html.RouteLink("My Link", "ProductIndex", new { controller = "Product", id = 10, name = "abcxyz" })</li>
Product Index action:
public ViewResult Index(int id, string name)
{
var product = db.Product.Include(t => t.SubCategory).Where(s => s.SubID == id);
return View(product.ToList());
}
The url render as I expected. But when I click on it, I got a 404 error with message
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
UPDATE
I place that Route above Default Route and the URL work fine. But there's a problem occure. My index page http://locahost point directly to Index action of Product controller, but I want it points to Index action of Home controller instead
It's because you have 2 optional parameters in your route and the engine can't work out which one to set the value to. See my answer to a similar issue here
You can create a specific route for your products controller first (with mandatory id) and then have the generic fallback route afterwards.
routes.MapRoute(
"ProductIndex", // Route name
"products/{id}/{name}", // URL with parameters
new { controller = "Product", action = "Index", name = UrlParameter.Optional } // Parameter defaults
);
Try it
routes.MapRoute(
"Default", // Route name
"{controller}/{id}/{name}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional, name = UrlParameter.Optional } // Parameter defaults
);
for routing details see this link. In this link every type of routing is discussed.
http://www.codeproject.com/Articles/408227/Routing-in-MVC3
Related
How can I replicate this default MVC route code below but to work with multiple ActionResults that are in the home controller. I want them to work just like Index where you do not need /Home/Index in the url to hit example.com/index
routes.MapRoute("Default", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
I would like to hit example.com/about and example.com/contact without needing the the controller name in the beginning.
I have tried adding that same code but replaced Index with another action method and it works but it doesn't allow you to have more than 1 existing in this structure at the same time.
Solution?
Ok so I think I got it to work after reading this thread:
ASP.NET MVC - Removing controller name from URL
In the RouteConfig I added the following right before the default route:
routes.MapRoute(
"Root",
"{action}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new { isMethodInHomeController = new RootRouteConstraint<HomeController>() }
);
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Then inside of the Controller whos name you are trying to remove from the URL you need to add this:
public class RootRouteConstraint<T> : IRouteConstraint
{
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
var rootMethodNames = typeof(T).GetMethods().Select(x => x.Name.ToLower());
return rootMethodNames.Contains(values["action"].ToString().ToLower());
}
}
Now if I go to example.com/about , it works and I don't have to use example.com/Home/About
I have a the following default route set up and it works fine:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
Here is an example of successful route for me: "/PositionDetail/Candidates/2"
This is all fine and dandy, but the issue I have is that I want to set up a route that goes deeper. i.e. "/PositionDetail/Candidates/2/GetMoreCandidates" and "/PositionDetail/Candidates/2/Resume/3" where the Resume would be another action that I want to perform, and 3 would be ID. Note: Each of these route will load a new page, and not some partial view.
How do I set something up like this, and what would the 'PositionDetail' Controller Look like?
For example, for second task it may be as follows:
public ActionResult Resume(int CandidateID, int ResumeID)
{
return View();
}
In your Routing:
routes.MapRoute(
"Resume", // Route name
"{controller}/Candidates/{CandidateID}/{action}/{ResumeID}", // URL with parameters
new { controller = "PositionDetail", action = "Resume", CandidateID = UrlParameter.Optional, ResumeID= UrlParameter.Optional }
);
For fist task - the same logic
In an MVC3 app I have a view in my home controller that is accessed via the following URL:
http://mysite.com/home/mycontent
However, my user wants to accees it via:
http://mysite.com/mycontent (without a specific reference to the home controller)
I've tried modifying my global.asax with the following:
routes.MapRoute(
"MyContent", // Route name
"MyContent", // URL with parameters
new { controller = "Home", action = "MyContent"} // Parameter defaults
);
But I get 404 errors when I try to use it. Is there a way I can accomplish what my user is wanting to do - redirecting a URL to a specific controller/view pair?
I think you should keep some "parameters":
routes.MapRoute(
"MyContent", // Route name
"{action}/{id}", // URL with parameters
new { controller = "Home", action = "MyContent", id = ""} // Parameter defaults
);
In what order are your routes registered? That route should come before your default route.
E.g.
routes.MapRoute(
"MyContent", // Route name
"MyContent", // URL with parameters
new { controller = "Home", action = "MyContent"} // Parameter defaults
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Pages", action = "Index", id = UrlParameter.Optional }
);
Otherwise, it should work... I have routes defined exactly the same as that.
I'm trying to take advantage of the default routing so I get a URL without a query string parameter.
So, I've currently got this url:
http://www.mysite.Items/Edit?ItemID=19719
And I'm trying to get a URL like this:
http://www.mysite.Items/Edit/19719
The routing works, but I can't get the #Html.ActionLink method to produce the 2nd url.
Here is my razor code:
#Html.ActionLink("Edit", "Edit", new {item.ItemID}, new { id = "edit-" + item.ItemID })
The first argument is my link's text. The 2nd argument is the Action. 3rd is the ID Value and finally the last argument is and HTML attribute I use for some javascript I'm using.
Originally I had my 3rd Argument as
new {itemID = itemID}
This was when my Edit action expected an integer value named itemID as the parameter. I changed it to 'id' so the routing would work.
Ideally I would like a route that would pass the 19719 value to an action with the argument named itemID, but this is beyond the scope of this question.
Thanks in advance.
SOLVED
Thanks Darin Dimitrov for this solution.
I ended up leaving my html code and action arguments the way I had them originally. All that was really required was an update to my routes. I should note that I had to add my new route map before the default. Anyway, here is my route registration now that made this all work.
public static void RegisterRoutes(RouteCollection routes) {
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute("", "Items/{action}/{itemID}", new { controller = "Items", action = "Details", itemID = #"\d+" });
routes.MapRoute("Default", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional } );
}
The default routes uses id as route token name, so you want:
#Html.ActionLink(
"Edit",
"Edit",
new { id = item.ItemID },
new { id = "edit-" + item.ItemID }
)
Notice new { id = item.ItemID } and not new {itemID = itemID} and not new {item.ItemID}.
I have a web project using ASP.net MVC3. There's an child action in my project. I use
<% Html.RenderAction("Navigator", "Application");%>
to call a shared action. But I find that if my current url is "localhost/application", it throws an exception "No route in the route table matches the supplied values". But when current url is "localhost/application/index", it works fine. Index is a default action in my route config, which is shown below:
public static void RegisterRoutesTo(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("{*favicon}", new { favicon = #"(.*/)?favicon.ico(/.*)?" });
//routes.IgnoreRoute("{*chartName}", new { chartName = #"(.*)?Chart.aspx" }); //ignore request for charting request
routes.Ignore("{*pathInfo}", new { pathInfo = #"^.*(ChartImg.axd)$" });
routes.MapRoute(
"Default", // Route name
"{controller}/{id}/{action}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
new { httpMethod = new HttpMethodConstraint("GET", "POST") } // Allowed http methods
);
}
Note that I switch default id and action position. I see mvc can remove the default controller and action name in url when using "Html.ActionLink(...)". And I don't like to use explicit url string in my views. How can make it work?
My Action code is simple:
[ChildActionOnly]
public ActionResult Navigator()
{
return PartialView(appFacility.GetAll());
}
Thanks alot.
Wrong route URL definition and defaults combination
The problem is that you can't have non optional parameters after an optional parameter.
Why does localhost/application/index work? This are route values:
controller = "application" (supplied from URL)
id = "index" (supplied from URL)
action = "Index" (supplied as route default)
Basically these values equal to localhost/application/index/index request URL.
If you'd like your RenderAction to work, you'd have to call it this way:
<% Html.RenderAction("Navigator", "Application", new { id = 0 }); %>
which would equal to localhost/application/0/navigator request URL.
But you'll soon find out that your route doesn't work and you'll have to change it (because I suppose you don't like having that additional 0 in your URL). If you provide information how you'd like your route work (or why you've decided to switch action and id) we can provide an answer that will help you meet your requirements.
Optinal parameters work correctly only on the end of route. Try something like this:
routes.MapRoute("DefaultWithID", "{controller}/{id}/{action}",
new { action = "Index" },
new { id = "^[0-9]+$" }
);
routes.MapRoute("Default", "{controller}/{action}",
new { controller = "Home", action = "Index" }
);
edit: hopefully fixed :) this version counts on fact that ID will be numeric - without constraint we can't tell whether it would mean action or id, so there couldn't be default action on routes when ID is specified