2013-08-26 8 views
15

Próbuję użyć zaakceptowanej odpowiedzi od this question.Pobierz html z widoku MVC 4 na ciąg znaków

Wygląda na to, że będzie dokładnie to, czego szukam, ale mam problem. Nie wiem, jak to nazwać. To, co mam do tej pory:

pierwsze jestem kopiując kod z roztworu wspominałem:

public string ToHtml(string viewToRender, ViewDataDictionary viewData, ControllerContext controllerContext) 
{ 
    var result = ViewEngines.Engines.FindView(controllerContext, viewToRender, null); 

    StringWriter output; 
    using (output = new StringWriter()) 
    { 
     var viewContext = new ViewContext(controllerContext, result.View, viewData, controllerContext.Controller.TempData, output); 
     result.View.Render(viewContext, output); 
     result.ViewEngine.ReleaseView(controllerContext, result.View); 
    } 

    return output.ToString(); 
} 

to co mam:

string viewToRender = "..."; 
int Data1 = ...; 
int Data2 = ...; 

System.Web.Mvc.ViewDataDictionary viewData = new System.Web.Mvc.ViewDataDictionary(); 
viewData.Add("Data1",Data1); 
viewData.Add("Data2",Data2); 

string html = ToHtml(viewToRender, viewData, ?????)//Here is my problem. 

Co mam przekazać w parametr controllerContext?

+0

Kontekst kontrolera jest właściwością kontrolera MVC. Jeśli chcesz uzyskać widok bieżącego kontrolera, wpisz: this.ControllerContext – Oliver

+0

@Oliver Chcę wywołać tę metodę poza kontrolerem. Czy to możliwe? Jeśli tak, to chciałbym jakoś zdefiniować kontroler. Jak mam to zrobic? –

+0

Używam tego pomocnika: publiczny ciąg statyczny RenderPartialViewToString (kontroler kontrolera, string viewName, model obiektu), a następnie po prostu wywołuję kontroler.ControllerContext. – Oliver

Odpowiedz

7

Można utworzyć kontroler bazowy, który w oczywisty sposób rozszerza kontroler i korzysta z powyższej funkcji w kontrolerze bazowym, a inny kontroler, który rozszerza ten kontroler bazowy, będzie mógł z niego korzystać. Jednak ControllerContext musi być stosowany jako

Request.RequestContext 

a więc Twój BaseController będzie jak

public class BaseController: Controller 
{ 
//your function here 
} 

A twoja funkcja toHTML() będzie

protected virtual string ToHtml(string viewToRender, ViewDataDictionary viewData) 
{ 
    var controllerContext=Request.RequestContext; 
    var result = ViewEngines.Engines.FindView(controllerContext, viewToRender, null); 

    StringWriter output; 
    using (output = new StringWriter()) 
    { 
     var viewContext = new ViewContext(controllerContext, result.View, viewData, controllerContext.Controller.TempData, output); 
     result.View.Render(viewContext, output); 
     result.ViewEngine.ReleaseView(controllerContext, result.View); 
    } 

    return output.ToString(); 
} 

I na użyciu sterownika bazowego

public class MyController: BaseController 
{ 
//ToHtml(...); 
} 
+0

Dzięki! Czy wiesz, w jaki sposób mogę dodać obiekt "Model" do renderowania widoku? –

+1

Znalazłem :) 'ViewData.Model = obj;'. –

+0

Co wysłać w widoku danych? Nie rozumiem tego. –

33

Zamiast dziedziczyć Controller co oznacza, że ​​trzeba pamiętać, aby realizować to za każdym razem, czy dziedziczą z CustomControllerBase, co oznacza, że ​​trzeba pamiętać, aby odziedziczyć za każdym razem - wystarczy wykonać metodę rozszerzenia:

public static class ControllerExtensions 
{ 
    public static string RenderView(this Controller controller, string viewName, object model) 
    { 
     return RenderView(controller, viewName, new ViewDataDictionary(model)); 
    } 

    public static string RenderView(this Controller controller, string viewName, ViewDataDictionary viewData) 
    { 
     var controllerContext = controller.ControllerContext; 

     var viewResult = ViewEngines.Engines.FindView(controllerContext, viewName, null); 

     StringWriter stringWriter; 

     using (stringWriter = new StringWriter()) 
     { 
      var viewContext = new ViewContext(
       controllerContext, 
       viewResult.View, 
       viewData, 
       controllerContext.Controller.TempData, 
       stringWriter); 

      viewResult.View.Render(viewContext, stringWriter); 
      viewResult.ViewEngine.ReleaseView(controllerContext, viewResult.View); 
     } 

     return stringWriter.ToString(); 
    } 
} 

Następnie w ciągu Twój Controller można nazwać tak:

this.RenderView("ViewName", model); 
+0

Miły, podoba mi się twój approch. Thx mate – Ali

+2

I dla każdego, kto szuka częściowego widoku, zastąp FindView FindPartialView. – RitchieD

+1

Jak ustawić viewData? Dla mnie jest to wartość zerowa, która powoduje błąd. – FrenkyB

1

jest to dość dużo kopia dav_i's post chyba że masz model z silnego typowania i również zdolność wytwarzania cząstkowych widoków:

Zamiast dziedziczyć Controller co oznacza, że ​​trzeba pamiętać, aby realizować to za każdym razem, czy dziedziczą z CustomControllerBase, co oznacza, że ​​trzeba pamiętać, aby odziedziczyć za każdym razem - wystarczy wykonać metodę rozszerzenia:

public static class ControllerExtensions 
{ 
    public static string RenderView<TModel>(this Controller controller, string viewName, TModel model, bool partial = false) 
    { 
     var controllerContext = controller.ControllerContext; 
     controllerContext.Controller.ViewData.Model = model; 

     // To be or not to be (partial) 
     var viewResult = partial ? ViewEngines.Engines.FindPartialView(controllerContext, viewName) : ViewEngines.Engines.FindView(controllerContext, viewName, null); 

     StringWriter stringWriter; 

     using (stringWriter = new StringWriter()) 
     { 
      var viewContext = new ViewContext(
       controllerContext, 
       viewResult.View, 
       controllerContext.Controller.ViewData, 
       controllerContext.Controller.TempData, 
       stringWriter); 

      viewResult.View.Render(viewContext, stringWriter); 
      viewResult.ViewEngine.ReleaseView(controllerContext, viewResult.View); 
     } 

     return stringWriter.ToString(); 
    } 
} 

Następnie w swoim Controller można nazwać tak (dla pełnego widoku):

this.RenderView("ViewName", model); 

oznacza to, że dostaniesz doctype i element HTML etc też. Do użytku z częściowym wyświetlaniem:

this.RenderView("ViewName", model, true); 
Powiązane problemy