Sharepoint 2013 本地 C# CSOM 跨站点集合列表访问

Sharepoint 2013 On-Premises C# CSOM Cross Site Collection List Access

我看到这个问题之前已经被问过很多次了,但是我在 运行 中遇到的所有示例都不起作用或者在 JavaScript 中,我需要 C# 方面的帮助。

我有一个带有服务器网站集的场,我成功地创建了一个提供程序托管 addin/App,当它尝试访问启动它的 Web 上的列表时,一切正常!我需要尝试访问同一农场和同一域中其他网站上的列表,有没有人有可以执行此操作的 C# 代码示例

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

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 App 模型和 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 并获取一些值,所以这是执行此操作的实用程序 class:

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 专家。