2015-05-20 11 views
13

W poprzednich wersjach ASP.NET było możliwe, choć nie bardzo proste, renderowanie widoków Razor jako ciągi. Wydaje mi się, że używam fałszywego kontrolera lub używam zewnętrznego silnika, takiego jak RazorEngine.Render Razor widok na ciąg w ASP.NET 5

Teraz wiele rzeczy zmieniło się w ASP.NET 5 i zastanawiałem się, czy jest to teraz prostsze niż wcześniej. Tak więc w nowej wersji frameworku istnieje jeden prosty sposób renderowania widoków Razor jako ciągów lub nadal musimy używać metod z poprzednich wersji?

+0

Czy chcesz wstawić zawartość HTML akcji do zmiennej łańcuchowej? Lub po prostu render ActionResult wewnątrz innego widoku? –

+0

@FabioLuz Chcę renderować widok i umieścić renderowany kod HTML wewnątrz zmiennej łańcuchowej. – user1620696

+0

Jeśli chcesz to zrobić, gdy jesteś pod MVC 6, powinno być dość proste. To tylko kwestia uzyskania właściwej zależności, aby zwiększyć widok brzytwy. Jeśli jednak znajdujesz się poza nim, oto przykład: https://github.com/tugberkugurlu/RazorOnConsole/blob/34c2e308f1976680c654a06a066b6c7fda1387b6/RazorTemplatingSample.Console/Program.cs#L15, aby sprawdzić, jak działa 'Templater.Run' wdrożony. – tugberk

Odpowiedz

17

użyć następujących typów wtryskiwany z IServiceProvider:

ICompositeViewEngine viewEngine; 
ITempDataProvider tempDataProvider; 
IHttpContextAccessor httpContextAccessor; 

renderować zawartości przy użyciu następującej metody:

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 połączyć ją w następujący sposób

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); 

Oczywiście moje zmienne viewDataDictionary i actionContext są ustawiane za pomocą innego sposobu enkapsulacji. Modyfikacja linii new ViewDataDictionary może spowodować, że wpisany model zostanie powiązany z Twoim widokiem, jeśli wybierzesz.

Ten kod używa ciężkich zastosowań, myślę, że wymieniono je poniżej. W przeciwnym razie VS2015 jest całkiem niezły w ich odnajdywaniu.

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

Zostało to napisane w wersji beta-3; nadal się buduje, ale niektóre rzeczy mogą się zmienić. Spróbuję tu wrócić, żeby to zaktualizować.

+0

Cieszę się, że mogę Ci pomóc! I dziękuję za uwagę, że nadal działa - nie musiałem wracać i zmieniać tego, więc nie dodałem tej notatki do mojej odpowiedzi. –

+1

Nie widząc, w jaki sposób dostajesz te wstrzyknięte obiekty, a także podpis metody jest niespójny ze sposobem, w jaki ją nazywasz ... – Shockwaver

+1

@Shockwaver - na wypadek, gdyby ktoś się nad tym zastanowił, to tylko zastrzyk zależności (DI). Zależności usługi są ogólnie parametrami konstruktora klasy, a kontener DI działa tam, gdzie je uzyskać. W odniesieniu do niespójności podpisu, Matt prawdopodobnie napisał oryginalną metodę wewnątrz kontrolera, który ma właściwość ActionContext, więc można po prostu zmienić na wielką A i rozpocząć testowanie kodu z poziomu kontrolera. – Seth

3

Istnieje rozwiązanie, którego użyłem rok temu. Nie jestem pewien, czy istnieje nowy/lepszy sposób, ale rozwiązuje 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

Niestety, klasa ViewEngines również nie istnieje w asp.net-5. –

+0

@MattDeKrey Ale robi to w wersji 4 (nie jest to żądanie OP, wiem)! Aa i to jest absolutnie droga do tej wersji! Niezły, uratowałem mój dzień, żadnych problemów z pomocnikiem html używanym z maszynką do golenia. DZIĘKUJĘ – Shockwaver