在MVC2.0捕获HTML为String [英] Capturing HTML to String in MVC2.0

查看:211
本文介绍了在MVC2.0捕获HTML为String的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是新来MVC2.0。我用的是下面的code捕捉到HTML,并返回一个字符串。但是,这工作正常,在MVC1.0和.NET 3.5框架。最近我升级了code到.NET 4.0和MVC 2.0。现在这已经不再工作,上下文返回null。当我探讨,我看到两个错误 1.此操作需要IIS综合管道模式。 2.OutputStream ='response.OutputStream'引发了异常的类型system.Web.HttpException

I am new to MVC2.0. I use the below code to capture HTML and return it as a string. But this works fine in MVC1.0 and .NET 3.5 framework. Recently I upgraded the code to .NET 4.0 and MVC 2.0. Now this is no longer working and the context returns null. when I explore I saw two errors 1."This operation requires IIS integrated pipeline mode." 2.OutputStream = 'response.OutputStream' threw an exception of type system.Web.HttpException'

下面是调用函数

var htmlstring = this.CaptureActionHtml(new PdfController(_paService, _configService), c => (ViewResult)paController.GetHTML(p));

//和捕获方法。

//and the capture method.

  /// <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();
        }

我发现周围的工作..但打在了另一个问题。该模型没有通过view..Here是更新code

I found a work around.. but struck in another problem.. The model was not passing through the view..Here is the updated code

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();
    } 

任何建议将是很有益的。

any suggestions will be really helpful..

推荐答案

感谢您审阅。我发现我自己..愚蠢的我!它只是简单的事情。这里是全code ..

Thanks for reviewing.. I found it myself.. silly me!! its just simple thing.. Here is the full code..

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();
    } 

我刚刚更换这行code

I just replaced this line of code

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);

它工作正常..干杯!!

It works fine.. Cheers!!

这篇关于在MVC2.0捕获HTML为String的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆