0

I have controller with 2 methods, with following signature:

public class TestController
{
    [HttpGet]
    public ActionResult TestMethod1()
    {
        //here code
        return Json(1, JsonRequestBehavior.AllowGet);
    }

    [HttpGet]
    public ActionResult TestMethod2(long userId)
    {
        //here code
        return Json("userId= " + userId, JsonRequestBehavior.AllowGet);
    }
}

I want to create the following routers for this methods:

  1. For the first method:

    http://domain/test/

  2. For the second method:

    http://domain/test?userId={userId_value}

I tried to use the following routes:

1.

context.MapRoute("route_with_value",
        "test/{userId}",
        new { controller = "test", action = "TestMethod2" });

context.MapRoute("route_no_value",
        "test",
        new { controller = "test", action = "TestMethod1" });

but this way does not work for me

2.

context.MapRoute("route_with_value",
        "test?userId={userId}",
        new { controller = "test", action = "TestMethod2" });

context.MapRoute("route_no_value",
        "test",
        new { controller = "test", action = "TestMethod1" });

but I get the error:

The route URL cannot start with a '/' or '~' character and it cannot contain a '?' character.

Is it possible to create map route for my urls?

NightOwl888
  • 55,572
  • 24
  • 139
  • 212
netwer
  • 737
  • 11
  • 33
  • Your parameter is `id` so either the route needs to be `"test/{id}",` or the parameter needs to be `long userId` (but that will create `.../test/1` for the first and `.../test` for the 2nd) –  Jul 02 '16 at 12:38
  • @StephenMuecke thank for your comment, but I don't understand your opinion – netwer Jul 02 '16 at 12:41
  • What do you not understand? You first state you want `.../test?id=1` which is a query string value, not a route value, but then you show routes (so which do you want - query string values or route values?). If you have a url which is `.../test?id=1` it does not match the first route, because the first route requires a parameter named `userd` (not `id`) so it goes to the 2nd route (which calls `TestMethod1()`). –  Jul 02 '16 at 12:46
  • @StephenMuecke thank you, now I understand you. I need route values with routers which I shown above. – netwer Jul 02 '16 at 12:51
  • Just change the first one to `"test/{id}",` –  Jul 02 '16 at 12:55
  • @StephenMuecke oops sorry, I made a typo :( the first method have the parameter with name equal userId – netwer Jul 02 '16 at 12:57
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/116259/discussion-between-stephen-muecke-and-netwer). –  Jul 02 '16 at 13:01

1 Answers1

-1

The built-in routing methods are unaware of query string values. To make them aware, you need to build custom routes or constraints.

In this case, making a simple constraint will work since you just want to run the first route whenever the query string key is present.

public class QueryStringParameterConstraint : IRouteConstraint
{
    private readonly string queryStringKeyName;

    public QueryStringParameterConstraint(string queryStringKeyName)
    {
        if (string.IsNullOrEmpty(queryStringKeyName))
            throw new ArgumentNullException("queryStringKeyName");
        this.queryStringKeyName = queryStringKeyName;
    }

    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
    {
        if (routeDirection == RouteDirection.IncomingRequest)
        {
            return httpContext.Request.QueryString.AllKeys.Contains(this.queryStringKeyName, StringComparer.OrdinalIgnoreCase);
        }

        return true;
    }
}

Usage

context.MapRoute(
    name: "route_with_value",
    url: "test",
    defaults: new { controller = "test", action = "TestMethod2" },
    constraints: new { _ = new QueryStringParameterConstraint("userId") }
);

context.MapRoute(
    name: "route_no_value",
    url: "test",
    defaults: new { controller = "test", action = "TestMethod1" }
);
NightOwl888
  • 55,572
  • 24
  • 139
  • 212