Как перенаправить URL-адрес с помощью строки запроса в ASP.NET MVC?
Я пытаюсь настроить собственный маршрут в MVC, чтобы получить URL из другой системы в следующем формате:
../ABC/ABC01?Key=123&Group=456
01 после второго ABC - это номер шага, который изменится, и параметры Key и Group изменятся. Мне нужно направить это на одно действие в контроллере с ключом номера шага и группой в качестве параметров. Я попытался выполнить следующий код, однако он выдает исключение:
код:
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.`
Ответы
Ответ 1
Вы не можете включить строку запроса в маршрут. Попробуйте маршрут следующим образом:
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 автоматически сопоставляет параметры строки запроса с параметрами в методе контроллера.
Ответ 2
При определении маршрутов вы не можете использовать /
в начале маршрута:
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-адрес и отправит его в действие.
Ответ 3
Нет причин использовать маршрутизацию, основанную на querystring, в новом проекте 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 ());
}
Ответ 4
Аргументы строки запроса обычно специфичны для этого контроллера и конкретной логики приложения.
Итак, это будет лучше, если это не написано правилами маршрута, которые являются общими.
Вы можете встроить определение строки запроса в аргумент action следующим образом.
Я думаю, что лучше иметь один контроллер для обработки 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"}
);
Я использовал этот метод для получения значения ключа нескольких полей при действии контроллера.