|
Rank: Newbie Groups: Member
Joined: 5/28/2014 Posts: 9
|
I've been unable to get the MVCToPDF conversion to work on a new project using the latest version of Microsoft.Owin.Security as our authentication mechanism. We have version 5.0.84.2 of the EO.Pdf library. Every attempt at generating a PDF, even the simplest examples result in the following error: Quote:Exception information: Exception type: HttpException Exception message: Server cannot append header after HTTP headers have been sent. at System.Web.HttpHeaderCollection.SetHeader(String name, String value, Boolean replace) at System.Web.HttpHeaderCollection.Set(String name, String value) at Microsoft.Owin.Host.SystemWeb.CallHeaders.AspNetResponseHeaders.Set(String key, String[] values) at Microsoft.Owin.Host.SystemWeb.CallHeaders.AspNetResponseHeaders.set_Item(String key, String[] value) at Microsoft.Owin.Infrastructure.OwinHelpers.SetHeaderUnmodified(IDictionary`2 headers, String key, String[] values) at Microsoft.Owin.Infrastructure.OwinHelpers.AppendHeaderUnmodified(IDictionary`2 headers, String key, String[] values) at Microsoft.Owin.HeaderDictionary.AppendValues(String key, String[] values) at Microsoft.Owin.Infrastructure.ChunkingCookieManager.AppendResponseCookie(IOwinContext context, String key, String value, CookieOptions options) at Microsoft.Owin.Security.Cookies.CookieAuthenticationHandler.<ApplyResponseGrantAsync>d__f.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at Microsoft.Owin.Security.Infrastructure.AuthenticationHandler.<ApplyResponseCoreAsync>d__b.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at Microsoft.Owin.Security.Infrastructure.AuthenticationHandler.<ApplyResponseAsync>d__8.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at Microsoft.Owin.Security.Infrastructure.AuthenticationHandler.<TeardownAsync>d__5.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at Microsoft.Owin.Security.Infrastructure.AuthenticationMiddleware`1.<Invoke>d__0.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at Microsoft.AspNet.Identity.Owin.IdentityFactoryMiddleware`2.<Invoke>d__0.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at Microsoft.AspNet.Identity.Owin.IdentityFactoryMiddleware`2.<Invoke>d__0.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at Microsoft.AspNet.Identity.Owin.IdentityFactoryMiddleware`2.<Invoke>d__0.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at Microsoft.AspNet.Identity.Owin.IdentityFactoryMiddleware`2.<Invoke>d__0.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.IntegratedPipelineContextStage.<RunApp>d__5.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.IntegratedPipelineContext.<DoFinalWork>d__2.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at Microsoft.Owin.Host.SystemWeb.Infrastructure.ErrorState.Rethrow() at Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.StageAsyncResult.End(IAsyncResult ar) at Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.IntegratedPipelineContext.EndFinalWork(IAsyncResult ar) at System.Web.HttpApplication.AsyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,196
|
Hi, You will need to configure your route so that Owin does not touch the route that generates PDF file. A quick search yielded this page that you may find useful: http://www.strathweb.com/2014/04/ignoring-routes-asp-net-web-api/Thanks!
|
|
Rank: Newbie Groups: Member
Joined: 5/28/2014 Posts: 9
|
Yes, that does seem to be what needs to be done. Owin is expecting an auth cookie with the request but it doesn't look like the cookies exist when the PDF generation process makes the request.
The link provided is for ignoring routes entirely so that they can be handled by the WebApi routes instead (or served static files). I can't for the life of me figure out how to get Owin to ignore authenticating a specific route.
Is there any way for the PDF request to be made using the current user making the Http request or to include the domain cookies?
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,196
|
Hi,
You can pass the request cookies to the PDF converter through HtmlToPdf.Options.Cookies. However it looks that the the problem is with the response cookies, not request cookies. That part would depends on when you send the PDF file down to the client. We are not familiar with OWin but it appears that it tries to send down a cookie with a response where the code has already started to write Response.OutputStream. At that time it's too late to send HTTP header to the client since the server has already started to send the body down to the client (in this case the PDF file content). So the key for this is to start sending the file after OWin has done it's business. If that's not possible, then you may wish to consider use a single page/Url to send the PDF file down to the client browser and exclude that from the route entirely.
Thanks!
|
|
Rank: Newbie Groups: Member
Joined: 5/28/2014 Posts: 9
|
I think it turned out to be a cookie issue after all. I've got it working without messing with OWIN, however I have one more question. How can I apply formatting to the RenderedPDF before returning it to the client? I've tried the following: Quote: [Route("{id:int}/print")] [EO.Pdf.Mvc5.RenderAsPDF(AutoConvert = false)] public ActionResult Print(int id, bool pdf = false) {
using (BillingContext ctx = new BillingContext()) { InvoiceService invoiceService = new InvoiceService(ctx); Invoice invoice = invoiceService.Get(id); if (invoice == null || invoice.accountId != currentUser.accountId.Value) { throw new HttpException((int)HttpStatusCode.BadRequest, "Invoice not found"); }
PrintViewModel model = new PrintViewModel(currentUser, invoice);
if (pdf) { HtmlToPdf.Options.PageSize = EO.Pdf.PdfPageSizes.A4; HtmlToPdf.Options.OutputArea = new System.Drawing.RectangleF(0.25f, 0.25f, 8f, 10.5f);
MVCToPDF.SendToClient = true; MVCToPDF.ResultAsDownload = true; MVCToPDF.AutoFormsAuthentication = true; MVCToPDF.ResultFileName = id + ".pdf"; MVCToPDF.RenderAsPDF(); }
return View("~/Views/Invoice/Print.cshtml", model); }
} If I need to set SendToClient = false and override OnResultExecuted, how do I return the result to the client once I've set the options? Thank you!
|
|
Rank: Newbie Groups: Member
Joined: 5/28/2014 Posts: 9
|
Never mind, that's working. It's been a long day :( thanks for your help
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,196
|
Great. Glad to hear that it's working!
|
|