我有一个工作流程,当数据从服务进入时,使用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的情况下渲染局部视图的方法。有可能这样做吗?
答案 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();