locked
Unable to acces lists cross site collection using Linq To SharePoint RRS feed

  • Question

  • I'm currently developing a 2010 webpart project, where I query 3 lists on 3 different site collections.

    I query these list from a webpart that is located on the root site collection: http://portaltest

    Site col 1: http://portaldev/sites/site1 - list x
    Site col 2: http://portaldev/sites/site2 - list y
    Site col 3: http://portaldev/sites/site2 - list z

    When I try to access list x on the site collection: http://portaldev/sites/site1 (from a webpart on the root site collection http://portaldev)
    I receive an ArgumentException: {"Web at http://portaldev/sites/site1 could not be found"}

    The code that I am using is the folowing
     using (LinqDataContext ctx = new LinqDataContext("http://portaldev/sites/site1"))
     {
         EntityList<listx> entities = ctx.GetList<listx>("listx");
     }
    


    But when I try to run the same webpart on a web of http://portaldev/sites/site1, the code will run an I'm able to query the list x.
    Friday, January 8, 2010 12:11 PM

Answers

  • We have found a workaround by changing the SPContext before executing the LINQ query.

    In the webpart itself the HttpContext is stored in a variable before executing our search method.

    SPSecurity.RunWithElevatedPrivileges(delegate()
    {
         using (SPSite contextSite = new SPSite("http://<URL>"))
         {
              using (SPWeb contextWeb = contextSite.OpenWeb())
              {
                   HttpRequest httpRequest = new HttpRequest("", contextWeb.Url, "");
                   HttpContext.Current = new HttpContext(httpRequest, new HttpResponse(new StringWriter()));
                   SPControl.SetContextWeb(HttpContext.Current, contextWeb);               
                   using (MyLinqDataContext dc = new MyLinqDataContext("http://<URL>"))
                   {
                        EntityList<MyEntity> entities = dc.GetList<MyEntity>("<ListName>");
                        {
                        }
                   }
               }
         }
    }
    After performing the search we set the HttpContext back to the original HttpContext.


    tempContext = HttpContext.Current;
    this.Search();
    HttpContext.Current = tempContext;


    I'm not sure if this workaround is appropriate, but at least we can now perform our cross site collection LINQ query in our webpart :)

    Regards,
    Pascal

    Tuesday, January 19, 2010 3:43 PM

All replies

  • Permissions?
    Friday, January 8, 2010 6:08 PM
  • Nop,

    The account that I am using is over the 3 site collections, site collection admin.
    Saturday, January 9, 2010 11:06 AM
  • We even tested the code using a console application. In a console application there no problem, but when we use it in a webpart it throws the error.
    Monday, January 11, 2010 8:35 AM
  • Does anyone else has the same problem ?

    The code works perfectly on a console application one the Sharepoint server but doesn't work in a webpart.

    Regards,
    Pascal
    Monday, January 18, 2010 3:00 PM
  • We have found the cause of this problem. When an SPContext is available (like in the webpart), the constructor of SPServerDataConnection tries the open the url in the SPSite of the context.

    So querying a linq datasource in a different site collection doesn't work whenever an SPContext object is available.

    We managed to reproduce this problem in our console application by createing a fake SPContext object which causes the same error.

    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);
    }

    Is there anyone from Microsoft that can confirm if this behaviour is by design or a bug.

    Regards,
    Pascal
    Tuesday, January 19, 2010 9:45 AM
  • We have found a workaround by changing the SPContext before executing the LINQ query.

    In the webpart itself the HttpContext is stored in a variable before executing our search method.

    SPSecurity.RunWithElevatedPrivileges(delegate()
    {
         using (SPSite contextSite = new SPSite("http://<URL>"))
         {
              using (SPWeb contextWeb = contextSite.OpenWeb())
              {
                   HttpRequest httpRequest = new HttpRequest("", contextWeb.Url, "");
                   HttpContext.Current = new HttpContext(httpRequest, new HttpResponse(new StringWriter()));
                   SPControl.SetContextWeb(HttpContext.Current, contextWeb);               
                   using (MyLinqDataContext dc = new MyLinqDataContext("http://<URL>"))
                   {
                        EntityList<MyEntity> entities = dc.GetList<MyEntity>("<ListName>");
                        {
                        }
                   }
               }
         }
    }
    After performing the search we set the HttpContext back to the original HttpContext.


    tempContext = HttpContext.Current;
    this.Search();
    HttpContext.Current = tempContext;


    I'm not sure if this workaround is appropriate, but at least we can now perform our cross site collection LINQ query in our webpart :)

    Regards,
    Pascal

    Tuesday, January 19, 2010 3:43 PM
  • Friday, February 4, 2011 10:25 AM
  • Thanks Pascal,  it works for me :)
    regards, Sudhir Kesharwani
    Friday, April 1, 2011 2:39 AM
  • Thanks Pascal ...... it really helped.. 

    Kunal Valecha

    Friday, April 13, 2012 5:42 AM
  • Just use the  constructore of context  and every thing will work fine.

     using (LinqDataContext context = new LinqDataContext('WebPath'))
     {
     
     }

    i tried this many times before.

    Tuesday, May 15, 2012 5:30 AM
  • Thanks Pascal, this helped me a lot
    Thursday, November 29, 2012 10:54 PM
  • You can also use the crossSiteCollection flag when creating the DataContext ( see http://msdn.microsoft.com/en-us/library/jj835494.aspx).

    Although SPMetal does not provide this constructor by default it is simple enough to add:

    namespace spmetal
    {
        public partial class LinqDataContext: Microsoft.SharePoint.Linq.DataContext
        {
            public LinqDataContext(string requestUrl, bool crossSiteCollection) :
                base(requestUrl, crossSiteCollection)
            {
                this.OnCreated();
            }
        }
    }

    Then when you create the LinqDataContext and pass true for crossSiteCollection you wont need to change the HttpContext.
    Tuesday, June 11, 2013 10:53 PM