Search code examples
asp.netasp.net-mvccontrollerascx

Calling MVC controller's action from ASCX <% code %>


I am working with a "legacy system" that is a large ASP.NET Web Forms site. A main extensibility point of this system is writing a dynamically loaded and rendered .ascx controls.

A web site project has ASP.NET MVC 3 dependencies referenced, and even has a ground for MVC usage by introducing the following route into the ASP.NET 4 routing system:

    routes.MapRoute(
      "Default", // Route name
      "{controller}.mvc/{action}/{pid}", // URL with parameters
      new { controller = "Home", action = "Index", pid = "" } // Parameter defaults

According to this route, everything, that is to be called by the url pattern of {controller}.mvc will be rendered according to MVC paradigm.

In my ascx control (I can't avoid using ASCX, I have to live with it), I am making a call to my controller from code:

<% 
    var controller = new NamingsController(DependencyResolver.Current.GetService<InDocContext>());
    var htmlToRender = controller.RenderExistingNamings(); 
%>

   <%=htmlToRender%>

This way of calling a controller is wrong - I am creating it manually, whereas in the "normal way" it is getting created by the controller factory. In my case, the request context, and therefore a controller context are not populated and my controller is no better than a standard logic class.

What is the correct way of invoking a controller's action in my case, so that it executes as if a user made a call to it via the browser?


Solution

  • Try the following:

    <%
        var routeData = new RouteData();
        routeData.Values["controller"] = "Namings";
        routeData.Values["action"] = "RenderExistingNamings";        
        IController controller = new NamingsController(DependencyResolver.Current.GetService<InDocContext>());
        var rc = new RequestContext(new HttpContextWrapper(Context), routeData);
        controller.Execute(rc);        
    %>
    

    Notice that there's no <%=htmlToRender%>. The output will be immediately written to the response.

    You should be careful with the Content-Type response header that will be now the content type set by your controller action and not the content type set by your WebForm. If both are text/html it should be an issue.