[SharePoint 2010 User Profile Service] 关于User Profile Service的一些提示

SharePoint 2010 User Profile Service的逻辑结构如下图:

UPASubsystemMCM

1)在服务器场中可以创建多个User Profile Service Application实例。

2)一个User Profile Service Application实例仅可以关联一套User Profile同步服务(也就是说如果我们在单服务器的情况下创建了多个User Profile Service Application实例,只有一个能使用同步服务)。

3)每套User Profile同步服务由两个Windows服务组成,负责管理同步连接和属性映射。

PeopleSearchForefrontServices

4)如果你遇见了类似“Unable to process Put message”这样的错误,或者没法编辑同步连接和属性映射的情况,一种可以尝试的方法是:放着已有的User Profile Service Application实例不动,创建一个新的User Profile Service Application实例,与同步服务关联,然后设置同步,并成功同步一次后,把新建的实例删除,再把原来的实例与同步服务关联,多半可以解决问题。

5)同一个Web应用程序可以关联多个User Profile Service Application实例,但是只有设置为默认关联的实例才会被使用,并且为People Search所用。

参考:

1)Rational Guide to implementing SharePoint Server 2010 User Profile Synchronization

2)http://www.dotnetmafia.com/blogs/dotnettipoftheday/archive/2010/03/29/how-to-set-up-people-search-in-sharepoint-2010.aspx

3)http://blogs.msdn.com/b/russmax/archive/2010/01/20/sharepoint-2010-shared-service-architecture-part-1.aspx

[SharePoint 2010]关于基于声明(Claims)的用户认证模式

SharePoint 2010在用户认证模式上,较之以前的版本有了非常大的改变。在SharePoint 2010中,当你创建一个Web应用程序的时候,有两种认证方式可供选择:

image

1、 Classic Mode Authentication

就是传统的Windows认证模式,用户认证和用户身份都是标准的Windows认证机制;

2、Claims Based Authentication

基于声明的认证模式,这是一种全新的认证和用户身份标识机制;之所以成为基于声明的认证,用户的身份是以一个一个的Claim(声明)来标识的(你可以把一个Claim理解成一个属性,比如Name=Ipark就可以是一个Claim)。

SharePoint 2010中基于Claims的身份认证分成两部分:一个是用户认证,一个是用户身份。

> 用户认证可以支持多种方式:NTLM、表单认证等;

> 用户的身份信息则是统一为一组Claim,在浏览器中Claim会存储在Cookie里面;

关于SharePoint 2010的身份认证模式有下面几点信息供大家参考:

1)默认情况下,创建Web应用程序的时候,会默认选择Classic Mode Authentication;但是,推荐默认选择使用Claims Based Authentication(默认下还是会为基于声明的方式选择NTLM的认证方法)。因为,选择基于声明的认证模式,对于用户来说没有任何区别,也不需要有额外的配置工作。这样的做法是为了将来扩展认证方式提供基础,而且不会有从Classic模式往Claims模式转换过程中用户迁移造成的一些问题,比如Alert不工作,搜索的问题等;

2)从Classic模式转换成Claims的模式,在管理中心中没有管理界面进行配置,需要使用脚本进行,可以参考下面的文章:

http://technet.microsoft.com/zh-cn/library/gg251984.aspx

3)从Classic模式转换成Claims模式是不可逆的过程,进行转换前需要对Web应用程序进行备份是一个最佳实践!

4)在Claims模式下,可以在同一个Zone(区域)下支持多种认证方法,在之前的版本中每个Zone仅支持一种认证方法;这意味着我们可以为单一的URL支持多种用户认证方法;但在同一个Zone下,仅支持包含唯一的FBA和唯一的Windows认证方法;

[SharePoint 2010] Client OM-使用SharePoint 2010 Silverlight Client OM

1、SharePoint 2010 客户端对象模型

SharePoint 2007的时代,SharePoint给我们提供的客户端开发接口是一组Web Service,官方没有提供封装好的客户端API接口。同时,SharePoint 2007的Web服务提供的SharePoint内容访问的方法也存在一些不完善的地方,比如无法访问操作条目级权限信息。SharePoint 2010的时代,SharePoint提供了基于WCF的客户端访问Web服务,同时封装了客户端访问API,形成了如下图所示的客户端访问模式。

clientom

1)SharePoint 2010提供了两类客户端对象模型:ECMAScript(Javascript类对象模型)和托管客户端对象模型(Managed Client OM,这类OM包含了.NET Managed Client OM以及Silverlight Client OM两组对象模型);

2)所有的客户端OM都通过Client.svc进行访问,支持批量操作,提升性能;

3)所有的客户端OM都进行了对象化的封装,与Client.svc的基本的通讯都进行了封装,开发人员只需要使用对象模型,而不用处理于Client.svc的底层交互过程;

4)Managed Client对象模型支持Linq查询语法;

2、使用Silverlight Client OM

对于SharePoint平台来说,客户端开发技术包括了Javascript, CSS, HTML以及Flash,Silverlight之类的富客户端开发技术。Silverlight是微软平台中很重要的富客户端技术。SharePoint 2010中的客户端开发中,Silverlight是非常有用的技术,可以开发非常复杂而且界面效果酷炫的客户端应用,对于.NET平台开发人员来说是十分重要的客户端平台。

SharePoint提供的Silverlight 客户端对象模型的程序集可以在C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS\ClientBin,包含了两个Silverlight类库:

> Microsoft.SharePoint.Client.Silverlight.Runtime.dll:负责与Client.svc的通讯代理Proxy

> Microsoft.SharePoint.Client.Silverlight.dll:SharePoint访问数据对象模型

使用Silverlight OM的过程如下:

1)在Visual Studio中创建Silverlight Application应用,引用以上两个dll,使用Silverlight Client OM进行所需要的业务操作;

2)编译出.xap文件,上传到SharePoint文档库;

3)在SharePoint页面上添加Silverlight Web Part,配置其显示的.xap文件为你上传到SharePoint的那个文件;

4)访问SharePoint页面即可显示Silverlight应用程序,访问并显示SharePoint数据;

注意:Silverlight会将Microsoft.SharePoint.Client.Silverlight.Runtime.dll和Microsoft.SharePoint.Client.Silverlight.dll两个文件打包到编译好的.xap文件中,会使Silverlight应用增加407k的大小,并且客户端不能缓存dll。SharePoint在以上两个dll存放的位置有一个Microsoft.SharePoint.Client.xap文件,使用这个文件可以配置Silverlight应用程序来动态加载以上两个dll程序集,这样浏览器可以缓存程序集,提高访问速度。具体的做法可以参考http://msdn.microsoft.com/zh-cn/magazine/ff956224.aspx

[ContentType]关于内容类型文档模板引自其它文档库时,打开链接的模板在Offie中创建保存文档,其内容类型将不正确的问题

最近在项目中,需要使用一个SharePoint很典型的功能,内容类型和文档模板。

但是就在使用这个简单而经典的功能的时候,我发现了一个问题:当你使用URL链接设定内容类型的文档模板的时候,用内容类型新建文档的时候,新建文档的内容类型会出现不正确的情况。

我们的场景是这样的:

1)我们希望有一个文档库来管理所有的文档模板,这个文档库由文档模板管理员来管理;

2)另一个文档库是用户文档库,用户可以根据文档模板(确切的说是内容类型)来创建文档,并编辑保存。

这种场景很普遍,而且解决方案也非常的简单,我们通常是这样干的:

1)创建一个文档库叫Template,把模板文件templatea.docx, templateb.xls等上传到文档库中,管理员对这些模板进行必要的更新和维护;

2)创建很多内容类型(比如ContentType1, ContentType2…),将Template文档库中相应的文档的URL地址填入内容类型的文档模板地址中,完成内容类型创建;

3)创建用户文档库,将创建的内容类型(ContentType1, ContentType2…)添加到文档库中;

至此,完成了我们的配置工作,按道理来说现在用户点击文档库“新建”下拉列表的ContentType1的菜单,就可以打开Office,使用ContentType1关联的文档模板,创建并保存文档到SharePoitn网站上,该文档的内容类型为ContentType1。

但是,至此问题出现了:当我按照上述的过程进行操作的时候,我发现我创建了一个类型为Document的文档,而不是ContentType1。

经过我的猜测和试验,我发现:在SharePoint中,使用URL链接设置内容类型(CT1)的文档模板的时候,如果CT1是网站内容类型,则必须保证URL链接指向的文档继承自CT1;如果CT1是列表内容类型,则必须保证URL链接指向的文档内容类型和CT1的直接父级网站内容类型相同。只有这样,用内容类型CT1在Office客户端创建并保存的文档才能拥有正确的内容类型。

简言之,只有使用某个网站内容类型创建的文档的URL链接,作为该内容类型的文档模板地址的时候,根据该内容类型创建的文档才能拥有正确的内容类型设置。

在上述的场景中,我的正确的配置过程应该是:

1)先把内容类型创建好,文档模板先不要设置;

2)创建文档库Template保存文档模板,并将第一步创建好的内容类型添加到Template文档库中;

3)上传文档,并设置其内容类型为需要将其作为文档模板的内容类型;

4)将Template文档库中相应文档的URL设置为内容类型的文档模板地址;

5)创建用户文档库,将内容类型添加到用户文档库中;

至此,用户在用户文档库中“新建”下拉列表中选择某个内容类型(比如CT2),打开Office,打开文档模板,编辑保存文档到SharePoint网站上时,内容类型正确的被设置成了CT2。

[SharePoint 2010 Site Workflow]

SharePoint 2010 提供了Site Workflow的支持,至此,SharePoint里的Workflow可以不用绑定到文档或者列表项目了。

image

image

这给SharePoint的Workflow的应用带来了更大的灵活度,能更好的和其他系统进行结合。

一般跟其他系统进行集成,Service接口是不可少的,SharePoint的Workflow.asmx Web服务是唯一的一个默认自带的跟Workflow有关的Web服务。

但是,SharePoint 2010的Workflow.asmx的Web服务没有提供对Site Workflow的支持。

如果你是SharePoint 2010开发人员,你可以开发一个自己的Site Workflow的Web服务,部署到SharePoint 2010上。

CodePlex上也有一个项目是提供这方面增强的:Useful SharePoint Site Workflow Utilities

Design.png

[List Lookup Field, Save as Template]包含Lookup类型的列表“保存为模板”后,用模板创建列表后Lookup字段设置和内容丢失的解决方法

我们经常使用“保存为模板”(Save as Template)方法来导出列表设置和列表内容,然后恢复到其他SharePoint站点上(在下文中我们以“目标网站”来代表列表内容恢复的目标SharePoint站点)。

当列表中包含Lookup(查阅项)字段的时候,由模板创建列表后查阅项字段的设置和内容会丢失,当你查看查阅项字段的时候,你会发现:

image

查阅列表(Get Information from)为空……

解决方法1网上MVP给出解决问题的方法,List Template problems with look up columns:

因为列表模板时一个.stp文件,其实就是一个cab文件,把cab包解开以后,里面包含的是一个manifest.xml文件,里面定义了这个列表模板的字段和所有数据:

image

打开该xml文件,可以找到Lookup查阅项字段的定义:

image

Lookup查阅项类型的Schema里面有一个属性“List“,指定的就是查阅的列表的GUID,问题就出在这里,列表的GUID都是随机生成,目标网站肯定没有一个同一GUID的列表,所以设置的内容都会丢失。解决的方法就是将这个GUID更改成目标SharePoint网站上要查阅的列表的GUID。把manifes.xml文件更改完成后,用makecab manifest.xml [templatename].stp方法把修改后的xml文件打包到stp文件中,上传到目标网站,即可顺利使用模板把列表和内容创建出来。

解决方法1的问题

1)如果是一个计算机水平一般的最终用户,让他/她查找列表GUID,用makecab方法来打包修改的xml文件,是个不太好的做法。但是,管理员没法事先知道查阅的列表在目标网站创建出来的GUID,所以管理员也没法事先把列表模板修正好,提供给用户。

2)如果这个列表查阅了列表本身,根本没法获取到这个GUID….

最终的解决方法

1)仔细研究Lookup查阅项类型的Schema定义,你会发现“List”属性的定义可以使用列表的名称来取代GUID,这样我们的第一个问题就可以解决了:

举个例子,我们如果查阅的一个叫SourceList的列表,我们可以吧Lookup字段的定义更改成:

image

list属性的规则是“Lists\[列表名称]”

2)但是,如果是查阅了列表本身的话,上面的方法是不起作用的,“List”属性需要设置为“Self”,详细的解释我们可以参考:Lookup Fields to the Same List – Defined as a Site Column

好了,至此,包含Lookup查阅项字段的列表的导出成模板产生的问题就解决了。如果你觉得必要的话,可以写个简单的小工具来自动化这个过程……

[SharePoint Wiki]如何使用Web Service新建和更新Wiki页面的内容

公司内部有很多部门都创建了Wiki库,来做知识共享。公司是Hosting的SharePoint环境,不能写服务器端代码,要操作Wiki只能通过Web Service来完成,所以,碰到两个情况:

1)Wiki库中已经有了几百篇的文章,文章中有些文字需要更新,几百篇文章手动更新肯定累死;

2)有人想写个程序,自动将包含图片的Word文档内容新建成Wiki;

说白了,其实就是如何使用SharePoint Web Service来新建和更新Wiki页面。

在SharePoint里面,Wiki虽然也可以看成是List,但是又有些特殊,每篇Wiki就是一个aspx页面,Wiki的内容则存储在Wiki条目的WikiField字段里面。

1)对于更新Wiki页面的内容,我们可以使用Lists.asmx的UpdateListItems来完成:

以下是一个批量替换Wiki内容中的一段文字的代码示例:

Lists.Lists SPLists = new Lists.Lists();
SPLists.Credentials = System.Net.CredentialCache.DefaultCredentials;
SPLists.Url = strListsSvrURL;

//拼更新列表字段的XML
XmlDocument doc = new XmlDocument();
XmlElement batch = doc.CreateElement("Batch");
batch.SetAttribute("OnError", "Continue");
batch.SetAttribute("ListVersion", "1");

//获取Wiki库的所有Wiki条目
XmlNode ListItems = SPLists.GetListItems(strWikiLibName, null, null, null, null, null, null);

foreach (XmlNode ListItem in ListItems.ChildNodes[1].ChildNodes)
{
    if (ListItem.Attributes != null)
    {
        batch.InnerXml += "<Method ID='1' Cmd='Update'>" +
        "<Field Name='ID'>" + ListItem.Attributes["ows_ID"].Value + "</Field>" +
        "<Field Name='WikiField'><![CDATA[" + ListItem.Attributes["ows_WikiField"].Value.Replace("AA", "BB") + "]]></Field>"
        + "</Method>";
    }
}
SPLists.UpdateListItems(strWikiLibName, batch);

2)对于新建Wiki页面,我们不能使用Lists.asmx的UpdateListItems,通过传递<Method ID=’1′ Cmd=’New’>…命令来完成,一个办法是使用Copy.asmx,复制Wiki库中的一个Wiki页面,生成一个新的Wiki页面,更新它的WikiField字段。

string strWikiHomeURL = "http://site/wiki/home.aspx";

Copy.Copy SPListCopy = new Copy.Copy();
SPListCopy.Credentials = System.Net.CredentialCache.DefaultCredentials;
SPListCopy.Url = strCopySvrURL;

Copy.FieldInformation[] HomePagefieldInformation;
byte[] HomePageContentBytes;

uint myGetUint = SPListCopy.GetItem(
                                        strWikiHomeURL,
                                        out HomePagefieldInformation,
                                        out HomePageContentBytes);

//Wiki Page Title
string WikiName = "New" + DateTime.Now.ToString();
WikiName = WikiName.Replace("/", "").Replace(":", "").Replace(" ","");

Copy.FieldInformation headerInformation = new Copy.FieldInformation();
headerInformation.DisplayName = "Name";
headerInformation.InternalName = "LinkFilename";
headerInformation.Type = Copy.FieldType.Note;
headerInformation.Value = WikiName;

Copy.FieldInformation contentType = new Copy.FieldInformation();
contentType.DisplayName = "ContentType";
contentType.InternalName = "ContentType";
contentType.Type = Copy.FieldType.Text;
contentType.Value = "Wiki Page";

Copy.FieldInformation wikiField = new Copy.FieldInformation();
wikiField.DisplayName = "Wiki Content";
wikiField.InternalName = "WikiField";
wikiField.Type = Copy.FieldType.Text;
//Wiki Content Here
wikiField.Value = "new conent"+DateTime.Now.ToString();

Copy.FieldInformation[] fieldInformation = { headerInformation, contentType, wikiField };

Copy.CopyResult copyResult = new Copy.CopyResult();
Copy.CopyResult[] copyResults = { copyResult };

string[] copyDestination = { strWikiHomeURL.Substring(0,strWikiHomeURL.LastIndexOf("/")+1) + WikiName + ".aspx" };

SPListCopy.CopyIntoItems(strWikiHomeURL, copyDestination, fieldInformation, HomePageContentBytes, out copyResults);


 

[SDK]最新SharePoint 2010 SDK下载地址

微软5月20号发布了SharePoint 2010的SDK,下载地址如下:

http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=f0c9daf3-4c54-45ed-9bde-7b4d83a8f26f

Enjoy SharePoint 2010!

另附上以下两个开发人员学习资料:

  • Sharepoint 2010 Developer Training Kit
  • SharePoint Server 2010: Advanced Developer Training Presentations
  • [Deployment]SharePoint 2010安装贴士

    SharePoint 2010已经RTM,相比前一个版本,SharePoint 2010的整体架构在Application层发生了很大的变化,有机会再细说这个变化。

    在安装部署方面,SharePoint 2010也简化了不少,安装指南的话网上可以搜索到很多,在这里对于安装部署给出一些小贴士(注意红色文字)

    1)关于“安装必备条件”

    SharePoint 2010的安装程序提供了一个“安装必备条件”的功能,改步骤会帮你安装所有部署SharePoint 2010必要的程序和组件,但是这个程序必须联网实时下载这些必备程序和组件

    在某些企业里面,内网服务器不能直接连上外网网络,就需要安装人员手动来安装所有的必要程序和组件。

    Hardware and software requirements (SharePoint Server 2010)页面有所有的程序组件的下载链接。

    但是,这个页面中有两个下载链接下载的安装程序是错误的:

    a. Microsoft SQL Server 2008 Analysis Services ADOMD.NET正确的下载链接:http://download.microsoft.com/download/A/D/0/AD021EF1-9CBC-4D11-AB51-6A65019D4706/SQLSERVER2008_ASADOMD10.msi

    b.该页面的‘Microsoft Filter Pack 2.0’ 对应的下载页面下载的是Filter Pack 1.0版本,不过没有关系,SharePoint 2010安装软件中已经包含完整的Filter Pack 2.0安装程序,位于安装光盘的“\PrerequisiteInstallerFiles\FilterPack”文件目录下。

    如果你是自己下载并安装必备程序和组件,推荐你按照SharePoint 2010本身的“安装必备条件”的顺序安装:

    image

    一个最佳实践是:你手动安装完所有的必备程序和组件以后,仍然运行一次“安装必备条件”安装程序,以检验是否完全正确安装了

    2)SharePoint 2010同样是提供了两种安装模式:独立单服务器安装、服务器场安装。

    a.独立单服务器安装:如果你选择独立单服务器安装的话,会默认安装SQL Server 2008 Express版本。

    b.服务器场安装:需要你安装SQL Server数据库,然后再配置向导中输入使用的SQL服务器以及服务器服务账号。

    但是,如果你是因为测试或者其他原因,需要在域控制器上安装独立单服务器的SharePoint 2010,安装程序会默认使用服务器场模式安装,不会出现让你选择“独立”还是“完整”的窗口,这种情况下就需要你自己安装一个SQL Server 2008。

    另,在Beta和RC的时候要在域控制器上安装SharePoint 2010会需要一些额外的账号设置,在RTM后已经不需要了,直接安装即可。