ASP.NET MVC retrieving route to controller, action and parameters - asp.net

In ASP.NET MVC how can I generate a URL to a specific controller and action along with other parameters. The RedirectToAction allows me to redirect, but I would like to retrieve this URL instead from within my controller.
I tried using:
Url.Action("Page", "Administrator", New With {.page = _currentPage})
But that returned a link like /Administrator/Page?page=2 whereas I was hoping to retrieve something like /Administrator/Page/2
I've searched countless forums and I'm sure there is something around for this, but I cannot find it for the life of me.
Thanks!

What do your routes look like? The standard route expects an id as the third parameter. If you haven't changed your routes, try using:
Url.Action( "Page", "Administrator", New With { id = _currentPage } )

Related

How to approach making a controller with (unlimited) db look-up routes

I'm digging into ASP.NET MVC from classic asp, and have completed some tutorials. I understand the concept now, but I have a main question about the controller. How are you able to control the url structure if you are getting your url's (with params) from a sql database?
Example: /custom-url-1 or /custom-url-23423411
(Returns params accordingly to feed the code)
I'm guessing it would have to do with ActionResult Index() , but not sure where to go after that. Any idea's where to look or is this even possible? Does MVC even allow this?
One Way you can approach this is to have everything go to one action in one controller and resolve the content in the view.
This is useful only if you have one type of view.
Second way is to have route constraint or a custom route constraint for each type of content you have
say : Galleries, Blog, Pages
and in each constraint check if the given url is of this type ( by db call), if the constraint returns true, it will point the request to the given controller and action.
The third way is to have a custom route handler that does the checking and routing (mind you this is probably the hardest task but works best if you have complex system, if your is simple try using method 1 or 2
P.S. if you want your urls separataed by "-" instead of "/" you can do just this
routes.MapRoute(
"Default", // Route name
"{controller}-{action}-{id}",// URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
);

Capturing an incoming webforms request in an MVC route

I'm converting a legacy webforms app to MVC, working through it a page at a time. To make the project easier to work with I've moved all the webforms pages, which were previously in the route of the project into a /webforms subdirectory. So I need to capture any incoming requests for /page.aspx?param=123 and redirect them to /webforms/page.aspx?param=123. I thought an easy way to do this would be to setup a route handler that passed any such requests to a controller that does that job. I set up a route like so:
routes.MapRoute("WebformsRedirect", "{*page}",
new { controller = "Webforms", action = "ForwardToPage" },
new { page = #"\S+.aspx\S*" }
);
This kind of works but it doesn't capture the query string, only the page part. I can get the query string for the Request object in the controller so it's not a huge deal but it would be nice to be able to do it through the route only. My routing unit tests (which I copied from Steve Sanderson's MVC book) actually pass correctly when I test them with querystrings so I'm confused why it isn't working. Is my regular expression wrong? They aren't my strong point.
QueryStrings are not part of the routing
if you requested for example "Home/Index?foo=bar" and you have a route that match "Foo/Bar" to Controller Foo , Action Bar without any more routing info (don't know anything about foo) you still can write
class HomeController: Controller {
ActionResult Index(string foo) {
}
}
now foo variable will equal bar , why ?
because its the model binder that gets the value of the parameters passed.
the model binder check 4 repositories by default QueryString , Routing Place Holders ,FormsCollections and Files
so what i am trying to say , the route and QueryStrings are two different things , it doesn't need to capture it

Asp.NET MVC Route Performance

I have an application with a couple thousand routes.
This is because for each product we use a custom URL, as opposed to the textbook /product/id.
With this many urls, the performance is unacceptable in the router.
I am trying to find ways to improve it, but I am drawing a blank.
I have about 20 regex routes and about 3 thousand unique url routes.
Any Ideas?
Sorry for being so open ended, but I am not sure where to start.
If your urls are all on the format yoursite.com/{url}, you can still store all the three thousand urls in the database, and create a custom controller factory which uses the {url} parameter to look the correct information up in the database and assign correct controller, action and any parameters you're using.
There are lots of posts on google on how to implement the controller factory.
I imagine you'll also want some parsing of the existing routes to put them all in the database - this can probably be done by iterating over the RouteTable after you instantiate your application (i.e. after RegisterRoutes() is called).
I would get rid of the 3 thousand unique url routes and replace them with a generic route that is the last catch-all route. Something like:
routes.MapRoute("productRoute", "{category}/{manufacturer}/{productTitle}", new { controller = "Products", action = "Index", category = UrlParameter.Optional, manufacturer = UrlParameter.Optional, productTitle = UrlParameter.Optional });
You could also then add a custom IRouteConstraint to validate that the category exists (but just make sure it doesn't hit your database every time or performance will degrade).

Create route that will move the query string to part of the url

I'd like to change my routes so that instead of having:
/Users/Edit?UserID=1
I can do
/Users/Edit/1
How can I create a custom route to do that?
Also, can someone direct me to a good tutorial on routes? I don't wanna create a post every time I have a simple problem with routes.
Actually http://localhost/Users/Edit/1 can do the what you want without defining a new route. The default route structure is http://localhost/controllerName/actionMethodName/id.
So if you just use "id" instead of "UserID" in your action method. The number in the URL would be assigned to the parameter on action.
public ActionResult Edit(int id)
Here's a few lesson on routing. Take a look at them. It's a quite easy thing to understand.
http://www.asp.net/mvc/tutorials/asp-net-mvc-routing-overview-cs
http://www.asp.net/mvc/tutorials/creating-custom-routes-cs
http://weblogs.asp.net/scottgu/archive/2007/12/03/asp-net-mvc-framework-part-2-url-routing.aspx
You will want to use the htaccess file. You put in a regular expression which will extract pieces of the file path as if it is part of the query string.
This is a link I googled it may do the trick.
You will want to do something like this:
routes.MapRoute(
"MyRoute",
"{controller}/{action}/{UserId}",
new { controller = "DefaultController",
action = "DefaultAction",
UserId = UrlParameter.Optional }
);

ASP MVC Routing

now this is probably an stupid question but i'm new to mvc and can't seem to get it working.
Here is what i would like to be able to do with the urls/routes:
1) www.domain.com/name/home/index
2) www.domain.com/home/index
where both the home controllers are seperate controllers and the name part will very but all must go to the same controller and the name should be an param for all the actions in there.
Is this at all possible? Thanks for your help.
This might not be the answer you're looking for, but I think that it would be more usual to see
www.domain.com/home/index
www.domain.com/home/index/name
My initial thinking was that an overloaded Index action method would make sense, but Daniel pointed out that this not allowed (at least not in the manner I suggested).
Updated answer...
Your Index action method could take a string name argument, and your routes would need to contain something like
routes.MapRoute(
"Default",
"{controller}/{action}/{name}",
new { controller = "Home", action = "Index", name = "" }
In your action method a quick null check will tell you whether a name was included in the URL or not.

Resources