aditya
aditya

Reputation: 340

Dotnet core 2.2 libgdipplus exception

I am running a dotnet core 2.2 web api on openshift, i have an api method the returns a FileResult. The file is generated using epplus. However after containerizing the application the endpoint returns the below error. I believe this exception occurs if the system.drawing library is used, however i am not using any system.drawing functionality.

System.TypeInitializationException: The type initializer for 'Gdip' threw an exception. ---> System.DllNotFoundException: Unable to load DLL 'libgdiplus': The specified module could not be found.

public async Task<FileResult> GetPSACostCaseAndFeedData([FromQuery] int caseId, [FromQuery] int proposalId, [FromQuery] int equipmentId)
        {
            try
            {
                var queryParams = new Dictionary<string, string> { { "caseId", caseId.ToString() }, { "proposalId", proposalId.ToString() }, { "equipmentId", equipmentId.ToString() } };
                var restObj = _restFactory.createRestRequest(Method.GET, "ProposalService/PSACostData/GetPSACostCaseAndFeedData", queryParams);
                Console.WriteLine("Base URL - "  + restObj.Item2.BaseUrl);
                var response = await restObj.Item2.ExecuteTaskAsync(restObj.Item1);
                if (response.StatusCode == HttpStatusCode.OK)
                {
                    var result = JsonConvert.DeserializeObject<PSACostCaseDetailsResponse>(response.Content);
                    Console.WriteLine("result -" + response.Content.ToString());
                    Console.WriteLine("start writing file");
                    var excelPackage = await _iPSACostExcelHelper.PopulatePsaCostFile(result, Path.Combine(_hostingEnvironment.ContentRootPath, "App_data", "PSACOST_V9.2.2.xlsm"));
                    Console.WriteLine("finished writing file");
                    return await Task.FromResult(File(_excelHelper.ConvertWorkBookToByteArray(excelPackage), ContentTypeEnums.excel, result.customerInformationModel.ProposalNum + "_" + result.caseDataModel.CaseNm + ".xlsm"));
                }
                throw new Exception("There is no PSA cost data for this case");
            }

the line "finished writing file" does get printed to the stdout, the line after that fails. Can someone help me understand what is going wrong here? Why does a return FileResult type method require system.drawing?

Also below is my dockerfile.

FROM mcr.microsoft.com/dotnet/core/aspnet:2.2.7-alpine3.10
LABEL pipelineName="PSACOST.API" \
      pipelineKey="UMAOKJOH" \
      offeringKey="KKWEECBH"
RUN apk upgrade -U
EXPOSE 5000
ENV ASPNETCORE_URLS=http://*:5000
WORKDIR /app
COPY . /app
USER guest
ENTRYPOINT ["dotnet", "PSACOST.API.Web.dll"] 

Upvotes: 3

Views: 4244

Answers (1)

diegosasw
diegosasw

Reputation: 15654

I am experiencing something similar when using System.Drawing from a library that generates QR codes.

The problem seems to be that the DotNet Core docker images, sdk or runtime, don't have the libgdiplus. It's not a problem for Linux, as you could do something like apt-get install -y libgdiplus in your container or build your app docker image with the DotNetCore runtime image plus this libgdiplus.

It is an annoying problem. I am not sure there is any solution that does not require messing up with official docker images, but so far no luck.

At the moment I can see a few solution options.

OPTION A: If you're using docker DotNetCore images for linux, as it seems, use apt to install missing runtime dependencies such as libgdiplus because they are not part of the docker image.

OPTION B: Find a good docker DotNetCore image (sdk or runtime) with all these dependencies in-place

OPTION C: Find a different library other than epplus that does not depend on System.Drawing's libgdiplus. But I don't even know if that's possible


UPDATE 1 For the Option B, you can try with the following docker image that contains aspnet core runtime + the dependencies you need: lonwern/aspnetcore-libgdiplus:2.1

For more info on how to generate your image if you're after Option A, see how this was created here: https://hub.docker.com/r/lonwern/aspnetcore-libgdiplus/dockerfile


UPDATE 2 I've created public Docker images that contain the DotNet Core SDK and the AspNet Core plus libgdiplus so that they can be used when running applications that use System.Drawing either with the SDK DotNet Core CLI (e.g: dotnet vstest, dotnet test, etc.) or with a runtime.

https://hub.docker.com/repository/docker/sunnyatticsoftware/dotnet-core-sdk-libgdiplus

https://hub.docker.com/repository/docker/sunnyatticsoftware/dotnet-core-aspnet-libgdiplus

More info on the repos themselves.

I use them in my CI/CD pipelines and in my final Docker image for the web apps to avoid those runtime exceptions.

Upvotes: 6

Related Questions