web-dev-qa-db-fra.com

Récupérer du HTML depuis la vue MVC 4 dans une chaîne

J'essaie d'utiliser la réponse acceptée de cette question .

Il semble que ce sera exactement ce que je recherche, mais j'ai un problème. Je ne sais pas comment l'appeler. Voici ce que j'ai jusqu'à présent:

Je copie d'abord le code de la solution que j'ai mentionnée:

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

Voici ce que j'ai:

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.

Que dois-je passer dans le paramètre controllerContext?

20

Vous pouvez créer un contrôleur de base qui étend évidemment un contrôleur et utiliser la fonction ci-dessus dans le contrôleur de base et un autre contrôleur qui étend ce contrôleur de base pourra l'utiliser. Cependant, le ControllerContext doit être utilisé comme

Request.RequestContext

Et donc votre BaseController sera comme

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

Et votre fonction ToHtml () sera

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

Et sur l'utilisation du contrôleur de base

public class MyController: BaseController
{
//ToHtml(...);
}
9
serene

Plutôt que d'hériter de Controller ce qui signifie que vous devez vous rappeler de l'implémenter à chaque fois, ou hériter d'un CustomControllerBase, ce qui signifie que vous devez vous rappeler d'hériter à chaque fois - faites simplement une méthode d'extension:

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

Ensuite, dans votre Controller, vous pouvez appeler comme ceci:

this.RenderView("ViewName", model);
38
dav_i

Ceci est à peu près une copie de le post de dav_i sauf que vous avez un modèle avec un typage fort et également la possibilité de produire des vues partielles:

Plutôt que d'hériter de Controller ce qui signifie que vous devez vous rappeler de l'implémenter à chaque fois, ou hériter d'un CustomControllerBase, ce qui signifie que vous devez vous rappeler d'hériter à chaque fois - faites simplement une méthode d'extension:

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

Ensuite, dans votre Controller, vous pouvez appeler comme ceci (pour une vue complète):

this.RenderView("ViewName", model);

Cela signifie que vous obtiendrez également le doctype et l'élément HTML, etc. Pour une vue partielle, utilisez:

this.RenderView("ViewName", model, true);
4
Rubenisme