2015-05-20 11 views
13

In früheren Versionen von ASP.NET war es möglich, wenn auch nicht sehr einfach, Razor Ansichten als Strings zu machen. Die Methoden, die ich habe, scheinen einen falschen Controller zu verwenden, oder auch einige externe Engine wie RazorEngine zu verwenden.Render Razor bespannen sieht in ASP.NET 5

Jetzt sind viele Dinge mit ASP.NET 5 geändert und ich fragte mich, ob das jetzt einfacher ist als vorher. Also gibt es in der neuen Version des Frameworks eine einfache Möglichkeit, Razor-Ansichten als Strings darzustellen, oder wir müssen immer noch die Methoden der vorherigen Versionen verwenden?

+0

Haben Sie den HTML-Inhalt einer Aktion auf eine String-Variable eingefügt werden soll? Oder einfach ein ActionResult in einer anderen Ansicht rendern? –

+0

@FabioLuz Ich möchte die Ansicht rendern und den gerenderten HTML-Code in eine String-Variable einfügen. – user1620696

+0

Wenn Sie dies tun möchten, während Sie unter MVC 6 sind, sollte es ziemlich geradlinig sein. Es kommt nur darauf an, die richtige Abhängigkeit zu bekommen, um die Rasierklingenansicht auszuweiten. Wenn Sie jedoch außerhalb davon sind, hier ist ein Beispiel: https://github.com/tugberkugurlu/RazorOnConsole/blob/34c2e308f1976680c654a06a066b6c7fda1387b6/RazorTemplatingSample.Console/Program.cs#L15 eingraben, um zu sehen, wie 'Templater.Run' ist implementiert. – tugberk

Antwort

17

ich die folgenden Typen von IServiceProvider injiziert:

ICompositeViewEngine viewEngine; 
ITempDataProvider tempDataProvider; 
IHttpContextAccessor httpContextAccessor; 

I machen, den Inhalt der folgenden Methode:

private async Task<string> RenderView(string path, ViewDataDictionary viewDataDictionary, ActionContext actionContext) 
{ 
    using (var sw = new System.IO.StringWriter()) 
    { 
     var viewResult = viewEngine.FindView(actionContext, path); 

     var viewContext = new ViewContext(actionContext, viewResult.View, viewDataDictionary, new TempDataDictionary(httpContextAccessor, tempDataProvider), sw); 

     await viewResult.View.RenderAsync(viewContext); 
     sw.Flush(); 

     if (viewContext.ViewData != viewDataDictionary) 
     { 
      var keys = viewContext.ViewData.Keys.ToArray(); 
      foreach (var key in keys) 
      { 
       viewDataDictionary[key] = viewContext.ViewData[key]; 
      } 
     } 

     return sw.ToString(); 
    } 
} 

I es so nennen:

var path = "~/Views/Home/Index.cshtml"; 
var viewDataDictionary = new ViewDataDictionary(new Microsoft.AspNet.Mvc.ModelBinding.EmptyModelMetadataProvider(), new Microsoft.AspNet.Mvc.ModelBinding.ModelStateDictionary()); 
var actionContext = new ActionContext(httpContextAccessor.HttpContext, new Microsoft.AspNet.Routing.RouteData(), new ActionDescriptor()); 
viewDataDictionary.Model = null; 
var text = await RenderView(path, viewDataDictionary, actionContext); 

Natürlich werden meine viewDataDictionary und actionContext Variablen durch eine andere Methode für die Kapselung gesetzt. Eine Änderung an der Zeile new ViewDataDictionary kann dazu führen, dass ein typisiertes Modell an Ihre Ansicht gebunden wird, wenn Sie dies wünschen.

Dieser Code verwendet schwere usings, ich denke, ich habe sie unten aufgeführt. Ansonsten ist VS2015 ziemlich gut darin, sie zu finden.

using Microsoft.AspNet.Mvc; 
using Microsoft.AspNet.Mvc.Rendering; 

Dies wurde unter Beta-3 geschrieben; Es baut immer noch, aber einige Dinge können sich ändern. Ich werde versuchen, hierher zu kommen, um zu aktualisieren, wenn es das tut.

+0

Gut zu helfen! Und danke dafür, dass es immer noch funktioniert - ich musste nicht zurückgehen und es ändern, also habe ich diese Notiz nicht zu meiner Antwort hinzugefügt. –

+1

Nicht zu sehen, wie Sie diese injizierten Objekte bekommen und auch die Signatur der Methode ist inkohärent mit der Art, wie Sie es nennen ... – Shockwaver

+1

@Shockwaver - nur für den Fall jemand fragt sich, es ist nur Abhängigkeits-Injektion (DI). Die Dienstabhängigkeiten sind in der Regel Parameter für den Konstruktor der Klasse, und der DI-Container ermittelt, wo sie abgerufen werden. In Bezug auf die Signaturinkonsistenz hat Matt wahrscheinlich die ursprüngliche Methode in einen Controller geschrieben, der eine ActionContext-Eigenschaft besitzt, sodass Sie einfach in ein Großbuchstabe A wechseln und den Code innerhalb eines Controllers testen können. – Seth

3

Es gibt eine Lösung, die ich vor einem Jahr verwendet habe. Ich bin mir nicht sicher, ob es einen neuen/besseren Weg gibt, aber es löst das Problem.

public string RenderViewToString(string viewName, object model) 
{ 
    ViewData.Model = model; 
    using (var sw = new StringWriter()) 
    { 
     var viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName); 
     var viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw); 
     viewResult.View.Render(viewContext, sw); 
     viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View); 
     return sw.GetStringBuilder().ToString(); 
    } 
} 
+2

Leider ist die ViewEngines-Klasse auch nicht mit asp.net-5 vorhanden. –

+0

@MattDeKrey Aber es tut in v4 (Nicht die OP-Anfrage, ich weiß)! Aa und das ist absolut der Weg für diese Version! Schöne, rettete meinen Tag, keine Probleme mit einem der HTML-Helfer mit Rasiermesser verwendet. DANKE – Shockwaver