Welcome Guest Search | Active Topics | Sign In | Register

Inconsistent results with HtmlToPdf.ConvertUrl Options
nbhor
Posted: Monday, November 4, 2013 5:06:15 PM
Rank: Member
Groups: Member

Joined: 4/30/2013
Posts: 11
Hi, we have been using EO.Pdf (version 4.0.60.2) in our production environment from past 1 month and pdf conversion is not consistent. It works most of the time but sometimes we get following error for same URL. If you try to convert html page to pdf consistently, you may end up getting error few times.
On following Page, you can find different urls for (download pdf, printable page, email page..). For download pdf link we use the EO.Pdf HtmlToPdf.ConvertUrl funtion where we pass in the URL of Printable Page. Sometimes user are able to download pdf fine while sometime it just reports following error message.

Message :The constructor to deserialize an object of type 'EO.Pdf.HtmlToPdfException' was not found.

We are using ASP.Net MVC 4 framework for our application. We are using following classes, extension and entities in our application for HTML to PDF conversion purpose.

public class PdfActionResult : ViewResult
{
public string Url { get; set; }
public string OutputFileName { get; set; }

public PdfActionResult(string url, string outputFileName)
{
this.Url = url;
this.OutputFileName = outputFileName.Replace(',','-');
}

public override void ExecuteResult(ControllerContext context)
{
HttpResponseBase response = context.HttpContext.Response;
IEntityController currentController = context.Controller as IEntityController;
if (null != currentController)
{
byte[] pdfBytes;
using (Isolated<PdfConverter> isolated = new Isolated<PdfConverter>())
{
pdfBytes = isolated.Value.Process(
new PdfParameters
{
Key = currentController.AppConfig.EoPdfKey,
Url = this.Url,
Header = string.Empty,
HideItemIds = "trPrintBreadCrumb;trPrintButtons;"
});
}

response.ContentType = "application/pdf";
// send the PDF document as a response to the browser for download
response.Clear();
response.AddHeader("Content-Type", "application/pdf");
response.AddHeader("Content-Disposition", "attachment; filename=" + this.OutputFileName + ".pdf;");
response.Flush();
response.BinaryWrite(pdfBytes);
response.Flush();
}
response.End();
}
}

/*************************************************************************/
[Serializable]
public class PdfParameters
{
public string Url { get; set; }
public string Header { get; set; }
public string Footer { get; set; }
public string Key { get; set; }
public string HideItemIds { get; set; }
}

public class PdfConverter : MarshalByRefObject
{
public byte[] Process(PdfParameters pdfParams)
{
System.IO.MemoryStream stream = new System.IO.MemoryStream();
try
{
EO.Pdf.Runtime.AddLicense(pdfParams.Key);
PdfDocument doc = new PdfDocument();
HtmlToPdf.Options.HeaderHtmlFormat = pdfParams.Header ?? "PDF converted from {url}<hr />";
HtmlToPdf.Options.FooterHtmlFormat = pdfParams.Footer ?? @"<hr /><div style=""text-align:right""><span style=""font-family:Arial,Verdana;font-size:9px;"">" + DateTime.Now.ToShortDateString() + @" | Page {page_number} of {total_pages}</span></div>";
HtmlToPdf.Options.OutputArea = new RectangleF(0.25f, 0.25f, 8f, 10f);
HtmlToPdf.Options.ZoomLevel = 0.6f;
HtmlToPdf.Options.InvisibleElementIds = pdfParams.HideItemIds ?? string.Empty;
HtmlToPdf.Options.AutoFitX = HtmlToPdfAutoFitMode.ShrinkToFit;
HtmlToPdf.Options.NoLink = true;
HtmlToPdf.ConvertUrl(pdfParams.Url, doc);
doc.Save(stream);
stream.Position = 0;
return stream.ToArray();
}
catch (Exception excp)
{
throw new Exception(string.Format("HtmlToPdf.ConvertUrl failed for-{0}", pdfParams.Url), excp);
}
finally
{
stream.Dispose();
}
}
}
/*************************************************************************/
//http://www.superstarcoders.com/blogs/posts/executing-code-in-a-separate-application-domain-using-c-sharp.aspx
//http://www.essentialobjects.com/forum/postst7494_EOPdf-worker-processqueue-leads-to-unreliable-conversions-JavaScript-stops-being-processed.aspx
public sealed class Isolated<T> : IDisposable where T : MarshalByRefObject
{
private AppDomain _domain;
private T _value;

public Isolated()
{
_domain = AppDomain.CreateDomain("Isolated:" + Guid.NewGuid(),
null, AppDomain.CurrentDomain.SetupInformation);

Type type = typeof(T);

_value = (T)_domain.CreateInstanceAndUnwrap(type.Assembly.FullName, type.FullName);
}

public T Value
{
get
{
return _value;
}
}

public void Dispose()
{
if(_domain != null)
{
AppDomain.Unload(_domain);

_domain = null;
}
}
}
/*************************************************************************/
Error Message with stack trace


Message :The constructor to deserialize an object of type 'EO.Pdf.HtmlToPdfException' was not found.
Source :T******.P****.Web
Stack Trace : at T******.P****.Web.Infrastructure.Concrete.PdfConverter.Process(PdfParameters pdfParams)
at T******.P****.Web.Infrastructure.Concrete.PdfActionResult.ExecuteResult(ControllerContext context)
at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass1a.<InvokeActionResultWithFilters>b__17()
at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass25.<BeginInvokeAction>b__22(IAsyncResult asyncResult)
TargetSite :Byte[] Process(T******.P****.Web.Infrastructure.Concrete.PdfParameters)
eo_support
Posted: Monday, November 4, 2013 5:10:26 PM
Rank: Administration
Groups: Administration

Joined: 5/27/2007
Posts: 24,196
Hi,

The error "The constructor to deserialize an object of type 'EO.Pdf.HtmlToPdfException' was not found." is an error caused by your remoting code, not by our code. You will need to get the real error message in the HtmlToPdfException object, that is an error message from us and it should tell you what's wrong.

Thanks!
nbhor
Posted: Tuesday, November 5, 2013 12:23:46 PM
Rank: Member
Groups: Member

Joined: 4/30/2013
Posts: 11
Here is the real error behind the scene. Does this help?

Message :System.Exception: Times out while loading Url or HTML. Please try to increase HtmlToPdfOptions.MaxWaitTime.
at EO.Pdf.Internal.de.a(Boolean A_0, t A_1, Int32 A_2, h3 A_3)
at EO.Pdf.Internal.de.a(String A_0, Boolean A_1, Boolean A_2, Int32 A_3, t A_4, String[] A_5, Byte[] A_6, h3 A_7)
at EO.Pdf.Internal.de.a(HtmlToPdfOptions A_0, String A_1, Boolean A_2)
at EO.Pdf.Internal.de.b(HtmlToPdfOptions A_0, String A_1, Boolean A_2)
at EO.Pdf.Internal.de.a(bs A_0)
at EO.Pdf.Internal.lr.c.a(Byte[] A_0)
Source :EO.Pdf
Stack Trace : at EO.Pdf.Internal.a.b(BinaryReader A_0)
at EO.Pdf.Internal.lr.a(a A_0)
at EO.Pdf.HtmlToPdfSession.a(a A_0)
at EO.Pdf.HtmlToPdf.ConvertUrl(String url, PdfDocument doc, HtmlToPdfOptions options)
at T********.P****.Web.PdfConverter.Process(PdfParameters pdfParams)

If you need any further details please let us know.

Conversion works fine on our Test servers under load as well. But its having above mentioned issues in Production environment.

Thanks
eo_support
Posted: Tuesday, November 5, 2013 12:28:16 PM
Rank: Administration
Groups: Administration

Joined: 5/27/2007
Posts: 24,196
Hi,

This is normal under heavy load (if you get time out error all the time, then it would indicate a more serious problem somewhere). So there is no silver bullet to just make it go away. What you can do is to catch such errors and then display a more user friendly message to the user (for example, something like "system busy, please try again later") instead of just creating an empty PDF file for them.

Thanks!
nbhor
Posted: Tuesday, November 5, 2013 12:38:13 PM
Rank: Member
Groups: Member

Joined: 4/30/2013
Posts: 11
Unfortunately we are getting timeouts consistently now. All other section of website are behaving normal and not having any delays accessing pages. Only pdf conversion functionality is failing and reporting Timeout errors. Is there any technical support number where we can reach?

Thanks
eo_support
Posted: Tuesday, November 5, 2013 1:03:51 PM
Rank: Administration
Groups: Administration

Joined: 5/27/2007
Posts: 24,196
Hi,

This is the most common reason to cause time out error on your server:

http://www.essentialobjects.com/doc/4/web/troubleshoot.aspx

Thanks!
nbhor
Posted: Tuesday, November 5, 2013 1:23:16 PM
Rank: Member
Groups: Member

Joined: 4/30/2013
Posts: 11
Thanks for the quick response. We have looked into the troubleshoot guide and verified the pages we are trying to print are locally accessible on web server. Anything else we are missing?

Thanks
eo_support
Posted: Tuesday, November 5, 2013 2:06:13 PM
Rank: Administration
Groups: Administration

Joined: 5/27/2007
Posts: 24,196
Hi,

In that case we are not sure what else to tell you. There are essentially two cases when you get time out error: the converter can not get the page/contents from your web server in time, or the conversion can not finish in time. The former indicates a web server problem, which can be caused by a lot of different scenarios with the DNS issue being the most common one. If that's not the problem, I would suggest you to check your IIS log to see which part is failing. The later indicates a load problem, obviously there is no way to avoid that.

Thanks!
nbhor
Posted: Tuesday, November 5, 2013 3:26:28 PM
Rank: Member
Groups: Member

Joined: 4/30/2013
Posts: 11
Here is the most recent error we are getting consistently from eo pdf component.

Message :Convertion failed. Failed to initialize conversion (1).
Source :EO.Pdf
Stack Trace : at EO.Pdf.Internal.lr.a(hk A_0)
at EO.Pdf.HtmlToPdfSession..ctor(HtmlToPdfOptions A_0)
at EO.Pdf.HtmlToPdf.ConvertUrl(String url, PdfDocument doc, HtmlToPdfOptions options)
at EO.Pdf.HtmlToPdf.ConvertUrl(String url, PdfDocument doc)
at ThomasNet.Plp.Web.Infrastructure.Concrete.PdfConverter.Process(PdfParameters pdfParams)
TargetSite :EO.Pdf.Internal.lr a(EO.Pdf.Internal.hk)
nbhor
Posted: Tuesday, November 5, 2013 3:49:41 PM
Rank: Member
Groups: Member

Joined: 4/30/2013
Posts: 11
Ok, now I am getting different error whole pdf conversion. Please take a look. While at it, I tried looking into windows error log as well. I couldn't find anything useful in there besides what I already mentioned in error stack trace.

Message :Convertion failed. Unable to create worker thread.Error creating window handle.
Source :EO.Pdf
Stack Trace : at EO.Pdf.Internal.lr.a(hk A_0)
at EO.Pdf.HtmlToPdfSession..ctor(HtmlToPdfOptions A_0)
at EO.Pdf.HtmlToPdf.ConvertUrl(String url, PdfDocument doc, HtmlToPdfOptions options)
at EO.Pdf.HtmlToPdf.ConvertUrl(String url, PdfDocument doc)
at ThomasNet.Plp.Web.Infrastructure.Concrete.PdfConverter.Process(PdfParameters pdfParams)
TargetSite :EO.Pdf.Internal.lr a(EO.Pdf.Internal.hk)


eo_support
Posted: Tuesday, November 5, 2013 3:51:33 PM
Rank: Administration
Groups: Administration

Joined: 5/27/2007
Posts: 24,196
Hi,

You will need to remember what you did and be able to roll back the previous conditions. The problem has changed from "inconsistent" time out, to persistent time out, and to this new error for you without following through on any issue. So please roll back to your previous condition and follow through on the previous issue first.

Thanks!
nbhor
Posted: Tuesday, November 5, 2013 3:57:37 PM
Rank: Member
Groups: Member

Joined: 4/30/2013
Posts: 11
As mentioned earlier, I removed my isolated app domain execution part from the web application and trying to convert html to pdf on same request thread. This gives us correct error message in logs. If I rollback the code, I may not get correct error messages and I will be back at "The constructor to deserialize an object of type 'EO.Pdf.HtmlToPdfException' was not found" issue.
With recent code changes, I am able to see the errors generated by EO.Pdf component.
eo_support
Posted: Tuesday, November 5, 2013 4:23:33 PM
Rank: Administration
Groups: Administration

Joined: 5/27/2007
Posts: 24,196
Hi,

Removing your isolated app domain code does not change an inconsistent error to a persistent error. Nor will it change from a time out error to a "failed to initialize conversion". These are completely different errors due to completely different causes. You had a system that's running in production for 3 months and working well "most of time" as you mentioned. So there are other things you changed.

You must understand that our tech support is not somewhere you can just post an error message and we would tell you what to do. Because we do not charge for tech support, we require you to put into reasonable effort to do your part as well. We on the other hand try our best to point you to the right direction. This is why when you first post an error message that clearly originates from your own code, we only tell you to remove that code first. However when you changes code that causes other errors, you will have to be able to track back to what you have to changed and be able to at least restore to your previous point first. Most of the time during the process you will understand what you did wrong and resolve the problem. You can not keep changing things that you can not track or do not fully understand, and keep breaking things and drive us around. We do not do that not only because that would clearly encourage people to abuse our support, but also because you would never be able to find out the root cause of your original problem and you will never have a stable working system by working that way. We could run around with you for 100 times this way but in the end you will still have an unstable system due to all the changes you made but not fully understand. In the end we lose our time, you lose a stable system and you still think our product doesn't work. That's a triple lose scenario for us. So we do not do that. This is why we require you to know clearly what you have changed and revert back to your previous condition first. I hope you understand.

Thanks!


You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.