You must forcibly set "Copy Local" to true when referencing SharePoint Client Object Model assemblies

I recently ran into an issue when deploying a provider hosted app on Prem.  Everything ran perfect in my dev environment (of course it would, all on one machine), so I deployed to the remote web server in my distributed environment, a 3 server SharePoint farm and 1 remote web machine.

I published my web site to my dev machine then copied the installer to my remote web server and deployed the web site.  I then installed my app from the app catalog, the app installed OK but when forwarded to my landing page I received the infamous “An error occurred while processing your request.”.  Now that error message is just built in to the SharePointContext class that comes with the ootb template for provider hosted apps, it doesn't really give you the whole story about what happened under the sheets.

I was thinking "well, it must be some issue with the high trust cert, maybe some oAuth problem, app manifest or web.config not right, etc.  So I went off and checked all kinds of things and then almost accidentally I was looking at the bin directory and noticed that the SharePoint client assemblies were all missing.  I then checked my Visual Studio assembly references for the project in question and noticed that "Copy Local" was false for all of the SharePoint client assemblies.

There are some very specific reasons for the "Copy Local" flag to be set to false and I don't think the SharePoint assemblies meet the criteria so I'm a bit in the dark about why this would happen in the first place.

  1. If the reference is another project, called a project-to-project reference, then the value is true.
  2. If the assembly is found in the global assembly cache, the value is false.
  3. As a special case, the value for the mscorlib.dll reference is false.
  4. If the assembly is found in the Framework SDK folder, then the value is false.
  5. Otherwise, the value is true.

Anyway, lesson learned, always remember to check and verify the "Copy Local" flag is set to true on all assemblies that you've referenced unless you know they'll be in the GAC.