HenrikP
HenrikP

Reputation: 884

Rotativa PDF in model - ControllerContext

I'm using Rotativa to generate PDFs from actions/views and it works great. However is it possible to use it inside of models or can you purely use it in controllers?

The issue is that the function wants to use a ControllerContext which models doesn't have

var pdfResult = new ActionAsPdf("GeneratePDF", "PDF");

byte[] pdfFile = pdfResult.BuildPdf(this.ControllerContext);

My end result is that I want the PDF in a byte array if there are other ways of doing it

Upvotes: 4

Views: 4585

Answers (1)

Sean Thorburn
Sean Thorburn

Reputation: 1778

You can use the following code to instantiate controllers and then configure a ControllerContext through that instance - from anywhere in your application.

/// <summary>
/// Creates an instance of an MVC controller from scratch 
/// when no existing ControllerContext is present       
/// </summary>
/// <typeparam name="T">Type of the controller to create</typeparam>
/// <returns>Controller Context for T</returns>
/// <exception cref="InvalidOperationException">thrown if HttpContext not available</exception>
public static T CreateController<T>(RouteData routeData = null)
            where T : Controller, new()
{
    // create a disconnected controller instance
    T controller = new T();

    // get context wrapper from HttpContext if available
    HttpContextBase wrapper = null;
    if (HttpContext.Current != null)
        wrapper = new HttpContextWrapper(System.Web.HttpContext.Current);
    else
        throw new InvalidOperationException(
            "Can't create Controller Context if no active HttpContext instance is available.");

    if (routeData == null)
        routeData = new RouteData();

    // add the controller routing if not existing
    if (!routeData.Values.ContainsKey("controller") && !routeData.Values.ContainsKey("Controller"))
        routeData.Values.Add("controller", controller.GetType().Name
                                                    .ToLower()
                                                    .Replace("controller", ""));

    controller.ControllerContext = new ControllerContext(wrapper, routeData, controller);
    return controller;
}

This can be used like:

QuotesController quotesController = ViewRenderer.CreateController<QuotesController>();
ViewAsPdf view = (ViewAsPdf)quotesController.Preview(model.Guid);
byte[] pdf = view.BuildPdf(quotesController.ControllerContext);
EmailService.Send(model, pdf);

Reference: http://weblog.west-wind.com/posts/2013/Jul/15/Rendering-ASPNET-MVC-Razor-Views-outside-of-MVC-revisited

Upvotes: 4

Related Questions