Ich möchte zwei verschiedene Ansichten ausgeben (eine als Zeichenfolge, die als E-Mail gesendet wird) und die andere Seite, die einem Benutzer angezeigt wird.
Ist dies in ASP.NET MVC Beta möglich?
Ich habe mehrere Beispiele ausprobiert:
1. RenderPartial to String in ASP.NET MVC Beta
Wenn ich dieses Beispiel verwende, erhalte ich die Meldung "Nach dem Senden von HTTP-Headern kann nicht umgeleitet werden".
2. MVC Framework: Erfassen der Ausgabe einer Ansicht
Wenn ich dies verwende, kann ich anscheinend keine redirectToAction ausführen, da versucht wird, eine Ansicht zu rendern, die möglicherweise nicht vorhanden ist. Wenn ich die Ansicht zurückgebe, ist sie völlig durcheinander und sieht überhaupt nicht richtig aus.
Hat jemand Ideen / Lösungen für diese Probleme oder Vorschläge für bessere?
Danke vielmals!
Unten ist ein Beispiel. Ich versuche, die GetViewForEmail-Methode zu erstellen :
public ActionResult OrderResult(string ref)
{
//Get the order
Order order = OrderService.GetOrder(ref);
//The email helper would do the meat and veg by getting the view as a string
//Pass the control name (OrderResultEmail) and the model (order)
string emailView = GetViewForEmail("OrderResultEmail", order);
//Email the order out
EmailHelper(order, emailView);
return View("OrderResult", order);
}
Akzeptierte Antwort von Tim Scott (von mir ein wenig geändert und formatiert):
public virtual string RenderViewToString(
ControllerContext controllerContext,
string viewPath,
string masterPath,
ViewDataDictionary viewData,
TempDataDictionary tempData)
{
Stream filter = null;
ViewPage viewPage = new ViewPage();
//Right, create our view
viewPage.ViewContext = new ViewContext(controllerContext, new WebFormView(viewPath, masterPath), viewData, tempData);
//Get the response context, flush it and get the response filter.
var response = viewPage.ViewContext.HttpContext.Response;
response.Flush();
var oldFilter = response.Filter;
try
{
//Put a new filter into the response
filter = new MemoryStream();
response.Filter = filter;
//Now render the view into the memorystream and flush the response
viewPage.ViewContext.View.Render(viewPage.ViewContext, viewPage.ViewContext.HttpContext.Response.Output);
response.Flush();
//Now read the rendered view.
filter.Position = 0;
var reader = new StreamReader(filter, response.ContentEncoding);
return reader.ReadToEnd();
}
finally
{
//Clean up.
if (filter != null)
{
filter.Dispose();
}
//Now replace the response filter
response.Filter = oldFilter;
}
}
Anwendungsbeispiel
Angenommen, der Controller ruft an, um die Bestellbestätigungs-E-Mail zu erhalten, und übergibt den Standort Site.Master.
string myString = RenderViewToString(this.ControllerContext, "~/Views/Order/OrderResultEmail.aspx", "~/Views/Shared/Site.Master", this.ViewData, this.TempData);
quelle
Antworten:
Folgendes habe ich mir ausgedacht und es funktioniert für mich. Ich habe meiner Controller-Basisklasse die folgenden Methoden hinzugefügt. (Sie können diese statischen Methoden immer an einer anderen Stelle erstellen, die vermutlich einen Controller als Parameter akzeptiert.)
MVC2 .ascx-Stil
Rasiermesser .cshtml Stil
Bearbeiten: Rasiermesser-Code hinzugefügt.
quelle
Diese Antwort ist nicht auf meinem Weg. Dies ist ursprünglich von https://stackoverflow.com/a/2759898/2318354, aber hier habe ich gezeigt, wie man es mit dem Schlüsselwort "Static" verwendet, um es für alle Controller gemeinsam zu machen.
Dafür müssen Sie
static
Klasse in Klassendatei machen. (Angenommen, Ihr Klassendateiname lautet Utils.cs)Dieses Beispiel ist For Razor.
Utils.cs
Jetzt können Sie diese Klasse von Ihrem Controller aus aufrufen, indem Sie NameSpace wie folgt in Ihre Controller-Datei einfügen, indem Sie "this" als Parameter an Controller übergeben.
Als Vorschlag von @Sergey kann diese Erweiterungsmethode auch von cotroller aufgerufen werden, wie unten angegeben
Ich hoffe, dies ist nützlich, um den Code sauber und ordentlich zu machen.
quelle
Das funktioniert bei mir:
quelle
Ich habe eine neue Lösung gefunden, die eine Ansicht in eine Zeichenfolge umwandelt, ohne sich mit dem Antwortstrom des aktuellen HttpContext herumschlagen zu müssen (wodurch Sie den ContentType der Antwort oder andere Header nicht ändern können).
Grundsätzlich erstellen Sie lediglich einen gefälschten HttpContext, damit sich die Ansicht selbst rendern kann:
Dies funktioniert unter ASP.NET MVC 1.0 zusammen mit ContentResult, JsonResult usw. (das Ändern von Headern in der ursprünglichen HttpResponse löst nicht die Ausnahme " Server kann Inhaltstyp nicht festlegen, nachdem HTTP-Header gesendet wurden " aus).
Update: In ASP.NET MVC 2.0 RC ändert sich der Code ein wenig, da wir den
StringWriter
zum Schreiben der Ansicht verwendeten Code in Folgendes übergeben müssenViewContext
:quelle
StringWriter
Sie zum Schreiben in die verwendenStringBuilder
, nicht eine neue Instanz, da sonst die Ausgabe der Ansicht verloren geht.In diesem Artikel wird beschrieben, wie Sie eine Ansicht in einer Zeichenfolge in verschiedenen Szenarien rendern:
Die Lösung / der Code wird als Klasse namens ViewRenderer bereitgestellt . Es ist Teil von Rick Stahls WestwindToolkit bei GitHub .
Verwendung (3. - WebAPI-Beispiel):
quelle
Wenn Sie ganz auf MVC verzichten möchten, um das ganze HttpContext-Chaos zu vermeiden ...
Hier wird die fantastische Open Source Razor Engine hier verwendet: https://github.com/Antaris/RazorEngine
quelle
CompilerErrors
Eigenschaft der Ausnahme.Auf diese Weise erhalten Sie die Ansicht in einer Zeichenfolge
Wir nennen diese Methode auf zwei Arten
ODER
quelle
Zusätzlicher Tipp für ASP NET CORE:
Schnittstelle:
Implementierung:
Registrierung in
Startup.cs
Und Verwendung in der Steuerung:
quelle
Ich verwende MVC 1.0 RTM und keine der oben genannten Lösungen hat für mich funktioniert. Aber dieser tat:
quelle
Ich habe eine Implementierung für MVC 3 und Razor von einer anderen Website gesehen, die für mich funktioniert hat:
Weitere Informationen zu Razor Rendering - MVC3 View Render to String
quelle
Um eine Ansicht für eine Zeichenfolge in der Service-Schicht zu rendern, ohne ControllerContext weitergeben zu müssen, gibt es hier einen guten Rick Strahl-Artikel http://www.codemag.com/Article/1312081 , der einen generischen Controller erstellt. Code-Zusammenfassung unten:
So rendern Sie die Ansicht in der Service-Klasse:
quelle
Kurzer Tipp
Für ein stark typisiertes Modell fügen Sie es einfach der ViewData.Model-Eigenschaft hinzu, bevor Sie es an RenderViewToString übergeben. z.B
quelle
Um eine unbekanntere Frage zu wiederholen, werfen Sie einen Blick auf MvcIntegrationTestFramework .
Es erspart Ihnen das Schreiben eigener Helfer, um Ergebnisse zu streamen, und funktioniert nachweislich gut genug. Ich würde annehmen, dass dies in einem Testprojekt wäre und als Bonus würden Sie die anderen Testfunktionen haben, sobald Sie dieses Setup haben. Die Hauptaufgabe wäre wahrscheinlich, die Abhängigkeitskette zu sortieren.
quelle
Hier ist eine Klasse, die ich geschrieben habe, um dies für ASP.NETCore RC2 zu tun. Ich benutze es, damit ich mit Razor HTML-E-Mails generieren kann.
quelle
Ich habe einen besseren Weg gefunden, um die Seite der Rasiermesseransicht zu rendern, als ich Fehler mit den oben genannten Methoden bekam. Diese Lösung ist sowohl für die Webformularumgebung als auch für die MVC-Umgebung geeignet. Es wird kein Controller benötigt.
Hier ist das Codebeispiel. In diesem Beispiel habe ich eine MVC-Aktion mit einem asynchronen http-Handler simuliert:
quelle