【问题标题】:Transform partial view into string with calling controller's action通过调用控制器的操作将部分视图转换为字符串
【发布时间】:2016-03-29 14:20:41
【问题描述】:

我的 MVC 控制器带有返回部分视图的操作。 Action 包含大量逻辑,通过 ViewBag 对象在视图中发送数据。

我需要将此操作的结果呈现为字符串,然后作为电子邮件发送。我发现的所有解决方案都可以在没有动作调用的情况下呈现视图。

是否可以在我的代码中的某处初始化控制器,调用 action 方法并将 ActionResult(即部分视图)转换为字符串?

谢谢

【问题讨论】:

  • 如果您将其用于电子邮件,您可能需要查看MvcMailer 之类的内容,它几乎可以满足您的需求。我过去曾成功使用过它,而且很容易实现。

标签: c# asp.net asp.net-mvc viewbag


【解决方案1】:

我做到了。很痛苦。

首先我们需要在没有上下文的情况下初始化控制器。为此,我使用 Rick Strahl 的 CreateController 方法

 public static T CreateController<T>(RouteData routeData = null)
        where T : Controller, new()
    {
        // create a disconnected controller instance
        T controller = new T();

        // get context wrapper from HttpContext if available
        HttpContextBase wrapper = null;
        if (HttpContext.Current != null)
            wrapper = new HttpContextWrapper(System.Web.HttpContext.Current);
        else
            throw new InvalidOperationException(
                "Can't create Controller Context if no active HttpContext instance is available.");

        if (routeData == null)
            routeData = new RouteData();

        // add the controller routing if not existing
        if (!routeData.Values.ContainsKey("controller") && !routeData.Values.ContainsKey("Controller"))
            routeData.Values.Add("controller", controller.GetType().Name
                                                        .ToLower()
                                                        .Replace("controller", ""));

        controller.ControllerContext = new ControllerContext(wrapper, routeData, controller);
        return controller;
    }

来源:http://weblog.west-wind.com/posts/2013/Jul/15/Rendering-ASPNET-MVC-Razor-Views-outside-of-MVC-revisited

但是如果你在HttpContext的时候调用这个方法就会抛出异常。为了防止我使用此代码初始化虚假上下文:https://stackoverflow.com/a/19709225/1850880

然后我初始化控制器并调用操作。此操作的结果包含 viewData 以及从操作传递的所有数据。我们可以通过反射得到它(就像忍者一样)。 然后我们可以使用传递的模型将视图渲染为字符串。

        var controller = CreateController<ControllerName>();
        var result = controller.ActionName(param1, param2);
        object viewData = result.GetType().GetProperty("ViewData").GetValue(result);
        object values = viewData.GetType().GetProperty("Values").GetValue(viewData);
        var str = ec.RenderRazorViewToString("ViewName", values);
        return str;

此方法将视图渲染为字符串:

 public static string RenderRazorViewToString(this Controller controller, string viewName, object model)
    {
        controller.ViewData.Model = model;
        controller.ViewBag.Model = model;
        using (var sw = new StringWriter())
        {
            var viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName);
            var viewContext = new ViewContext(controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, sw);
            viewResult.View.Render(viewContext, sw);
            viewResult.ViewEngine.ReleaseView(controller.ControllerContext, viewResult.View);
            return sw.GetStringBuilder().ToString();
        }
    }

看起来这不是最好的方法,但它确实有效。因此,如果您有任何想法,请务必写下来。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-03-02
    • 1970-01-01
    • 1970-01-01
    • 2014-03-27
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    相关资源
    最近更新 更多