Как создать краткий и мастер RESTful под MVC? - PullRequest
8 голосов
/ 03 апреля 2009

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

Возьмем, к примеру, многостраничный процесс регистрации.

Вариант 1: Я могу создать контроллер для каждого шага и вызывать новый или редактировать, когда пользователь достигает этого шага (или возвращается к нему). Я заканчиваю step1_controller, step2_controller и т. Д ...

Вариант 2: Я могу создать один контроллер и отслеживать, где они находятся в процессе регистрации, с помощью параметра, переменной сеанса, конечного автомата - что угодно. Таким образом, у меня есть signup_controller / step? Id = 1

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

Есть ли лучший вариант?

Я работаю в ruby ​​на рельсах, но этот вопрос относится к другим реализациям MVC, таким как ASP.NET MVC

Ответы [ 3 ]

12 голосов
/ 04 апреля 2009

Если вы примените здесь некоторую DDD-логику, которая дополняет букву «M» в MVC, состояние пользовательского интерфейса (процесс регистрации) принадлежит прикладному уровню, который может напрямую взаимодействовать с уровнями домена и инфраструктуры (четыре уровня: пользовательский интерфейс) Приложение, домен и инфраструктура). Концепция DDD заставляет вас «задуматься» о том, как сначала решить решение в коде. Давайте пройдем через это ...

Это индикатор прогресса

Состояние, которое вы хотите сохранить, - это шаг или ход регистрации. Итак, мой первый шаг - документировать прогресс или «шаги». Например, Шаг 1: Получить имя пользователя / пароль, Шаг 2: Получить электронную почту. В этом случае я бы применил логику, чтобы «переместить» модель на следующий шаг. Скорее всего, с помощью метода NextStep () в RegistrationService (RegistrationService.NextStep ()).

Ах, но это относится к слою приложения

Я бы создал службу на уровне приложений под названием RegistrationService. Я бы разместил здесь метод NextStep (). Но помните, что домен не будет содержать состояние модели здесь. В этом случае вы бы хотели сфокусировать состояние на прикладном уровне. Таким образом, в этом случае NextStep () будет воздействовать не на объект модели (поскольку он не входит в сферу ответственности домена), а на пользовательский интерфейс. Итак, вам нужно что-то, чтобы сохранить состояние процесса регистрации.

Отойдите от модели предметной области, как насчет ViewModel?

Итак, теперь мы знаем, что должны сохранять состояние чего-либо в пользовательском интерфейсе. MVC допускает концепцию под названием ViewModels (в ASP.NET MVC не уверен, как это называется в RoR). Модель представления представляет модель, которая будет отображаться представлением и / или частичными представлениями.

ViewModel будет отличным местом для сохранения состояния этого объекта. Давайте назовем его RegistrationProgressViewModel () и добавим к нему метод NextStep (). Это, конечно, означает, что прикладному уровню придется сохранять местоположение RegistrationProgressViewModel, а уровень APplication изменяет его внутреннее содержимое на основе действий NextStep. если это сложно, вы можете создать RegistrationProgressService () на уровне приложения и поместить в него NextStep (), чтобы абстрагировать вашу логику.

Как передать ViewModel?

Последняя часть - как отследить состояние этого объекта. Поскольку веб-приложения не имеют состояния, вы должны сохранять контроль другими способами, а не приложением. В этом случае я хотел бы вернуться к: 1) сериализации ViewModel клиенту и разрешению клиенту передавать его назад и вперед, или 2) сохранять копию ViewModel на стороне сервера и передавать некоторый тип идентификатора назад и вперед клиенту и обратно.

Это хороший пример для размышления, так как я сам еще этого не делал. Для # 2 наиболее безопасный и застрахованный способ сохранения состояния этой ViewModel - это сохранение его на уровне инфраструктуры (да, уровень APp может напрямую связываться с уровнем инфраструктуры). Мне кажется, это много работы, потому что что-то, что может исчезнуть, и у меня будет частичная регистрация в моей БД.

Но, # 2 будет хранить личную информацию пользователя (имя пользователя, пароль, адрес электронной почты, CC # и т. Д.) На стороне сервера и не передавать ее туда и обратно.

Наконец-то ответ!

Итак, пройдя через это, мы придумали:

  • Создайте RegistrationProgressViewModel () на прикладном уровне.
  • Создайте RegistrationProgressService () с помощью метода NextStep (ViewModel vm) на уровне приложений.
  • Когда NextStep () выполняется, сохраните ViewModel в базе данных через слой инфраструктуры.

Таким образом, вам никогда не придется отслеживать, что такое «step? Id = 2» в самом View или самом пользовательском интерфейсе, так как ViewModel обновляется и обновляется (Authenticated, Verified, persisted to DB) по мере продвижения вперед.

Итак, ваша следующая задача - «двигаться вперед» в пользовательском интерфейсе. Это легко сделать с 1 контроллером, используя шаг или именованные шаги.

Я прошу прощения, но я пишу код C # ниже, так как это мой язык.

public class RegistrationController : Controller
{
  // http://domain.com/register
  public ActionResult Index()
  {
    return View(new RegistrationProgressViewModel);
  }

  // http://domain.com/register
  // And this posts back to itself.  Note the setting 
  // of "CurrentStep" property on the model below.
  //
  public ActionResult Index(
      RegistrationProgressViewModel model)
  {

    // The logic in NextStep() here checks the
    // business rules around the ViewModel, verifies its
    // authenticity, if valid it increases the
    // ViewModel's "CurrentStep", and finally persists
    // the viewmodel to the DB through the Infrastructure
    // layer.
    //
    RegistrationProgressService.NextStep(model);

    switch (model.CurrentStep)
    {
      case 2:
        // wire up the View for Step2 here.
        ...
        return View(model);
      case 3:
        // wire up the View for Step3 here.
        ...
        return View(model);
      case 4:
        // wire up the View for Step4 here.
        ...
        return View(model);
      default:
        // return to first page
        ...
        return View(model);
    }
  }
}

Вы заметите, что это абстрагирует «бизнес-логику» проверки внутреннего состояния модели в метод RegistrationProcessService.NextStep ().

Хорошее упражнение. :)

В конце концов, ваш «RESTful» url - это приятный и чистый POST для: / register, который ожидает ViewModel с конкретными заполненными свойствами. Если ViewModel недействителен, / register не переходит к следующему шагу.

7 голосов
/ 03 апреля 2009

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

1 голос
/ 25 ноября 2009

Хотя ответы - очень хорошие варианты, я все же использую подход, приведенный в:

Плечи великанов | Мастер RESTful с использованием ASP.Net MVC .

Это определенно стоит посмотреть. Хотя я должен сказать, что ответы, приведенные здесь, заставляют меня задуматься о том, чтобы переделать этого мастера, когда у меня будет время.

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