Daten von Controller-Passing View-Controller an zurück, zurück zum Ansehen
-
06-07-2019 - |
Frage
Ich bin neu in ASP.NET MVC. mit traditionellem ASP.NET Modell so lange nach der Arbeit, es nimmt etwas Zeit für mich, dieses Modell zu erhalten, zu verstehen.
Ich werde durch NerdDinner zu verstehen, wie die Dinge funktionieren.
So habe ich ein Objekt, das durch einige Ansichten weitergegeben werden muss. Ähnlich wie bei dem Artikel NerdDinner Schritt 6:. Viewdata und Ansichtsmodell
ich die Daten behalten von Get zum ersten Mal zu Post, dann habe ich es in TempData und gibt sie an eine andere Aktion (AnotherAction). Sobald ich meine Daten auf Get bekomme ich es auf Posten nicht behalten kann.
Hier ist mein Code:
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
}
}
Lösung
Nach dieser Blog-Post TempData ist nur etwa für 1 Einzel Anfrage nach seinem Satz.
Hier ist ein Zitat aus dem Beitrag:
Wenn Sie setzen TempData und Ihre Aktion gibt dann eine Viewresult, dann die nächste Anforderung, was auch immer es passiert zu sein (eine AJAX-Anforderung, eine andere Seite der Benutzer in einem anderen Tab geöffnet, etc.), wird die TempData sehen Wert, den Sie festgelegt, und keine andere Anforderung wird es sehen.
Also den Code gegeben, die ich sehe, können Sie das Abendessen von TempData auf dem get von AnotherAction
erhalten, die die erste Anforderung ist, nachdem Sie es auf Action
gesetzt. Allerdings Blick auf den Code und den Code nicht für Ansicht für AnotherAction
sehen es unklar ist, wie Sie die Daten auf den Posten für AnotherAction
sind vorbei. Das Abendessen Instanz wird nicht für diese Anforderung in TempData sein, weil es die zweite Anforderung ist, nachdem Sie es in TempData gesetzt. Und wenn Sie die richtigen keine Form-Tags auf der AntoherAction
Ansicht festgelegt haben das Framework wird nicht die richtige Form Werte müssen ein Abendessen Objekt in der Post instanziiert.
Also entweder Sie TempData mit dem Abendessen Instanz es das erste AnotherAction
Aufruf zurückgesetzt und dann rufen Sie das Abendessen aus TempData in der Post AnotherAction
, oder Sie können den Rat von dm folgen und versteckte Felder in der Ansicht verwenden.
IMO, sollten Sie DMs Weg, dies zu tun und vermeiden TempData verwenden.
Bearbeiten am Beispiel der TempData in AnotherAction Reseting Zugang zu ihm in der Post zu erhalten.
Modell:
public class Dinner
{
public string Name{get;set;}
}
public class DinnerFormViewModel
{
public Dinner Dinner {get;private set;}
public DinnerFormViewModel( Dinner dinner )
{
Dinner = dinner;
}
}
Controller:
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 ) );
}
}
Action View:
<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 Ausblick:
<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>
<% } %>
Andere Tipps
das Format erhalten, die Sie erwarten, müssen Sie einige versteckte Felder bevölkern können, wie Sie die Informationen aus verschiedenen Ansichten zu sammeln.
Auch mit Modell Bindung könnten Sie Ihren Code Blick auf wenig besser machen und vermeiden TempData in Orten:
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
}
So in der AnotherAction ansehen würden Sie so etwas wie haben:
<% using(Html.BeginForm()) { %>
<%= Html.Hidden("dinnerProperty1") %>
<%= Html.Hidden("dinnerProperty2") %>
<%= Html.Hidden("dinnerProperty3") %>
<%= Html.TextBox("dinnerProperty4") %>
<%= Html.TextBox("dinnerProperty5") %>
<%= Html.TextBox("dinnerProperty6") %>
<% } %>
Es gibt keine Benutzerfreundlichkeit im obigen Beispiel, aber Sie erhalten den Punkt.
Sie können nicht roh C # Objekte von Ansichten zu Controllern passieren.
In ASP.NET MVC, wenn eine Aktion ein Objekt für einen Parameter nimmt, sieht ASP.NET MVC in allen POST / GET-Daten und sucht nach Werten, die mit Eigenschaftsnamen auf dem Parameter-Objekt übereinstimmen.
public ActionResult SomeAction(Dinner myDinner)
{
// do stuff
}
myDinner Objekt wird nur ausgefüllt werden, wenn Sie die Aktion mit Formularfeldern erstellen, die auf das Abendessen Eigenschaften des Objekts (Ort, Datum, etc.) entsprechen oder wenn Sie diese Informationen in einer GET-URL (Dinner / SomeAction platzieren sind? location = chicago & date = 12/1/2009 usw.)
Wenn Sie absolut nicht ausgeblendeten Felder verwenden können (A DM vorgeschlagen), dann Sessions sind wahrscheinlich die einzige Option.
Sie sollten Abendessen aus dem Repository erhalten. Sie Aktion sollte wie:
[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 Aktionen können auch aus dem Repository übernehmen, so können Sie nur id übergeben.
Bearbeiten
Wenn Sie Zaubererartschnittstelle Seite erstellen möchten, speichern können Sie zuvor Daten in Session-Objekt eingetragen.
Session['CurrentDinner'] = dinner;
Daten in Session gespeichert bestehen durch Anfragen.