Calling MVC view from asp.net class throws exception

I would like to get HTML of the MVC view. Call is being made from ASCX.CS class. (I am trying to inject MVC View to ASPX page). My ASPX page is created dynamically (controls are added from code behind).

I've found part of the answer here. The only problem is that this extension method is made for MVC controller class.

What I do in my call from ASCX.CS:

 fCatEve.Controllers.ASPXTestController test = new Controllers.ASPXTestController();
      string htmlView = test.RenderView("Index", null);

In this action the only problem I have is ControllerContext . I don't know how to set this class, so it will find partial view that I am looking for.

Here are methods I am using (from page mentioned above):

public static class ControllerExtensions
{
    public static string RenderView(this Controller controller, string viewName, object model)
    {
        return RenderView(controller, viewName, new ViewDataDictionary(model));
    }

    public static string RenderView(this Controller controller, string viewName, ViewDataDictionary viewData)
    {
        RouteData routeData = new RouteData();
  routeData.Values.Add("controller", controller);
  var controllerContext = new ControllerContext { Controller = controller, RouteData = routeData };

  var viewResult = ViewEngines.Engines.FindView(controllerContext, viewName, null);

        StringWriter stringWriter;

        using (stringWriter = new StringWriter())
        {
            var viewContext = new ViewContext(
                controllerContext,
                viewResult.View,
                viewData,
                controllerContext.Controller.TempData,
                stringWriter);

            viewResult.View.Render(viewContext, stringWriter);
            viewResult.ViewEngine.ReleaseView(controllerContext, viewResult.View);
        }

        return stringWriter.ToString();
    }
}

The exception is:

The RouteData must contain an item named 'controller' with a non-empty string value.

After trying first answer, here is stack trace of exception:

at System.Web.HttpContextBase.get_Items() at System.Web.WebPages.DisplayModeProvider.GetDisplayMode(HttpContextBase context) at System.Web.Mvc.VirtualPathProviderViewEngine.GetPath(ControllerContext controllerContext, String[] locations, String[] areaLocations, String locationsPropertyName, String name, String controllerName, String cacheKeyPrefix, Boolean useCache, String[]& searchedLocations) at System.Web.Mvc.VirtualPathProviderViewEngine.FindView(ControllerContext controllerContext, String viewName, String masterName, Boolean useCache) at System.Web.Mvc.ViewEngineCollection.<>c__DisplayClass6.b__4(IViewEngine e) at System.Web.Mvc.ViewEngineCollection.Find(Func`2 lookup, Boolean trackSearchedPaths) at System.Web.Mvc.ViewEngineCollection.FindView(ControllerContext controllerContext, String viewName, String masterName) at fCatEve.Helpers.ControllerExtensions.RenderView(Controller controller, String viewName, ViewDataDictionary viewData) in C:ProjectsG_Test - KOPIJAfCatEve03Solution fCatEvefCatEveHelpersControllerExtensions.cs:line 43 at fCatEve.Controls.KoledarReception.PutValuesToTabControlEVEBEVEN(Panel paControl, REFields REField) in C:ProjectsG_Test - KOPIJAfCatEve03SolutionfCatEvefCatEvewfControlsKoledarReception.ascx.cs:line 2747 at fCatEve.Controls.KoledarReception.PutValuesToTabControl() in C:ProjectsG_Test - KOPIJAfCatEve03SolutionfCatEvefCatEvewfControlsKoledarReception.ascx.cs:line 2710 at fCatEve.Controls.KoledarReception.Page_Load(Object sender, EventArgs e) in C:ProjectsG_Test - KOPIJAfCatEve03SolutionfCatEvefCatEvewfControlsKoledarReception.ascx.cs:line 817 at System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) at System.Web.UI.Control.OnLoad(EventArgs e) at System.Web.UI.Control.LoadRecursive() at System.Web.UI.Control.LoadRecursive() at System.Web.UI.Control.LoadRecursive() at System.Web.UI.Control.LoadRecursive() at System.Web.UI.Control.LoadRecursive() at System.Web.UI.Page.ProcessRequ estMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)


以下是我用于生成PDF文件的单元测试之一的示例代码,不确定它是否对您有任何好处。

var controller = new MyAwesomePdfController();

var httpRequest = new HttpRequest("", "http://mySomething", "");
var stringWriter = new StringWriter();
var httpResponse = new HttpResponse(stringWriter);
var routeData = new RouteData();
routeData.Values.Add("Controller", "MyAwesomePdf");  //must match your Controller name
routeData.Values.Add("Action", "Receipt");  //must match your Action name

var httpContextMock = new HttpContext(httpRequest, httpResponse)
{
    //this is probably irrelevant to you, can set user principal here
    //User = new GenericPrincipal(
    //  new GenericIdentity(username),
    //  userRoles //new string[0]
    //)
};

controller.ControllerContext = new ControllerContext(new HttpContextWrapper(httpContextMock), routeData, controller);

var receiptId = 1234;
var pdfResult = await controller.Receipt(receiptId) as ViewAsPdf;  //should return a pdf file

I rewrote the call (most important: HttpContext.Current, which is later used in MVC):

fCatEve.Controllers.ASPXTestController test = new Controllers.ASPXTestController();
      string htmlView = test.RenderView("Index", null, HttpContext.Current);

I also slightly rewrote both methods:

   public static string RenderView(this Controller controller, string viewName, object model, HttpContext currentContext)
    {
      return RenderView(controller, viewName, new ViewDataDictionary(model), currentContext);
    }


    public static string RenderView(this Controller controller, string viewName, ViewDataDictionary viewData, HttpContext currentContext)
    {
      var routeData = new RouteData();
      routeData.Values.Add("Controller", "ASPXTest");  //must match your Controller name
      routeData.Values.Add("Action", "Test");  //must match your Action name

      HttpContextWrapper wrapper = new HttpContextWrapper(currentContext);
      controller.ControllerContext = new ControllerContext(wrapper, routeData, controller);
      var viewResult = ViewEngines.Engines.FindView(controller.ControllerContext, viewName, null);

      StringWriter stringWriter;
      viewData = new ViewDataDictionary();


      using (stringWriter = new StringWriter())
      {
        var viewContext = new ViewContext(
            controller.ControllerContext,
            viewResult.View,
            viewData,
            controller.ControllerContext.Controller.TempData,
            stringWriter);

        viewResult.View.Render(viewContext, stringWriter);
        viewResult.ViewEngine.ReleaseView(controller.ControllerContext, viewResult.View);
      }

      return stringWriter.ToString();
    }
链接地址: http://www.djcxy.com/p/27994.html

上一篇: 默认比较器如何在C#中工作?

下一篇: 从asp.net类调用MVC视图会引发异常