ASP.NET MVC ActionLink: сгенерирован странный URL - PullRequest
2 голосов
/ 06 февраля 2010

Почему следующий Html.ActionLink звонит:

Html.ActionLink("Approve", "Advance", new { id = Model.ID, step = StepType.Approve })

создать URL-адрес с параметрами запроса, а не "успокоительный" URL, т. Е .:

http://localhost/Website/Case/Advance/1?step=Refer

У меня зарегистрирован только маршрут по умолчанию, нужны ли мне дополнительные маршруты, которые могут понять, что такое параметр "StepType"?

Я пытался добавить этот маршрут в после маршрута по умолчанию:

routes.MapRoute(
    "CaseAdvance",
    "{controller}/{action}/{id}/{step}",
    new {controller = "Case", action = "Advance", id = "", step = StepType.Refer});

но это не имело никакого эффекта. При добавлении регистрации нового маршрута до по умолчанию я получил ошибку:

Словарь параметров содержит пустая запись для параметра 'id' из необнуляемый тип 'System.Int64' для метод 'System.Web.Mvc.ActionResult Advance (Int64, Website.Core.StepType) ' в 'Website.Controllers.CaseController. Чтобы сделать параметр необязательным, его тип должен быть либо ссылочным типом, либо Обнуляемый тип.

Ответы [ 4 ]

2 голосов
/ 07 февраля 2010

Пользовательский маршрут в данный момент перехватывает слишком много

Ваше исключение говорит только о том, что ваш пользовательский маршрут перехватывает то, что вы не собирались перехватить. Так что если будет запрос к корневому URL вашего приложения:

http://localhost/Website

Ваш пользовательский маршрут поймает его. И установите его по умолчанию. И назови свое CaseController.Advance() действие. И, конечно, выведите исключение, потому что id не определено.

Держите ваш собственный маршрут перед маршрутом по умолчанию

Но вам придется изменить свой пользовательский маршрут или добавить к нему ограничения маршрута, чтобы он фактически перехватывал только те запросы, которые он должен перехватить.

Но какое изменение вы должны сделать? Если нужен только один контроллер, то измените его на:

routes.MapRoute(
    "CaseAdvance",
    "Case/{action}/{id}/{step}",
    new { controller = "Case", action = "Advance", id = "", step = StepType.Refer});

Если есть другие контроллеры, вы можете оставить их как есть, просто добавьте ограничения:

routes.MapRoute(
    "CaseAdvance",
    "{controller}/{action}/{id}/{step}",
    new { controller = "Case", action = "Advance", id = "", step = StepType.Refer},
    new { controller = "Case|Other" });

Если может быть любой контроллер, вы можете указать, чтобы ваш идентификатор был числовым:

routes.MapRoute(
    "CaseAdvance",
    "{controller}/{action}/{id}/{step}",
    new { controller = "Case", action = "Advance", id = "", step = StepType.Refer},
    new { id = @"\d+" })

В этом случае этот маршрут будет перехватывать только те запросы, для которых фактически определен идентификатор. Как число конечно.

Вы будете знать, какой из них подходит вам лучше всего.

2 голосов
/ 06 февраля 2010

Да, если нет маршрута, такого как "{controller} / {action} / {id} / {step}", тогда метод ActionLink просто передаст "step" в качестве параметра строки запроса.

1 голос
/ 06 февраля 2010

Попробуйте использовать RouteLink и посмотрите, подходит ли вам это.

Html.RouteLink("Approve", "CaseAdvance", new { controller = "Case", action = "Advance", id = Model.ID, step = StepType.Approve })

Если вызов RouteLink создает действительную ссылку, это по крайней мере будет означать, что ваш маршрут настроен правильно.

1 голос
/ 06 февраля 2010

В вашем маршруте вы указали параметр stepType, но передавали параметр с именем step.

Имена ваших параметров actionlink должны совпадать с именами параметров маршрута, иначе вы получите именно то, что видите.

РЕДАКТИРОВАТЬ: Хорошо, вы изменили свой код, пока я печатал этот ответ !!

...