12

I am working on a Web API project that uses an in-house mocking framework that allows to intercept and modify the responses from the controllers. It uses MEF to loading an assembly that contains code that is executed if some preconditions are matched.

I know that this is working properly, because I can see in the response that the mock has been executed, but for some reason I am unable to debug the code in the dynamically loaded assembly. Although breakpoints look active, execution never breaks there.

The breakpoint is active

I tried calling Debugger.Break(); and it indeed breaks, but the call stack appears empty, and Visual Studio only shows this message:

The application is in break mode

I can see that the assembly and its symbols are loaded in the modules window:

Modules window shows that symbols were loaded correctly

I am able to break just before the call to the dynamically loaded assembly (the behavior parameter), which looks like this:

private HttpResponseMessage ApplyBehavior(
    IMockBehavior behavior,
    string controller, string action,
    HttpRequestMessage request,
    HttpResponseMessage mockedResponse)
{
    return behavior.Apply(controller, action, request, mockedResponse);
}

If I try to inspect the behavior variable in the immediate window, Visual Studio shows the following exception:

behavior.GetType()
'behavior.GetType()' threw an exception of type 'System.IO.FileNotFoundException'
    Data: {System.Collections.ListDictionaryInternal}
    FileName: null
    FusionLog: null
    HResult: -2147024894
    HelpLink: null
    InnerException: null
    Message: "Cannot load assembly 'SuperMam.WebAPI.Mocking'."
    Source: null
    StackTrace: null
    TargetSite: null

This is part of a fairly large application, and I am unable to extract the relevant parts. I tried to gather as much information as I could, but still have no clue on why this is happening.

What can I do to fix this problem?

EDIT 1

Just to be sure, if I call the code from my controller, I am able to step into it normally:

var behaviourType = AppDomain.CurrentDomain.GetAssemblies()
    .First(a => a.FullName.Contains("SuperMam.WebAPI.Mocking"))
    .GetType("SuperMam.WebAPI.Mocking.MyBehaviour");

var behavior = (IMockBehavior)Activator.CreateInstance(behaviourType);
// I can step into this, and view the behaviour variable in the watch
behavior.Apply("dummy", "dummy", Request, null);

but even when I do this, when the same method is called by the mocking framework, I can't step into it.

EDIT 2

I also noticed that the same assembly (FullName is identical) is loaded twice. The difference between the two instances is their CodeBase and Location properties:

  • One of them has CodeBase equal to my applications's bin directory, and Location equal to C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\...
  • The other one of them has CodeBase equal to the first one's Location(C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\...), and Location is an empty string.

Could this be the cause of the problem?

Antoine Aubry
  • 12,203
  • 10
  • 45
  • 74

4 Answers4

4

Your app has entered a break state, but no code is currently executing that is supported by the selected debug engine.

I also met this error message before:

https://social.msdn.microsoft.com/Forums/en-US/99b43950-6c82-4945-ba16-04355abf9612/vs2015-breakpoints-dont-work?forum=vsdebug

If possible, you could check that whether it is related to the Debugging options/settings or the VS setup.

(1) The latest update for VS2015 is the update 3.

(2) Enable Use Managed Compatibility Mode would be a directory for this issue.

Jack Zhai
  • 6,230
  • 1
  • 12
  • 20
  • 1
    Your second suggestion turned out to be very helpful. *Future visitors* - Please refer to the screenshot in [this](https://stackoverflow.com/q/42158547/465053) post for a quick visual reference to see where does the `Managed Compatibility Mode` option/setting is found. – RBT Jan 23 '18 at 05:46
  • Enabling Use Managed Compatibility Mode is the answer for general situations when vs just don't want to show variables while loading dlls with Assembly. It also works for VS19. Thanks! – Vlad Isoc Jan 29 '21 at 11:23
4

Turns out that the reason was that the assembly was not being loaded by MEF as I thought. It was being loaded using Assembly.Load(File.ReadAllBytes(mockDllPath)). Since the assembly was loaded from a byte array, no debugging information was available to the debugger.

Antoine Aubry
  • 12,203
  • 10
  • 45
  • 74
  • Did you find a solution for this problem ? I have the EXACT same problem!, I'm able to hit breakpoints by disabling "Only my Code" but only occasionally. Most of the time the breakpoint is not hit. – Martin Kirk Oct 23 '18 at 09:48
  • I had exactly the same problem and my assembly was also loaded using `Assembly.Load(File.ReadAllBytes(dllPath))`. However I noticed that using the overload `.Load(byte[],byte[])` to also specify a PDB file did not help. In my case, the same assembly was previously loaded from disk and now it was loaded again from the byte array. This seems to confuse the debugger so that I could never step into the code. The solution was to skip the first file load. Then `Assembly.Load(File.ReadAllBytes(dllPath))` did its job and also found the PDB automatically. – Tobias Feb 20 '19 at 14:56
3

The assembly that you're trying to load dynamically is compiled on your system?

In order to debug dynamically loaded assemblies you need a PDB file alongside the DLL. That file contains debugging information about your assembly required by Visual Studio. When you compile an assembly in debug mode, then the PDB is automatically created in your project's ./bin/Debug/ folder. If you have moved your DLL to another location, then try to move the PDB to the same location too.

sc3w
  • 1,154
  • 9
  • 21
  • The PDB is present alongside the DLL, as demonstrated by Visual Studio being able to load the debugging symbols (see the "modules" window screenshot). – Antoine Aubry Nov 09 '16 at 14:08
  • Both project are targeting the same framework version? – sc3w Nov 09 '16 at 14:24
  • In Visual Studio check if in `Debug > Options` menu the Managed compatibility mode or the Native compatibility mode is enabled? You can try playing with those :). – sc3w Nov 09 '16 at 14:36
0

The problem should be due to the method used for loading the assembly.

I suppose you are using:

  Assembly.LoadFrom ...

try using

Assembly.Load

Giovanni Russo
  • 273
  • 2
  • 7
  • It doesn't matter which method you use for loading (except ReflectionOnly). The only thing needed is the .pdb file and starting the application in debug mode. – Oliver Nov 09 '16 at 13:36
  • 1
    'Load From' does not allow the right loading of pdb, while the 'load' method does. – Giovanni Russo Nov 09 '16 at 13:47
  • The assembly is loaded by MEF (using `[ImportMany]`). I don't know how MEF is implemented, but I assume that it should be possible to debug the code. – Antoine Aubry Nov 09 '16 at 14:09
  • MEF loaded assembly can be debugged, just the .pdb file as to lay next to the .dll file. – Oliver Nov 10 '16 at 07:29