Как мне перенаправить URL с помощью строки запроса в ASP.NET MVC? - PullRequest
33 голосов
/ 04 августа 2011

Я пытаюсь настроить собственный маршрут в MVC для получения URL-адреса из другой системы в следующем формате:

../ABC/ABC01?Key=123&Group=456

01 после второго ABC является шагомчисло это изменится, и параметры ключа и группы будут изменены.Мне нужно направить это на одно действие в контроллере с ключом номера шага и группой в качестве параметров.Я попытался следующий код, однако он выдает исключение:

Код:

routes.MapRoute(
    "OpenCase", 
    "ABC/ABC{stepNo}?Key={key}&Group={group}",
    new {controller = "ABC1", action = "OpenCase"}
);

Исключение:

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

Ответы [ 4 ]

39 голосов
/ 04 августа 2011

Вы не можете включить строку запроса в маршрут. Попробуйте с таким маршрутом:

routes.MapRoute("OpenCase", "ABC/ABC{stepNo}",
   new { controller = "ABC1", action = "OpenCase" });

Затем на вашем контроллере добавьте метод, подобный этому:

public class ABC1 : Controller
{
    public ActionResult OpenCase(string stepno, string key, string group)
    {
        // do stuff here
        return View();
    }        
}

ASP.NET MVC автоматически сопоставит параметры строки запроса с параметрами в методе контроллера.

4 голосов
/ 04 августа 2011

При определении маршрутов вы не можете использовать / в начале маршрута:

routes.MapRoute("OpenCase",
    "/ABC/{controller}/{key}/{group}", <-- Bad; see / at beginning
    new { controller = "", action = "OpenCase" },
    new { key = @"\d+", group = @"\d+" }
    );

routes.MapRoute("OpenCase",
    "ABC/{controller}/{key}/{group}", <-- Good; No /  at beginning
    new { controller = "", action = "OpenCase" },
    new { key = @"\d+", group = @"\d+" }
    );

Попробуйте это:

routes.MapRoute("OpenCase",
    "ABC/{controller}/{key}/{group}",
    new { controller = "", action = "OpenCase" },
    new { key = @"\d+", group = @"\d+" }
    );

Тогда ваше действие должно выглядеть следующим образом:

public ActionResult OpenCase(int key, int group)
{
    //do stuff here
}

Похоже, вы соединяете stepNo и "ABC", чтобы получить контроллер, который ABC1.Вот почему я заменил этот раздел URL на {controller}.

Поскольку у вас также есть маршрут, который определяет «ключ» и «группу», вышеприведенный маршрут также перехватит ваш начальный URL и отправит его действию.

1 голос
/ 31 мая 2014

Нет причин использовать маршрутизацию на основе строки запроса в новом проекте ASP.NET MVC.Это может быть полезно для старого проекта, который был преобразован из классического проекта ASP.NET, и вы хотите сохранить URL-адреса.

Одним из решений может быть маршрутизация атрибутов.

Другим решением может быть написание пользовательскихмаршрутизации, производной от RouteBase:

public class MyOldClassicAspRouting : RouteBase
{

  public override RouteData GetRouteData(HttpContextBase httpContext)
  {
    if (httpContext.Request.Headers == null) //for unittest
      return null;

    var queryString = httpContext.Request.QueryString;

    //add your logic here based on querystring
    RouteData routeData = new RouteData(this, new MvcRouteHandler());
    routeData.Values.Add("controller", "...");
    routeData.Values.Add("action", "...");
  }

  public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
  {
     //Implement your formating Url formating here
     return null;
  }
}

И зарегистрируйте свой собственный класс маршрутизации

public static void RegisterRoutes(RouteCollection routes)
{
  ...

  routes.Add(new MyOldClassicAspRouting ());
}
0 голосов
/ 07 февраля 2017

Аргументы строки запроса обычно являются специфическими для этого контроллера и логики этого конкретного приложения.

Так что будет лучше, если это не записано в общих правилах маршрута.

Вы можете встроить обнаружение строки запроса в аргумент действия следующим образом.

Я думаю, что лучше иметь один контроллер для обработки StepNo.

public class ABC : Controller
{
    public ActionResult OpenCase(OpenCaseArguments arg)
    {
        // do stuff here
        // use arg.StepNo, arg.Key and arg.Group as You need
        return View();
    }        
}

public class OpenCaseArguments
{
    private string _id;
    public string id
    {
        get
        {
            return _id;
        }

        set
        {
            _id = value; // keep original value;
            ParseQueryString(value);
        }
    }

    public string  StepNo { get; set; }
    public string Key { get; set; }
    public string Group { get; set; }

    private void ParseQueryString(string qs)
    {
        var n = qs.IndexOf('?');
        if (n < 0) return;
        StepNo = qs.Substring(0, n); // extract the first part eg. {stepNo}
        NameValueCollection parms = HttpUtility.ParseQueryString(qs.Substring(n + 1));
        if (parms.Get("Key") != null) Key = parms.Get("Key");
        if (parms.Get("Group") != null) Group = parms.Get("Group");
    }

}

ModelBinder присваивает значение {id} полю id из OpenCaseArguments.Метод set обрабатывает логику разделения строк запроса.

И продолжайте маршрутизацию таким образом.При маршрутизации примечания получите строку запроса в аргументе id.

routes.MapRoute(
    "OpenCase", 
    "ABC/OpenCase/{id}",
    new {controller = "ABC", action = "OpenCase"}
);

Я использовал этот метод для получения значения ключа нескольких полей при действии контроллера.

...