ReflectionTypeLoadException in ASP.NET Core MVC ap

2019-08-26 16:33发布

问题:

I'm running into a problem running an ASP.NET Core 1.0 application targeting .NET Framework 4.6. The problem didn't occur until we tried to run the application on a server running Windows Server 2016. The app is hosted in IIS and I have the .NET Core 1.0 Windows Hosting Bundle installed on the server.

Upon loading the site a 500 error is returned and this is written to the Logs:

An unhandled exception has occurred: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information. (fc7986d0) System.Reflection.ReflectionTypeLoadException: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.

Researching this it appears to relate to a missing dll or mismatched version, and that I should look at the LoaderExceptions property to get more info, but I'm not sure how to do that in this instance. The log entry is created just from setting up the loggerFactory in the Configure() method of Startup.cs.

I tried adding an IExceptionFilter ActionFilter implementation and reading the LoaderExceptions property if the exception is of type ReflectionTypeLoadException, but it doesn't get hit when ran on the server.

Is there a way to drill down into the Exception to read the LoaderExceptions property (in a production environment, there is no error when running in Visual Studio so debugging didn't help), or else another way to troubleshoot the original error to determine what is wrong with the server setup?

回答1:

Instead of using IExceptionFilter, I wrote my own Middleware for catching this sort of exception and was able to log each exception from the LoaderExceptions property and determine what my problem is. Here is what I added to log the LoaderExceptions:

public class ExceptionCatchMiddleware
{
    private readonly RequestDelegate _delegate;
    private readonly ILogger _logger;

    public ExceptionCatchMiddleware(RequestDelegate requestDelegate, ILogger<ExceptionCatchMiddleware> logger)
    {
        _delegate = requestDelegate;
        _logger = logger;
    }

    public async Task Invoke(HttpContext context)
    {
        try
        {
            await _delegate(context);
        }
        catch (ReflectionTypeLoadException e)
        {
            foreach (Exception ex in e.LoaderExceptions)
            {
                _logger.LogCritical(ex.Message + Environment.NewLine + ex.StackTrace);
            }
        }
    }
}

And then I just needed to add the Middleware to the Configure() method in Startup.cs:

app.UseMiddleware<ExceptionCatchMiddleware>();

In my case it was a missing dll that wasn't included in the project but since it was in my dev machine's GAC it ran there just fine.