Custom SharePoint application and System.IO.FileNotFoundException

Question: I have normal user access rights at SharePoint but I'm administrator of the physical SharePoint box. I don't have access rights to SharePoint databases but I still need to run few lines of code against SharePoint. I have created small console application but when I run it I get nasty System.IO.FileNotFoundException:

FileNotFoundException

What can I do?

My answer: So you have used Microsoft.SharePoint.dll and probably you have something like this in your code: "using (SPSite site = new SPSite("...")) " and that causes the exception. Well that exception is actually pretty understandable since you're using API that connects directly to the SharePoint databases... and you mentioned that you don't have access rights to databases so it makes sense. And on top of that you have only standard user rights to SharePoint so we're at the dead end anyway.

That means that we need to change our approach a little bit. Of course the solution differs little bit what you're trying to do but I think that you have few options. First one is that you could use SharePoint web services to implement your functionality. I know that it's not the easiest way to go but it should to the trick. Another approach could be custom application page that does the trick. It is a bit "hacky" approach but if you need to "do something against SharePoint" that is something you could try. I'll give you example so that you'll get the idea what I mean.

First create your custom aspx page into layouts folder (C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\LAYOUTS\ ). I created MySharePointAdminTask.aspx to the root of layouts but you should add subfolder with correct naming (e.g. Company.Project.Functionality). I added following code to my page:

 12345678910111213141516171819202122232425262728293031323334353637383940414243444546
 <%@ Page language="C#" %><%@ Import Namespace="Microsoft.SharePoint" %><%@ Import Namespace="Microsoft.SharePoint.WebControls" %><script runat="server"> void Page_load(object sender, EventArgs e) {  if (Request.IsLocal == true && Request.IsSecureConnection == true)  {    SPSecurity.RunWithElevatedPrivileges(delegate()    {      using (SPSite site = new SPSite(SPControl.GetContextSite(HttpContext.Current).ID))      {        using (SPWeb web = site.RootWeb)        {          // TODO: add your code here          // Example:          Response.Write(web.Title + " at url " + web.Url);        }      }    });  }  else  {    Response.StatusCode = 404;    Response.SuppressContent = true;    Response.End();  } }</script><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"  "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="https://www.w3.org/1999/xhtml" ><head id="Head1" runat="server">  <title>MySharePointAdminTask</title></head><body>  <form id="form1" runat="server">  <div>    <!-- TODO: add your code here -->  </div>  </form></body></html>

I have some basic checks at line 8 to see that is this request local and is the connection secure but in order to make this even a bit safe you need to add more checks to it. If that line fails then everybody who knows the url can execute code with elevated privileges. So you need to be really careful if you want to use this kind of approach and using code behind class would be much better than this inline example. On lines 12 to 20 I'll just do my fancy SharePoint stuff (in this example I'll just write out title and url of the site).

On lines 25 to 27 I'll just make the page look like 404 page just in case some of our checks didn't pass. We only want to run this code by the local user. So let see what is the end result:

For the local user it looks like this (and the user has only normal SharePoint access rights):

SharePoint Admin task for the local user

For the remote user (even with System admin rights):

SharePoint Admin task for the remote user

So this kind of approach is okay for small SharePoint operations but if you need to do more complex and long running operations then you need to reconsider your options. It's a bit hacky approach but it works :-)

Anyway... Happy hacking!

J