データをコントローラーからビューに渡し、コントローラーに戻し、ビューに戻す

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はセット後、1つのリクエスト。

投稿からの引用:

  

TempDataを設定し、アクションがViewResultを返す場合、次のリクエストは、AJAXリクエスト、ユーザーが別のタブで開いた別のページなど、TempDataを表示します。設定した値で、他のリクエストには表示されません。

したがって、私が見ているコードを考えると、 Action に設定した後の最初の要求である AnotherAction からの取得で、TempDataから夕食を取得できます。 。ただし、コードを見て、 AnotherAction の表示用のコードが表示されない場合、 AnotherAction の投稿にデータを渡す方法が不明です。夕食のインスタンスは、TempDataで設定した後の2番目のリクエストであるため、そのリクエストのTempDataには含まれません。また、 AntoherAction ビューに適切なフォームタグが設定されていない場合、フレームワークには投稿でディナーオブジェクトをインスタンス化するための適切なフォーム値がありません。

したがって、最初の AnotherAction 呼び出しで、TempDataをディナーインスタンスでリセットし、ポスト AnotherAction のTempDataからディナーを取得するか、またはdmのアドバイスに従い、ビューで非表示フィールドを使用できます。

IMO、DMでこれを行う方法を使用し、TempDataの使用を避ける必要があります。

編集AnotherActionでTempDataをリセットして、投稿でアクセスできるようにする例を追加しました。

モデル:

  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>

<% } %>

AnotherActionビュー:

<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オブジェクトのプロパティ(場所、日付など)に対応するフォームフィールドを使用してアクションに投稿した場合、またはその情報をGET URL(Dinners / SomeAction? location = chicago&amp; date = 12/1/2009など)

非表示フィールドを絶対に使用できない場合(DMの推奨)、おそらくセッションが唯一のオプションです。

夕食はリポジトリから取得する必要があります。アクションは次のようになります。

[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アクションはリポジトリからも取得できるため、idのみを渡すことができます。

編集

ウィザードスタイルページを作成する場合、以前に入力したデータをSessionオブジェクトに保存できます。

Session['CurrentDinner'] = dinner;

セッションに保存されたデータはリクエストを通じて持続します。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top