我是MVC2.0的新手。我使用下面的代码来捕获HTML并将其作为字符串返回。但这在MVC1.0和.NET 3.5框架中运行良好。最近我将代码升级到.NET 4.0和MVC 2.0。现在这不再起作用,上下文返回null。当我探索时,我看到了两个错误 1.“此操作需要IIS集成管道模式。” 2.OutputStream ='response.OutputStream'抛出了类型system.Web.HttpException的异常'
这是调用函数
var htmlstring = this.CaptureActionHtml(new PdfController(_paService, _configService), c => (ViewResult)paController.GetHTML(p));
//和捕获方法。
/// <summary>
/// Captures the HTML output by a controller action that returns a ViewResult
/// </summary>
/// <typeparam name="TController">The type of controller to execute the action on</typeparam>
/// <param name="controller">The current controller</param>
/// <param name="targetController">The controller which has the action to execute</param>
/// <param name="action">The action to execute</param>
/// <returns>The HTML output from the view</returns>
public static string CaptureActionHtml<TController>(
this Controller controller,
TController targetController,
Func<TController, ViewResult> action)
where TController : Controller
{
return controller.CaptureActionHtml(targetController, null, action);
}
/// <summary>
/// Captures the HTML output by a controller action that returns a ViewResult
/// </summary>
/// <typeparam name="TController">The type of controller to execute the action on</typeparam>
/// <param name="controller">The current controller</param>
/// <param name="targetController">The controller which has the action to execute</param>
/// <param name="masterPageName">The name of the master page for the view</param>
/// <param name="action">The action to execute</param>
/// <returns>The HTML output from the view</returns>
public static string CaptureActionHtml<TController>(
this Controller controller,
TController targetController,
string masterPageName,
Func<TController, ViewResult> action)
where TController : Controller
{
if (controller == null)
{
throw new ArgumentNullException("controller");
}
if (targetController == null)
{
throw new ArgumentNullException("targetController");
}
if (action == null)
{
throw new ArgumentNullException("action");
}
// pass the current controller context to orderController
var controllerContext = controller.ControllerContext;
targetController.ControllerContext = controllerContext;
// replace the current context with a new context that writes to a string writer
var existingContext = System.Web.HttpContext.Current;
var writer = new StringWriter();
var response = new HttpResponse(writer);
var context = new HttpContext(existingContext.Request, response) {User = existingContext.User};
System.Web.HttpContext.Current = context;
// execute the action
var viewResult = action(targetController);
// change the master page name
if (masterPageName != null)
{
viewResult.MasterName = masterPageName;
}
// we have to set the controller route value to the name of the controller we want to execute
// because the ViewLocator class uses this to find the correct view
var oldController = controllerContext.RouteData.Values["controller"];
controllerContext.RouteData.Values["controller"] = typeof(TController).Name.Replace("Controller", "");
// execute the result
viewResult.ExecuteResult(controllerContext);
// restore the old route data
controllerContext.RouteData.Values["controller"] = oldController;
// restore the old context
System.Web.HttpContext.Current = existingContext;
return writer.ToString();
}
我找到了一个解决方案..但是遇到了另一个问题..模型没有通过视图......这是更新后的代码
public static string CaptureActionHtml<TController>(this Controller controller, TController targetController, string masterPageName, Func<TController, ViewResult> action) where TController : Controller
{
if (controller == null)
{
throw new ArgumentNullException("controller");
}
if (targetController == null)
{
throw new ArgumentNullException("targetController");
}
if (action == null)
{
throw new ArgumentNullException("action");
}
// pass the current controller context to orderController
var controllerContext = controller.ControllerContext;
targetController.ControllerContext = controllerContext;
// replace the current context with a new context that writes to a string writer
var existingContext = HttpContext.Current;
var writer = new StringWriter();
var response = new HttpResponse(writer);
var context = new HttpContext(existingContext.Request, response) { User = existingContext.User };
HttpContext.Current = context;
// execute the action
var viewResult = action(targetController);
// change the master page name
if (masterPageName != null)
{
viewResult.MasterName = masterPageName;
}
// we have to set the controller route value to the name of the controller we want to execute
// because the ViewLocator class uses this to find the correct view
var oldController = controllerContext.RouteData.Values["controller"];
controllerContext.RouteData.Values["controller"] = typeof(TController).Name.Replace("Controller", "");
// execute the result
viewResult.ExecuteResult(controllerContext);
StringWriter sw = new StringWriter();
//var viewContext = new ViewContext(controllerContext, viewResult.View, new ViewDataDictionary(controllerContext.Controller.ViewData.Model), new TempDataDictionary(), sw);
var viewContext = new ViewContext(controllerContext, viewResult.View, targetController.ViewData, new TempDataDictionary(), sw);
viewResult.View.Render(viewContext, HttpContext.Current.Response.Output);
response.Flush();
// restore the old route data
controllerContext.RouteData.Values["controller"] = oldController;
// restore the old context
HttpContext.Current = existingContext;
return sw.ToString();
}
任何建议都会非常有用..
答案 0 :(得分:1)
感谢您的复习..我自己找到了......傻我!它只是简单的事情..这是完整的代码..
public static string CaptureActionHtml<TController>(this Controller controller, TController targetController, string masterPageName, Func<TController, ViewResult> action) where TController : Controller
{
if (controller == null)
{
throw new ArgumentNullException("controller");
}
if (targetController == null)
{
throw new ArgumentNullException("targetController");
}
if (action == null)
{
throw new ArgumentNullException("action");
}
// pass the current controller context to orderController
var controllerContext = controller.ControllerContext;
targetController.ControllerContext = controllerContext;
// replace the current context with a new context that writes to a string writer
var existingContext = HttpContext.Current;
var writer = new StringWriter();
var response = new HttpResponse(writer);
var context = new HttpContext(existingContext.Request, response) { User = existingContext.User };
HttpContext.Current = context;
// execute the action
var viewResult = action(targetController);
// change the master page name
if (masterPageName != null)
{
viewResult.MasterName = masterPageName;
}
// we have to set the controller route value to the name of the controller we want to execute
// because the ViewLocator class uses this to find the correct view
var oldController = controllerContext.RouteData.Values["controller"];
controllerContext.RouteData.Values["controller"] = typeof(TController).Name.Replace("Controller", "");
// execute the result
viewResult.ExecuteResult(controllerContext);
StringWriter sw = new StringWriter();
var xx = targetController.TempData["pdf"];
//var viewContext = new ViewContext(controllerContext, viewResult.View, new ViewDataDictionary(targetController.ViewData.Model), new TempDataDictionary(), sw);
var viewContext = new ViewContext(controllerContext, viewResult.View, viewResult.ViewData, new TempDataDictionary(), sw);
viewResult.View.Render(viewContext, HttpContext.Current.Response.Output);
response.Flush();
// restore the old route data
controllerContext.RouteData.Values["controller"] = oldController;
// restore the old context
HttpContext.Current = existingContext;
return sw.ToString();
}
我刚刚更换了这行代码
var viewContext = new ViewContext(controllerContext, viewResult.View, new ViewDataDictionary(targetController.ViewData.Model), new TempDataDictionary(), sw);
与
var viewContext = new ViewContext(controllerContext, viewResult.View, viewResult.ViewData, new TempDataDictionary(), sw);
工作正常..干杯!!