Я новичок в MVC2.0. Я использую код ниже, чтобы захватить HTML и вернуть его в виде строки. Но это отлично работает в MVC1.0 и .NET 3.5 framework. Недавно я обновил код до .NET 4.0 и MVC 2.0. Теперь это больше не работает, и контекст возвращает ноль. когда я исследую, я увидел две ошибки
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();
}
любые предложения будут действительно полезны ..