The problem: normally, you use DLLImport and P/Invoke. However, it only works if DLL is loaded. For normal program you can put it into the same folder as managed executable, and everything will be just fine. Not for ASP.NET, which is compiled into an obscure location, which you would not want to mess up with. Other places like System32 folder are also not a good choice. So, what can you do?

The solution: Actually, people already thought about this problem and found some solutions. See, for example, here. Some people even suggest to create the class dynamically, putting the correct DLLImport attribute value using the reflections. (See. here). However, the reality is much simpler. The only real problem is to ensure that DLL is loaded. One way to do that, is to create a special folder and put it into the PATH environment variable. If you don't like that, you can use the same solution, I did lately, simply load DLL ahead using LoadLibrary. Once it's in memory, the system will not look around on disk and will simply use it.

Code fragments (C#):

Declaration of LoadLibrary:

 [DllImport("kernel32.dll")]
 public static extern IntPtr LoadLibrary(string lpFileName);

 [DllImport("kernel32.dll")]
 public static extern IntPtr FreeLibrary(IntPtr library);

Declaration of your functions from C++ DLL:

 [DllImport("SampleLib.dll", PreserveSig = true, CharSet = CharSet.Unicode)]
 public static extern UInt32 DoStuff(...parameters...);

Loading DLL:

 String DLLPath;
 DLLPath = ... full path to your DLL...
 IntPtr lib = LoadLibrary(DLLPath);
 ... now, if lib is equal zero, you failed...

Now you can call it:

 UInt32 res = DoStuff(...);

And after you did what you wanted, don't forget to free it:

 FreeLibrary(lib); // check HRESULT, if that bothers you 

-----

Added 3/8/07: Thanks to PSP (see his comment below), an additional important point is uncovered: DLLImport seems to increase refcount on the library just like LoadLibrary() does. Hence, it looks like you will need to call FreeLibrary() twice. Very odd, but looks real. I wonder, who calls FreeLibrary() when LoadLibrary() is not used?