I am working on MVC 6 application(DNX Core 5.0 framework). Unfortunately, I don't find any library for pdf export.
Any help will be appreciated.
I finally figured out a way to generate pdf's from .NET Core (without any .NET framework dependencies) is using Node.js from within my .NET Core application. The following example shows how to implementing a HTML to PDF converter in a clean ASP.NET Core Web Application project (Web API template).
Install the NuGet package Microsoft.AspNetCore.NodeServices
In Startup.cs add the line services.AddNodeServices()
like this
public void ConfigureServices(IServiceCollection services)
{
// ... all your existing configuration is here ...
// Enable Node Services
services.AddNodeServices();
}
Now install the required Node.js packages:
From the command line change working directory to the root of the .NET Core project and run these commands.
npm init
and follow the instructions to create the package.json file
npm install jsreport-core --save
npm install jsreport-jsrender --save
npm install jsreport-phantom-pdf --save
Create a file pdf.js
in the root of the project containing
module.exports = function (callback) {
var jsreport = require('jsreport-core')();
jsreport.init().then(function () {
return jsreport.render({
template: {
content: '<h1>Hello {{:foo}}</h1>',
engine: 'jsrender',
recipe: 'phantom-pdf'
},
data: {
foo: "world"
}
}).then(function (resp) {
callback(/* error */ null, resp.content.toJSON().data);
});
}).catch(function (e) {
callback(/* error */ e, null);
})
};
Have a look here for more explanation on jsreport-core
.
Now create an action in an Mvc controller that calls this Node.js script
[HttpGet]
public async Task<IActionResult> MyAction([FromServices] INodeServices nodeServices)
{
var result = await nodeServices.InvokeAsync<byte[]>("./pdf");
HttpContext.Response.ContentType = "application/pdf";
string filename = @"report.pdf";
HttpContext.Response.Headers.Add("x-filename", filename);
HttpContext.Response.Headers.Add("Access-Control-Expose-Headers", "x-filename");
HttpContext.Response.Body.Write(result, 0, result.Length);
return new ContentResult();
}
Off course you can do whatever you want with the byte[]
returned from nodeServices, in this example I'm just outputting it from a controller action so it can be viewed in the browser.
You could also exchange the data between Node.js and .NET Core by a base64 encoded string using resp.content.toString('base64')
in pdf.js
and use
var result = await nodeServices.InvokeAsync<byte[]>("./pdf");
in the action and then decode the base64 encoded string.
Most pdf generator solutions still depend on .NET 4.5/4.6 framework. None of the two answers above (JsReport and RazorPDFCore) works for .NET Core yet.
There seems to be some paid alternatives available if you don't like to use Node.js:
I haven't tried any of these though.
I hope we will soon see some open source progress in this area.
If you must rely on Core you'll have two options:
Core is still RC1, slowly moving to RC2, and you won't find much libs really soon. Since .NET Core is taking much attention, first libs should come out in a few months, but I'd guess you'll have to wait for at least RC2 release.
You can grab an open-source project that best fits your needs, fork (if on GitHub) or just download and start updating to .NET Core. I've just done that with DapperExtensions
and it's working like a charm. You can even add some spicy just for you ;)
On the other hand, if you just need something that works but with no direct need of embedding into .NET Core, I've managed to make JsReport work fine. It will start it's very own server (embedded server) based on Node
but integration is really easy (with AspNet Core very own Dependecy Injection system!) and PDF are created with no further issue.
If that interests you, here are some instructions:
Add those to your project.json:
"jsreport.Embedded": "0.8.1",
"jsreport.Client": "0.8.1"
After, follow instructions from jsReport here. You can configure AspNet DI system as here:
public void ConfigureServices(IServiceCollection services)
{
// ...
var _server = new EmbeddedReportingServer();
_server.StartAsync().Wait();
services.AddInstance<IEmbeddedReportingServer>(_server);
services.AddSingleton<IReportingService>((s) => { return s.GetRequiredService<IEmbeddedReportingServer>().ReportingService; });
// ...
}
To use you'll just have to either receive an IReportingService
or manually grab it from Resolver
on your controller, for instance.
public IActionResult SomeReport()
{
// This is <my> type of usage. It's a bit manual because I'm currently loading reports from DB. You can use it in a diferent way (check jsReport docs).
var service = Resolver.GetRequiredService<jsreport.Client.IReportingService>();
var phantomOptions = new jsreport.Client.Entities.Phantom()
{
format = "A4",
orientation = "portrait",
margin = "0cm"
};
phantomOptions.footer = "<h2>Some footer</h2>";
phantomOptions.footerHeight = "50px";
phantomOptions.header = "<h2>Some header</h2>";
phantomOptions.headerHeight = "50px";
var request = new jsreport.Client.RenderRequest()
{
template = new jsreport.Client.Entities.Template()
{
content = "<div>Some content for your report</div>",
recipe = "phantom-pdf",
name = "Your report name",
phantom = phantomOptions
}
};
var _report = service.RenderAsync(request).Result;
// Request file download.
return File(_report.Content, "application/pdf", "Some fancy name.pdf");
}
Due to changes from NuGet on AspNet projects, you have to manually move some content files which are not moved automatically.
First, find your dnx cache for the embedded server. Should be something like:C:\Users\<name>\.dnx\packages\jsreport.Embedded\0.8.1
.
You'll notice a folder called content
there. Simply copy it's contents (two files: node.exe
and jsreport-net-embedded.zip
) into lib\net45
.
So, to be plain simple and fool-proof: copy contents (files only) from C:\Users\<name>\.dnx\packages\jsreport.Embedded\0.8.1\contents
into C:\Users\<name>\.dnx\packages\jsreport.Embedded\0.8.1\lib\net45
.
That should solve startup issues. Remember: first startup will extract files and should take a few minutes. After that, it will be much much faster.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With