Передача данных из контроллера для просмотра, обратно в контроллер, обратно в просмотр - PullRequest
0 голосов
/ 29 ноября 2009

Я новичок в ASP.NET MVC. После долгой работы с традиционной моделью ASP.NET мне потребуется некоторое время, чтобы понять эту модель.

Я прохожу через NerdDinner, чтобы понять, как все работает.

Итак, у меня есть объект, который нужно пропустить через пару представлений. Аналогично статье NerdDinner Шаг 6: ViewData и ViewModel .

Я впервые сохраняю данные из Get to Post, затем помещаю их в TempData и передаю другому действию (AnotherAction). Как только я получу свои данные на Get, я не смогу сохранить их на Post.

Вот мой код:

public class DinnerFormViewModel
{
    public Dinner Dinner { get; private set; }

    public DinnerFormViewModel(Dinner dinner)
    {
        Dinner = dinner;
    }
}

public class DinnersController : Controller
{
    public ActionResult Action()
    {
        Dinner dinner = new Dinner();
        return View(new DinnerFormViewModel(dinner));
    }

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Action(Dinner dinner, FormCollection collection)
    {
        try
        {
            // Some code
            TempData["Dinner"] = dinner;
            return RedirectToAction("AnotherAction");
        }
        catch
        {
            return View();
        }
    }

    public ActionResult AnotherAction()
    {
        Dinner dinner = (Dinner)TempData["Dinner"]; // Got my dinner object
        return View(new DinnerFormViewModel(dinner));
    }

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult AnotherAction(Dinner dinner, FormCollection collection)
    {
        // Lost my dinner object, dinner comes in as null
    }
}

Ответы [ 4 ]

2 голосов
/ 29 ноября 2009

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

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

public ActionResult Action()
{
    Dinner dinner = new Dinner();
    return View(new DinnerFormViewModel(dinner));
}

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Action(Dinner dinner)
{
    try
    {
        return RedirectToAction("AnotherAction", dinner);
    }
    catch
    {
        return View();
    }
}

public ActionResult AnotherAction(Dinner dinner)
{
    return View(new DinnerFormViewModel(dinner));

    //In this view is where you may want to populate some hidden fields with the Dinner properties that have already been entered... so when the Post action picks up the dinner object it will be fully populated
}

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult AnotherAction(Dinner dinner)
{
    //work with fully populated Dinner object
}

Так что в представлении AnotherAction у вас будет что-то вроде:

<% using(Html.BeginForm()) { %>

    <%= Html.Hidden("dinnerProperty1") %>
    <%= Html.Hidden("dinnerProperty2") %>
    <%= Html.Hidden("dinnerProperty3") %>
    <%= Html.TextBox("dinnerProperty4") %>
    <%= Html.TextBox("dinnerProperty5") %>
    <%= Html.TextBox("dinnerProperty6") %>

<% } %>

В приведенном выше примере нет дружелюбия к пользователю, но вы получите точку.

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

Вы не можете передавать необработанные объекты C # из представлений в контроллеры.

В ASP.NET MVC, когда действие принимает объект для параметра, ASP.NET MVC просматривает все данные POST / GET и ищет значения, которые совпадают с именами свойств в объекте параметра.

public ActionResult SomeAction(Dinner myDinner)
{
        // do stuff
}

Объект myDinner будет заполняться ТОЛЬКО в том случае, если вы публикуете в действии поля формы, соответствующие свойствам объекта Dinner (местоположение, дата и т. Д.), Или если вы должны были разместить эту информацию в URL GET (Dinners / SomeAction? местоположение = Чикаго и дата = 12/1/2009 и т. д.)

Если вы абсолютно не можете использовать скрытые поля (как рекомендует DM), то, вероятно, ваш выбор - Sessions.

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

Согласно этому сообщению в блоге TempData существует только для одного запроса после его установки.

Вот цитата из поста:

Если вы установили TempData, а ваше действие затем возвращает ViewResult, то следующий запрос, каким бы он ни был (запрос AJAX, другая страница, которую пользователь открыл на другой вкладке и т. Д.), Увидит TempData значение, которое вы установили, и никакой другой запрос его не увидит.

Итак, учитывая код, который я вижу, вы можете получить обед из TempData при получении от AnotherAction, который является первым запросом после того, как вы установили его на Action. Однако, глядя на код и не видя код для просмотра для AnotherAction, неясно, как вы передаете данные в сообщение для AnotherAction. Экземпляр ужин не будет находиться в TempData для этого запроса, потому что это второй запрос после того, как вы установили его в TempData. И если в представлении AntoherAction не установлены правильные теги формы, в каркасе не будет правильных значений формы для создания экземпляра объекта ужин в публикации.

Так что либо вам придется сбросить TempData с помощью экземпляра обеда при первом вызове AnotherAction, а затем извлечь обед из TempData в сообщении AnotherAction, либо вы можете последовать совету dm и использовать скрытые поля. на ваш взгляд.

IMO, вы должны использовать способ DM для этого и избегать использования TempData.

Edit Добавлен пример сброса TempData в AnotherAction, чтобы получить доступ к нему в посте.

Модель:

  public class Dinner
  {
    public string Name{get;set;}
  }

  public class DinnerFormViewModel
  {
    public Dinner Dinner {get;private set;}

    public DinnerFormViewModel( Dinner dinner )
    {
      Dinner = dinner;
    }
  }

Контроллер:

  public class DinnersController : Controller
  {
    public ActionResult Action()
    {
      Dinner dinner = new Dinner();
      return View( new DinnerFormViewModel( dinner ) );
    }

    [AcceptVerbs( HttpVerbs.Post )]
    public ActionResult Action( Dinner dinner, FormCollection collection )
    {
      try
      {
        // Some code
        TempData[ "Dinner" ] = dinner;
        return RedirectToAction( "AnotherAction" );
      }
      catch
      {
        return View();
      }
    }

    public ActionResult AnotherAction()
    {
      Dinner dinner = ( Dinner )TempData[ "Dinner" ]; // Got my dinner object
      TempData[ "Dinner" ] = dinner; // Reset the dinner object in temp data
      return View( new DinnerFormViewModel( dinner ) );
    }

    [AcceptVerbs( HttpVerbs.Post )]
    public ActionResult AnotherAction( Dinner dinnerFromPostedFormValues, FormCollection collection )
    {
      //dinnerFromPostedFormValues is null
      var dinnerFromTempData = TempData[ "Dinner" ] as Dinner; // Got my dinner object

      return View( "Action", new DinnerFormViewModel( dinnerFromTempData ) );
    }
  }

Вид действия:

<h2>Action</h2>

<% using (Html.BeginForm()) {%>

    <fieldset>
        <legend>Fields</legend>
        <p>
           Name: <%= Html.TextBox("Name", Model.Dinner.Name ) %>
        </p>
        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>

<% } %>

Другой вид действия:

<h2>AnotherAction</h2>

<% using (Html.BeginForm()) {%>

  <fieldset>
      <legend>Fields</legend>
      <p>
          Name:
          <%= Html.Encode(Model.Dinner.Name) %>
      </p>

      <p>
          <input type="submit" value="Do Something" />
      </p>
  </fieldset>

<% } %>
0 голосов
/ 29 ноября 2009

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

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult AnotherAction(int dinnerId, FormCollection collection)
{
    var dinner = dinnerRepository.Get(dinnerId);
    ... do something with dinner ...
    dinnerRepository.Save(dinner);
    return RedirectToAction("AnotherAction", ... pass dinner id ...);
}

Действия GET также можно выполнять из репозитория, поэтому вы можете передавать только идентификатор.

РЕДАКТИРОВАТЬ

Если вы хотите создать страницу стиля мастера, вы можете сохранить ранее введенные данные в объекте Session.

Session['CurrentDinner'] = dinner;

Данные, хранящиеся в сеансе, сохраняются в запросах.

...