MVC Маршруты на основе параметров POST - PullRequest
0 голосов
/ 17 февраля 2011

У нас есть приложение PHP, которое мы конвертируем в MVC.Цель состоит в том, чтобы приложение оставалось идентичным с точки зрения URL и HTML (SEO и подобный + сайт PHP все еще работают).У нас есть процесс бронирования, состоящий из 3 просмотров, и на текущем PHP-сайте все эти представления возвращаются на один и тот же URL, отправляя скрытое поле, чтобы определить, какая страница / шаг в процессе бронирования отправляется обратно (данные между страницами сохраняются).в состоянии, как запрос построен).

Чтобы воспроизвести это в MVC, у нас может быть один метод действия, на который отправляются все 3 страницы, с одним переплетом, который заполняет только часть модели в зависимости от того, с какой страницы она была опубликована, и контроллерсмотрит на модель и решает, что будет дальше в процессе бронирования.Или, если это возможно (и это мой вопрос) , настройте маршрут, который может считывать параметры POST и, основываясь на значениях параметров POST, направьте метод различного действия.

Насколько я понимаю, в MVC-маршрутизации нет такой поддержки, как она есть (но я бы хотел ошибиться в этом), поэтому где мне нужно взглянуть на расширение MVC, чтобы поддержать это??(Я думаю, что несколько методов действия чище).

Ваша помощь будет высоко ценится.

1 Ответ

2 голосов
/ 21 марта 2011

Я натолкнулся на два решения, одно из которых было разработано кем-то, с кем я работаю, а затем другое, более элегантное для меня!

Первое решение состояло в том, чтобы указать класс, который расширяет MVcRouteHandler для указанного маршрута.Этот обработчик маршрута может проверить маршрут в форме HttpContext, прочитать данные формы и затем обновить RouteData в RequestContext.

MapRoute(routes, 
            "Book",
            "{locale}/book",
            new { controller = "Reservation", action = "Index" }).RouteHandler = new ReservationRouteHandler();

ReservationRouteHandler выглядит следующим образом:

public class ReservationRouteHandler: MvcRouteHandler
{
    protected override IHttpHandler GetHttpHandler(RequestContext requestContext)
    {
        var request = requestContext.HttpContext.Request;

        // First attempt to match one of the posted tab types
        var action = ReservationNavigationHandler.GetActionFromPostData(request);

        requestContext.RouteData.Values["action"] = action.ActionName;
        requestContext.RouteData.Values["viewStage"] = action.ViewStage;

        return base.GetHttpHandler(requestContext);
    }        

NavigationHandler фактически выполняет работу по поиску данных формы, но вы поняли идею.

Это решение работает, однако, оно выглядит немного неуклюжим и, глядя на класс контроллера, вы никогда не узнаетеэто происходило, и я бы не понял, почему en-gb / book будет указывать на разные методы, не говоря уже о том, что это не так уж многократно.

Лучшее решение состоит в том, чтобы перегружать методы на контроллере, т. Е. В этом случае они все называются book, а затем определять ваш собственный обычный ActionMethodSelectorAttribute.Это то, из чего вытекает атрибут HttpPost.

 public class FormPostFilterAttribute : ActionMethodSelectorAttribute
{
    private readonly string _elementId;
    private readonly string _requiredValue;

    public FormPostFilterAttribute(string elementId, string requiredValue)
   { 
        _elementId = elementId;
        _requiredValue = requiredValue;
    }

    public override bool IsValidForRequest(ControllerContext controllerContext, System.Reflection.MethodInfo methodInfo)
    {
        if (string.IsNullOrEmpty(controllerContext.HttpContext.Request.Form[_elementId]))
        {
            return false;
        }

        if (controllerContext.HttpContext.Request.Form[_elementId] != _requiredValue)
        {
            return false;
        }

        return true;
    }
}

MVC вызывает этот класс, когда пытается разрешить правильный метод действия на контроллере с учетом URL-адреса.Затем мы объявляем методы действия следующим образом:

public ActionResult Book(HotelSummaryPostData hotelSummary)
    {
        return View("CustomerDetails");
    }

    [FormFieldFilter("stepID", "1")]
    public ActionResult Book(YourDetailsPostData yourDetails, RequestedViewPostData requestedView)
    {
        return View(requestedView.RequestedView);
    }

    [FormFieldFilter("stepID", "2")]
    public ActionResult Book(RoomDetailsPostData roomDetails, RequestedViewPostData requestedView)
    {
        return View(requestedView.RequestedView);
    }

    [HttpGet]
    public ActionResult Book()
    {
        return View();
    }

Нам нужно определить скрытое поле stepID на разных страницах, чтобы при отправке форм на этих страницах обратно на общий URL-адрес атрибуты SelectorAttributes правильно определяли, какое действиеметод для вызова.Я был удивлен, что он правильно выбирает метод действия, когда метод с одинаковым именем существует без набора атрибутов, но также рад.

Я не смотрел, можете ли вы сложить эти селекторы методов, я думаю, что вы можетехотя это сделало бы эту чертовски классную функцию в MVC.

Я надеюсь, что этот ответ пригодится кому-то, кроме меня.:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...