Can you use Routes and Query String Values Together? - c#

Is it possible to use routing and query strings together?
An example would be the following as a route in my Global.asax file:
void RegisterRoutes(System.Web.Routing.RouteCollection routes)
{
routes.MapPageRoute("My Route Name", "users/{UserName}", "~/users/UserInfo.aspx");
}
Could I somehow use http://www.mywebsite.com/users/usernamehere?info=bla and pass info=bla to the page? I would rather not try to encode this in the route schema.

Of course you can use routes and query string values together. When you define a route, your route is not determined by the query string; rather, it's determined by your URL parts.
Check out this concise article about using routes and query strings -- Sanderson points out that you can easily use the two together.
And even though the referenced article is about MVC2, you can use routing with ASP.NET web forms. I've used it before and it's not too hard to implement.

Related

ASP.NET Core : AddAreaPageRoute - parameter more than one time in the route

What I am trying to do is something like this:
services
.AddRazorPages()
.AddRazorPagesOptions(options =>
{
options.Conventions.AddAreaPageRoute("Products", "/DownloadDoc", "Products/{keycode}/{keycode}-document.pdf");
});
So if keycode was productTest, the url generated should be:
Products/productTest/productTest-document.pdf
Not sure if it is possible or not?
Currently it throws this error:
RoutePatternException: The route parameter name 'keycode' appears more than one time in the route template.
I have even tried things like this:
options.Conventions.AddAreaPageRoute("Products", "/DownloadDoc", "Products/{keycode2:keycode}/{keycode}-document.pdf");
actually, the problem is the naming problem.
The URL format doesn't support multi able same parameters name.
Can you try like this
options.Conventions.AddAreaPageRoute("Products", "/DownloadDoc", "Products/{keycode}/{keycode2}-document.pdf");
According to your route rule Products/{keycode}/{keycode}-document.pdf, this rule means it will match the two part for the url with the same parameter. This is not expected inside the asp.net core rule mapping rule.
If you think this two parameter should be the same, you could make a check by using a specific middleware or else.
If you make sure this two parameters will be the same, I think just one keycode is enough.

web api 2 routing with version and route attributes

Within my project I have 2 versions of an API. From this Post I understand that a custom control selector needs writing so it get get the different versions (as webapi looks for controller name match and ignores the namespaces they are in).
This all works OK and I can make the calls to the different versions.
However, I also utilise the new data attribute routing from web api 2 and when using this the customer control selector does not handle the routing correctly.
The routing data attributes I am using are as follows.
(The V01 differs between the versions so it can be V02)
[Route("api/v01/enumeration/{type}/{subtype}")]
This can contain some additional query string params at the end as well
[Route("api/V01/user/readbyreference")]
this takes a query string of ?id=EMAIL|email.domain.com
The code for the customer control selector can be found here
I can see the issue is with GetRouteVariable to get the needed namespace part and controller, but I was wondering if anyone else has had to do something like this and if they have any way around it.
I will be looking into so if I find something I will update on here but if you have anything please let me know.
Thanks
Mark
After a bit of digging I have found out that attribute routing goes via a different path.
So to handle attribute routing in the GetRouteVariable you need to grab the MS_SubRoutes values and then perform the needed action on the result to get the namespace and controller.
The below needs tidying up but it at least gives you the idea of what is done to process data attribute routing in your custom control selector
var subroutes = (IEnumerable<IHttpRouteData>)routeData.Values["MS_SubRoutes"];
var routeBreakDown= subroutes.First().Route.RouteTemplate.Split('/');
if (name == "namespace")
{
return (T)(object)routeBreakDown[1]; //namespace
}
else if (name == "controller")
{
return (T)(object)routeBreakDown[2]; //controller
}
Cheers
Mark

Generate new url by substituting action in current url - ASP.NET MVC

I'm curious whether this is possible, or as I suspect, by design not.
In an ASP.NET MVC project I have multiple routes like this:
new Route(
url, // This can be arbitrary
new RouteValueDictionary {
{"area", "MyArea"},
{"controller", "MyController"},
{"action", "Index"}
},
new RouteValueDictionary(),
new RouteValueDictionary {
{"area", "MyArea"},
},
new MvcRouteHandler()))
I'd like to generate urls (or links) in the (Razor) views used by the actions of MyController. These urls should point to another action of MyController.
Now the problem is, there are multiple routes like above registered under different urls, so simply calling Html.ActionLink() or Url.Action() with the current route values yields a link that points to the url that's route first matches it. That's not necessarily the url the action is currently invoked from.
So basically what I'd like is take the current route and substitute the action with another one. I couldn't find any way to do that.
The urls can be arbitrary, but if necessary, constraints can be applied, e.g. so that the url must contain an action token. Actually all of them currently do, so urls have the following structure:
/AnotherArea/SubSegment/{action} // Routes point from other areas to MyArea/MyController
These urls are there in Html.ViewContext.RouteData.Route.Url of the view, so that action token should be changed somehow when generating a new url. (Well, one could do that with string replacement, but I guess if there is a solution, it should be better than that.)
Thank you for your time!
Now I found a solution, pretty simple:
#Url.RouteUrl("RouteName", new { Action = "OtherAction" })
However this implies the knowledge of the currently used route's name. Since this isn't stored in the Route object itself I opted with the kind of hackish solution of storing the name in the route's DataTokens dictionary. That seemingly doesn't harm and since routes are filled through a service this convention of using DataTokens doesn't need to be kept in mind.
I'm wondering if there's a better solution, though.

How to route URLs like /controller/action-name to controller/action_name in ASP.NET MVC

I want my URLs use '-' but the C# method name cannot contains that character. How do I make this route?
You would need to define a new route handler which handles the hyphens before the controller and action elements are mapped to class and methods. Check out this StackOverflow question

How to get all active parameters in ASP.NET MVC (2)

I was wondering whether there is a way to create an ActionLink or similar, that changes only a few parameters of the actual query, and keeps all the other parameters intact. For example if I'm on an URL like http://example.com/Posts/Index?Page=5&OrderBy=Name&OrderDesc=True I want to change only the Page, or OrderBy parameter and keep all other parameters the same, even those I don't yet know of (like when I want to add a Search parameter or something similar too).
The header of my current action looks like this:
public ActionResult Index(int? Page, string OrderBy, bool? Desc)
and I'm only interested in the values that this controller "eats". I want however that when I extend this action (for example with a string Search parameter) the links should work the same way as before.
Here is what I did already:
Create a new RouteValueDictionary and fill it with everything from RouteData.Values
Problem: This only fills the parameters that are used in the Routing, so all other optional parameters (like Page) to the controller are lost
Add everything from HttpContext.Request.QueryString to the previous dictionary
This is what I am currently using
Problem: It might have some junk stuff, that the Controller didn`t ask for, and it doesn't work if the page was loaded using POST. You also don't have any ModelBindings (but this isn't much of a problem, because we are re-sending everything anyway)
Use HttpContext.Request.Params
Problem: this has too much junk data which imho one shouldn't add to a RouteValueDictionary that is passed to an ActionLink
So the questions:
Is there an RVD that has all the data that was passed to the Controller and was used by it?
Is this solution good, or are there any caveats I didn't think about (mainly in the context of changing a few query parameters while keeping the others intact)?
Is there a way to filter out the "junk" data from the Params object?
EDIT: Checked the RouteData.DataTokens variable, but it's usually empty, and doesn't contain everything I need. It seems to only contain parameters that are needed for the routing somewhere, but not all of the parameters.
Have a look in RouteData.DataTokens.
RouteData.DataTokens # MSDN documentation:
Gets a collection of custom values that are passed to the route handler but are not used when ASP.NET routing determines whether the route matches a request.
HTHs,
Charles

Categories

Resources