Sharepoint 2013内部部署C#CSOM跨站点集合列表访问

本文关键字:站点 集合 列表 访问 C#CSOM 2013 内部 部署 Sharepoint | 更新日期: 2023-09-27 17:58:17

我看到这个问题以前被问过很多次,但我遇到的所有例子都不起作用,或者都是JavaScript,我需要C#的帮助。

我有一个农场,上面有服务器网站集,我成功地创建了一个提供商托管的插件/应用程序,当它尝试访问启动它的网站上的列表时,一切都很好!我需要尝试访问同一服务器场和同一域中其他网站上的列表。有人有C#代码的例子可以做到这一点吗?

Sharepoint 2013内部部署C#CSOM跨站点集合列表访问

您可以创建这样的存储库方法:

public class SharepointRepository
    {
        public ListItemCollection ListTopN(string urlSite, string listName, bool ascending, string column, int rowLimit)
        {
            using (var context = new ClientContext(urlSite))
            {
                context.Credentials = CredentialCache.DefaultCredentials;
                List list = context.Web.Lists.GetByTitle(listName);
                string myQuery = string.Format("<View><Query><OrderBy><FieldRef Name='{0}' Ascending='{1}' /></OrderBy></Query><RowLimit>{2}</RowLimit></View>", column, ascending.ToString(), rowLimit);
                CamlQuery query = new CamlQuery();
                query.ViewXml = myQuery;
                ListItemCollection collection = list.GetItems(query);
                context.Load(list);
                context.Load(collection);
                context.ExecuteQuery();
                return collection;
            }
        }
}

这种方法使用托管csom。

如果你遇到ADFS的问题,试着在这行后面添加

context.Credentials = CredentialCache.DefaultCredentials;

这个

context.ExecutingWebRequest += new EventHandler<WebRequestEventArgs>(MixedAuthRequestMethod);

和这个功能

void MixedAuthRequestMethod(对象发送方,WebRequestEventArgs e){e.WebRequestExecutor.RequestHeaders.Add("X-FORMS_BASED_AUTH_ACCEPTED","f");}

这是一个基本的参考:https://msdn.microsoft.com/en-us/library/office/fp179912.aspx

您还应该查看Sharepoint应用程序模型和Rest OData API。

我发现了这一点,所以我发布它只是为了以防万一其他人需要它,也请理解我对SharePoint一无所知,这可能不是最好的方式,甚至不是SharePoint接受的做事方式。

首先,你需要给你的应用租户权限(完全控制或管理)!-非常重要的

其次,我创建了这个函数,使一个SharePoint上下文指向一个网站,而不是应用程序在上运行的网站

 public ClientContext CreateRemoteSharePointContext(string TargetWebURL, SharePointContext CurrentSharePointContext)
    {
        //In order for us to create a share point client context that points to 
        //site other then the site that this app is running we need to copy some url parameters from the current 
        //context. These parameters are found on the current share-point context 
        NameValueCollection QueryString = Request.QueryString;
        //Since, The Query string is a read only collection, a use of reflection is required to update the 
        //values on the request object,  we must use the current request object because it contains 
        //security and other headers/cookies that we need for the context to be created, Grab the url params that we need 
        //other then TargetWebUrl, that will be the url of the site we want to manipulate
        Utility.AddToReadonlyQueryString(QueryString, "SPHostUrl", CurrentSharePointContext.SPHostUrl.ToString(), System.Web.HttpContext.Current.Request);
        Utility.AddToReadonlyQueryString(QueryString, "SPAppWebUrl", TargetWebURL, System.Web.HttpContext.Current.Request);
        Utility.AddToReadonlyQueryString(QueryString, "SPLanguage", CurrentSharePointContext.SPLanguage, System.Web.HttpContext.Current.Request);
        Utility.AddToReadonlyQueryString(QueryString, "SPClientTag", CurrentSharePointContext.SPClientTag, System.Web.HttpContext.Current.Request);
        Utility.AddToReadonlyQueryString(QueryString, "SPProductNumber", CurrentSharePointContext.SPProductNumber, System.Web.HttpContext.Current.Request);
        //This is a special line, we need to get the AppOnly access token and pass it along to the target site, its is a little counter intuitive
        //Because we are using TokenHelper.GetS2SAccessToeknWithWindowsIdentity - but we pass NULL as the User identity, this will 
        //check the app manifest and if the app has a CERT and AppOnly Permission it will return a valid app only token to use
        Utility.AddToReadonlyQueryString(QueryString, "AppContextToken", TokenHelper.GetS2SAccessTokenWithWindowsIdentity(new Uri(TargetWebURL), null), System.Web.HttpContext.Current.Request);
        //Return the newly created context
        return SharePointContextProvider.Current.CreateSharePointContext(HttpContext.Request, TargetWebURL).CreateAppOnlyClientContextForSPAppWeb();
    }

正如你所看到的,我不得不破解Querystring并获取一些值,所以这里有一个Utility类可以做到这一点:

public class Utility
{
    public static void UpdateReadonlyQueryString(NameValueCollection collectionToUpdate, string paramName, string paramValue, HttpRequest Request)
    {
        collectionToUpdate = (NameValueCollection)Request.GetType().GetField("_queryString", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(Request);
        PropertyInfo readOnlyInfo = collectionToUpdate.GetType().GetProperty("IsReadOnly", BindingFlags.NonPublic | BindingFlags.Instance);
        readOnlyInfo.SetValue(collectionToUpdate, false, null);
        collectionToUpdate[paramName] = paramValue;
        readOnlyInfo.SetValue(collectionToUpdate, true, null);
    }
    public static void AddToReadonlyQueryString(NameValueCollection collectionToUpdate, string paramName, string paramValue, HttpRequest Request)
    {
        collectionToUpdate = Request.QueryString;
        collectionToUpdate = (NameValueCollection)Request.GetType().GetField("_queryString", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(Request);
        PropertyInfo readOnlyInfo = collectionToUpdate.GetType().GetProperty("IsReadOnly", BindingFlags.NonPublic | BindingFlags.Instance);
        readOnlyInfo.SetValue(collectionToUpdate, false, null);
        collectionToUpdate.Add( paramName, paramValue);
        readOnlyInfo.SetValue(collectionToUpdate, true, null);
    }
}

最后,SharePoint访问代码看起来与网络上的SharePoint代码非常相似,我不得不从中删除一些可以识别项目或为谁服务的内容,但应该很容易从内部中挑选出你需要的内容

 try
{
    //Get the name of the sharepoint list that needs to be updated from settings 
    var ListName = ConfigurationManager.AppSettings[Constants.SettingsConstants.SPLaunchQueList];
    var TargetSiteToUpdate =  "URL TO THE SITE YOUR TRYING TO UPDATE"; 
    //Get the sharepoint context from session 
    var spContext = <SOME HOW CREATE YOUR CONTEXT> 
    //Lets create a client context from the current sharepoint context to the target site 
    //NOTE this requires the application to HAVE Tenant level permission, it must be trusted by
    //the farm admin 
    using (var spClientContext = CreateRemoteSharePointContext(TargetSiteToUpdate, spContext))
    {
        //Get the current Web (Sharepoint Web) from the client context 
        var web = spClientContext.Web;
        //Load all the webs properties including title , url all the lists and get the subwebs if any as well 
        spClientContext.Load(web, x => x.Title, x => x.Url, x => x.Lists, x => x.Webs.Include(w => w.Title, w => w.Url));
        spClientContext.ExecuteQuery();
        //Lets grab the list that needs to be updated 
        SP.List OrgList = web.Lists.GetByTitle(ListName);
        //Construct a caml query Where the groupID of the SQL Server record is the same 
        //as the list GroupID 
        var caml = new Caml<DetailParts>().Where(o => o.GroupID == updateRecord.GroupID);
        CamlQuery camlQuery = new CamlQuery();
        camlQuery.ViewXml = caml.ToString();
        //Load the CAML query 
        ListItemCollection Rows = OrgList.GetItems(camlQuery);
        spClientContext.Load(Rows);
        spClientContext.ExecuteQuery();
        //The CAML Query should only return one row because GroupID should be UNQIUE 
        //however due to how sharepoint returns list data we are forcing the first value 
        //here 
        ListItem RowToUpdate = Rows[0];
        //Get a list of sharepoint columns that match the local detail parts 
        var ColumnsToUpdate = GetSharePointColumns(typeof(DetailParts));
         RowToUpDate["SomeColumn"] = "YOUR NEW VALUE"; 
         RowToUpdate.Update();
         //Commit the changes 
         spClientContext.ExecuteQuery();
        }
    }
}
catch (Exception ex)
{
    //Log any exception and then throw to the caller 
    logger.Error("Sharepoint exception", ex);
}

代码的最后一部分应该在某种函数或方法中,我只是提取了相关的部分。正如我所说,这是我发现的唯一有效的方法,如果有人有更好的方法,请分享,因为我不是SharePoint专家。