Передача данных из контроллера в представление, обратно в контроллер, обратно в представление

StackOverflow https://stackoverflow.com/questions/1814049

Вопрос

Я новичок в 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
    }
}
Это было полезно?

Решение

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

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

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

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

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

ИМО, вам следует использовать способ DM и избегать использования TempData.

Изменить Добавлен пример сброса 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>

<% } %>

Другие советы

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

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

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") %>

<% } %>

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

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

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

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

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

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

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

[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;

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top