locked
SPMetal doesn't work with impersonated context RRS feed

  • Question

  • Hello,

    I'm using SPMetal in one of my application.

    Sometimes, I need to elevate the code, so I use something like :

    using (var elevatedSite = new SPSite(context.Site.ID, context.Site.SystemAccount.UserToken))
    {
    	using (var elevatedWeb = elevatedSite.OpenWeb(context.Web.ID))
    	{
    		// ModelContext is my generated context.
    		using (var ctx = new ModelContext(elevatedWeb.Url))
    		{
    			// Do something with the context
    
    			ctx.SubmitChanges(); // Hangs here
    		}
    	}
    }
    

    This code does not works as expected. The SubmitChanges() call throw an Unauthorized exception.

    After a bit of digging, I saw this code in the internal implementation of SPServerDataContext :

    // Microsoft.SharePoint.Linq.Provider.SPServerDataConnection
    public SPServerDataConnection(string url)
    {
    	if (SPContext.Current != null)
    	{
    		this.defaultSite = SPContext.Current.Site;
    		this.defaultWeb = ((SPContext.Current.Web.Url == url) ? SPContext.Current.Web : this.defaultSite.OpenWeb(new Uri(url).PathAndQuery));
    	}
    	else
    	{
    		this.defaultSite = new SPSite(url);
    		this.defaultWeb = this.defaultSite.OpenWeb(new Uri(url).PathAndQuery);
    	}
    	if (!this.defaultWeb.Exists)
    	{
    		throw new ArgumentException(Resources.GetString("CannotFindWeb", new object[]
    		{
    			url
    		}));
    	}
    	this.defaultWebUrl = this.defaultWeb.ServerRelativeUrl;
    	this.openedWebs = new Dictionary<string, SPWeb>();
    	this.openedWebs.Add(this.defaultWebUrl, this.defaultWeb);
    }

    This code show that SPMetal will use the current context if it exists. So it simply ignore my impersonation.

    How can I properly use SPMetal to support impersonation?

    PS: I know I could use SPSecurity.RunWithElevatedPrivileges, but for some reason out of this scope, I cannot use this construct.

    thanks,

    steve


    Paying back the community for its help by writing articles :
    Have a Nice Day.Net Blog

    Wednesday, July 4, 2012 3:03 PM

Answers

  • Hi Steve,

    As you have discovered, DataContext in this situation actually executes a constructor of SPServerDataConnection class, and execute the code with SPContext which use SPSite or SPWeb instances under the current context. So, to elevate the code as to your scenario, you may try to build context manually first, then use it with linq, or another considerable workaround is to use SPQuery insteand of linq to SharePoint to execute the function.

    More information,
    Linq to SharePoint and RunWithElevatedPrivileges:
    http://blogs.msdn.com/b/sowmyancs/archive/2010/09/19/linq-to-sharepoint-and-runwithelevatedprivileges.aspx

    Thanks,


    Qiao Wei

    TechNet Community Support

    • Marked as answer by Steve B_ Monday, July 9, 2012 9:39 AM
    Monday, July 9, 2012 9:20 AM
  • As you have discovered, DataContext in this situation actually executes a constructor of SPServerDataConnection class, and execute the code with SPContext which use SPSite or SPWeb instances under the current context. So, to elevate the code as to your scenario, you may try to build context manually first, then use it with linq, or another considerable workaround is to use SPQuery insteand of linq to SharePoint to execute the function.

    More information,
    Linq to SharePoint and RunWithElevatedPrivileges:
    http://blogs.msdn.com/b/sowmyancs/archive/2010/09/19/linq-to-sharepoint-and-runwithelevatedprivileges.aspx

    Thanks for the link. You confirmed my hypothesis. 

    I'm not comfortable with playing with httpcontext. And because I have another bunch of deceptions with SPMetal I rewrote a custom tool with some of its functionality. Actually, I choose SPMetal mainly for its (unreliable) ability to create classes representing SPListItem. Linq queries were very simple, 90% where queries to find by ID, 5% for searching related records (using lookup) and 5% custom query. So I ended by writing a repository pattern over sharepoint, that is not linq-compliant, but provides a IRepository<TItem> ExecuteQuery.

    I hope Microsoft will make SPMetal a lot more customizable and reliable. I loose a great amount of time in my project trying to workaround its limitations to finally rewrite half of its functionnalities.

    tx

    steve


    Paying back the community for its help by writing articles :
    Have a Nice Day.Net Blog

    • Marked as answer by Steve B_ Tuesday, July 10, 2012 7:30 AM
    Monday, July 9, 2012 9:45 AM

All replies

  • Hi Steve,

    As you have discovered, DataContext in this situation actually executes a constructor of SPServerDataConnection class, and execute the code with SPContext which use SPSite or SPWeb instances under the current context. So, to elevate the code as to your scenario, you may try to build context manually first, then use it with linq, or another considerable workaround is to use SPQuery insteand of linq to SharePoint to execute the function.

    More information,
    Linq to SharePoint and RunWithElevatedPrivileges:
    http://blogs.msdn.com/b/sowmyancs/archive/2010/09/19/linq-to-sharepoint-and-runwithelevatedprivileges.aspx

    Thanks,


    Qiao Wei

    TechNet Community Support

    • Marked as answer by Steve B_ Monday, July 9, 2012 9:39 AM
    Monday, July 9, 2012 9:20 AM
  • As you have discovered, DataContext in this situation actually executes a constructor of SPServerDataConnection class, and execute the code with SPContext which use SPSite or SPWeb instances under the current context. So, to elevate the code as to your scenario, you may try to build context manually first, then use it with linq, or another considerable workaround is to use SPQuery insteand of linq to SharePoint to execute the function.

    More information,
    Linq to SharePoint and RunWithElevatedPrivileges:
    http://blogs.msdn.com/b/sowmyancs/archive/2010/09/19/linq-to-sharepoint-and-runwithelevatedprivileges.aspx

    Thanks for the link. You confirmed my hypothesis. 

    I'm not comfortable with playing with httpcontext. And because I have another bunch of deceptions with SPMetal I rewrote a custom tool with some of its functionality. Actually, I choose SPMetal mainly for its (unreliable) ability to create classes representing SPListItem. Linq queries were very simple, 90% where queries to find by ID, 5% for searching related records (using lookup) and 5% custom query. So I ended by writing a repository pattern over sharepoint, that is not linq-compliant, but provides a IRepository<TItem> ExecuteQuery.

    I hope Microsoft will make SPMetal a lot more customizable and reliable. I loose a great amount of time in my project trying to workaround its limitations to finally rewrite half of its functionnalities.

    tx

    steve


    Paying back the community for its help by writing articles :
    Have a Nice Day.Net Blog

    • Marked as answer by Steve B_ Tuesday, July 10, 2012 7:30 AM
    Monday, July 9, 2012 9:45 AM