Search code examples
.netjsonajaxwkhtmltopdfrotativa

Ajax is not running with Rotativa ViewAsPdf


I have in my .Net MVC Application a "Localization" Controller with a JsonResult Action.

[HttpGet]
public ActionResult Index(string id)
{
  var data = JsonConvert.DeserializeObject("\"" +  ResourceHelper.GetString(id) + "\"");

  return Json(data, JsonRequestBehavior.AllowGet);
}

This Controller gets a specific resource string from the resource file and returns it as Json.

I create a pdf with the nuget package "Rotativa" Version 1.7.1 based on wkhtmltopdf. I can create the Pdf, thats not the problem. The issue comes, when I use Js-files on this pdf view which makes Ajax calls to the localization controller abve.. My Js on the pdf View:

var dataValues = "";
$.getJSON("/Localization/Index/" + "resourceStringXY", function (data) {
    dataValues = data;
    myFunction();
});

My Rotativa Pdf Controller:

return new ViewAsPdf("PdfView", model)
{
   FileName = "PdfName.pdf",
   PageMargins = new Margins(15, 20, 15, 0),
   IsJavaScriptDisabled = false,
   CustomSwitches = cs
};

Somehow the JS Ajax call cannot be made, even if I use the wkhtmltopf customswitch options

"--no-stop-slow-scripts"

and

"--javascript-delay 25000"

When I simply return the View as a View, I get the Ajax data without any problems. I dont get a js error or something like that. Is there maybe any possibilty to get .Net resources in my Js on the Pdf View instead of Ajax?

Thx for helping :)


Solution

  • It seems like Rotativa doesn't support ajax calls. And because the site is processed by Rotativa and not in a browser or something there is no way to fix this. And this is also the reason why you get no js error showing in your browser console.

    I see two solutions here for you.

    • Generate the PDF differently
    • Serialize all your strings into a json string and put it into the HTML. From there use javascript to read it again.

    You could write a Helper class like this.

    public class TranslationStrings
    {
        public Dictionary<string, string> Strings { get; set; }
    
        public TranslationStrings()
        {
            //init translation dictionary in constructor
            Strings = new Dictionary<string, string>
            {
                //All the keys you need
                {"resourceStringXY" , Resources.General.resourceStringXY},
                {"resourceStringAB" , Resources.General.resourceStringAB}
            };
        }
    
        //simple Method to serialize the dictionary.
        public string GetJsonString()
        {
            JavaScriptSerializer js = new JavaScriptSerializer();
            return js.Serialize(Strings);
        }
    }
    

    Then you can simple put the Json string in the ViewBag like this.

    ViewBag.translations = new TranslationStrings().GetJsonString();
    

    In the cshtml view you can write it in a javascript variable. I save it as a child of window, so its globaly accessible in you javascript.

    <script type="text/javascript">
        window.translations = @(Html.Raw(ViewBag.translations));
    </script>
    

    Than you should be available to access the string like this.

    window.translations["resourceStringXY"]