2

MVC アプリで signalR を介して部分ビューを文字列として返せるようにする必要があります。ハブを使用しています。

次のメソッドを使用して、部分的なビュー文字列を返します (ここから):

    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 なしで部分ビューをレンダリングする方法はありますか?
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 に答える