signalR通过集线器发送部分视图结果字符串

时间:2013-04-02 12:46:44

标签: asp.net-mvc asp.net-mvc-4 signalr signalr-hub

我需要能够通过signalR在我的MVC应用中将部分视图作为字符串返回。我正在使用集线器。

我正在使用以下方法返回部分视图字符串(来自here):

    public static string RenderPartialView(string controllerName, string partialView, object model)
    {
        var context = httpContextBase as HttpContextBase;

        var routes = new RouteData();
        routes.Values.Add("controller", controllerName);

        var requestContext = new RequestContext(context, routes);

        string requiredString = requestContext.RouteData.GetRequiredString("controller");
        var controllerFactory = ControllerBuilder.Current.GetControllerFactory();
        var controller = controllerFactory.CreateController(requestContext, requiredString) as ControllerBase;

        controller.ControllerContext = new ControllerContext(context, routes, controller);

        var ViewData = new ViewDataDictionary();

        var TempData = new TempDataDictionary();

        ViewData.Model = model;

        using (var sw = new StringWriter())
        {
            var viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext, partialView);
            var viewContext = new ViewContext(controller.ControllerContext, viewResult.View, ViewData, TempData, sw);

            viewResult.View.Render(viewContext, sw);
            return sw.GetStringBuilder().ToString();
        }
    }

为了使这个方法有效,我需要HttpContext.Current因此在我的OnConnected(我注意到它总是存在)我设置它是这样的:

    public class TaskActionStatus : Hub
    {
        private static HttpContextBase httpContextBase;
...

        public override Task OnConnected()
        {
            httpContextBase = new HttpContextWrapper(HttpContext.Current) as HttpContextBase;
...

然后我在我的RenderPartialView方法中使用它:

var context = httpContextBase as HttpContextBase;

这样我总能访问当前的HttpContext。但是,我注意到有时我的HttpContext静态副本为null。这是为什么?。

  • 这里最好的方法是什么?
  • 有没有办法在没有HttpContext的情况下渲染局部视图?

1 个答案:

答案 0 :(得分:1)

我使用假的http上下文来生成视图:

    public static string GetRazorViewAsString(object model, string filePath)
    {
        HttpContext httpContext = MockHelper.FakeHttpContext();

        var st = new StringWriter();
        var context = new HttpContextWrapper(httpContext);

        var routeData = new RouteData();
        var controllerContext = new ControllerContext(new RequestContext(context, routeData), new FakeController());
        var razor = new RazorView(controllerContext, filePath, null, false, null);
        razor.Render(
            new ViewContext(controllerContext, razor, new ViewDataDictionary(model), new TempDataDictionary(), st), 
            st);
        return st.ToString();
    }

    #endregion
}

public class FakeController : Controller
{
}

public class MockHelper
{
    #region Public Methods and Operators

    public static HttpContext FakeHttpContext()
    {
        var httpRequest = new HttpRequest(string.Empty, "http://novomatic/", string.Empty);
        var stringWriter = new StringWriter();
        var httpResponce = new HttpResponse(stringWriter);
        var httpContext = new HttpContext(httpRequest, httpResponce);

        var sessionContainer = new HttpSessionStateContainer(
            "id", 
            new SessionStateItemCollection(), 
            new HttpStaticObjectsCollection(), 
            10, 
            true, 
            HttpCookieMode.AutoDetect, 
            SessionStateMode.InProc, 
            false);

        httpContext.Items["AspSession"] =
            typeof(HttpSessionState).GetConstructor(
                BindingFlags.NonPublic | BindingFlags.Instance, 
                null, 
                CallingConventions.Standard, 
                new[] { typeof(HttpSessionStateContainer) }, 
                null).Invoke(new object[] { sessionContainer });

        return httpContext;
    }

    #endregion
}