代码改变世界

SharePoint 客户端对象模型共用ClientContext的坑

2016-04-20 12:47  四毛的家  阅读(1790)  评论(1编辑  收藏  举报

首先请看代码

private static void Main(string[] args)
{
	Test2();
}

private static void Test2()
{
	var clientContext = CreateClientContext();
	var oList = clientContext.Web.Lists.GetByTitle("title");
	var title = "xxxxxx";
	var email = "abc@qq.com";

	var itemCreateInfo = new ListItemCreationInformation();
	var oListItem = oList.AddItem(itemCreateInfo);
	oListItem["Title"] = title;
	//两个方法的坑
	oListItem["Email"] = GetUserIdByEmail(email); //GetUserIdByEmail(clientContext, email);

	oListItem.Update();
	clientContext.ExecuteQuery();
}

private static int GetUserIdByEmail(string email)
{
	using (var ctx = CreateClientContext())
	{
		var result = Utility.ResolvePrincipal(ctx, ctx.Web, email, PrincipalType.User,
			PrincipalSource.All, null, true);

		ctx.ExecuteQuery();
		if (result != null)
		{
			var user = ctx.Web.EnsureUser(result.Value.LoginName);
			ctx.Load(user);
			ctx.ExecuteQuery();
			return user != null ? user.Id : -1;
		}
	}
	return -1;
}
//错误的方法
private static int GetUserIdByEmail(ClientContext ctx, string email)
{
	var result = Utility.ResolvePrincipal(ctx, ctx.Web, email, PrincipalType.User,
		PrincipalSource.All, null, true);
	ctx.ExecuteQuery();
	if (result != null)
	{
		var user = ctx.Web.EnsureUser(result.Value.LoginName);
		ctx.Load(user);
		ctx.ExecuteQuery();
		return user != null ? user.Id : -1;
	}
	return -1;
}

private static ClientContext CreateClientContext()
{
	var clientContext = new ClientContext("site url")
	{
		Credentials = new NetworkCredential("_userName", "_password", "_domainName")
	};
	return clientContext;
}

 代码很简单,就是利用CSOM往列表里插入一条数据。其中列表有个栏是用户或组类型,但用户提供的值是email,所以转成对应的用户ID。

问题的坑在于GetUserIdByEmail()两个重载方法。

其中 GetUserIdByEmail(string email)是正确的,而GetUserIdByEmail(ClientContext ctx, string email)却会导致Title列始终插入不成功。

对比两种方法可以看出,第二种共用的调用处的ClientContenxt,也就是这个问题,导致失败。原因就是此方法内部调用了ctx.ExecuteQuery();

他会提交一次数据到服务器。导致Title列也随之被提交,但是列表此时并未执行Update,所以提交到服务器的数据就失败了。

而真正列表调用clientContext.ExecuteQuery();时,Title列却早已为空了。最终结果就是列表里只插入Email列数据。