RSS

博客迁移到博客园

由于最近博客堂这边不太稳定(可能也和我网络有关系,我通过一台公网服务器访问就还好),

把所有博客迁移到了博客园,之后就在那边安家落户了。

image

地址:http://www.cnblogs.com/erucy/

RSS:http://www.cnblogs.com/erucy/rss

感谢这几年来超哥提供的服务器!

 

Posted by on 2012 年 03 月 24 日 in 未分类

Leave a comment

SharePoint Wiki发布页面的“保存冲突”

昨天客户说修改页面的时候,弹出了这个对话框(用的是发布功能里面的企业Wiki页面布局):

image

最奇怪的是,页面内容、页面属性都可以修改,只有页面名称不能改,一保存就弹框。

我开始以为是锁定的问题(页面没有被Check Out,所以不是Check Out问题),我用代码把这个文件锁定(SPFile.Lock),现象和这个一样,区别在于不管修改什么内容都不能保存,而客户那边只有修改名字不能保存。

最后到客户现场检查了一下,发现是一个特别白痴的问题:有文件重名……(话说重名的时候就不能直接提示重名么,什么叫保存冲突啊)

btw,如果因为锁定的原因导致的问题(常见于有工作流的场景),如果要修改的话,用SPFile.ReleaseLock解锁就行了

 

Posted by on 2012 年 03 月 22 日 in SharePoint

Leave a comment

2010的Web部件页和网站图标

在一个项目中发现了这样的问题(其实应该是比较常见的问题,不过刚刚遇到):

我们在网站设置的标题、说明和图标中自定义了网站图标(Site Icon),其他页面都正常切换了,只有在一个自己创建的Web部件页中,发现网站图标一开始时自定义的那张图片,到页面加载完毕之后,就变成了SharePoint的默认图标。

网上搜到了解决方法,其实也很简单。直接在Ribbon的“页面”标签上点击“标题栏属性”,然后把“图像链接”改成自定义的图标就行了。

归根结底,这个东西就是在PlaceHolderPageTitleInTitleArea这个PlaceHolder里面的一个特殊的WebPart——TitleBarWebPart(就是那个所谓的标题栏)的Image属性造成的,这个属性的默认值就是SharePoint默认的网站图标,如果不指定的话,就会使用默认值了。

据说如果直接把自定义的这个Web部件页放到页面库里就没事了,不过我没试(出于某些原因,这个页面必须放在页面库外面)。

 

Posted by on 2012 年 02 月 24 日 in SharePoint

Leave a comment

托管元数据(2)——托管元数据和搜索中的精简面板

精简面板(Refinement Panel,SharePoint也有些地方把Refinement翻译成“优化”)是SharePoint 2010搜索中新增加的一个非常好的功能,可以通过搜索结果中的文件类型、作者、修改时间、网站等属性,对搜索结果进行二次过滤,方便用户快速找到自己想要的功能。

2010搜索结果页面中的精简面板是一个Web部件,而且是允许用户进行自定义的,管理员可以随意增加需要在这里进行“过滤”的属性。关于如何在精简面板Web部件中添加自己需要的属性,玉树临风的kaneboy童鞋在这篇博客(点我点我)中已经解释得非常清楚了。这篇博客主要介绍一下托管元数据这种特殊类型的属性在SharePoint搜索结果精简面板中的表现。

如果我们使用默认的Web部件设置,通过点击Web部件属性,在“优化”属性分组中,我们可以看到SharePoint默认使用的优化参数设置。在默认设置的这一段Xml里面,除了文件类型、网站、作者、修改时间之外,我们会看到最后包含两个属性:

1、Title(标题)为“Managed Metadata Columns”、Type(类型)为“Microsoft.Office.Server.Search.WebControls.TaxonomyFilterGenerator”、MappedProperty(映射属性)为“ows_MetadataFactedInfo”

2、Title为“标记”(在英文版中是“Tags”)、Type与第一个相同,MappedProperty为“ows_MetadataFacetInfo, popularsocialtags”

这两个就是SharePoint默认设置中针对托管元数据的处理。它和其它的属性过滤的方式非常不同,而且这种区别不仅仅表现在Type的不同上。

“Managed Metadata Columns”是针对所有已经被配置为可以在搜索结果中进行优化过滤的托管元数据映射属性,只要配置“一切正常”的话,SharePoint会自动从搜索结果中找到这些托管元数据的属性,并且按照不同的来源字段,呈现出多种不同的属性过滤。它的MappedProperty必须设置为“ows_MetadataFacetInfo”,这样SharePoint才能够按照托管元数据的方式对其进行处理(后面会说明SharePoint针对托管元数据属性的处理和对文本类型属性的处理的不同之处);其次,这个看似奇怪的Title是不能随意修改的,只有把它设置为“Managed Metadata Columns”,SharePoint才会去寻找搜索结果中的所有已配置为可优化的托管元数据字段类型,如果我们只需要针对某个字段进行过滤,可以把Title设置成这个字段的名称(显示名称),而任何其他的设置,都会导致这个配置无效。

“标记”(Tags)是针对所有未在上一个节点中出现的其他托管元数据类型的数据的过滤(包括企业关键字、用户标签)。它的MappedProperty设置同样是不可修改的,而且Title也是不可修改的。

 

BUT!

有些时候,虽然是一个托管元数据类型的字段,它并不会按照字段的名称出现在精简面板中,而是一律出现在“标记”这个面板中,如下图所示:

p5

在我进行配置过的几个环境中,只有在我自己的开发虚机中自动根据字段的名称出现了正常的样式(而且这个虚机的多个托管元数据类型的字段,只有一个会出现),如下图所示:

p1

后来经过多次试验(期间改过多种配置,重新进行过多次完全爬网……),后来发现了一个可能的问题:

当我们进行完全爬网的时候,貌似SharePoint会针对每个托管元数据字段自动创建一个映射属性,这些映射属性的名称都是以owstaxId开头的,后面跟着这个字段的名称(应该是内部名称),下面这张图是我开发虚机里面的映射属性的一个截图:

p6

如果仔细看一下的话,就知道为什么只有“知识分类”这个托管元数据字段会“正常”地出现在搜索结果的精简面板中了,它的第三个设置是“是”,其他所有托管元数据字段的设置都是“否”,而这个设置,就是是否允许此映射属性在精简面板中进行过滤,具体的属性设置如下图所示(红框圈起来的那个):

image

在我的另一个项目虚机里面,当我把这个owstaxIdxxxxx的这个设置开启之后,它在精简面板中就可以正常显示了(不过我在做试验的时候,还修改过其他配置,比如爬网账号、托管元数据的各级管理员、甚至手动给这个字段添加了一个映射属性,我不是100%地确定这些设置是否和这个问题有关系,但是只有当我把这个taxId的属性修改了之后,才一切正常)。

如果在你的环境里面,托管元数据类型的字段不能正常出现在搜索结果精简面板中的话,可以按照本文介绍的内容来配置一下。

 

最后,介绍一下SharePoint对托管元数据的“过滤”处理,和一个普通的文本类型属性的过滤处理有何不同。

我们可以尝试按照kaneboy那篇博客中的方法,把一个托管元数据的字段,添加一个“文本”类型的映射属性,并且修改默认的精简面板,添加这个属性(注意Type使用ManagedPropertyFilterGenerator,而不是TaxonomyFilterGenerator)。这种配置方法,在某些情况下,确实是可以按照我们的预期进行工作的,但是它主要的区别在于如下两个方面:

1、对于多值的处理。即使我们在创建映射属性的时候,选择了“具有多个值”,在精简面板中也不会真正地进行多值处理,只会把所有值拼合在一起,作为一个值进行过滤(比如在精简面板中会变成“分类1; 分类2;”,而不是“分类1”和“分类2”两个过滤条件)。

2、对于层级结构的处理。如果是按照本文前面的部分配置的托管元数据类型的过滤器,会按照托管元数据的层级结构进行过滤。举个例子来说,如果我们的搜索结果中某个字段的值有如下几种:猫、波斯猫、孟买猫(其中“猫”是后两者的父级),那么这三个值都会出现在精简面板中,如果我们在精简面板中选择了“猫”的时候,搜索结果中所有标记为“猫”的,以及所有标记为“猫”的所有后代节点的结果,都会被过滤出来。而如果我们是作为一个文本类型的字段进行处理的时候,选择“猫”时,就只会过滤出被标记为“猫”的那些结果,而不会出现被标记为“波斯猫”、“孟买猫”的那些结果了……

其实这两个区别背后的原因,应该是针对不同的字段进行的设置,一个是表面的字段(就是我们存放托管元数据那个类型的字段),一个是背后的字段(注意看上面那张截图中,映射的实际字段是“ows_taxId_KBCatalog”,而不是“ows_KBCatalog”)。

我折腾这个问题的时候,google了很多文章,不过似乎没有谁提到过这个背后的“taxId”字段的那个精简设置的属性。

参考链接:

1、精简面板的设置参考(来自MSDN)

2、在列表定义中创建托管元数据类型字段时需要的一些额外设置(里面提到了一些精简面板的问题,看了这篇blog我才注意到一个托管元数据字段的背后居然有这么多个辅助字段)

btw,春节快乐!

 

Posted by on 2012 年 01 月 22 日 in SharePoint

Leave a comment

Tags:

托管元数据(1)——隐藏列表以及一些相关问题

托管元数据服务(Managed Metadata Service)是SharePoint 2010新加入的一个服务(其实我们在2007上自己做过一个类似的自定义字段),关于这个服务的介绍应该就不用再多说了,关于编程访问托管元数据、托管元数据字段的方法也有很多博客都介绍过了(包括中文的),也不再废话了。

这篇Blog主要是介绍一下托管元数据背后的隐藏列表,以及因为这个隐藏列表所带来的一些问题。

如果我们去看一下托管元数据字段类型(TaxonomyField)的继承关系,我们会发现TaxonomyField是继承LookupField的,换句话说,托管元数据在本质上是个查阅项,它查阅的是网站集根网站上,一个名字叫TaxonomyHiddenList的隐藏列表(没错,查阅项是可以跨网站查阅的,从2007的时候就可以,只不过微软没有开放设置界面而已,用代码可以创建出来跨网站的查阅项)。

这个隐藏列表保存了所有在网站集中正在使用以及使用过的所有托管元数据的值(包括企业关键字,这也是个托管元数据类型的字段),当我们在托管元数据字段中选择了某个值并保存之后,SharePoint会判断这个隐藏列表中是否包含这个值,如果不包含的话,会自动把这个值加到列表里。此外,SharePoint在后台有一个TimerJob去把托管元数据服务中的数据同步到这个隐藏列表中(比如改了名字、换了路径、删除之类的)。

自然,这样的设计提供了托管元数据在网站集中的缓存,本意上是在一定程度上提高了性能。但是因为这个背后隐藏列表的存在,以及这种随用随加的机制,导致了一些问题。目前遇到的有如下三个可能存在的问题或不方便之处:

1、权限问题

这种问题出现的可能性不大,不过确实在实际的客户那里遇到过。

TaxonomyHiddenList是不继承网站权限的,他默认的权限设置是所有用户有读取权限(如果你是Windows认证的网站的话,这里的所有用户是Authenticated Users这个AD组),系统账号拥有完全控制权限,如果网站开启了匿名的话,匿名用户拥有查看项目的权限。这样的设置即保证了用户能够正常读取到其中的值,也能够防止其他用户修改列表中的内容(针对这个列表的所有修改都是通过托管元数据服务以及后台的TimerJob来完成的)。

但是上次在客户现场遇到过一个问题,这个Authenticated Users的权限不知道因为什么原因被去掉了,于是就造成了如下的诡异现象:

(1)用户可以在托管元数据导航的地方看到完整的元数据信息,但是点击进行筛选的时候报错(除非系统账号之前点过)

(2)用户在视图、查看页面上看不到任何托管元数据的值,但是在编辑页面和新建页面都能够正常看到。

这个很明显就是用了查阅项、而且查阅的那个列表上没有权限的现象;而新建、编辑、托管元数据导航之所以正常,因为这些数据都是直接来自托管元数据服务的。系统账号点过之后就可以用,估计是因为有缓存神马的。

2、视图筛选

如果你想在一个托管元数据字段上设置视图的筛选条件,那么你就只能使用“等于”和“不等于”这两种运算符,而且这两种运算符都会把托管元数据字段退化成一个“单行文本”行为的字段,换句话说,只能筛选到特定的那一个值,而不包含其中的子项的值。

举个例子来说,如果有下面一个托管元数据字段的设置:

动物;动物/猫;动物/猫/波斯猫;动物/猫/孟买猫;动物/狗;动物/狗/哈士奇;动物/狗/雪纳瑞

如果你想筛选这个字段的值 = 波斯猫的,那么ok,因为波斯猫是处于叶子结点的位置;但是如果你想通过视图去筛选所有的猫,这个是实现不了的。

你会说,如果我用API或者PowerShell设置视图的Query属性,把所有可能的值都包含进去(2010在CAML查询中新提供了一个In的运算符,行为就和SQL里面的In是一样的)呢?

如果你用文本的话,如果管理员修改了某个元数据的值,那查询条件就不对了;如果你用查阅项ID,那么因为背后那个隐藏列表有着随用随加的机制,如果你在设置视图的时候,某些值还从来没有使用过,当这些值被使用的时候,你的视图就查不到这些值了。而且不管你用哪一种方式,当管理员在后台更改了托管元数据的结构或者增加了新的节点的时候,这个视图条件都不再正确了。

一种变通的方式,是使用托管元数据导航,选中你需要的节点,然后把Url记下来,以后使用这个Url作为你这个视图的入口(SharePoint会在后台动态生成一个使用In运算符,包含所有子节点的CAML查询)。但是如果你要想在一个页面上放置多个视图,那就彻底没辙了。同样,对于“内容查询Web部件”来说,针对托管元数据的查询也会因为类似的原因而无能为力。

只能自己写代码做Web部件了(如果你有其他更好的方式,欢迎告诉我erucy9[_at_]gmail[_dot_]com)

3、API不正常的By Design行为

托管元数据提供了一套完整的API,这里面有一个方法需要特别说明,那就是GetTerms。

在TaxonomySession、TermStore、TermSet上都提供了这个方法,这个方法可以通过托管元数据的字符串值(Label)获取到特定名称的那一个(或多个)Term。

BUT……

当我们通过TaxonomySession和TermStore去使用这个方法的时候,只能获取到那些已经存在于TaxonomyHiddenList中的值(也就是网站中曾经使用过的值);只有当通过TermSet去使用GetTerms的时候,才能够获取到所有的值……

 

预告:

下一篇的内容是介绍托管元数据在SharePoint搜索结果页面中的“精简面板”(Refinement Panel)中的设置。

 

Posted by on 2012 年 01 月 20 日 in SharePoint

Leave a comment

Tags:

SharePoint Designer中无法显示任何列表

最近在自己的虚机上发现了这样的现象:

SharePoint Designer 2010中,列表和库中间,无法显示任何内容,母版页之类的链接干脆就消失了,网站页面、网站资产这几个文档库也都显示“无法显示为文档库”:

spd

后来网上搜了一大圈,也琢磨了好久,想到刚刚卸载了一个工作流的产品,这是唯一一个可能造成影响的地方。

最终发现就是因为某个列表定义(List Definition)随着产品的卸载被干掉了,但是列表实例(List Instance)还在,这个也是feature卸载时候的一个问题。于是这些找不到对应定义的列表实例,导致了SPD出现这种状况。

解决方法也很简单,手动把那几个列表删掉就好了(如果是隐藏列表的话,需要用PowerShell或者自己写个Console删掉)。

 

Posted by on 2011 年 12 月 27 日 in SharePoint

Leave a comment

Tags:

文档库下载副本,文件名被截断

今天在TechNet上看到一个人问的问题(应该很早就有人发现这个问题了,2007应该就是这个样子),所以我估计我这个Blog里面写的也是很old的结论了。

原帖如下:sharepoint2010 从文档库下载文档副本 文件名被截断的问题

概括起来就是,当从文档库中下载副本的时候,过长的文件名被截断了(但是扩展名被保留);之前也有人发现过通过某些版本的浏览器文件另存为的时候也会这样。

这个原因是这样的:

下载副本是通过 /_layouts/download.aspx?SourceUrl=xxxx (xxxx就是你那个文件的路径)页面实现的,后台的类是Microsoft.SharePoint.ApplicationPages.Download,里面代码不多,不过篇幅所限就不全贴了,文件名是通过HttpHeader实现的,里面的核心方法AddContentDispostionHeader如下:

   1: private void AddContentDispositionHeader(string fileName)
   2: {
   3:     if ((this.Web != null) && (this.Web.Site.WebApplication.BrowserFileHandling == SPBrowserFileHandling.Strict))
   4:     {
   5:         base.Response.AppendHeader("X-Content-Type-Options", "nosniff");
   6:         base.Response.AppendHeader("X-Download-Options", "noopen");
   7:     }
   8:     base.Response.AppendHeader("Content-Disposition", "attachment;filename=\"" + SPHttpUtility.UrlEncodeFilenameForHttpHeader(fileName) + "\"");
   9: }
  10:  

可以看到,其中核心调用的方法是 SPHttpUtility.UrlEncodeFilenameForHttpHeader(str)

这个方法的实现如下:

   1: public static string UrlEncodeFilenameForHttpHeader(string fileName)
   2: {
   3:     string str = UrlEncodeForFilename(Path.GetExtension(fileName), 0x80, true);
   4:     string str2 = string.Empty;
   5:     if (str.Length < 0x80)
   6:     {
   7:         str2 = UrlEncodeForFilename(Path.GetFileNameWithoutExtension(fileName), 0x80 - str.Length, true);
   8:     }
   9:     return (str2 + str);
  10: }

我们可以看到,SharePoint把编码后文件名的总长度限制为128个字符,如果可能的话保留扩展名部分,截断超长的文件名。而Encode之后的中文类似于“%E4%B8%AD”这个样子(在UTF-8下,一个汉字用三个字节表示,前面那个表示“中”这个汉字),可以看到,一个汉字占了9个字符,因此就不难得到,如果扩展名是"“.docx”的话,那么前面的文件名长度最多只能容纳 (128 – 5) / 9 = 13.67,也就是13个汉字。

btw,实际上,在RFC中(参见:The Content-Disposition Header Field)中,规定了参数的长度不得超过78个字符,而且必须是编码的。当然,RFC只是个参考标准,每家都有自己的选择……

 

Posted by on 2011 年 09 月 30 日 in SharePoint

Leave a comment

SharePoint 2010 SP1新功能(存储标准)

首先,“存储标准”名词翻译的真是太奇怪了……英文是“Storage Metrics”,功能就是观察网站、文档库、文件夹、文档所占用的存储空间。

这个功能在2007的时候其实就有,不过因为种种原因(比如性能之类的问题)在2010里面被去掉了,在SP1的时候,经过一番改进又加了回来。

功能在网站集管理中的“存储标准”,点击进入后,可以看到如下的界面:

image

点击网站的名字、文件夹的名字可以进入网站/文件夹,看到里面的内容,一直具体到某个文件所占用的空间(这个占用空间是该文件所有版本加在一起占用的空间,而不是最新版本的大小,所以可以真实反应实际的存储容量)。此外,界面中还能够看到这些对象在父容器中所占的百分比、在网站配额中所占的百分比(我这个网站集没有设置网站配额),以及最后修改时间。

需要注意的是,这些数据不是实时更新的(07里面是实时更新的,对性能有一定的影响),而是靠一个Timer Job定期更新的,这个Timer Job叫“存储标准处理”(这翻译……),默认是5分钟运行一次,可以根据情况自行修改:

image

 

Posted by on 2011 年 09 月 13 日 in 未分类

Leave a comment

SharePoint 2010 SP1的新功能(网站回收站)

SP1已经出了有两个月多了,估计有不少人都已经安装了,SP1里面新增的两个功能估计也有不少人知道了,不过可能还有些人不知道,所以还是写一写好了。

新功能之一就是网站/网站集回收站。

在SharePoint 2007的时候,推出了回收站功能,这是一个很多ITPro都非常需要的功能(尽管以国内的项目实施经验来看,最终用户能用到回收站的可能性很少,绝大部分时候都是开发者在用,汗……)。不过07的时候,回收站仅能针对网站中的文档库、列表、文件夹、文件和列表条目,如果网站被删掉了,甚至网站集被删掉了,就没有办法了(除非恢复数据库备份,或者借助一些第三方的备份/还原产品)。

到了2010 SP1的时候,产品组终于把网站/网站集的回收站功能加入了进来。

先来看网站(SPWeb)的回收站

当我们删除一个网站的时候,页面中会提示这个网站删除后将被发送到网站集回收站中,如下图所示:

image

删除之后,进入网站集回收站,在“已从最终用户回收站删除”这个部分,可以看到被删除的网站,并可以进行还原(说实话,我个人觉得放在这个位置有点奇怪,这里是放置那些被从网站回收站里删掉的东西的地方,也就是说是一个二级回收站),如下图:

image

接下来看看网站集(SPSite)的回收站

删除网站集可以使用删除顶级网站的方式,或者在管理中心里面直接删除网站集。不论采用任何一种方式都是同样的效果,而且在删除网站集的时候,页面上似乎并没有什么提示信息说这个删除是可以被还原的。

实际上,还原一个被删除的网站集是没有UI的,只能通过PowerShell来完成。

首先,可以使用Get-SPDeletedSite得到被删除的网站集:

image

然后,可以用Restore-SPDeletedSite的方式回复网站,利用PowerShell管道的方式传递:

image

 

参考博客:SharePoint 2010 SP1 – Site Recycle Bin

 

Posted by on 2011 年 09 月 13 日 in SharePoint

Leave a comment

Tags:

SharePoint上无法显示Lync的在线状态

今天伙同公司某Exchange MVP给某POC环境部署Lync,前面都比较顺利,结果到最后打开SharePoint发现无法查看用户的在线状态。

Google搜了个遍,连init.js的相关方法都打开看了一遍、ActiveX的文档也都看了一遍都木有找到原因。最后一个偶然的灵机一动,才发现居然忘了在AD里配置用户的邮箱(POC环境里不需要邮件演示)……

于是干脆把上网搜的内容总结一下,以后再出现此类问题的时候可以按照这个内容来进行排查。(其实SharePoint + Lync基本上不需要做任何配置就可以实现在线状态的查看的……)

0、Lync客户端一切正常(这个是前提条件,排除掉Lync服务器端配置的问题)

1、客户端是否安装了Lync客户端,是否正在运行(这个是废话,嗯)

2、客户端是否安装了Office(2010或者2007 + SP2或者2003 + SP2),因为在线状态的查看是依赖一个ActiveX控件(NameCtrl,文件是name.dll)来实现的,这个ActiveX控件是随着Office一起安装的。如果是Office 2007或者2003的话,需要安装到最新的一个SP。

3、是否使用的是IE7以上的浏览器(我看js代码,似乎对非IE也有一定程度的支持,不过我没试),是否启用了ActiveX(理由同上一条)

4、站点是否设置为Intranet或者受信任站点,这是那个ActiveX控件的要求(在NameCtrl的MSDN文档中写的)。不过Office365网站要家到信任站点的话,好像会出问题?这个有时间再试试……

5、是否在Web应用程序常规设置中开启了显示用户在线状态,默认是开启的(在管理中心 – 应用程序shezhi – Web应用程序设置 – 常规设置中)。另外多说一句,有很多网站,尤其是用SharePoint做的外网,我们在访问的时候经常会弹出那个NameCtrl的ActiveX提示询问我们是否启用,这个时候就可以通过这个设置,很简单的去掉这个提示信息。

6、用户在AD中是否配置了电子邮件?这又分成两个部分:

6.1、在个人网站里能否显示在线状态?如果不能的话,那应该是用户配置文件中的电子邮件没有配置(用户配置文件中也有一个SIP地址,我不能肯定是哪个起的作用)

6.2、在列表视图(或列表表单等地方)中,能否显示在线状态?如果不能的话,是因为网站的用户信息列表中没有配置电子邮件地址,即SPUser的Email属性(用户信息列表里面也有一个SIP地址,但是起作用的应该是电子邮件这个属性)。注意这个的数据来源和个人网站里面是不一样的,而且页面调用的代码也不太一样……

当然,如果用户配置文件和User Profile Service配置正常的话,是可以把用户属性从AD导入到用户配置文件,然后再进一步导入到网站的用户信息列表中的……如果不能的话,写个程序设置一下就好了……

 

Posted by on 2011 年 08 月 15 日 in SharePoint

Leave a comment

Tags: