RSS

Monthly Archives: 六月 2011

组织结构配置文件的诡异行为

组织结构配置文件(OrganizationProfile),大家可能比较陌生,尤其对编程访问。具体的操作我就不在这里一一列举了,SDK里面也有例子,这里面只说一个可能和我们的预期不太一样的一个API行为。

在组织结构配置文件中,一个组织中的成员分为两种类型,Leader和Member。可以通过OrganizationProfile的AddMember方法来向这两个部分中加入用户(通过一个参数来进行区分是Leader还是Member),并通过RemoveMember的方式删除之。

如果这个用户不在Member中,我们可是使用下面这句话把用户user1加为Leader

   1: orgProfile.AddMember("domain\\user1", 
   2:               OrganizationMembershipType.Leader);

假设在之前这个组织中空无一人,执行完上面这句话的时候,user1既会出现在Leader中,也会出现在Member中,也就是说这个用户同时会自动加到Member里。这个行为很好理解,也make sense。

BUT!(又来了)

假设这个时候user1已经是Leader了(当然他也是Member),看下面这个代码:

   1: orgProfile.AddMember("domain\\user1",    
   2:               OrganizationMembershipType.Member);

执行完这句话你觉得会发生什么?把user1又一次加为Member,你觉得在上面那种假设情况下,应该不会发生任何变化是吧?错了!当我们执行完这句话的时候,user1还在Member中,但已经从Leader中消失掉了。很奇怪吧……我相信这是一个By Design的Bug……

换句话说,当我们要把一个用户加为成员的话,首先你得看一下这个用户是不是已经在成员中了,如果他已经存在,就不要再加一遍了。否则,万一这位用户是这个组织的领导,你一加,领导就没了(这在中国的项目中是多么可怕的行为)

 

Posted by on 2011 年 06 月 30 日 in SharePoint

Leave a comment

Tags:

UserProfile创建时拒绝访问?

这两天在做一个POC,组织结构的同步。做了一个通用框架,为了做示例和测试,写了一个到用户配置文件(UserProfile)和组织结构配置文件(OrganizationProfile)的接口,然后通过事件处理程序来调用UserProfile的相关接口,把信息同步到用户配置文件中。

然后就出现了问题:在通过事件处理程序调用UserProfileManager的CreateUserProfile方法时,SharePoint抛出了一个拒绝访问的异常:只有管理员和和本人才能创建用户配置文件云云……可是我执行的账号本来就是系统账号啊,我还又去User Profile Service那边查了一下,有完全控制的管理员权限啊……

然后经过一番搜索,发现关键问题的所在:

UserProfileManager在创建的时候,是依赖HttpContext(不是SPContext)的,而事件处理程序中是没有HttpContext的(即使在w3wp进程中运行也没有,SPContext也没有)。(但是为什么用Console程序写UserProfile程序的时候,也没有HttpContext,就能执行成功呢……不解)

临时岔开一下,而且由于是依赖HttpContext而不是SPContext,在提升权限的时候也会出一些问题,网上有人是重新构造了HttpContext作为创建SPServiceContext的参数,然后再去创建UserProfileManager。期间还用到了反射的方法修改WindowsIdentity的某个非公开属性……

上述方法太麻烦,于是我决定绕路,写一个Web Service扔到layouts里,这样就有HttpContext的上下文信息了。然后在事件处理程序中调用Web Service,并使用DefaultCredential(嗯,在我的场景中,只有管理员有权限去管理这个组织结构,所以直接传递当前身份,也不需要做权限提升)。看起来一切正常了……

BUT!人生最厉害的就是这个BUT!(好吧,这句话是九把刀说的)

当我去调用RemoveUserProfile,妄图去删除一个用户配置文件的时候,再次爆发了拒绝访问的异常(同样的代码Console还是正常,无语)。然后搜索了一下,发现msdn论坛上的一个帖子中描述了类似的问题,不过是在2007中的,本着试试看的方式按照如下方法尝试了一下(2007中的ServerContext被废弃,换成了SPServiceContext):

   1: SPSecurity.RunWithElevatedPriviliges(delegate(){
   2:   HttpContext oldCtx = HttpContext.Current;
   3:   SPServiceContext sc = SPServiceContext.GetContext(oldCtx);
   4:   HttpContext.Current = null;    // 亮点在这里
   5:   UserProfileManager upm = new UserProfileManager(sc);
   6:   upm.RemoveUserProfile("domain\\user");
   7:   HttpContext.Current = oldCtx;  // 还原回来
   8: });

于是乎就可耻的成功了……我表示很费解,也很无语……

 

Posted by on 2011 年 06 月 30 日 in SharePoint

Leave a comment

Tags:

SharePoint 2010 SP1更新发布

前几天微软SharePoint产品组正式发布了产品的SP1,中文版下载地址如下:

1、SharePoint Foundation 2010 Service Pack (KB2460058)

2、Microsoft SharePoint Foundation 2010 Language Pack Service Pack (KB2460059)(中文语言包)

3、Microsoft SharePoint Server 2010 Service Pack (KB2460045)

4、Server Language Pack 2010 Service Pack (KB2460056)(中文语言包)

5、Microsoft Office Web Apps 2010 Service Pack (KB2460073)

安装顺序也如上所示(如果你没有安装语言包的话,可以跳过2、4)。

[6月30日更新]如果你只安装了Foundation的话,只需要装1、2;如果你装的是Server,则不再需要安装Foundation的SP1,因为Server的SP是包含了FoundationSP的。(李劼的这篇Blog解释得很清楚:点我点我

此外,官方网站上也描述了一些安装的已知问题和注意事项(原文地址点我),主要包括:

  • 要确认有足够的剩余磁盘空间(几个SP的安装文件加一起有600来MB)
  • 安装SP1之后必须要重启计算机(当然重新运行配置向导是肯定要的,这个不用多说了)
  • 如果你只打算安装OWA的SP1,而SharePoint还保留在RTM(非SP1)版本的话,需要预先装两个补丁文件25106392510648,然后再安装OWA的SP1。
  • 在安装完SP1之后,新建的网站集的工作流Feature默认会禁用,需要手动启用一下(为啥会这样……)

 

此外,需要注意的是SP1包含了到2011年4月份为止的所有安装更新,但是不包括最新的6月份的安全更新(CU),所以微软建议在安装完SP1之后,再安装一下6月份的CU。不过一般来说,我们认为在生产环境中,除非确实遇到了问题,而且确认CU能够解决这个问题的话,再去安装,否则有一定的风险。

除了累积安全更新外,SP1还主要提供了如下更新内容:

  • 支持安装在SQL Server Denali上(下一版的SQL,目前还只有测试版)
  • 支持在移动网站集的时候使用浅拷贝(Shallow Copy,从文档来看,这个主要是针对应用了RBS的网站集,在迁移到另外一个内容数据库的时候,可以保留以前的RBS存储位置等设置)
  • 网站和网站集的回收站(这个功能终于出现了……现在你在删掉一个网站或网站集之后,可以很方便地从回收站里再还原回去了,就像以前还原列表或文档一样)
  • 增加了StorMan.aspx管理页面,可以查看到网站中文档库具体的存储大小,便于IT进行监控和管理
  • PPS中筛选器的改进
  • 增加对Chrome浏览器的支持
 

Posted by on 2011 年 06 月 29 日 in SharePoint

Leave a comment

Tags:

左侧导航太长了?

这是目前正在做的这个POC的一个副产品,嗯。

当左侧导航太长的时候,通过js加上一个折叠展开的效果(用jquery,嗯),在页面里导航加载后的任何地方以任何一种形式执行如下的js(引用jquery的部分略掉):

   1: $('div.vertical > ul.root > li').each(function () {
   2:   var $a = $("<a style='float:right' href='javascript:void(0)' exp='1'><img border='0' src='/_layouts/images/dlmin.gif'/></a>")
   3:               .click(function () {
   4:                 if ($(this).attr('exp') == '1') {
   5:                   $(this).find('img').attr('src', '/_layouts/images/dlmax.gif');
   6:                   $(this).attr('exp', '0');
   7:                   $(this).parents('.menu-item').next().slideUp();
   8:                 } else {
   9:                   $(this).find('img').attr('src', '/_layouts/images/dlmin.gif');
  10:                   $(this).attr('exp', '1');
  11:                   $(this).parents('.menu-item').next().slideDown();
  12:               }
  13:             });
  14:   $(this).find('span:eq(2)').append($a);
  15: });

代码很简单,我就不解释啥了,效果如下图(归功于jquery,这个是带收缩展开动态效果的哦):

image

(这个导航的样式是靠CSS实现的,跟本文没啥关系)

当然,现在这个打开的时候依然是所有二级导航都处于展开状态,稍微修改一下上面的代码就可以很容易实现页面刚加载的时候默认折叠一些或所有的一级导航。

 

Posted by on 2011 年 06 月 24 日 in SharePoint

Leave a comment

Tags:

多语言和自定义CSS

最近在一个SharePoint 2010项目中发现,在装了英文、日文语言包之后,在网站设置的语言设置中,选择备用语言的时候,系统返回一个异常,大意是包含自定义样式表(CSS)的网站不支持多语言。

之前一直没太注意到底什么算是“自定义CSS”,经过一番研究,发现了问题:

一般网站引用CSS的时候,引用的都是layouts目录中的文件(比如/_layouts/2052/Styles/corev4.css),这个CSS显然是整个服务器场共用的;但是出问题的这个网站引用的是本网站中的/_styles/corev4.css(这不是个虚拟路径,就是在网站中的一个目录,存在数据库里的)——这个就是所谓的“自定义CSS”。你想啊,人家在layouts里面的CSS是按照语言划分的,不同语言的情况下引用的是不同的CSS,而在_styles里面,全都一样,当然不成了,于是多语言就不干了。

那么下一个问题就是,这个自定义CSS到底是怎么出现的?怎么恢复成非自定义CSS?到底应该怎么去修改默认的CSS?一个一个来。

一、自定义CSS是如何出现的?

其实自定义CSS从SharePoint 2007的时候就出现了,但是由于当时并没有2010这种多语言机制,并没有把这个问题凸显出来。

经过一番调查,发现这个是由于我们的美工在使用SharePoint Designer改CSS的时候造成的。在SPD里面打开一个页面,页面里面自然会列出若干class,而当我们按住Ctrl键点击这些CSS的时候,就会打开对应CSS文件的编辑:

image

而当我们保存这个CSS的时候:

image

看到“自定义样式表”了吧?就是从这儿来的。一旦点了“是”,SharePoint就会把layouts下对应的这个CSS文件保存到网站的_styles目录中(如果之前没这个目录会自动创建一个,注意这是个目录,不是个文档库)。其实这是非常合理的,总不能因为你要修改页面里的一个CSS,就要影响到整个服务器场的所有网站吧?于是就有了这个类似于unghost的过程。

当然,使用对象模型的方式也可以很方便地完成这个过程,只需要一句话:

   1: spWeb.CustomizeCss("corev4.css");

(其实我就是翻SDK翻到的这个方法,然后用reflector确定了那个多语言就是这个东西造成的)

二、如何恢复成非自定义CSS?

既然知道了自定义的方法,恢复就有头绪了。直接写个Console,同样用一句话搞定:

   1: spWeb.RevertCss("corev4.css");

三、到底应该如何自定义CSS?

标准的做法当然不是去修改layouts下的CSS文件(除非你想整个服务器场所有网站都变化)。你可以把你要改的地方单放到一个CSS里,然后设置成网站的备用CSS,见下图:

image

上面这个界面是在网站设置 – 母版页(不是库分类下的那个母版页),这是在开启了发布功能的前提下才会出现的一个链接。如果没有开启发布功能的话,直接进去“/_Layouts/ChangeSiteMasterPage.aspx”这个页面应该也行(我没试过),或者干脆用程序改一下。这个备用CSS会自动放在系统默认的CSS文件之后进行引用,所以会覆盖掉默认的CSS样式(默认样式中有一些是标记了“!important”的,在自定义CSS里想要覆盖这个设置的话也要加上这个)

当然你也可以改母版页,在系统CSS引用(母版页中的SharePoint:CssLink和SharePoint:Theme)之后,使用SharePoint:CssRegistration控件进行引用,这样也可以自动根据不同的语言自动进行切换(具体的写法请自行msdn或者google)

 

Posted by on 2011 年 06 月 17 日 in SharePoint

Leave a comment

Tags: ,