.Net Client issue "Unable to render template"
-
There seems to be an issue with the function call service.RenderAsync which is returning the following error
JsReportException: Unable to render template. <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body> <pre>Cannot POST /api/api/report</pre> </body> </html>Its looks like its adding path 'api' twice even though the call sent is
ReportingService service = new ReportingService("https://{host}/reporting/api/report");Removing 'api' from path works and returns the pdf file only when its the root path but for the scenario above where 'reporting' is the root path it fails.
-
The
ReportingServiceconstructor parameter accepts url to the jsreport service
If your jsreport instance runs onhttps://host/reporting, you should do:ReportingService service = new ReportingService("https://host/reporting");
-
If I keep just reporting its returns a 404 error
JsReportException: Unable to render template. <html> <head><title>404 Not Found</title></head> <body bgcolor="white"> <center><h1>404 Not Found</h1></center> <hr><center>nginx/1.14.0 (Ubuntu)</center> </body> </html>I have 2 enterprise licenses for 2 clients, I had faced the issue before when the path sent was
ReportingService service = new ReportingService("https://host/api/report");I ended up sending
ReportingService service = new ReportingService("https://host/report");and it worked for that scenario.
-
So you can open
https://host/reportingin the browser, see jsreport studio and render template?
But if you use(new ReportingService(https://host/reporting)).renderAsyncyou get 404 error?The 404 error you shared is from nginx, not jsreport. Are you sure you have the correct settings there?
What if you invoke jsreport render request using a postman or some other tool?
-
A postman call to the link below returns the pdf file
https://host/reporting/api/reportThe issue is the JsReport .Net Client package, below is the snippet of code
//ReportingService service = new ReportingService("https://{host}/reporting/api/report"); ReportingService service = new ReportingService("https://{host}/reporting"); service.Username = {username}; service.Password = {password}; using (var fileStream = File.Create(Server.MapPath("~/temp/") + {reportname}+ ".pdf")) { var report = service.RenderAsync({jsreport_shortid}, {data}).Result; //Error pops up here report.Content.CopyTo(fileStream); Response.ContentType = "application/pdf"; Response.AppendHeader("Content-Disposition", "attachment; filename=" + {reportname} + ".pdf"); fileStream.Seek(0, SeekOrigin.Begin); fileStream.CopyTo(Response.OutputStream); Response.Flush(); Response.Close(); Response.End(); }
-
Hmm. Thanks. Nothing comes to my mind, unfortunately. I don't see any reason why the postman should behave differently than the client.
I would recommend doing the same HTTP post you do from postman but inside c#, and see if it actually works.
-
Hey Jan! Yes attempted HTTP Post in C# replicating postman and it works.
-
Thank you. I guess you use also the .net
HttpClientlib?
Could you check what you do differently, there is no big magic in the jsreport-client code.
https://github.com/jsreport/jsreport-dotnet-client/blob/master/jsreport.Client/ReportingService.cs#L154
-
Please see below, I replicated most of what was available on the jsreport-dotnet-client git
public class JsReportHelper { public TimeSpan? HttpClientTimeout { get; set; } public IContractResolver ContractResolverForDataProperty { get; set; } public async Task<Report> RenderAsync(string templateUri, string templateShortid, JObject jsonData) { JObject root = new JObject(); JObject template = new JObject { { "shortid", templateShortid } }; root.Add("template", template); root.Add("data", jsonData); string request = SerializerHelper.SerializeRenderRequest(templateShortid, jsonData.ToString(), ContractResolverForDataProperty); CancellationToken ct = default(CancellationToken); var client = new HttpClient(); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", System.Convert.ToBase64String( Encoding.UTF8.GetBytes(String.Format("{0}:{1}", Constants.JsReport_Username, Constants.JsReport_Password)))); if (HttpClientTimeout != null) client.Timeout = HttpClientTimeout.Value; var content = new StringContent(root.ToString(), Encoding.UTF8, "application/json"); var response = await client.PostAsync(templateUri, content, ct).ConfigureAwait(false); if (response.StatusCode != HttpStatusCode.OK) throw JsReportException.Create("Unable to render template. ", response); response.EnsureSuccessStatusCode(); return await ReportFromResponse(response).ConfigureAwait(false); } private static async Task<Report> ReportFromResponse(HttpResponseMessage response) { var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); IDictionary<string, string> meta = new Dictionary<string, string>(); response.Headers.ToList().ForEach(h => meta[h.Key] = h.Value.FirstOrDefault()); response.Content.Headers.ToList().ForEach(h => meta[h.Key] = h.Value.FirstOrDefault()); return new ReportHttp() { Content = stream, Response = response }; } }This is how I invoke it
JsReportHelper jsService = new JsReportHelper(); //item.jsreport_url ("https://{host}/reporting/api/report") //item.jsreport_shortid (js report template id) //root (JObject) var report = jsService.RenderAsync(item.jsreport_url, item.jsreport_shortid, root).Result;I am not sure why but the error with the original code (see below) still persists.
ReportingService service = new ReportingService("https://{host}/reporting/api/report"); //or ReportingService service = new ReportingService("https://{host}/reporting");
-
It
jsreport.Clientuses theBaseAddressparam forHttpClient. Could you try the same?var client = new HttpClient() { BaseAddress = "https://{host}/reporting"}; var response = await client.PostAsync("api/report", content, ct).ConfigureAwait(false);
-
Attempted with jsreport.Client, I get the 404 error.

Attempted with custom, It downloads the file


I bet its something silly on my end but cant for heaven's sake figure it out :'D .
For now I have gone ahead with the custom implementation. A voice in my head keeps wanting me to figure out the cause of this error :D If you want to get to the bottom of this error as well, I can put in a request for a test user and set up a mirror report and DM you the details.