An asynchronous operation cannot be started at this time in webservice

108 views Asked by At

I have a webservice to convert html to pdf using PuppeteerSharp but this line

await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultChromiumRevision);

is returning this error

An asynchronous operation cannot be started at this time. Asynchronous operations may only be started within an asynchronous handler or module or during certain events in the Page lifecycle. If this exception occurred while executing a Page, ensure that the Page is marked <%@ Page Async="true" %>. This exception may also indicate an attempt to call an "async void" method, which is generally unsupported within ASP.NET request processing. Instead, the asynchronous method should return a Task, and the caller should await it.

My code:

    [WebMethod]
    public string HtmlToPdf(string htmlString, string baseURL, int anchoPagina, string tamanoPagina, string orientacionPagina, string calidad, string leftMargin, string rightMargin, string topMargin, string bottomMargin, bool bCabecera, int bImagenCabecera, string imagenCabecera, bool bJS, bool bActiveX, bool bJpeg, bool bPie, bool bFirma, bool bPaginador, string textoPaginador, int tipoTextoPie, string textoPie, int anchoTextoPie, bool bImagenPie, string imagenPie, int ImagenPieX, int ImagenPieY, string textoLateral, int iPosX, int iPosY, string entorno, int posYnumPagina, int altoCabecera, bool bLineaPie, bool bCabeceraPortada, bool bPiePortada, string portadaPDF)
    {
        try
        {
            GestionTraza.Utilidades.escribirLog("WSTOPDF", string.Join(" ", " -- Arranca el proceso de transformación de HTML a PDF"), LogTrazas.DBG, LogCapas.CN, 34);                

            bool orientacion = (orientacionPagina == "V" ? false : true);

            var fichero = GenerarPdf(htmlString, imagenCabecera, altoCabecera, orientacionPagina, anchoPagina, leftMargin, rightMargin, topMargin, bottomMargin, textoPie);
            fichero.Wait();

            return fichero.Result;

        } catch (Exception e)
        {
            GestionTraza.Utilidades.escribirLogError(e, "WSTOPDF", "HtmlToPdf", "HtmlToPdf", (int)LogTrazas.ERR, (int)LogCapas.CN, 34);
            throw e;
        }
        
    }

    private async Task<string> GenerarPdf(string htmlString, string imagenCabecera, int altoCabecera, string orientacionPagina, int anchoPagina, string leftMargin, string rightMargin, string topMargin, string bottomMargin, string textoPie) {

        string outputFile = "";

        try
        {
            bool orientacion = (orientacionPagina == "V" ? false : true);                

            Console.WriteLine("Downloading chromium");
            await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultChromiumRevision);

            Console.WriteLine("Navigating google");
            var browser = await Puppeteer.LaunchAsync(new LaunchOptions
            {
                Headless = true
            });
            var page = await browser.NewPageAsync();
            await page.GoToAsync(htmlString);
            await page.PdfAsync(outputFile, new PdfOptions
            {
                HeaderTemplate = imagenCabecera,
                Height = altoCabecera,
                Landscape = orientacion,
                //OmitBackground = false,
                //PageRanges =,
                //PreferCSSPageSize = ,
                //PrintBackground =,
                //Scale =,
                Width = anchoPagina,
                Format = PaperFormat.A4,
                DisplayHeaderFooter = true,
                MarginOptions = new MarginOptions
                {
                    Top = topMargin,
                    Right = rightMargin,
                    Bottom = bottomMargin,
                    Left = leftMargin
                },
                //FooterTemplate = "<div id=\"footer-template\" style=\"font-size:10px !important; color:#808080; padding-left:10px\">Footer Text</div>"
                FooterTemplate = textoPie
            });

            return outputFile;
        }
        catch (Exception e)
        {
            GestionTraza.Utilidades.escribirLogError(e, "WSTOPDF", "GenerarPdf", "GenerarPdf", (int)LogTrazas.ERR, (int)LogCapas.CN, 34);
            throw e;
        }            
    }
}
}
1

There are 1 answers

0
Stephen Cleary On

You might want to consider upgrading your web framework. Microsoft started recommending people move away from ASMX in 2006, and officially declared ASMX a "legacy technology" in 2009. It is now 2023; ASMX has been dead (or "in maintenance", if you prefer) for almost 15 years.

But, assuming that you cannot upgrade to a modern framework, there is a way to get it working.

First, you must target .NET Framework 4.5 (or higher), and set httpRuntime@targetFramework to 4.5 (or higher). If you are still on .NET Framework 4.0 (i.e., Windows XP), then full stop: you cannot use async or await at all (in an ASP.NET project).

Once you are targeting 4.5 or higher (and have set targetFramework to 4.5 or higher), then you can use asynchronous WebRequest methods. Unfortunately, ASMX being a legacy technology, it does not understand or support async/await. You can use async/await in your own methods, but not in any methods marked WebRequest. Instead, you need to consume your TAP methods and provide them to ASMX as APM methods. Something like this:

[WebMethod]
public IAsyncResult BeginHtmlToPdf(string htmlString, string baseURL, int anchoPagina, string tamanoPagina, string orientacionPagina, string calidad, string leftMargin, string rightMargin, string topMargin, string bottomMargin, bool bCabecera, int bImagenCabecera, string imagenCabecera, bool bJS, bool bActiveX, bool bJpeg, bool bPie, bool bFirma, bool bPaginador, string textoPaginador, int tipoTextoPie, string textoPie, int anchoTextoPie, bool bImagenPie, string imagenPie, int ImagenPieX, int ImagenPieY, string textoLateral, int iPosX, int iPosY, string entorno, int posYnumPagina, int altoCabecera, bool bLineaPie, bool bCabeceraPortada, bool bPiePortada, string portadaPDF, AsyncCallback callback, object state)
{
  var tcs = new TaskCompletionSource<string>(state);
  var task = HtmlToPdfAsync(htmlString, baseURL, ...);
  task.ContinueWith(t =>
  {
    if (t.IsFaulted)
      tcs.TrySetException(t.Exception.InnerExceptions);
    else if (t.IsCanceled)
      tcs.TrySetCanceled();
    else
      tcs.TrySetResult(t.Result);

    if (callback != null)
      callback(tcs.Task);
  });

  return tcs.Task;
}

[WebMethod]
public string EndHtmlToPdf(IAsyncResult result)
{
  return ((Task<string>)result).GetAwaiter().GetResult();
}

private async Task<string> HtmlToPdfAsync(string htmlString, string baseURL, int anchoPagina, string tamanoPagina, string orientacionPagina, string calidad, string leftMargin, string rightMargin, string topMargin, string bottomMargin, bool bCabecera, int bImagenCabecera, string imagenCabecera, bool bJS, bool bActiveX, bool bJpeg, bool bPie, bool bFirma, bool bPaginador, string textoPaginador, int tipoTextoPie, string textoPie, int anchoTextoPie, bool bImagenPie, string imagenPie, int ImagenPieX, int ImagenPieY, string textoLateral, int iPosX, int iPosY, string entorno, int posYnumPagina, int altoCabecera, bool bLineaPie, bool bCabeceraPortada, bool bPiePortada, string portadaPDF)
{
  try
  {
    GestionTraza.Utilidades.escribirLog("WSTOPDF", string.Join(" ", " -- Arranca el proceso de transformación de HTML a PDF"), LogTrazas.DBG, LogCapas.CN, 34);                

    bool orientacion = (orientacionPagina == "V" ? false : true);

    return await GenerarPdf(htmlString, imagenCabecera, altoCabecera, orientacionPagina, anchoPagina, leftMargin, rightMargin, topMargin, bottomMargin, textoPie);
  }
  catch (Exception e)
  {
    GestionTraza.Utilidades.escribirLogError(e, "WSTOPDF", "HtmlToPdf", "HtmlToPdf", (int)LogTrazas.ERR, (int)LogCapas.CN, 34);
    throw e;
  }
}

I'm not entirely sure if it will work in your case, since you have a massive number of arguments, but it's worth a shot.