PartialView到Html字符串

Jon*_*lis 3 c# asp.net-mvc partial-views signalr

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

Service -> SignalR Hub           Controller
                       v      ^              v
                         View                   Partial
Run Code Online (Sandbox Code Playgroud)

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

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

Service -> Controller -> SignalR Hub
                                     v
                                        View
Run Code Online (Sandbox Code Playgroud)

控制器将部分视图的字符串表示发送到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();
        }
    }
Run Code Online (Sandbox Code Playgroud)

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

Sve*_*sen 6

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

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;
}
Run Code Online (Sandbox Code Playgroud)

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

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

并称之为:

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