2

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

我正在使用以下方法返回部分视图字符串(从这里):

    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 静态副本为空。这是为什么?。

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

1 回答 1

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
}
于 2014-04-15T08:20:27.267 回答