Sharepoint 2013内部部署C#CSOM跨站点集合列表访问
本文关键字:站点 集合 列表 访问 C#CSOM 2013 内部 部署 Sharepoint | 更新日期: 2023-09-27 17:58:17
我看到这个问题以前被问过很多次,但我遇到的所有例子都不起作用,或者都是JavaScript,我需要C#的帮助。
我有一个农场,上面有服务器网站集,我成功地创建了一个提供商托管的插件/应用程序,当它尝试访问启动它的网站上的列表时,一切都很好!我需要尝试访问同一服务器场和同一域中其他网站上的列表。有人有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应用程序模型和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专家。