I have an action in my HomeController like this:
public ActionResult HowItWorks()
{
return View();
}
I can access this by going to /Home/HowItWorks as you might expect.
How can I make it so that it will go to the same place if I go to /HowItWorks (omitting the "Home" prefix)?
I know I can change this in RouteConfig.cs but I was wondering if there was an attribute or something like that.
routes.MapRoute(
name: "HowItWorks",
url: "HowItWorks",
defaults: new { controller = "Home", action = "HowItWorks", id = UrlParameter.Optional }
);
You can do it as above. and yes, you need to put it in RouteConfig.cs
If you want all your methods work like that you can use following:
routes.MapRoute(
name: "HomePages",
url: "{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
In this case though, you can use a single controller only, if and only if you dont define a custom route as follows:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Note that precedence of routes matters. ie: whichever is matched first will be embraced.
I know I can change this in RouteConfig.cs but I was wondering if
there was an attribute or something like that.
Take a look at AttributeRouting, it's pretty cool.
Related
When attempting to pass a parameter to a simple controller I receive the parameter as always being null.
Controller
public class GetOrgController : Controller
{
private DirectoryEntities de;
public getOrgController()
{
de = new DirectoryEntities();
}
// GET: getOrg
public ActionResult Index(string district)
{
getorg_Result org = de.getorg(district).FirstOrDefault();
return View(org);
}
}
When I try to navigate to that url with a parameter localhost:660366/GetOrg/Index/D123 the district variable is always null.
I thought maybe it had to do something with the default RouteConfig. When I put a new value ahead of the default route config it worked! However now, whenever I try to launch the application it goes to the GetOrgController first. What happens when I want a new controller with different parameters? I have to do this every time? Here is my new RouteConfig with the new entry.
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "GetOrg",
url: "{controller}/{action}/{district}",
defaults: new { controller = "GetOrg", action = "Index", district = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
I actually started doing Rest initially in Web Api 2, but the view-model attracted me to MVC. It is a lot easier specifiying above the method the routes/parameters I wanted like below. Is this possible in MVC?
WebApi2
[Route("Index/{district}")]
public ActionResult Index(string district)
{
getorg_Result orgs = de.getorg(district).FirstOrDefault();
return View(orgs);
}
The above method seems so much cleaner than having to rely on the order of controllers being correct in the RouteConfig
These two routes literally make no sense. The first one says, for ANY controller with ANY method default to GetOrgController. That isn't what you want because now id won't work for all the other controllers and the second MapRoute is close to a duplicate.
routes.MapRoute(
name: "GetOrg",
url: "{controller}/{action}/{district}",
defaults: new { controller = "GetOrg", action = "Index", district = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
What you really should be doing is saying for any call starting with GetOrg then call GetOrgController for any method....
routes.MapRoute(
name: "GetOrg",
url: "GetOrg/{action}/{district}",
defaults: new { controller = "GetOrg", action = "Index", district = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
thats because both routs are generic thats why it hits the first route by default so you can remove UrlParameter.Optional so that the route should be a little specific
routes.MapRoute(
name: "GetOrg",
url: "{controller}/{action}/{district}",
defaults: new { controller = "GetOrg", action = "Index"}
);
but still you can use the default route for that purpose no need of additional route unless you want to use a custom url like random/234
I am very new to MVC and trying to build my first website. I couldnt set my RouteConfig file properly. I have 2 rules that apply to different ActionResults. But, only one of them works properly. if GetProducts is above the GetProductByCode, then GetProducts works. If GetProductByCode is above the GetProducts, then GetProductByCode works. What am I doing wrong?
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "GetProducts",
url: "{controller}/{action}/{PageNo}",
defaults: new { controller = "Home", action = "GetProducts", PageNo = UrlParameter.Optional }
);
routes.MapRoute(
name: "GetProductByCode",
url: "{controller}/{action}/{ProductCode}",
defaults: new { controller = "Home", action = "GetProductByCode", ProductCode = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
My Solution is like below
routes.MapRoute(
name: "GetProducts",
url: "{controller}/GetProducts/{PageNo}",
defaults: new { controller = "Home", action = "GetProducts", PageNo = UrlParameter.Optional }
);
routes.MapRoute(
name: "GetProductByCode",
url: "{controller}/GetProductByCode/{ProductCode}",
defaults: new { controller = "Home", action = "GetProductByCode", ProductCode = UrlParameter.Optional }
);
If you look at the default route:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Then think of the portion after url: as a format or pattern:
{controller}
{action}
{id}
Your 3 URLs Home/GetProducts, Home/GetProductsByCode and Home/Index all match this pattern.
With the {action} portion being GetProducts, GetProductsByCode and Index respectively.
You would need to leverage routing if you wanted to map the parameter to a variables called PageNo or ProductCode in the Action, but in general you don't need routes for each possible combination. If your parameters in these actions are id then it will just work without you needing to create routes for each.
E.g.
public ActionResult GetProducts(int id)
{
// stuff
}
public ActionResult GetProductsByCode(string id)
{
// stuff
}
To have the parameter names, specify the controller and action explicitly:
routes.MapRoute(
name: "GetProducts",
url: "Home/GetProducts/{PageNo}",
defaults: new { controller = "Home", action = "GetProducts", PageNo = UrlParameter.Optional }
);
routes.MapRoute(
name: "GetProductByCode",
url: "Home/GetProductsByCode/{ProductCode}",
defaults: new { controller = "Home", action = "GetProductByCode", ProductCode = UrlParameter.Optional }
);
And
public ActionResult GetProducts(int PageNo)
{
// stuff
}
public ActionResult GetProductsByCode(string ProductCode)
{
// stuff
}
But in general, only define custom routes that differ from the normal {controller}/{action}/{id} pattern.
The default section of MapRoute means that if it can't find a controller and action that exists in your code base use these instead. It's a fallback, not the functionality driver.
All 3 routes are identical in that they contain 3 segments (the controller name, action name and an optional parameter) and which ever of the 3 are placed first will always be hit.
If you want GetProducts to be hit the you could modify the definition to
routes.MapRoute(
name: "GetProducts",
url: "Home/GetProducts/{PageNo}",
defaults: new { controller = "Home", action = "GetProducts", PageNo = UrlParameter.Optional }
);
although there seems no real point. If you just changed the name of the parameter in the GetProducts() and GetProductByCode() to id then the only route definition you require is the Default
There is not way for asp.net to understand if the last parameter is /{ProductCode}", or {ProductCode}", since the action is the same - so your URL looks the same,
Therefor only the first match is taken, a solution would be using a full query string since the /{id} is just a shorthand for id=5 in the query string
I have multiple routes configured, but for some reason, despite the rules addressing different Controllers and different Views, different links are routing to the same view. Please see below, I have included my RouteConfig file and example links below:
RouteConfig.cs
using System.Web.Mvc;
using System.Web.Routing;
namespace WebApplication1
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Account",
url: "Account/{action}/{id}",
defaults: new { controller = "Account", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Member",
url: "Member/{action}/{id}",
defaults: new { controller = "Member", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Root",
url: "{action}/{id}",
defaults: new { controller = "Home", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Details",
url: "{controller}/{action}/{u}",
defaults: new
{
controller = "Member",
action = "Details",
u = UrlParameter.Optional
}
);
routes.MapRoute(
name: "Article",
url: "{Home}/{Article}/{id}/{articleName}",
defaults: new { controller = "Home", action = "Article" }
);
routes.MapRoute(
name: "Item",
url: "{News}/{Item}/{id}/{itemName}",
defaults: new { controller = "News", action = "Item" }
);
}
}
}
Links
http://localhost:11508/Home/Article/2/Participate
http://localhost:11508/News/Item/2/Second-Test
As so can see, the links and rules are most certainly unique but for some reason the Item rule is being ignored, it is simply passing Id 2 to the Home/Article view.
You shouldn't include controller / action names in brackets - just pass them as is, so that path can be matched. Your last two routes should look like this:
routes.MapRoute(
name: "Article",
url: "Home/Article/{id}/{articleName}",
defaults: new { controller = "Home", action = "Article" }
);
routes.MapRoute(
name: "Item",
url: "News/Item/{id}/{itemName}",
defaults: new { controller = "News", action = "Item" }
);
Also, it is good to place such specific routes before any other routes, not after default routes.
UPDATE
Basically it should be separate question, but it is easier to just answer it here.
From comment:
how I can get http://localhost:11508/Member/Details?u=testuser to be routed to http://localhost:11508/Member/Details/testuser instead of a showing parameter.
Create controller action which accepts this parameter, like this one:
public ActionResult Details(string u, ...)
{
var model = new ...
...
return View(model);
}
Register route, which accepts u parameter as URL part, like this one
routes.MapRoute(
name: "MyRoute",
url: "Member/Details/{u}",
defaults: new { controller = "Member", action = "Details", u = UrlParameter.Optional }
);
Here {u} actually declares parameter name, and how it should be used (parsed / rendered) inside URL.
Render link to the URL like this one:
linktext
In all these steps, u is that name of parameter which you will use.
The Mapping takes the first matching rule.
The "Item"-Route would never be used because the Article-Root will catch all request that could match "Item"-Route.
Check the order of the routes AND delete the {} surrounding news.
routes.MapRoute(
name: "Item",
url: "News/Item/{id}/{itemName}",
defaults: new { controller = "News", action = "Item" }
);
Your problem is in the order in which you are registering your routes. The rule is that you should register them from the most specific to the least. In other words, your "default" route(s) should be the very last.
With how you have it right now, MVC gets a hit on your default route, because your item route matches that, so once it hits on that, it stops looking for other routes and uses it.
Move your item route up to the top of your RegisterRoutes method and it should work fine.
During my work I must solve one URL rewriting problem. I have to use URLs as a template:
{controller}/{action}-{id}
instead of
{controller}/{action}/{id}
so the processed url should look like:
myController/myAction-128
where 128 is a parameter
My route map:
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(
name: "NewRoute", // Route name
url: "{controller}/{action}-{id}/{extId}", // URL with parameters
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional, extId = UrlParameter.Optional } // Parameter defaults
);
}
Controller code:
[HttpGet]
public ActionResult DocumentDetails(int? id)
{
if (doc.HasValue)
{
...
}
}
This route doesn't provide any successful results. I still have 404 Errors. When I use / instead of "-" everything is ok, but my JS View environment won't work.
Is there something I could do to fix this? All help will be appreciated, thanks.
Routes are evaluated in the same order as you defined them, so make sure you respect the same order. Also adding a constraint for the id (as being a number for example) would help the routing engine disambiguate your routes. Not to mention that in your example you have made the id token optional which of course is not possible, only the last part of a route can be optional.
So:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "NewRoute",
url: "{controller}/{action}-{id}/{extId}",
defaults: new { controller = "Home", action = "Index", extId = UrlParameter.Optional },
new { id = #"\d+" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
I'm thinking your request is being processes by the first routing rule and then action-id is considered as a whole action and not being found.
Set your NewRoute before the Default route. Just move the code up.
I am working with ASP.NET MVC 4 and am attempting to write a really basic route, but it's not working and getting very frustrated with it!
I want the URL http://www.mywebsite.com/my-page to trigger the controller called Page and the action method Index.
I have no other route setup apart from this:
RouteTable.Routes.MapRoute(
name: "Default",
url: "my-page",
defaults: new { controller = "Page", action = "Index" }
);
Is there something incorrect with my setup or where am I going wrong?
The error I get is:
The controller for path '/my-page' was not found or does not implement IController.
Main problem is you are trying to override the default route. In MVC4, the routes are defined in App_Start/RouteConfig.cs. The "Default" route should be the LAST route:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Then, for your specific route, use the following BEFORE the default route:
routes.MapRoute(
name: "MyPage",
url: "my-page",
defaults: new { controller = "Page", action = "Index" }
);
Fianlly, ensure you have a controller PageController.cs with an action Index and a View Views/Page/Index.cshtml:
public class PageController : Controller
{
public ActionResult Index()
{
return View();
}
}