Click here to Skip to main content
15,867,834 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
Hello, so I'm in process of migrating of my app from .NET Framework 4.8 to .NET6. Due to some .NET classes being obsolete in newer version I am experiencing some problems.

I have a controller in which one of endpoints is supposed to return a PDF file. But instead of this what it returns right now is just a JSON file containing only a few values.

Endpoint method:

C#
[HttpPost]
       public ActionResult DownloadFile([FromForm] string data, [FromForm] string fileType)
       {
           try
           {
               if (!string.IsNullOrWhiteSpace(data))
               {
                   return GenerateReportDocument(data, fileType);
               }
           }
           catch (Exception ex)
           {
               logger.LogError(ex, $"Unexpected error occured in {nameof(DownloadFile)}.");
               return StatusCode(500);
           }

           return NoContent();
       }


Then data is taken into GenerateReportDocument method:

C#
private ActionResult GenerateReportDocument(string data, string fileType)
      {
          var specificationString = specificationGeneratorService.GenerateSpecificationString(JObject.Parse(data));

          logger.LogWarning($"Check images in specificationString: '{specificationString}'");

          if (string.IsNullOrWhiteSpace(specificationString))
          {
              specificationString = "<p></p>";
          }

          var reportGenerator = generateReportDocuments.SingleOrDefault(r => r.FileType.ToLower().Equals(fileType.ToLower()));

          if (reportGenerator is not null)
          {
              return Ok(reportGenerator.GenerateReportDocument(SpecificationFileName, specificationString));
          }

          return NoContent();
      }


Which then is supposed to be taken into third method:

C#
public HttpContent GenerateReportDocument(string fileName, string specificationString)
		{
			var requestContent = new StringContent(JsonConvert.SerializeObject(new { Html = specificationString }));
			requestContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");

			var httpResponse = Flurl.Url.Combine(_abcPdfOptions.PdfConverterUrl, "pdf/convertfromhtmltopdf")
					.PostAsync(requestContent).GetAwaiter().GetResult();

			HttpContent httpContent = httpResponse.Content;

			httpContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
			{
				FileName = $"{fileName}.{FileExt}",
			};

			httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");

			return httpContent;
		}


This is how those methods looked like in .NET Framework 4.8 (when they were working correctly, presented in same order as their equivalent methods in .NET6 project):

C#
[HttpPost]
       public HttpResponseMessage DownloadFile(HttpRequestMessage requestMessage)
       {
           try
           {
               var specification = requestMessage.Content.ReadAsFormDataAsync().Result;
               string data = specification.Get("Data");
               string fileType = specification.Get("FileType");

               if (!string.IsNullOrWhiteSpace(data))
               {
                   return GenerateReportDocument(data, fileType);
               }
           }
           catch (Exception ex)
           {
               logger.LogError(ex, $"Unexpected error occured in {nameof(DownloadFile)}.");
               return new HttpResponseMessage(HttpStatusCode.InternalServerError);
           }

           return new HttpResponseMessage(HttpStatusCode.NoContent);
       }

C#
private HttpResponseMessage GenerateReportDocument(string data, string fileType)
     {
         var specificationString = specificationGeneratorService.GenerateSpecificationString(JObject.Parse(data));

         logger.LogWarning($"Check images in specificationString: '{specificationString}'");

         if (string.IsNullOrWhiteSpace(specificationString))
         {
             specificationString = "<p></p>";
         }

         var reportGenerator = generateReportDocuments.SingleOrDefault(r => r.FileType.ToLower().Equals(fileType.ToLower()));

         if (reportGenerator != null)
         {
             return new HttpResponseMessage(HttpStatusCode.OK)
             {
                 Content = reportGenerator.GenerateReportDocument(SpecificationFileName, specificationString),
             };
         }

         return new HttpResponseMessage(HttpStatusCode.NoContent);
     }


C#
public HttpContent GenerateReportDocument(string fileName, string specificationString)
		{
			var requestContent = new StringContent(JsonConvert.SerializeObject(new { Html = specificationString }));
			requestContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");

			var httpResponse = Flurl.Url.Combine(_abcPdfOptions.PdfConverterUrl, "pdf/convertfromhtmltopdf")
					.PostAsync(requestContent).GetAwaiter().GetResult();

			HttpContent httpContent = httpResponse.Content;

			httpContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
			{
				FileName = $"{fileName}.{FileExt}",
			};

			httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");

			return httpContent;
		}


What I have tried:

I have tried editing my code and changing the methods into IActionResult or HttpResponse, also altering the return types and their arguments. What am I doing wrong?
Posted
Updated 5-Aug-22 2:36am
Comments
[no name] 4-Aug-22 14:22pm    
By leaving variables as "var", you leave everyone else to guess what their "real" types are. Too much effort on someone else's part.

1 solution

Your .NET Framework code was returning a HttpResponseMessage message. The .NET 6 code is returning an OkObjectResult which will attempt to format the HttpContent as JSON.

If you want to return the HttpResponseMessage in .NET 6, you'll need a custom result type:
C#
public class HttpContentResult : IActionResult
{
    private readonly HttpContent _content;

    public HttpContentResult(HttpContent content)
    {
        _content = content ?? throw new ArgumentNullException(nameof(content));
    }

    public async Task ExecuteResultAsync(ActionContext context)
    {
        using (_content)
        {
			HttpResponse response = context.HttpContext.Response;
            response.StatusCode = 200;
            
            foreach (var header in _content.Headers)
            {
                response.Headers.Append(header.Key, header.Value.ToArray());
            }

            await _content.CopyToAsync(response.Body);
        }
    }
}
To use it:
C#
private IActionResult GenerateReportDocument(string data, string fileType)
{
    string specificationString = specificationGeneratorService.GenerateSpecificationString(JObject.Parse(data));
    logger.LogWarning($"Check images in specificationString: '{specificationString}'");

    if (string.IsNullOrWhiteSpace(specificationString))
    {
        specificationString = "<p></p>";
    }

    if (generateReportDocuments.SingleOrDefault(r => string.Equals(r.FileType, fileType, StringComparison.OrdinalIgnoreCase) is not {} reportGenerator)
    {
        return NoContent();
    }
    
    HttpContent content = reportGenerator.GenerateReportDocument(SpecificationFileName, specificationString);
    return new HttpContentResult(content);
}
 
Share this answer
 
v2
Comments
Member 15341738 6-Aug-22 4:14am    
Hello Richard, thank you for your input. I have applied the suggested code changes, unfortunately at the line "return new HttpContentResult(content);" I am getting an error: Cannot implicitly convert type 'HttpContentResult' to 'Microsoft.AspNetCore.Mvc.ActionResult.
Richard Deeming 8-Aug-22 3:31am    
Change the method return type to IActionResult.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900