ASP.NET MVC : Ignore latter route elements in url for a form's action - asp.net

I have a URL /products/search where Products is the controller and Search is the action. This url contains a search form whose action attribute is (and should always be) /products/search eg;
<%using( Html.BeginForm( "search", "products", FormMethod.Post))
This works ok until I introduce paging in the search results. For example if I search for "t" I get a paged list. So on page 2 my url looks like this :
/products/search/t/2
It shows page 2 of the result set for the search "t". The problem is that the form action is now also /products/search/t/2. I want the form to always post to /products/search.
My routes are :
routes.MapRoute( "Products search",
"products/search/{query}/{page}",
new { controller = "Products", action = "Search", query = "", page = 1 });
routes.MapRoute( "Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" });
How can I force Html.BeginForm(), or more specifically Url.Action( "Search", "Products"), to ignore the /query/page in the url?
Thanks

Fixed by adding another route where query and page are not in the url which is kind of counter intuitive because the more specific route is lower down the order
routes.MapRoute(
"",
"products/search",
new { controller = "Products", action = "Search", query = "", page = 1 });
routes.MapRoute(
"",
"products/search/{query}/{page}",
new { controller = "Products", action = "Search"} //, query = "", page = 1 });
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" });

The order is really important, the first route it hits that matches it uses. Therefore catch all type routes should be at the very end. Here is a helpful route debugger youc an use to figure out what the problem is.
Route Debugger

Related

In ASP.NET MVC5, how can I hide the Action name when an a tag is generated in Razor using Url.Action?

As the title says.
I have a route set up and working fine, which provides a default action when none is specified. I just want to hide the action from the URL because it's unnecessary clutter.
Setting the "ActionName" parameter as null, or "", will just result in the current page's action being substituted instead - which doesn't work.
I'm open to using #Html.ActionLink() if that will get me what I need.
My route definition is
routes.MapRoute(
name: "MyBookRoute",
url: "Book/{id}",
defaults: new { controller = "Book", action = "Index" }
);
If all else fails, I suppose I can deal with writing out the hrefs manually, but this should not be a difficult thing for Razor to do.
Has anyone else come across this and knows what to do?
Base on your route definition, then either
#Url.Action("Index", "Book", new { id = 1 })
or
#Html.ActionLink("Your link text", "Index", "Book", new { id = 1 }, null)
will remove the action name from the generated url.

How to pass a parameter in place of controller name in ASP MVC?

I would like to know about this.
As we already know, the first parameter to a URL in ASP MVC would be a controller name as in
http://www.somedomain.com/Home/Index
Here, Home is controller and Index is action.
So if some one wanted to pass a value to this URL, he would do so like
http://www.somedomain.com/Home/Index/abc-power-corporation
where abc-power-corporation is a string identifier for a registered organization.
This is pretty much simple and routine. But I would like to know if there is a way to use this URL.
http://www.somedomain.com/abc-power-corporation
so that the URL is much friendlier and easier.
This should take me to the profile of the desired company.
Yes, you can do this in RouteConfig.cs.
Replace this:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
With this:
routes.MapRoute(
name: "RetrieveById",
url: "{id}",
defaults: new { controller = "ControllerNametoUse",
action = "ActionNameToUse", id = UrlParameter.Optional }
);
Note that it wouldn't be all that advisable to use both of these at the same time because it would create ambiguity, but it's still possible to use both of them as long as Action is explicitly specified in the URL and you specify the RetrieveById first in RouteConfig.cs.
You could also add more specific routes to get around the ambiguity issue:
routes.MapRoute(
name: "Customers",
url: "Customers/{action}/{id}",
defaults: new { controller = "Customers", action = "Index", id = UrlParameter.Optional }
);
These would need to be specified before the RetrieveById route so that they take precedence.

mvc3 map routes

I am looking to use the following urls and maps some routes accordingly
<domain>/Home/About
<domain>/Home/SiteList
<domain>/Site/<id>/ (this one is defaulted to the details view)
<domain>/Site/<id>/section1/ (this one goes to section1 route in the Site controller)
<domain>/Site/<id>/section2/ (this one goes to section2 route in the Site controller)
e.g.
<domain>/Site/london/siteinfo
The above are covered by
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
However, i also want to use the following routes
<domain>/Site/<siteid>/section1/controller/action (where controller gets data linked to the <siteid> and action is optional)
an example link would be:
<domain>/Site/london/siteinfo/manager (manager is a controller and will list managers for the site)
if have tried various routes and read various posts but could not find anything which was applicable to me.
Can anyone provide some help please?
Thanks
Rudy
Add one more route below "Default":
routes.MapRoute(
"MyRouteName", // Route name
"{controller}/{action}/{id}/{section}/{subsection}", // URL with parameters
new { controller = "Home", action = "Index", id= "", section= "", subsection = "" } // Parameter defaults
);

ASP.NET MVC How can better filter my route?

I have added a new route to my routing table:
routes.MapRoute(
"ModuleRoute", // Route name
"Module/{href}", // URL with parameters
new { controller = "Module", action = "GetHtml" }// Parameter defaults
);
I need this route to match on the following url structure:
/module/123abc.html
The problem is it also matches on this structure
/module/Launch/123abc.html
Calling link :
<%: Html.ActionLink("Launch", "Launch", new { href = item.Href })%>
How do I stop that from happening? I want he second structure to continue to be matched by the default route. I thought that because the number of parameters are different that this would not be a problem.
How can better filter my route to prevent this?
Thanks!
i agree with Max Toro, i've done some testing and that URL doesn't match Module/{href}.
This:
<%: Html.ActionLink("Launch", "Launch", new { href = item.Href })%>
is actually hitting the default route. You see this if you change the default route to the below (note the id is changed to href
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{href}", // URL with parameters
new { controller = "Home", action = "Index", href = UrlParameter.Optional } // Parameter defaults
);
so, this proves it is falling through the first route since it gets a proper url (no querystrings)
what it is doing (when you have the usual default route with id) is that the controller and action are matched but the id isn't. This is OK - the route still matches but leaves off the id. All additional values, such as your href are appended as querystring parameters so you end up with:
module/Launch?href=123abc.html
The way to get around it is to add another route similar to the one above that uses href instead of id
something like:
routes.MapRoute(
"Launch",
"Module/Launch/{href}",
new { controller = "Module", action = "Launch", href = UrlParameter.Optional }
);

How do I get this ASP.NET routing to work properly?

I'm trying to write a really simple prototype of a CMS system using ASP.Net MVC 3.
The system has a single controller with two actions: show and create.
The format for the 'Show' action is meant to take up to 5 optional parts, e.g. domain.com/part1/part2/part3/part4/part5
The format for the 'Show' action is similar, but should have a leading 'create' part e.g. domain.com/create/part1/part2/part3/part4/part5
I have the following settings in my global.asax:
routes.MapRoute(
"CreatePageRoute",
"create/{part1}/{part2}/{part3}/{part4}/{part5}",
new
{
controller = "Page",
action = "Create",
part1 = UrlParameter.Optional,
part2 = UrlParameter.Optional,
part3 = UrlParameter.Optional,
part4 = UrlParameter.Optional,
part5 = UrlParameter.Optional
});
routes.MapRoute(
"Default",
"{part1}/{part2}/{part3}/{part4}/{part5}",
new
{
controller = "Page",
action = "Show",
part1 = UrlParameter.Optional,
part2 = UrlParameter.Optional,
part3 = UrlParameter.Optional,
part4 = UrlParameter.Optional,
part5 = UrlParameter.Optional
}
);
If my 'Show' method fails to find a page matching the supplied path, it returns a 'not found' page that includes an options to create a new page with the supplied path. This link is defined using the following:
#Html.ActionLink("Yes", "Create")
[the "Yes" represents the answer to the question "do you want to create a page for this path?"]
So when testing the 'Default' route, I see that my 'Show' action is called successfully for all of the following paths:
{empty}
a
a/b
a/b/c
a/b/c/d
a/b/c/d/e
which is great.
However, the resulting 'create' link generated by the statement "#Html.ActionLink("Yes", "Create")" gives inconsistent results. It seems to generate a different hyperlink depending on the length of the input. The results are as follow:
For path "{empty}", the link offers "localhost{:port}/" - I was hoping for "localhost{:port}/create"
For path "/a", the link offers "localhost{:port}/" - I was hoping for "localhost{:port}/create/a"
For path "/a/b", the link offers "localhost{:port}/a" - I was hoping for "localhost{:port}/create/a/b"
For path "/a/b/c", the link offers "localhost{:port}/a/b" - I was hoping for "localhost{:port}/create/a/b/c"
For path "/a/b/c/d", the link offers "localhost{:port}/create/a/b/c/d" - which is what I was hoping for
For path "/a/b/c/d/e", the link offers "localhost{:port}/create/a/b/c/d/e" - which is what I was hoping for
Why does it only work when I supply "/a/b/c/d" or "/a/b/c/d/e"?
I know I'm being idiotic, please help me
Sandy
I believe that multiple optional parameters are causing the discrepency.
How about:
routes.MapRoute("Create5", "create/{part1}/{part2}/{part3}/{part4}/{part5}", new { controller = "Page", action = "Create", part5 = UrlParameter.Optional });
routes.MapRoute("Create3", "create/{part1}/{part2}/{part3}", new { controller = "Page", action = "Create", part3 = UrlParameter.Optional });
routes.MapRoute("Create1", "create/{part1}", new { controller = "Page", action = "Create", part1 = UrlParameter.Optional });
routes.MapRoute("Default5", "{part1}/{part2}/{part3}/{part4}/{part5}", new { controller = "Page", action = "Show", part5 = UrlParameter.Optional });
routes.MapRoute("Default3", "{part1}/{part2}/{part3}", new { controller = "Page", action = "Show", part3 = UrlParameter.Optional });
routes.MapRoute("Default1", "{part1}", new { controller = "Page", action = "Show", part1 = UrlParameter.Optional });

Resources