部分视图到Html字符串

时间:2014-02-28 14:44:09

标签: c# asp.net-mvc signalr partial-views

我有一个工作流程,当数据从服务进入时,使用signalR更新页面。目前流程如下:

Service -> SignalR Hub           Controller
                       v      ^              v
                         View                   Partial

顶线是服务器端,底部是客户端。我使用signalR来访问我的jquery函数,该函数使用AJAX从控制器获取局部视图并更新页面。

似乎我可以将此过程缩短为:

Service -> Controller -> SignalR Hub
                                     v
                                        View

控制器将部分视图的字符串表示发送到SignalR Hub。

我的问题是尝试获取局部视图的字符串表示形式。我环顾四周找到了这段代码:

protected string RenderPartialViewToString(string viewName, object model)
    {
        if (string.IsNullOrEmpty(viewName))
            viewName = ControllerContext.RouteData.GetRequiredString("action");

        ViewData.Model = model;

        using (StringWriter sw = new StringWriter())
        {
            ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
            ViewContext viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
            viewResult.View.Render(viewContext, sw);

            return sw.GetStringBuilder().ToString();
        }
    }

但这需要ControllerContext,对我而言总是为null,因为我没有从客户端调用此方法。我还没有找到一种在没有ControllerContext的情况下渲染局部视图的方法。有可能这样做吗?

2 个答案:

答案 0 :(得分:6)

评论中的答案是一种方法。我偶然发现了这个page的另一种方式:创建一个虚假的控制器上下文。我在过去几周内自己实现了这一点并且运行良好。

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;
    if (System.Web.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;
}

所以,你会像这样更新你的代码:

protected string RenderPartialViewToString(ControllerContext context, string viewName, object model)
{
    if (string.IsNullOrEmpty(viewName))
        viewName = context.RouteData.GetRequiredString("action");

    ViewData.Model = model;

    using (StringWriter sw = new StringWriter())
    {
        ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(context, viewName);
        ViewContext viewContext = new ViewContext(context, viewResult.View, ViewData, TempData, sw);
        viewResult.View.Render(viewContext, sw);

        return sw.GetStringBuilder().ToString();
    }
}

并称之为:

//can include RouteData parameter here if needed...
var bogusController = Util.CreateController<YourControllerType>();
var partialViewGuts = RenderPartialViewToString(bogusController.Context, "view", model);

答案 1 :(得分:0)

我发现这一行代码完美无缺。 orderModel是我的模型对象。这个不使用ControllerContext,而是使用辅助方法的html上下文。

System.Web.Mvc.Html.PartialExtensions.Partial(html, "~/Views/Orders/OrdersPartialView.cshtml", orderModel).ToString();