Übergeben von Daten zwischen verschiedenen Controller-Aktionsmethoden

74

Ich benutze ASP.NET MVC 4. Ich versuche, Daten von einem Controller an einen anderen Controller zu übergeben. Ich verstehe das nicht richtig. Ich bin mir nicht sicher, ob das möglich ist?

Hier ist meine Quellaktionsmethode, von der ich die Daten übergeben möchte:

public class ServerController : Controller
{
     [HttpPost]
     public ActionResult ApplicationPoolsUpdate(ServiceViewModel viewModel)
     {
          XDocument updatedResultsDocument = myService.UpdateApplicationPools();

          // Redirect to ApplicationPool controller and pass
          // updatedResultsDocument to be used in UpdateConfirmation action method
     }
}

Ich muss es an diese Aktionsmethode in diesem Controller übergeben:

public class ApplicationPoolController : Controller
{
     public ActionResult UpdateConfirmation(XDocument xDocument)
     {
          // Will add implementation code

          return View();
     }
}

Ich habe Folgendes in der ApplicationPoolsUpdateAktionsmethode versucht , aber es funktioniert nicht:

return RedirectToAction("UpdateConfirmation", "ApplicationPool", new { xDocument = updatedResultsDocument });

return RedirectToAction("UpdateConfirmation", new { controller = "ApplicationPool", xDocument = updatedResultsDocument });

Wie würde ich das erreichen?

Brendan Vogt
quelle
3
Das hat mich ewig gestolpert - benutze im Grunde TempData / Session. Siehe stackoverflow.com/questions/672143/…
glosrob

Antworten:

73

HTTP und Weiterleitungen

Lassen Sie uns zunächst die Funktionsweise von ASP.NET MVC zusammenfassen:

  1. Wenn eine HTTP-Anforderung eingeht, wird sie mit einer Reihe von Routen abgeglichen. Wenn eine Route mit der Anforderung übereinstimmt, wird die der Route entsprechende Controller-Aktion aufgerufen.
  2. Vor dem Aufrufen der Aktionsmethode führt ASP.NET MVC eine Modellbindung durch. Bei der Modellbindung wird der Inhalt der HTTP-Anforderung, bei der es sich im Grunde nur um Text handelt, den stark typisierten Argumenten Ihrer Aktionsmethode zugeordnet

Erinnern wir uns auch daran, was eine Weiterleitung ist:

Eine HTTP-Umleitung ist eine Antwort, die der Webserver an den Client senden kann und die den Client auffordert, unter einer anderen URL nach dem angeforderten Inhalt zu suchen. Die neue URL ist in einem LocationHeader enthalten, den der Webserver an den Client zurückgibt. In ASP.NET MVC führen Sie eine HTTP-Umleitung durch, indem Sie eine RedirectResultvon einer Aktion zurückgeben.

Daten übergeben

Wenn Sie nur einfache Werte wie Zeichenfolgen und / oder Ganzzahlen übergeben, können Sie diese als Abfrageparameter in der URL im LocationHeader übergeben. Dies würde passieren, wenn Sie so etwas verwenden würden

return RedirectToAction("ActionName", "Controller", new { arg = updatedResultsDocument });

wie andere vorgeschlagen haben

Der Grund, warum dies nicht funktioniert, ist, dass XDocumentes sich um ein möglicherweise sehr komplexes Objekt handelt. Es gibt keine einfache Möglichkeit für das ASP.NET MVC-Framework, das Dokument in etwas zu serialisieren, das in eine URL passt, und dann die Modellbindung vom URL-Wert zurück zu Ihrem XDocumentAktionsparameter zu modellieren .

Im Allgemeinen ist das Übergeben des Dokuments an den Client, damit der Client es bei der nächsten Anforderung an den Server zurückgeben kann, ein sehr spröder Vorgang: Es würde alle Arten von Serialisierung und Deserialisierung erfordern, und alle möglichen Dinge könnten schief gehen. Wenn das Dokument groß ist, kann dies auch eine erhebliche Verschwendung von Bandbreite darstellen und die Leistung Ihrer Anwendung erheblich beeinträchtigen.

Stattdessen möchten Sie das Dokument auf dem Server aufbewahren und eine Kennung an den Client zurückgeben. Der Client übergibt dann die Kennung zusammen mit der nächsten Anforderung und der Server ruft das Dokument unter Verwendung dieser Kennung ab.

Speichern von Daten zum Abrufen bei der nächsten Anforderung

Nun stellt sich die Frage, wo der Server das Dokument in der Zwischenzeit speichert. Nun, das müssen Sie entscheiden und die beste Wahl hängt von Ihrem speziellen Szenario ab. Wenn dieses Dokument auf lange Sicht verfügbar sein muss, können Sie es auf der Festplatte oder in einer Datenbank speichern. Wenn es nur vorübergehende Informationen enthält, ist es möglicherweise die richtige Lösung , diese im Speicher des Webservers, im ASP.NET-Cache oder im Session(oder TempData, was mehr oder weniger dem Sessionam Ende entspricht) zu speichern . In beiden Fällen speichern Sie das Dokument unter einem Schlüssel, mit dem Sie das Dokument später abrufen können:

int documentId = _myDocumentRepository.Save(updatedResultsDocument);

und dann geben Sie diesen Schlüssel an den Client zurück:

return RedirectToAction("UpdateConfirmation", "ApplicationPoolController ", new { id = documentId });

Wenn Sie das Dokument abrufen möchten, rufen Sie es einfach anhand des Schlüssels ab:

 public ActionResult UpdateConfirmation(int id)
 {
      XDocument doc = _myDocumentRepository.GetById(id);

      ConfirmationModel model = new ConfirmationModel(doc);

      return View(model);
 }
Rune
quelle
1
Danke Rune. Es ist Gud.
Devsainii
64

Haben Sie versucht, ASP.NET MVC TempData zu verwenden ?

Das ASP.NET MVC TempData-Wörterbuch wird verwendet, um Daten zwischen Controller-Aktionen auszutauschen. Der Wert von TempData bleibt bestehen, bis es gelesen wird oder bis die Sitzung des aktuellen Benutzers abgelaufen ist. Das Speichern von Daten in TempData ist in Szenarien wie der Umleitung nützlich, wenn Werte über eine einzelne Anforderung hinaus benötigt werden.

Der Code wäre ungefähr so:

[HttpPost]
public ActionResult ApplicationPoolsUpdate(ServiceViewModel viewModel)
{
    XDocument updatedResultsDocument = myService.UpdateApplicationPools();
    TempData["doc"] = updatedResultsDocument;
    return RedirectToAction("UpdateConfirmation");
}

Und im ApplicationPoolController:

public ActionResult UpdateConfirmation()
{
    if (TempData["doc"] != null)
    {
        XDocument updatedResultsDocument = (XDocument) TempData["doc"];
            ...
        return View();
    }
}
user1073075
quelle
1
Stimmt es, dass TempData nicht für die Verwendung auf mehreren Servern mit Lastenausgleich sicher ist, es sei denn, ich lege auch einen gemeinsam genutzten Sitzungscache darunter?
GGleGrand
Ich bin immer noch der Meinung, dass wir die Verwendung von Sessions, in diesem Fall ViewData, auf jeden Fall vermeiden sollten. Sie werden nicht eingegeben und funktionieren nur im In-procSitzungsmodus. Bei jedem Server mit Lastenausgleich State Severoder im Sql ServerSitzungsmodus gehen die ViewData verloren.
Blaise
11

Persönlich mag ich TempData nicht, aber ich bevorzuge es, ein stark typisiertes Objekt zu übergeben, wie unter Übergeben von Informationen zwischen Controllern in ASP.Net-MVC erläutert .

Sie sollten immer einen Weg finden, dies explizit und erwartet zu machen.

L-Vier
quelle
TempData wurde absichtlich erstellt, um einige einfache Daten von einem Ansichtscontroller an einen anderen zu übergeben, ohne alle Daten auf der Client-URL oder in der Anforderung verfügbar zu machen. Es ist nicht ideal, aber effizienter als Sessions. Es handhabt ViewModels (oder einfache Modelle) perfekt. Und ist eine praktische Funktion zu verwenden.
Piotr Kula
2
ViewData wird nicht verarbeitet, da ViewData nicht serialisierbar ist. Dies ist eine Voraussetzung für Sitzungen, die nicht in Bearbeitung ausgeführt werden können (Webfarm). Ich mag TempData nicht (ist die schönste Art, wie ich es ausdrücken könnte).
Novox
4

Ich bevorzuge dies anstelle von TempData

public class Home1Controller : Controller 
{
    [HttpPost]
    public ActionResult CheckBox(string date)
    {
        return RedirectToAction("ActionName", "Home2", new { Date =date });
    }
}

und ein anderer controller Actionist

public class Home2Controller : Controller 
{
    [HttpPost]
    Public ActionResult ActionName(string Date)
    {
       // do whatever with Date
       return View();
    }
}

Es ist zu spät, aber ich hoffe, dass ich in Zukunft für jeden hilfreich sein kann

Amgad Mohamed
quelle
2
Aber in vielen Fällen wollen wir ein komplexes Modell in der übergeben RedirectToAction.
Blaise
-3

Wenn Sie Daten von einem Controller an einen anderen übergeben müssen, müssen Sie Daten nach Routenwerten übergeben. Da beide unterschiedliche Anforderungen sind. Wenn Sie Daten von einer Seite zur anderen senden, müssen Sie eine Benutzerabfragezeichenfolge (wie Routenwerte) verwenden.

Aber Sie können einen Trick machen:

Rufen Sie in Ihrer aufrufenden Aktion die aufgerufene Aktion als einfache Methode auf:

public class ServerController : Controller
{
 [HttpPost]
 public ActionResult ApplicationPoolsUpdate(ServiceViewModel viewModel)
 {
      XDocument updatedResultsDocument = myService.UpdateApplicationPools();
      ApplicationPoolController pool=new ApplicationPoolController(); //make an object of ApplicationPoolController class.

      return pool.UpdateConfirmation(updatedResultsDocument); // call the ActionMethod you want as a simple method and pass the model as an argument.
      // Redirect to ApplicationPool controller and pass
      // updatedResultsDocument to be used in UpdateConfirmation action method
 }
}
Jishnu Saha
quelle
4
Glaubst du, es lohnt sich, so etwas zu tun? Wird es die Routenwerte ändern und die richtige Ansicht laden, wenn Sie versuchen, View () in der Aktion UpdateConfirmation zurückzugeben?
KD
Ja, trotzig. Wenn Sie UpdateConfirmation () aufrufen, basiert die zurückgegebene Ansicht auf der Aktion "UpdateConfirmation", dh der Ansicht "/ ApplicationPool / UpdateConfirmation". Sie sollten dies versuchen. Ich denke, es wird funktionieren.
Jishnu Saha
1
Es wird nicht. Der Wert des Routenwertwörterbuchs wird nicht geändert, daher versucht MVC, die Ansicht für die Aktion
KD
Ab der ersten Aktion geben Sie jedoch eine Ansicht zurück, die die Adresse der zweiten Ansicht enthält. So funktioniert es.
Jishnu Saha