ipark's blog[MVP MOSS]

Office System ( MOSS...)
随笔 - 23, 评论 - 122, 引用 - 3

导航

关于

My Old Blog: http://freepark.cnblogs.com Email:ipark.cn@gmail.com


Locations of visitors to this page

Creative Commons License

标签

每月存档

最新留言

广告

【第1页/共2页,23条】
首页
前页
1
2009年06月10日

使用Excel Servcie连接数据库等数据源,并发布Excel文件后,可以在浏览器中打开Excel文件,并可以看到外部数据,但是点击“Refresh All Connections”(刷新所有连接)的时候,会遇到以下问题:

Data Refresh Failed

Unable to retrieve external data for the following connections:

Connection_Name

The data sources may be unreachable, may not be responding, or may have denied you access.

Verify that data refresh is enabled for the trusted file location and that the workbook data authentication is correctly set.

遇到这个问题的时候,你可以尝试在服务器上依次运行下面三个命令:

1. stsadm -o set-ecssecurity -accessmodel delegation -ssp sspname
2. stsadm -o execadmsvcjobs
3. iisreset

不出意外的话,应该刷新就没有问题了。

posted on 2009-06-10 18:25:34 by ipark  评论(1) 阅读(1968)

 
2009年01月16日

QuickPart

QuickPart大家都知道是我们大名鼎鼎的Kaneboy同学的大作,是用户控件包装器的杰出代表,是进行可视化Web部件开发的重要工具。

使用QuickPart的一般过程是:

1)先创建一个Web工程,新建用户控件,然后编译发布网站,得到我们需要的ASCX和dll文件;

2)部署QuickPart,并在网站上激活QuickPart Feature;

3)把Web应用程序的Trust Level该成可以使用Web部件;

4)把ASCX拷贝到Web应用程序的wpresources文件夹下,把dll拷贝到相应的bin目录下;

5)在网站上添加QuickPart,编辑属性,选择相应的ASCX文件;

6)现在,你可以使用包装好的用户控件了。

我想QuickPart再方便点

如果,我们想自动把开发的用户控件和dll部署好,然后能直接在网站上拖入一个包装了用户空控件的QuickPart就能使用了,添加Web部件的时候,丝毫感觉不出来是使用了QuickPart,那我们该怎么办呢?

我们首先需要了解一下Web Part的dll和.webpart文件的关系:

image

同样的一个QuickPart.dll,使用不同的.webpart描述文件可以把其描述成不同的Web Part。在.webpart文件里面指定WrappedUserControlPath就可以设置默认加载的用户控件了,再在.webpart文件里设置一个有意义的Title,这样同样一个QuickPart.dll在你的Web Part选择页面中就会对应出现多个更有意义的可用Web Part了。

利用.webpart文件我们解决了在网站上添加QuickPart,再选择加载哪个User Control的麻烦。

我们还没有解决怎样自动把ASCX文件和dll拷贝到相应目录下的问题。

Solution里面的Assembly Element有一个子Element叫做ClassResources,用来部署程序集的资源,所以我们可以把ASCX文件作为dll的资源,使得WSP可以帮我们完成这个部署,比如我们要部署IparkDebugPartUC.dll这个用户控件的程序集,它对应的资源会在bin\wpresources\IparkDebugPartUC\路径下(注意路径最后的文件夹就是程序集的名称),所以,我们在WSPBuilder下创建如下的文件夹结构:

image

把dll拷贝到80\bin目录下,ascx文件拷贝到80\bin\wpresources\IparkDebugPartUC\路径下

利用Solution的Assembly以及ClassResource我们解决了自动拷贝部署ASCX和dll的问题。

WSPBuilder生成WSP文件的时候manifest文件里面会自动为程序集添加CodeAccess相关的设置,所以修改Web应用程序的TrustLevel也就不需要了。

---------------------------------解决方案开始了------------------------------

所以我们的解决方案就是:

1)首先根据“[Best Practice]如何在SharePoint团队开发中利用WSPBuilder”中介绍的,创建好一个WSPBuilder项目来做Web Part的打包部署调试;创建好需要的文件夹结构,添加一个WSPBuilder Blank Feature,形成如下类似的样子:

image 

注意,wpresources下面的文件夹必须和你要生成的用户控件所在的dll的名称一致。

2)创建一个Web Application项目,在项目里面创建一个.webpart文件,注意type这个metadata用来表示对应的dll是哪个,这里当然就是我们的QuickPart里面的包装器类型了。

<?xml version="1.0" encoding="utf-8"?>
<webParts>
  <webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
    <metaData>
      <!--
      The following Guid is used as a reference to the web part class,
      and it will be automatically replaced with actual type name at deployment time.
      -->
      <type name="Microsoft.PRC.SharePoint.ConsumerQuickPart, QuickPart, Version=1.0.0.0, Culture=neutral, PublicKeyToken=2d0bb71b2dd16f9e" />
      <importErrorMessage>Cannot import Web Part.</importErrorMessage>
    </metaData>
    <data>
      <properties>
        <property name="Title" type="string">Ipark Debug Demo Web Part</property>
        <property name="Description" type="string">Ipark Debug Demo Description</property>
        <property name="WrappedUserControlPath" type="string">~\wpresources\IparkDebugPartUC\IparkDebugPartUC.ascx</property>
      </properties>
    </data>
  </webPart>
</webParts>

这样,这个Web Application项目就形如:

image

把IparkDebugPartUC.ascx和IparkDebugPart.webpart文件设置为Copy Always:

image

在项目属性的Build Events中添加Post-build命令:

copy "$(TargetDir)IparkDebugPartUC.dll" "$(SolutionDir)IparkSolution\80\bin\";
copy "$(TargetDir)IparkDebugPartUC.ascx" "$(SolutionDir)IparkSolution\80\wpresources\IparkDebugPartUC\";
copy "$(TargetDir)IparkDebugPart.webpart"  "$(SolutionDir)IparkSolution\12\Template\Features\IparkDebugPartFeature\";

3)修改WSPBuilder项目中IparkDebugPartFeature的elements.xml,在Elements节中添加

<Module Name="WebParts" List="113" Url="_catalogs/wp">
  <File Path="IparkDebugPart.webpart" Url="IparkDebugPart.webpart" Type="GhostableInLibrary" />
</Module>

4)好了,你的解决方案样子就变成了:

image

首先build一下IparkDebugPartUC项目,然后在“IparkSolution”上右键菜单中,点击“Build WSP”,生成WSP文件,然后在右键菜单中可以看到Deploy和Upgrade都变成可用了,然后你就可以deploy这个解决方案了。转到你的网站集,激活IparkDebugPartFeature,你就可以在网站的Web Part列表中找到这个Web部件了:

image

你可以在你的Web Application项目上右键菜单的WSPBuilder菜单中点击“Attach to IIS Worker Processes”,开始调试你的用户控件了。

image

当你刷新用户控件所在页面,你的Visual Studio就会开始Debug了:

image

---------------------------------解决方案结束了------------------------------

补充:使用这种方法,你不需要提前部署QuickPart,你需要做的只是把QuickPart.dll拷贝到WSPBuilder的80\bin目录下,WSP包会自动部署它的:

image

posted on 2009-01-16 14:15:01 by ipark  评论(2) 阅读(3262)

 
2009年01月15日

本文关注SharePoint开发的Assembly Development(何为Assembly Development,请参见http://msdn.microsoft.com/en-us/library/bb428899.aspx

WSPBuilder

到目前为止,我觉得WSPBuilder是SharePoint社区中最好的辅助开发工具之一(VSeWSS 1.3 CTP版本有一些功能就是“模仿”了WSPBuilder,呵呵)。

WSPBuilder的特点是根据文件夹结构来生成WSP文件,这是我个人觉得WSPBuilder最好的特性,也是最有用的功能。现在,CodePlex上WSPBuilder提供了Visual Studio Addin的安装项目,该Extensions也可以在Visual Studio 2008上使用,该Extensions使得WSPBuilder更好的融合到Visual Studio的开发操作中,安装完“WSPBuilder Extensions 1.03 - Visual Studio Addin (0.9.8.0830)”后,你打开Visual Studio可以有如下WSPBuilder项目:

image

在创建好的WSPBuilder项目后,右键点击项目可以看到以下WSPBuilder菜单:

image

以上菜单中,值得注意的是以下两个:

> Build WSP: 创建WSP文件,仅仅是创建而已,不会帮你部署!有很多时候我们其实只需要WSP文件(使用VSeWSS的人应该很希望VSeWSS也能这样)

> Attach to IIS Worker Processes: 不用在点好几步,然后查找w3wp.exe进程,然后附加了,只要点一下即可开始调试!

SharePoint的团队开发

在SharePoint团队开发,我感觉比较焦点的话题有几点:

0)团队开发怎么个模式比较好;

这个请先看看http://msdn.microsoft.com/en-us/library/bb428899.aspx

然后,我补充一点我个人的看法:

> 你会需要一个集中代码管理服务器,SharePoint开发集成环境,SharePoint测试服务环境,然后你会想要自动编译部署(WSPBuilder为你的这个愿望提供了很好的基础)

> 我偏向于程序员每个人都有自己的SharePoint开发环境(与生产环境相同的版本),环境中的Visual Studio有Web Application开发模板,安装WSPBuilder 的Visual Studio Extensions。

> 如果有条件开发人员的SharePoint环境使用虚拟机为好(如果SharePoint环境坏了,恢复快,好处肯定不止这个)。

> 另外,开发人员应该有一个非Windows Server的环境(用来自己做测试用,模拟一个真正的开发机和客户机环境,所有的开发测试都在SharePoint环境里面做是不明智的,很多时候你会发现当用客户机访问的时候,问题才能暴露)。也就是说,或者开发人员本机是非Windows Server环境,虚机是SharePoint开发环境;或者是本机是SharePoint环境,有一个非Windows Server的虚机环境。

1)开发的各种SharePoint部件(事件处理、Web Part、模板等)怎么方便的组合起来集成部署(知道用WSP,但是总是没有找到比较好的实施的方法);

做Solution Package的最主要的问题在于

a、如何正确的使用Solution Schema里的Element来部署不同的开发产出;

b、编写正确的manifest.xml文件,打包成WSP文件

WSPBuilder的好处就在于,你需要做的就是把开发出来的东西放对文件夹!其他一切交给WSPBuilder

使用WSPBuilder自己的模板创建出来的项目,WSPBuilder会自动生成正相应的文件夹结构

image

所以,我的做法是使用WSPBuilder项目加上Visual Studio的Post-Event来满足要求:

1、专门创建一个WSPBuilder Project,作为维护创建WSP文件的文件夹结构的项目(也就是说专门用来生成WSP文件的项目);

2、为不同的功能模块(某个Web Part、事件处理程序等)创建不同的项目,这样方便进行代码管理,工作分配,多人协作,创建的项目加入到第一步创建的解决方案中;

3、然后接着就是在WSPBuilder Project项目中,创建文件夹,直到每个功能模块对应的项目都能在该项目中找到相应的文件夹;对于每个功能模块对应的项目则在Post-Built中加入命令行脚本,使在编译通过以后,把编译的结果拷贝到第一步创建的项目的文件夹目录下。

---------------------------------例子开始了----------------------------

举个例子,你创建一个WSPBuilder的项目作为维护生成WSP文件的项目:

image

创建一个Web Part项目(用的是VSeWSS的Web Part模板),加入到解决方案中

image

在WSPBuilder项目中,添加一个叫DemoWebPartFeature的Blank Feature:

image

image

解决方案变成:

image

我会把自动生成的elements.xml文件删除,然后修改feature.xml文件:

把ElementManifests节改成以下样子:

<ElementManifests>
  <ElementManifest Location="WebPart1.xml"/>
  <ElementFile Location="WebPart1.webpart"/>
</ElementManifests>

然后在WSPBuilder项目中创建出80\bin目录,这时候解决方案样子如下:

image 

然后,对DemoWebPart项目做一些设置,首先把WebPart1.webpart和WebPart1.xml文件的属性改成“Copy Always”,这样在该项目的Debug目录中会出现这两个文件:

image

接下来,就是在Post-built中添加Copy命令行,把生成的文件拷贝到WSPBuilder项目对应的文件夹下:

copy "$(TargetDir)DemoWebPart.dll" "$(SolutionDir)WSPBuilder\80\bin\";
copy "$(TargetDir)WebPart1\WebPart1.xml" "$(SolutionDir)WSPBuilder\12\Template\Features\DemoWebPartFeature";
copy "$(TargetDir)WebPart1\WebPart1.webpart"  "$(SolutionDir)WSPBuilder\12\Template\Features\DemoWebPartFeature";

这样,整个项目的初始创建和设置就完成了,把项目迁入到代码管理服务器中,以后就不需要再改动这些设置了。

当你编译DemoWebPart项目的时候,WSPBuilder项目的文件夹下就会是如下样子:

image

在WSPBuilder项目的文件夹里面就已经有了所有DemoWebPart相关的文件了,然后我们可以在WSPBuilder项目中创建WSP文件(Deploy和Upgrade菜单在第一次点击Build WSP后才会变成可用)

image

所有在WSPBuilder解决方案中的项目右键点击都会出现以上菜单,可以方便的点击“Attach to IIS Worker Processes”来调试。

---------------------------------例子结束了----------------------------

这样的话

> 开发人员的工作过程就是:从代码管理服务器上获取解决方案的最新版本,然后迁出自己开发的项目,直接选择Deploy Solution,WSP会生成并自动部署到他的环境中,然后在代码中设置断点,点击“Attach to IIS Worker Processes”即可进行调试。

> 集成人员的工作过程:从代码管理服务器上获取最新的项目版本,然后Build WSP,把WSP部署到开发集成服务器上。这个过程,大家可以想象,使用自动build部署的方案完全是可以完成的。

2)可视化Web Part开发的最佳实践;(下一篇文章,我会介绍一个WSPBuilder和QuickPart合作进行Web Part开发的好方法)

posted on 2009-01-15 23:55:07 by ipark  评论(6) 阅读(3289)

 
2008年12月03日

对于需要安装,维护SharePoint环境的人员来说,及时了解最新的更新和补丁,并正确的进行更新和补丁的安装是很重要的,本页主要汇总相关的信息,方便参考:

<update date=”2009-6-29”>

    <Info>微软已经发布对安装SP2后,可能导致软件变成试用版的Hotfix</Info>

</update>

<update date=”2009-5-27”>

    <Info>安装SP2后,可能导致软件变成试用版,参考“Attention: Important Information on Service Pack 2”</Info>

</update>

一、到目前位置都有哪些更新和补丁,安装的顺序是什么?

到目前位置,有以下更新和补丁,推荐的安装顺序按下列项目的编号,从小到大安装,如果你安装的是带SP1的产品,请从3开始安装

编号 标题 下载 说明 修复的问题 更新后的产品版本 适用的产品
1 Windows SharePoint Services 3.0 SP2 下载 说明 - 12.0.0.6421 WSS 3.0、MOSS
2 Microsoft Office SharePoint Server 2007 SP2 下载 说明 - 12.0.0.6421 MOSS
3 SP2 Update for expiration date issue fixing x86 x64 说明 - 12.0.0.6421 MOSS
1 Windows SharePoint Services 3.0 SP1 下载 说明 修复的问题 12.0.0.6219 WSS 3.0、MOSS
2 Microsoft Office SharePoint Server 2007 SP1 下载 说明 修复的问题 12.0.0.6219 MOSS
3 Windows SharePoint Services 3.0 Infrastructure Update x86 x64 说明 修复的问题 12.0.0.6318 WSS 3.0
4 Microsoft Office SharePoint Server 2007 Infrastructure Update x86 x64 说明 修复的问题 12.0.0.6318 WSS 3.0、MOSS
5 Security Update for MOSS(包含Excel Services安全更新) KB953397 x86 x64 说明 修复的问题 12.0.0.6318 MOSS
6 Document Lifecycle Workflow Update
(KB 955586)
下载 MOSS
7 August Cumulative Update for Windows SharePoint Services 3.0 Global Local 说明 修复的问题 12.0.0.6327 WSS 3.0、MOSS
8 August Cumulative Update for Microsoft Office SharePoint Server 2007 下载 说明 修复的问题 12.0.0.6327 MOSS

二、在生产环境里面,怎么安装更新和补丁最合理安全?

Deploy software updates for Windows SharePoint Services 3.0

http://technet.microsoft.com/en-us/library/cc288269.aspx

Deploy software updates for Office SharePoint Server 2007

http://technet.microsoft.com/en-us/library/cc263467.aspx

三、怎么知道我现在的SharePoint到底是哪个版本,安装了哪些补丁呢?

关于运行的SharePoint的版本:到SharePoint管理中心 > 操作 > 服务器场中的服务器 (Central Administration > Operations > Servers in Farm)可以查看当前的SharePoint产品的版本。

关于已经装的更新与补丁:到控制面板的“添加删除程序”窗口,勾选“显示更新”(Show Updates),可查看安装的更新与补丁,如下:

Untitled

参考:How to find the level of SharePoint you are running

参考文献

本页的信息来自SharePoint Team Blog,Microsoft KB/support,Technet,MSDN以及其他博客。

posted on 2008-12-03 22:25:40 by ipark  评论(0) 阅读(5992)

 
2008年04月03日

在现在的SharePoint中默认我们新建Web应用程序的时候,SharePoint会帮我们新建一个对应的应用程序池。

当我们为某个Web应用程序扩展新的应用程序的时候,SharePoint会让扩展出来的和被扩展的Web应用程序使用同一个Application Pool。在这里,推荐你为扩展出来的Web应用程序也创建一个新的Application Pool,可以使用和父级的Web应用程序的Application Pool一样的配置。这样做的目的只有一个,优化性能。

关于Application

每个Application Pool会对应一个w3wp.exe进程,w3wp.exe这个进程将在你访问www应用程序的时候启动。这个服务器端的进程不会在你关闭了客户端浏览器以后,就马上关闭的.那是因为Http是无连接的访问,当你关闭了web网页,不会返回相应的关闭信息,所以W3WP.EXE这个进程不会因为你关闭了web应用程序而关闭. IIS会负责处理w3wp.exe进程。在应用程序池的配置中,"空闲超时"中设定合适的时间,系统默认的是20分钟.设定好指定的时间,那么在这个时间范围内没有在访问应用程序,那么系统会自动的关闭W3WP.EXE这个进程的。

posted on 2008-04-03 15:43:30 by ipark  评论(0) 阅读(4041)

 
2008年04月01日

SharePoint默认的出错界面,对于最终用户来说有时候真是不友好:

怎么自定制的处理错误呢?

一般的ASP.Net的项目我们可以在global.asax文件中添加Application_Error方法来在全局范围内处理错误。

但是在SharePoint中我们没有办法这么做,所以我们只能通过写自定义的HttpModule来实现自定制的出错处理了。

具体的可以参考这篇Blog:

Catching unhandled exceptions in SharePoint

http://blogs.msdn.com/jannemattila/archive/2008/02/04/catching-unhandled-exceptions-in-sharepoint.aspx

 

posted on 2008-04-01 15:39:47 by ipark  评论(0) 阅读(3914)

 
2008年03月25日

我们知道SharePoint 的Solution Schema里面有很多Element都是涉及到部署某个文件的,比如:

FeatureManifest

TemplateFile

ApplicationResourceFile

Resource

ClassResource

DwpFile

RootFile

Site definitions

但是这些文件到底会被部署到服务器的什么位置呢,在SDK中没有详细的说明,查了一下,具体应该是:

Features <FeatureManifest>:

C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\FEATURES\

Template Files <TemplateFile>:

C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\

Application Resources <ApplicationResourceFile>:

C:\Inetpub\wwwroot\wss\VirtualDirectories\{virtual app port}\resources

Global Resources <Resource>:

C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\FEATURES\

Assemble ClassResource<ClassResource>:

C:\Inetpub\wwwroot\wss\VirtualDirectories\{virtual app port}\wpresources\程序集名称\

Web Parts <DwpFile>:

C:\Inetpub\wwwroot\wss\VirtualDirectories\80\wpcatalog

Root Files <RootFile>:

C:\Program Files\Common Files\Microsoft Shared\web server extensions\12

Site definitions:

C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\SiteTemplates

参考自以下文章:

 SharePoint Solution Manifests

Creating Advanced Solutions for SharePoint 2007

posted on 2008-03-25 13:36:01 by ipark  评论(0) 阅读(3406)

 
2008年03月21日
1.Overview

SharePoint中的菜单都是基于ASP.Net 2.0的Menu和TreeView,这些控件生成的Html源码都是用table的结构,使得使用CSS控制菜单的样式不是很方便。

针对这个问题,网上有一个解决办法就是使用CSS Friendly Adapters(http://www.asp.net/cssadapters/ )可以让IIS中所有Web Site的Menu和TreeView菜单控件生成CSS友好的菜单结构,但是这种技术作用于整个IIS的所有网站。如果我在SharePoint中使用意味这整个服务器上的所有网站都会受到影响。

所以,为了灵活,我单独写了一个纯粹生成CSS友好的菜单结构的Web Control——CSSFriendlyMenu。使用方法和ASP.Net中的Menu控件一样,都是与一个SiteMapDataSource联合使用,大家可以到  这里  去下载Ipark.Web.WebControls.CSSFriendlyMenu试用。

Ipark.Web.WebControls.CSSFriendlyMenu是一个产生CSS友好的菜单的服务器端控件,较CSS Friendly Adapters灵活。
需与SiteMapDataSource控件联合使用。

CSSFriendlyMenu在SharePoint下的一个例子如下:

CSSFriendlyMenu

(红色框 就是由CSSFriendlyMenu生成的CSS友好的菜单结构)其结构形如:

MenuStructure

2.Deployment
把dll部署到GAC($system\windows\assembly)中即可,此时在Visual Studio中即可在工具箱中找到。
如果在SharePoint中使用,请在对应的Web Application的Web.config的SafeControls节中添加
<SafeControl Assembly="Ipark.Web.WebControls.CSSFriendlyMenu, Version = 1.0.0.0, Culture = neutral, PublicKeyToken=064925da862cab62" Namespace="Ipark.Web.WebControls" TypeName="*" Safe="True" AllowRemoteDesigner="True"  />
注: AllowRemoteDesigner="True"为了使在SharePoint Designer等设计器中可编辑。安装完成之后重启IIS,如正在用SharePoint Designer编辑页面,请重开SharePoint Designer方能正确使用。

3.Use
在页面顶端添加:
<%@ Register TagPrefix="Ipark" Namespace="Ipark.Web.WebControls" Assembly="Ipark.Web.WebControls.CSSFriendlyMenu, Version = 1.0.0.0, Culture = neutral, PublicKeyToken=064925da862cab62" %>
在页面中:
<Ipark:CSSFriendlyMenu ID="CSSFriendlyMenu" DataSourceID="topSiteMapDS" Direction="Horizontal " MenuLevel="2" runat="server"></Ipark:CSSFriendlyMenu>           
<SharePoint:DelegateControl runat="server" ControlId="TopNavigationDS">
    <Template_Controls>
            <asp:SiteMapDataSource
              ShowStartingNode="False"
              SiteMapProvider="CurrentNavSiteMapProvider"
              id="topSiteMapDS"
              runat="server" />
    </Template_Controls>
</SharePoint:DelegateControl>
注:本例中的SiteMapDataSource以SharePoint平台为例,除了CurrentNavSiteMapProvider外,SharePoint还提供了很多其他的SiteMapProvider,下次找机会介绍一下。

CSSFriendlyMenu包含两个主要属性:

Direction: Horizontal 或者 vertical,这个主要是控制输出的菜单外层的div的class的名称,便于在页面有多个CSSFriendlyMenu的时候,分别控制垂直和水平的Menu的CSS Style
DataSourceID:SiteMapDataSource控件的ID
MenuLevel:需要显示的菜单的层级,默认显示3级菜单

4.CSS Tag
设计CSS来定制菜单的显示样式,CSSFriendlyMenu生成的结构中使用的CSS class如下:

IparkCSSFriendlyMenu: root div
AspNet-Menu-Vertical: Vertical Menu root
AspNet-Menu-Horizontal: Horizontal Menu root
AspNet-Menu: root ul
AspNet-Menu-WithChildren: Submenu with children
AspNet-Menu-WithChildren-Current: Current Submenu with children
AspNet-Menu-Leaf: single Submenu
AspNet-Menu-Leaf-Current: Current single submenu
AspNet-Menu-Link: the link

<update>2008-3-23</update>

posted on 2008-03-21 04:48:09 by ipark  评论(0) 阅读(3758)

 
2008年03月19日

WSS 3.0中我们使用:

SPSecurity.RunWithElevatedPrivileges(delegate()
{
    // implementation details omitted
});

可以提升代码的运行权限,实现模拟管理员身份的功能。

在RunWithElevatedPrivileges中不要使用SPContext.Current.Web,SPContext.Current.Site,SPControl.GetContextWeb(HttpContext.Current)之类的根据当前上下文得到当前的Web或者Site,根据这些方法得到的所有对象(包括从根据这些对象得到的List,ListItem等等对象)都是以当前网站登录用户权限运作的,即使是在RunWithElevatedPrivileges其运作权限也不会是管理员。

所以,如果要真正让在RunWithElevatedPrivileges中的代码以管理员权限正常运作的话,必须重新初始化相应的对象,比如:

SPSecurity.RunWithElevatedPrivileges(delegate()
{
    using (SPSite mySite = new SPSite(SPContext.Current.Site.Url))
    {
        Response.Write(mySite.RootWeb.CurrentUser.LoginName);
    }
});
以上mySite.RootWeb.CurrentUser.LoginName返回的是管理员的登录帐号。
但是如果按之前所说使用SPContext:
SPSecurity.RunWithElevatedPrivileges(delegate()
{
     Response.Write(SPContext.Current.Web.CurrentUser.LoginName);
});

这时候即使在提升权限的范围内运行,得到的也是当前网站登录帐户名,而不是管理员登录帐号。

posted on 2008-03-19 00:21:24 by ipark  评论(1) 阅读(3685)

 
2008年03月09日

下面这个网站是在SharePoint中集成Silverlight的一个网站,包含了很多示例,值得一看!

http://www.ssblueprints.net/sharepoint/

包含下面一些例子:

1)Hello Silverlight Web Parts and the SilverlightPart

2)Silverlight Navigation Controls

3)Silverlight Social Networking Web

4)Visual How-To Center with Silverlight

5)Picture Viewer Sample

6)Silverlight Custom Field Types

posted on 2008-03-09 12:18:01 by ipark  评论(1) 阅读(3171)

 
2008年01月15日

就我的认识,SharePoint Designer的无代码工作流设计器在SharePoint中有两个作用,一个是设计列表的工作流,另一个是给DataForm Web part提供Custom Action(自定义列表操作)的支持(在上一篇文章中我叙述过相关的内容[SharePoint Designer -3]DataForm Web Part中的数据操作)。

不管是哪种使用方法,使用无代码工作流设计器的最终的结果都是:SharePoint会在网站的Workflows文件夹下面创建相应的文件(有XOML文件,工作流配置的XML文件,规则的rules文件,以及很多的asp页面,xoml和xml文件是一定存在的),然后给列表添加一个工作流关联(association)。其中很重要的一个文件是*.wfconfig.xml文件,其形式大致如下:

<WorkflowConfig>
	<Template 
		BaseID="{963BA7F4-2105-4793-85BB-C1D90367D961}" 
		DocLibID="{8a493f4e-22e4-4f34-aefd-55325667ef0f}" 
		XomlHref="Workflows/工作流 1/工作流 1.xoml" 
		XomlVersion="V4.0">
	</Template>
	<Association 
		ListID="{32a8da29-ac60-4e06-86b8-70d4780e563a}" 
		TaskListID="{6822A246-52D5-4BA8-BCBE-826D17620BE7}" 
		StartOnChange="true">
	</Association>
	<ContentTypes>
	</ContentTypes>
	<Initiation URL="Workflows/工作流 1/工作流 1.aspx">
		<Fields />
		<Parameters></Parameters>
	</Initiation>
</WorkflowConfig>

其中DocLibID是Workflows文档库的GUID,ListID是这个工作流绑定到的列表的GUID。

我们可以通过备份还原网站来迁移部署SharePoint Designer设计的工作流。

但是,当我们备份还原网站后,SharePoint Designer设计的工作流在新的网站中不能工作!

问题出在两个地方:

1)新的网站中工作流对应的*.wfconfig.xml中的DocLibID和ListID不能更新到新网站的对应列表的GUID;

2)列表与相应工作流的关联(Association)丢失了。

根据对问题的分析,我们可以找到方法来重建并绑定工作流。

1)首先更新*.wfconfig.xml文件的DocLibID和ListID

2)重新绑定工作流

SharePoint Designer设计的工作流绑定需要利用WebPartPagesWebService的ValidateWorkflowMarkupAndCreateSupportObjectsAssociateWorkflowMarkup方法。

基于以上的分析,我的解决方案是:

1)在Workflows的文件夹下面维护一个Lists.xml文件,形式如下:

<?xml version="1.0" encoding="utf-8" ?>
<Lists>
	<List Name="test" ID="{23d0e43d-b6bf-4670-b69f-871a63f77941}"></List>
	<List Name="custom workflow process" ID="{76ed547a-aa40-4aab-86e2-5e525ea49e1d}"></List>
</Lists>

为什么维护这样一个列表呢?因为网站备份在还原后,列表的名字不会变,但是GUID会变!所以,维护一个存储所有绑定了SharePoint Designer无代码工作流的列表的ID和Name对应关系的XML文件,方便之后更新*.wfconfig.xml文件用。

2)在网站还原以后,通过一下的ReAttachWorkflows方法来更新*.wfconfig.xml文件,并绑定工作流到相应的列表,代码如下:

public static void ReAttachWorkflows(SPWeb objWeb)
{
    string strXOML = string.Empty;
    string strConfig = string.Empty;
    string strRules = string.Empty;
    string strConfigPath = string.Empty;
    string strVersion = string.Empty;
    string strLists = string.Empty;

    SPList objWorkflowList = null;

    try
    {objWorkflowList = objWeb.Lists["Workflows"];}
    catch
    {objWorkflowList = objWeb.Lists["工作流"];}
    System.IO.StreamReader objReader;
    SPFile Filelists = objWorkflowList.RootFolder.Files["Lists.xml"];
    objReader = new System.IO.StreamReader(Filelists.OpenBinaryStream());
    strLists = objReader.ReadToEnd();
    objReader.Dispose();

    System.Xml.XmlDocument xmlLists = new System.Xml.XmlDocument();
    xmlLists.LoadXml(strLists);

    foreach (SPListItem objItem in objWorkflowList.Folders)
    {
	SPFolder objFolder = objItem.Folder;
	foreach (SPFile objFile in objFolder.Files)
	{
	    objFile.CheckOut(false, string.Empty);
	    objReader = new System.IO.StreamReader(objFile.OpenBinaryStream());
	    if (objFile.Name.EndsWith("xoml"))
	    {
		strXOML = objReader.ReadToEnd();
		objReader.Dispose();
	    }
	    if (objFile.Name.EndsWith("rules"))
	    {
		strRules = objReader.ReadToEnd();
		objReader.Dispose();
	    }
	    if (objFile.Name.EndsWith("xml"))
	    {
		strConfig = objReader.ReadToEnd();
		objReader.Dispose();
		strConfigPath = objFile.ServerRelativeUrl.Substring(objFile.ServerRelativeUrl.IndexOf(objWeb.Name) + objWeb.Name.Length + 1);
		System.Xml.XmlDocument xmlConfig = new System.Xml.XmlDocument();
		xmlConfig.LoadXml(strConfig);
		//update GUID of the 'Workflows' document library
		xmlConfig.SelectSingleNode("/WorkflowConfig/Template/@DocLibID").Value = "{" + objWorkflowList.ID.ToString() + "}";
		System.Xml.XmlNode xmlNodeList = xmlConfig.SelectSingleNode("/WorkflowConfig/Association/@ListID");
		System.Xml.XmlNode xmlNodeListOrigin = xmlLists.SelectSingleNode("/Lists/List[@ID='"+xmlNodeList.Value.ToLower()+"']");
		//update GUID of the list to be associated 
		xmlNodeList.Value = "{" + objWeb.Lists[xmlNodeListOrigin.Attributes["Name"].Value].ID.ToString() + "}";
		strConfig = xmlConfig.OuterXml;
		objFile.SaveBinary(System.Text.Encoding.UTF8.GetBytes(strConfig));
	    }
	    objFile.Update();
	    objFile.CheckIn(string.Empty);
	}

	Microsoft.SharePoint.SoapServer.WebPartPagesWebService objWebPartPages = new Microsoft.SharePoint.SoapServer.WebPartPagesWebService(objWeb);
	string strResult;
	strResult = objWebPartPages.ValidateWorkflowMarkupAndCreateSupportObjects(strXOML, strRules, strConfig, "2");

	//associate with list
	string param1 = strConfigPath;
	string param2 = strVersion;
	strResult = objWebPartPages.AssociateWorkflowMarkup(param1, param2);
    }

    xmlLists = null;

}

 

一些想法

1)了解了SharePoint Designer工作流的工作原理了,我们似乎是可以在一定程度上重用一下用SPD设计出来的工作流呢?

思路可以是这样:两个列表必须具有相同的字段(至少是与工作流相关的字段要一样,然后把Workflows文件夹下面的对应的工作流的文件夹复制一个,修改*.wfconfig.xml文件(更新路径,把绑定的列表的GUID更新,然后用ReAttachWorkflows把工作流绑定好。

从原理上来说这样做是行得通的,当然我并没有试过:)

posted on 2008-01-15 22:48:00 by ipark  评论(3) 阅读(6324)

 
2008年01月13日

上次我们介绍了一些DataForm的基本的概念[SharePoint Designer-2]DataForm Web Part解析。在你的SharePoint项目中,不管项目大还是小,有时候可以考虑用DataForm来代替编写Web Part来创建一些页面,特别是显示所有列表以及列表显示的页面。从开发时间上看,使用DataForm不比你单独写一个数据显示交互的Web Part来的时间长,维护与部署甚至会比Web Part来得简单。DataForm利用XSLT进行数据转换展现还是比较灵活的,也易于改变样式,同时DataForm也可以进行各种的数据交互。下面我介绍一下使用DataForm我们可以做哪些数据的交互操作,希望可以给大家一些启发。

1、客户端中对DataForm中数据的操作

说到这个一般是指对列表新建和编辑的DataForm中数据的操作,我们知道在编辑和新建DataForm中,只有形如:

<SharePoint:FormField runat="server" id="ff2{$Pos}" ControlMode="New" FieldName="Title" __designer:bind="{ddwrt:DataBind('i',concat('ff2',$Pos),'Value','ValueChanged','ID',ddwrt:EscapeDelims(string(@ID)),'@Title')}"/>

的FormField类型的SharePoint的WebControl才被最终的数据提交操作识别,并提交,而且,如果在页面上同一个字段有多个FormField Control的话,最终提交的数据是页面自上到下最后一个FormField的值。

所以,我们一般就是利用Javascript来操作FormField在客户端生成的HTML标签,这些标签是有一些规律的,SharePoint Designer的Team Blog里面有一篇文章详细介绍了如何利用Javascript来操作这些字段控件:Using Javascript to Manipulate a List Form Field

如果我们可以操作这些字段控件,对这些字段控件生成的HTML标签值进行赋值修改的话,我们可以隐藏原本生成的控件标签,使用自己的编辑控件,然后,在提交前,把用户编辑的值赋给隐藏的DataForm提交时能识别的字段控件标签,就可以实现比较深入的编辑新建页面的定制了。

其实,在这种状况下,我们相当于只把DataForm作为提交数据的一个载体了。

 

2、提交数据到服务器端

DataForm中与服务器端的数据交互基本是由“http://schemas.microsoft.com/WebParts/v2/DataView/runtime”这个名称空间下(一般在DataForm的XSLT中以ddwrt出现)ddwrt:GenFireServerEvent(string EventString)方法来实现。其实原理很简单ddwrt:GenFireServerEvent这个方法解析出来以后是__dopostback()方法,会触发Postback,把EventString作为Postback的参数,然后DataForm会根据EventString处理相应的数据提交操作。

比如,如果你在DataForm使用了一个<a href="javascript: {ddwrt:GenFireServerEvent('__commit;__refresh;')}">Submit</a>来向服务器端做一个提交操作,在客户端显示的时候这个串就被解析成了<a href="javascript: __doPostBack('ctl00$m$g_18a01f88_4df1_41ef_abef_151d51648f2c','__commit');">Submit</a>,前部分ctl00$m$g_18a01f88_4df1_41ef_abef_151d51648f2c是DataForm Web Part的ID,后面的就是事件的参数,__doPostBack的方法在每个页面你都可以通过查看源文件看到这个方法,它干的事情就是提交页面。

GenFireServerEvent可以通过__dopostback向服务器提交任何参数,DataForm可以识别的一些特定的参数包括:

1)__commit;    所有的数据提交都要包括这个参数。DataForm会根据当前的模式进行提交操作,如果当前是Listform模式,就会把数据提交到列表中去。如果是Table模式,就确认对DataForm的其他操作。说白了,所有的新建,修改,删除都需要加上这个参数才能生效。

2)__refresh;    刷新页面

3)__cancel;    取消这个参数之前的所有操作,即在这个参数之前的所有参数都不起作用

4)__redirectsource;    把页面转向到URL中的Source参数对应的地址,如果URL中没有Source参数则返回列表的默认视图

5)__redirect={URL};    把页面转向到一个制定的URL,这个URL中可以是通过XSLT动态赋值,一个列表编辑DataForm页面提交的例子:<a href="javascript: {ddwrt:GenFireServerEvent(concat('__commit;__refresh;__redirect={DispForm.aspx?ID=',@ID))}">Submit</a> 意思就是编辑提交完成以后跳转到项目显示页面。

6)__delete={ID=3};    删除某个列表项,参数是ID,一般我们可以在显示所有列表的页面给每个项目加一个删除超链接,这个ID的参数就需要在XSLT里面动态附加,形如

<a href="javascript: {ddwrt:GenFireServerEvent(concat('__delete={ID=',@ID,'};__delete={ID=4};__delete={ID=5};__delete={ID=6};__commit;__refresh;'))}">delete</a>

其中concat是用来拼接文本的xslt函数,把@ID与其他的参数拼接。

__delete这个参数在一个GenFireServerEvent中可以存在多个比如:

<a href="javascript: {ddwrt:GenFireServerEvent('__delete={ID=3};__delete={ID=4};__delete={ID=5};__delete={ID=6};__commit;__refresh;')}">delete</a>这个删除链接就是同时删除ID为3,4,5,6的四个列表项。可以看到用了__commit;参数来真正让DataForm去执行删除的动作。

7)__workflowStart={{06D5963E-BE1C-4EC8-9021-3DB29C1E55F0},New,{FCE8E874-EE7D-4475-8F2D-F64CAEB07CE0},Parameters}    这个参数比较特殊,一般用户不会直接去手写这个参数,它是使用“自定义操作”(Custom Actions)后自动生成的。DataForm中的这个自定义操作是巧妙的利用了工作流来满足对数据可能的复杂操作的需求,比如删除项目后,给管理员发邮件提醒等,都可以利用自定义操作来实现。

自定义操作(Custom Actions)的原理也不复杂:每个网站都会有一个叫Custom workflow process的列表,所有自定义操作和其他SharePoint列表的工作流一样都会在Workflows文档库下面创建出来,不同的是所有自定义操作会绑定到Custom workflow process列表上,并允许用户手动启动。__workflowStart中的第一个参数就是网站上Custom workflow process列表的GUID,New是新建一个工作流实例,第三个参数是自定义操作对应的工作流模板的GUID,最后的就是自定义操作里面设置的工作流参数了。

GenFireServerEvent还可以用来Postback任意参数,DataForm中包含一种类型的参数形如:

<ParameterBinding Name="dvt_groupdir" Location="Postback;Connection"/>

这种参数就是从Postback回来的值中取得,做分页的时候需要使用到利用GenFireServerEvent来传值。

 

3、一些补充

1)既然GenFireServerEvent方法其实就是解析成了__dopostback方法,把DataForm的ID和参数给了__dopostback方法。所以如果我们需要,我们可以修改DataForm的ID,不要使用默认生成的GUID,如果你用了自定制的ID以后,使用备份恢复部署后DataForm的ID就不会变了,这样的话我们直接在javascript里面写__dopostback方法了,因为DataForm的ID我们可以确定的知道了。

这个东西有什么用呢?目前我碰到的唯一一个需要用到这个变态方法的地方是,当需要实现可以让用户选择列表中的某几个列表项进行删除的时候,就必须用到这个方法了。

 

2)使用了自定义操作以后,我们通过备份网站,恢复网站进行定制的部署后,我们会发现自定义操作都不能用了,点击带有自定义操作的按钮就报错!这个的解决办法我会在下一篇文章中给出解决方法。

3)我们是用Custom List Form以后,“Attach File”这个功能就失效了!如何即可以定制编辑页面,有可以正常使用附件上传功能呢?我会在后来第5篇文章中谈到;

 

(本文中所有的方法都是定制技术,是不使用任何后端代码下对SharePoint列表数据进行定制操作的方法。

所以,可能有些你感觉用代码开发的时候都不是问题的问题在这里却被当成问题拿出来讨论了。

但是,当你遇到一个完全的定制项目或者你想了解SPD的能力的时候,你会发现这是有价值的)

posted on 2008-01-13 23:23:00 by ipark  评论(6) 阅读(6939)

 
2007年12月09日

相信,大家都知道WSS 3.0中的DataForm Web Part。在使用SharePoint Designer定制SharePoint的时候很多的时候我们需要用到DataForm Web Part,前一篇文章我介绍了DataForm做模糊列表查询的简单的例子。这篇文章将向大家详细解析一些DataForm Web Part,供大家做有关DataForm应用的时候做参考,希望能启发大家的思路,灵活应用DataForm来满足NoCoding下的应用需求。

在SharePoint Designer中插入DataForm以后,你会发现它的代码部分由四大部分组成:

1)DataSources:数据源,可以是单数据源,多数据源链接,SharePoint也提供了各种数据源控件(XML,web服务,数据库,等等)。进行SharePoint中单数据列表操作的时候,用的是SPDataSource控件,本篇文章会主要介绍这个控件,另外将简要说明一下多数据源链接,及其应用场景。

2)ParameterBindings:Web Part的所有参数就包含在这里面

3)DataFields:可在Web Part上显示的所有数据域

4)XSL:XSLT,把数据源的数据转换成你想要的显示样式

DataForm的工作过程一般是这样的:

1)DataForm Web Part会首先处理参数Parameter,数据源中可能含有参数,以筛选数据,XSLT里面也可能有一些参数需要赋值,Web部件会把ParameteBindings块中的所有参数赋值给数据源和XSLT里面ParameterKey相同的参数;

2)然后,DataForm Web Part把数据源对应的数据取出来返回的XML格式数据;

<update>我们在SharePoint Designer里面看见的筛选窗口一般就是用来筛选数据源的,它会修改SPDatasource的Selectcommand属性</update>

3)最后,利用XSLT把数据源转换并返回给客户端。

<update>

我们在SharePoint Designer里面看见的筛选窗口的高级XPath筛选则是XSLT层次的筛选。

也就是说数据源筛选先进行,然后XSLT在逐条数据进行筛选,XSLT的筛选在数据量大的时候可能会影响性能。所以,没有特别的需求最好筛选数据源,不用XPath。

</update>

------

下面介绍一些DataSources,ParameterBindings和XSL相关的一些信息以及有用的链接:

1)DataSources

SPDataSource这个web控件有多种数据源模式:ListItem(单个列表项), List(某个列表), CrossList(跨列表), ListofLists(列表集合,显示列表的信息), Webs(网站的信息)

关于SPDataSource控件的信息,SharePoint Designer Team有一篇很好的Blog:SPDataSource and Rollups with the Data View

如果在ListItem和List模式下,DataForm Web Part中的SPDataSource必须要包含DataFormParameter,DataFormParameter是一个独立的参数类,DataForm Web Part用这个参数来定位数据源列表,同时DataFormParameter也只识别特定的ParameterKey:ListID,ListItemId,ListName,WebUrl等。

如果是ListItem模式下,必须要有(ListID or ListName) and ListItemId参数。

如果是List模式下,必须要有ListID 或者ListName参数。

技巧:如果你要迁移部署定制好的页面的话,你一定要使用ListName参数来定位列表。原因很简单,列表名称在迁移后不会变,但是ListID是会变化的。

在CrossList,ListofLists和Webs模式下的时候,SPDataSource的SelectCommand的写法和SPSiteDataQuery的查询规则相似。比如用<Lists></Lists>可以选择所有的当前网站的列表,以下是一个列出所有当前网站列表的例子:

<WebPartPages:DataFormWebPart runat="server" AllowConnect="True" PartImageSmall="" MissingAssembly="Can't exported" IsIncludedFilter="" ExportMode="All" ID="g_eea4c5ed_0ae5_498b_9840_32b8409212b8" AllowRemove="True" FrameState="Normal" ConnectionID="00000000-0000-0000-0000-000000000000" DetailLink="" ExportControlledProperties="True" IsIncluded="True" IsVisible="True" AllowEdit="True" Dir="Default" SuppressWebPartChrome="False" ViewContentTypeId="" PageSize="-1" FrameType="Default" DataSourceID="" UseSQLDataSourcePaging="True" AllowHide="True" AllowMinimize="True" ShowWithSampleData="False" HelpMode="Modeless" ViewFlag="0" Title="test1" HelpLink="" Description="" PartOrder="2" AllowZoneChange="True" PartImageLarge="" NoDefaultStyle="TRUE" __MarkupType="vsattributemarkup" __WebPartId="{EEA4C5ED-0AE5-498B-9840-32B8409212B8}" __AllowXSLTEditing="true" WebPart="true" Height="" Width="">
<DataSources> <SharePoint:SPDataSource runat="server" SelectCommand="&lt;Lists&gt;&lt;/Lists&gt;" DataSourceMode="ListOfLists" UseInternalName="True" ID="dataformwebpart1"></SharePoint:SPDataSource> </DataSources> <ParameterBindings> 	<ParameterBinding Name="dvt_apos" Location="Postback;Connection"/> 	<ParameterBinding Name="UserID" Location="CAMLVariable" DefaultValue="CurrentUserName"/> 	<ParameterBinding Name="Today" Location="CAMLVariable" DefaultValue="CurrentDate"/> 	<ParameterBinding Name="ListName" Location="QueryString(ListName)" DefaultValue="test1"/> </ParameterBindings> <DataFields>@__spAlertTemplate,__spAlertTemplate;@__spAllowContentTypes,__spAllowContentTypes;@__spAllowDeletion,__spAllowDeletion;@__spAllowMultiResponses,__spAllowMultiResponses;@__spAnonymousPermMask,__spAnonymousPermMask;@__spAnonymousPermMask64,__spAnonymousPermMask64;@__spAudit,__spAudit;@__spAuthor,__spAuthor;@__spBaseTemplate,__spBaseTemplate;@__spBaseType,__spBaseType;@__spCanReceiveEmail,__spCanReceiveEmail;@__spContentTypes,__spContentTypes;@__spContentTypesEnabled,__spContentTypesEnabled;@__spCreated,__spCreated;@__spCurrentChangeToken,__spCurrentChangeToken;@__spDefaultView,__spDefaultView;@__spDefaultViewUrl,__spDefaultViewUrl;@__spDescription,__spDescription;@__spDirection,__spDirection;@__spDraftVersionVisibility,__spDraftVersionVisibility;@__spEffectiveBasePermissions,__spEffectiveBasePermissions;@__spEmailAlias,__spEmailAlias;@__spEnableAssignToEmail,__spEnableAssignToEmail;@__spEnableAttachments,__spEnableAttachments;@__spEnableMinorVersions,__spEnableMinorVersions;@__spEnableModeration,__spEnableModeration;@__spEnableSyndication,__spEnableSyndication;@__spEnableVersioning,__spEnableVersioning;@__spEventReceivers,__spEventReceivers;@__spEventSinkAssembly,__spEventSinkAssembly;@__spEventSinkClass,__spEventSinkClass;@__spEventSinkData,__spEventSinkData;@__spExcludeFromTemplate,__spExcludeFromTemplate;@__spFields,__spFields;@__spFirstUniqueAncestor,__spFirstUniqueAncestor;@__spFlags,__spFlags;@__spForceCheckout,__spForceCheckout;@__spForms,__spForms;@__spHasExternalEmailHandler,__spHasExternalEmailHandler;@__spHasUniqueRoleAssignments,__spHasUniqueRoleAssignments;@__spHidden,__spHidden;@__spID,__spID;@__spImageUrl,__spImageUrl;@__spInternalName,__spInternalName;@__spItemCount,__spItemCount;@__spItems,__spItems;@__spLastItemDeletedDate,__spLastItemDeletedDate;@__spLastItemModifiedDate,__spLastItemModifiedDate;@__spLists,__spLists;@__spMultipleDataList,__spMultipleDataList;@__spOnQuickLaunch,__spOnQuickLaunch;@__spOrdered,__spOrdered;@__spParentWeb,__spParentWeb;@__spParentWebUrl,__spParentWebUrl;@__spPermissions,__spPermissions;@__spProperties,__spProperties;@__spPropertiesXml,__spPropertiesXml;@__spReadSecurity,__spReadSecurity;@__spReusableAcl,__spReusableAcl;@__spRoleAssignments,__spRoleAssignments;@__spRootFolder,__spRootFolder;@__spRootFolderUrl,__spRootFolderUrl;@__spSchemaXml,__spSchemaXml;@__spSendToLocationName,__spSendToLocationName;@__spSendToLocationUrl,__spSendToLocationUrl;@__spShowUser,__spShowUser;@__spTitle,__spTitle;@__spVersion,__spVersion;@__spViews,__spViews;@__spWorkflowAssociations,__spWorkflowAssociations;@__spWriteSecurity,__spWriteSecurity;</DataFields> <Xsl> <xsl:stylesheet xmlns:x="http://www.w3.org/2001/XMLSchema" xmlns:d="http://schemas.microsoft.com/sharepoint/dsp" version="1.0" exclude-result-prefixes="xsl msxsl ddwrt" xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime" xmlns:asp="http://schemas.microsoft.com/ASPNET/20" xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:SharePoint="Microsoft.SharePoint.WebControls" xmlns:ddwrt2="urn:frontpage:internal"> 	<xsl:output method="html" indent="no"/> 	<xsl:decimal-format NaN=""/> 	<xsl:param name="dvt_apos">&apos;</xsl:param> 	<xsl:param name="ListName">test1</xsl:param> 	<xsl:variable name="dvt_1_automode">0</xsl:variable> 	<xsl:template match="/" xmlns:x="http://www.w3.org/2001/XMLSchema" xmlns:d="http://schemas.microsoft.com/sharepoint/dsp" xmlns:asp="http://schemas.microsoft.com/ASPNET/20" xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer" xmlns:SharePoint="Microsoft.SharePoint.WebControls"> 	        <xsl:call-template name="dvt_1"/> 	</xsl:template> 	<xsl:template name="dvt_1"> 		<xsl:variable name="dvt_StyleName">Table</xsl:variable> 		<xsl:variable name="Rows" select="/dsQueryResponse/Rows/Row[@__spTitle=$ListName]"/> 		<xsl:variable name="dvt_RowCount" select="count($Rows)" /> 		<xsl:variable name="dvt_IsEmpty" select="$dvt_RowCount = 0" /> 		<xsl:choose> 			<xsl:when test="$dvt_IsEmpty"> 				<xsl:call-template name="dvt_1.empty" /> 			</xsl:when> 			<xsl:otherwise><table border="0" width="100%" cellpadding="2" cellspacing="0"> 			        <tr valign="top"> 				<xsl:if test="$dvt_1_automode = '1'" ddwrt:cf_ignore="1"> 					<th class="ms-vh" width="1%" nowrap="nowrap"></th> 				</xsl:if><th class="ms-vh" nowrap="">__spTitle</th><th class="ms-vh" nowrap="">__spID</th></tr>     			        <xsl:call-template name="dvt_1.body"> 				        <xsl:with-param name="Rows" select="$Rows"/> 			        </xsl:call-template> 		                </table></xsl:otherwise> 		</xsl:choose>			 	</xsl:template> 	<xsl:template name="dvt_1.body"> 		<xsl:param name="Rows"/> 		<xsl:for-each select="$Rows"> 			<xsl:call-template name="dvt_1.rowview"/> 		</xsl:for-each> 	</xsl:template> 	<xsl:template name="dvt_1.rowview"> 		<tr> 			<xsl:if test="position() mod 2 = 1"> 				<xsl:attribute name="class">ms-alternating</xsl:attribute> 			</xsl:if><td class="ms-vb"> 				<xsl:value-of select="@__spTitle" /></td><td class="ms-vb"> 				<xsl:value-of select="@__spID" /></td> 			<xsl:if test="$dvt_1_automode = '1'" ddwrt:cf_ignore="1"> 				<td class="ms-vb" width="1%" nowrap="nowrap"> 					<span ddwrt:amkeyfield="ID" ddwrt:amkeyvalue="ddwrt:EscapeDelims(string(@ID))" ddwrt:ammode="view"></span> 				</td> 			</xsl:if> 			</tr> 	</xsl:template> 	<xsl:template name="dvt_1.empty"> 		<xsl:variable name="dvt_ViewEmptyText">Nothing</xsl:variable> 		<table border="0" width="100%"> 			<tr> 				<td class="ms-vb"> 					<xsl:value-of select="$dvt_ViewEmptyText" /> 				</td> 			</tr> 		</table> 	</xsl:template> </xsl:stylesheet></Xsl> </WebPartPages:DataFormWebPart> 

多数据源

我们经常在SharePoint里面使用查阅项,但是当我们用SharePoint Designer定制列表的时候,我们会发现我们能得到的查阅项字段都是以;隔开的查阅字段字符串,当我们需要得到更多的查阅项目的信息的时候我们就需要用到多数据源了,在SharePoint Designer里面我们叫“链接源”,你创建完了可以看到数据源详细信息形如下图:

multiplesources

上图例中,Rating列表是对test1列表进行评分的列表,Rating查阅了test1的标题,然后在一个视图中我需要查看test1的标题,以及对应标题的项目的评分情况(并且要取出评分日期),如下:

multiplesources1

代码如下:

<WebPartPages:DataFormWebPart runat="server" IsIncluded="True" FrameType="None" NoDefaultStyle="TRUE" ViewFlag="0" Title="D?¨oy?Y???" __markuptype="vsattributemarkup" __WebPartId="{43FE3CE1-BF73-4433-91B7-4F3545D4B808}" id="g_43fe3ce1_bf73_4433_91b7_4f3545d4b808"> 	<DataSources><SharePoint:AggregateDataSource runat="server" IsSynchronous="false" SeparateRoot="true" id="dataformwebpart1"><sources><SharePoint:SPDataSource runat="server" DataSourceMode="List" UseInternalName="true" selectcommand="&lt;View&gt;&lt;/View&gt;"><SelectParameters><asp:Parameter Name="ListID" DefaultValue="{84363D4D-19AD-4C8E-9743-B5EB85A8AF08}"/><asp:Parameter Name="WebURL" DefaultValue="/test/"/></SelectParameters><DeleteParameters><asp:Parameter Name="ListID" DefaultValue="{84363D4D-19AD-4C8E-9743-B5EB85A8AF08}"/><asp:Parameter Name="WebURL" DefaultValue="/test/"/></DeleteParameters><UpdateParameters><asp:Parameter Name="ListID" DefaultValue="{84363D4D-19AD-4C8E-9743-B5EB85A8AF08}"/><asp:Parameter Name="WebURL" DefaultValue="/test/"/></UpdateParameters><InsertParameters><asp:Parameter Name="ListID" DefaultValue="{84363D4D-19AD-4C8E-9743-B5EB85A8AF08}"/><asp:Parameter Name="WebURL" DefaultValue="/test/"/></InsertParameters></SharePoint:SPDataSource> 			<SharePoint:SPDataSource runat="server" DataSourceMode="List" UseInternalName="true" selectcommand="&lt;View&gt;&lt;/View&gt;"><SelectParameters><asp:Parameter Name="ListID" DefaultValue="{71C39267-AEB8-4111-B00F-161AC8C65EC4}"/><asp:Parameter Name="WebURL" DefaultValue="/test/"/></SelectParameters><DeleteParameters><asp:Parameter Name="ListID" DefaultValue="{71C39267-AEB8-4111-B00F-161AC8C65EC4}"/><asp:Parameter Name="WebURL" DefaultValue="/test/"/></DeleteParameters><UpdateParameters><asp:Parameter Name="ListID" DefaultValue="{71C39267-AEB8-4111-B00F-161AC8C65EC4}"/><asp:Parameter Name="WebURL" DefaultValue="/test/"/></UpdateParameters><InsertParameters><asp:Parameter Name="ListID" DefaultValue="{71C39267-AEB8-4111-B00F-161AC8C65EC4}"/><asp:Parameter Name="WebURL" DefaultValue="/test/"/></InsertParameters></SharePoint:SPDataSource> 		</sources><aggregate><concat name="data source"><datasource name="Rating" id="0" Type="SPList"/><datasource name="test1" id="1" Type="SPList"/></concat></aggregate></SharePoint:AggregateDataSource></DataSources> 	 	<datafields>@Title,?à¨o¨?a;@test1,test1;@rating,rating;@ID,ID;@ContentType,?¨2¨¨Y¨¤¨¤D¨a;@Modified,DT??¨o?à??;@Created,??????§¨o?à??;@Author,??????§??;@Editor,DT????;@_UIVersionString,????à?;@Attachments,???t;@File_x0020_Type,???t¨¤¨¤D¨a;@FileLeafRef,??3? (¨??¨?¨2?à¨a|죤);@FileDirRef,??¤??;@FSObjType,????¨¤¨¤D¨a;@_HasCopyDestinations,??¨?D????????à¨o;@_CopySource,????????;@ContentTypeId,?¨2¨¨Y¨¤¨¤D¨a ID;@_ModerationStatus,¨|¨??¨2?á??¨??;@_UIVersion,UI ????à?;@Created_x0020_Date,??????§¨o?à??;@FileRef,URL ??¤??;@Choices,Choices;</datafields> 	<XSL><xsl:stylesheet xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:x="http://www.w3.org/2001/XMLSchema" xmlns:d="http://schemas.microsoft.com/sharepoint/dsp" version="1.0" exclude-result-prefixes="xsl msxsl ddwrt" xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime" xmlns:asp="http://schemas.microsoft.com/ASPNET/20" xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:SharePoint="Microsoft.SharePoint.WebControls" xmlns:ddwrt2="urn:frontpage:internal"> 	<xsl:output method="html" indent="no"/> 	<xsl:decimal-format NaN=""/> 			<xsl:param name="dvt_apos">'</xsl:param> 			<xsl:variable name="dvt_1_automode">0</xsl:variable> 			<xsl:variable name="RatingRows" select="/dsQueryResponse/Rating/Rows/Row" /> 			<xsl:template match="/"> 				<xsl:call-template name="dvt_1"/> 	</xsl:template> 			<xsl:template name="dvt_1"> 				<xsl:variable name="dvt_StyleName">Table</xsl:variable> 				<xsl:variable name="Rows" select="/dsQueryResponse/test1/Rows/Row"/> 				<xsl:variable name="dvt_RowCount" select="count($Rows)" /> 				<xsl:variable name="IsEmpty" select="$dvt_RowCount = 0" /> 				<xsl:variable name="dvt_IsEmpty" select="$dvt_RowCount = 0" /> 				<xsl:choose> 					<xsl:when test="$dvt_IsEmpty"> 						<xsl:call-template name="dvt_1.empty" /> 					</xsl:when> 					<xsl:otherwise><table border="0" width="100%" cellpadding="2" cellspacing="0"> 			<tr valign="top"> 				<xsl:if test="$dvt_1_automode = '1'" ddwrt:cf_ignore="1"> 					<th class="ms-vh" width="1%" nowrap="nowrap"></th> 				</xsl:if> 				<th class="ms-vh" nowrap="" style="width: 227px">?à¨o¨?a</th> 				<th class="ms-vh" nowrap="" style="width: 89px">DT????</th> 				<th class="ms-vh" nowrap="">Rating</th></tr> 			<xsl:call-template name="dvt_1.body"> 				<xsl:with-param name="Rows" select="$Rows" /> 			</xsl:call-template> 		</table></xsl:otherwise> 				</xsl:choose> 				 	</xsl:template> 			<xsl:template name="dvt_1.body"> 				<xsl:param name="Rows"/> 				<xsl:for-each select="$Rows"> 					<xsl:variable name="XPath"> 						<xsl:call-template name="dvt.xpath" /> 					</xsl:variable> 					<xsl:call-template name="dvt_1.rowview"> 						<xsl:with-param name="Pos" select="concat('_', ddwrt:Counter())" /> 						<xsl:with-param name="XPath" select="$XPath" /> 					</xsl:call-template> 					 		</xsl:for-each> 	</xsl:template> 			<xsl:template name="dvt_1.rowview"> 		<xsl:param name="Pos" /> 		<xsl:param name="XPath" /> 		<tr> 			<xsl:if test="position() mod 2 = 1"> 				<xsl:attribute name="class">ms-alternating</xsl:attribute> 			</xsl:if> 			<xsl:if test="$dvt_1_automode = '1'" ddwrt:cf_ignore="1"> 				<td class="ms-vb" width="1%" nowrap="nowrap"> 					<span ddwrt:amkeyfield="" ddwrt:amkeyvalue="string($XPath)" ddwrt:ammode="view"></span> 				</td> 			</xsl:if> 			<td class="ms-vb" style="width: 227px"> 				<xsl:value-of select="@Title"/> 			</td> 			<td class="ms-vb" style="width: 89px"> 				<asp:Label runat="server" id="ff1{$Pos}" text="{@Editor}" __designer:bind="{ddwrt:DataBind('u',concat('ff1',$Pos),'Text','','',string($XPath),'@Editor')}" /> 				 			</td> 			<td class="ms-vb"> 				<xsl:call-template name="Rating"> 					<xsl:with-param name="title"><xsl:value-of select="@Title" /></xsl:with-param> 				</xsl:call-template> 			</td></tr> 		 	</xsl:template> 	<xsl:template name="Rating"> 		<xsl:param name="title" /> 		<xsl:variable name="rowsnumber" select="count($RatingRows[@test1=$title])"/> 		<xsl:choose> 			<xsl:when test="$rowsnumber=0"> 				Not rated yet! 			</xsl:when> 			<xsl:otherwise> 			<xsl:for-each select="$RatingRows[@test1=$title]"> 			 			<strong><xsl:value-of select="@rating"/></strong><xsl:text disable-output-escaping="yes">&amp;nbsp;</xsl:text>(RateDate:<xsl:value-of select="ddwrt:FormatDate(string(@Created), 2052, 5)"></xsl:value-of>) 		</xsl:for-each> 			</xsl:otherwise> 		</xsl:choose> 		 	</xsl:template> 	<xsl:template name="dvt.xpath"> 		<xsl:for-each select="ancestor-or-self::*"><xsl:value-of select="concat('/node()[',count(preceding-sibling::node())+1,']')" /></xsl:for-each> 	</xsl:template> 	<xsl:template name="dvt_1.empty"> 		<xsl:variable name="dvt_ViewEmptyText">Not Rated yet!</xsl:variable> 		<table border="0" width="100%"> 			<tr> 				<td class="ms-vb"> 					<xsl:value-of select="$dvt_ViewEmptyText" /> 				</td> 			</tr> 		</table> 	</xsl:template></xsl:stylesheet></XSL> <parameterbindings> 			<ParameterBinding Name="dvt_apos" Location="Postback;Connection"/> 			<ParameterBinding Name="UserID" Location="CAMLVariable" DefaultValue="CurrentUserName"/> 			<ParameterBinding Name="Today" Location="CAMLVariable" DefaultValue="CurrentDate"/> 		</parameterbindings></WebPartPages:DataFormWebPart>
注意:其中RatingRows和Rating template是用来取评分信息的XSLT模板。

 

2)ParameterBindings

我们把我们在DataForm Web Part里面需要用到的所有的参数在这里面进行定义,这里的参数会被同时应用到DataForm的数据源和XSLT里面。DataForm Web Part让我们可以定义统一的参数。SPDataSource的Selectcommand可以包含参数,DataFormParameter的值可以来自参数,XSLT中的参数值也可以来自统一定义的参数。在DataForm中有提供了了定义参数的界面如下:

parameterwindow

可以看到提供了5中参数来源,其中:

>> 控件:来自页面上的控件的值

>> 表单:这个在上一篇Blog中就是用了这种参数 [SharePoint Designer技巧-1]使用DataView与Form Web Part实现列表的关键字查询

>> 查询字符串:URL中的参数

 

3)XSL

XSL这个主要就是XSLT和XPath的东西了,要能很好的定制DataForm的话,需要比较熟练XSLT和XPath。

SharePoint提供了XSLT的扩展函数,相关信息:

SharePoint Data View Web Part Extension Functions in the ddwrt Namespace(虽然是2003的版本,但是可以参考)

SharePoint Data View Conditional Formatting based on user permissions (这个是关于WSS 3.0中一个新的扩展函数IfHasRights的详细说明,这个函数可以用于判断当前用户对列表有某种权限作为筛选数据的条件,实际中比较有用的一个扩展函数)

 

关于DataForm的话题还没有结束!

对数据显示的深入定制是我们的目的之一,我们的另一个目的是和显示的数据进行交互(定制分页,定制排序,定制分组),对数据进行操作(添加,修改,删除),利用DataForm提供的功能我们可以方便的定制编辑,添加页面。如果大家等不及我下一篇相关的文章的话可以先看看SharePoint Designer Team 的一篇关于用Javascript操作编辑和添加页面的字段控件的文章:Using Javascript to Manipulate a List Form Field

posted on 2007-12-09 22:18:00 by ipark  评论(9) 阅读(7061)

 
2007年11月01日

最近参与一个SharePoint项目,客户要求不能包含任何服务器端代码(脚本除外),只能定制,所以项目中需要大量使用SharePoint Designer。当我们不能使用任何开发手段的时候,我就需要尽量研究SharePoint Designer,了解SPD的限制与潜力,进而与客户博弈,一方面尽量挖掘SPD的能力来满足客户需求,另一方面根据对SPD能力的研究控制客户的需求。在项目进行过程中,我会逐渐把项目中积累的一些SharePoint Designer应用的技巧拿出来和大家分享。

在客户众多需求中包含一个“关键字查询列表”,客户希望用关键字模糊搜索列表中所有的文本字段。该需求其实很简单,不过翻遍默认的web part,只有“filter”和“search”相关的Web part和这个需求能挂上边。但是,‘filter’都是筛选器,无法做到关键字查询,只能精确匹配,search相关的都是与SharePoint搜索引擎相关的Web Part,杀鸡用不着牛刀!

我们的解决方法是:利用Data View Web Part的filter和parameter实现带参数的查询,使用Form Web Part给DataView WebPart提供关键字。

有以下一个列表:

image

用SharePoint Designer打开新创建的Web 部件页“View.aspx”页面,把以上列表拖入Web Part区域中即可插入一个Data View(数据视图):

编辑列,设置显示列为“标题”,“描述”,“来源”

image

选择上图“常用Data View任务”的“参数”,新建建一个“表单”参数“Keyword”:

image

选择上图“常用Data View任务”的“筛选”,添加需要查询的文本字段,使用“包含”实现模糊查询,“值”选择使用新建的“Keyword”参数,“与/或”则均选择“或”:

image

设置完成后,点“确定”,并保存页面。浏览View.aspx,在页面添加一个Form Web Part:

image

设置“表单Web部件”与Data View Web Part进行连接:

image

image

选择连接类型为“参数 获取位置”,点“配置”

image

选择Keyword,点击“完成”。结束配置,回到页面。输入“猪肉”关键字,搜索如下:

image

输入“新浪”关键字,搜索如下:

image

注:其实Form Web Part可以添加多个文本框,也可以添加下拉框,Data View的filter的可设置选项也比较多,也可以使用XSLT进行筛选,所以这种方法实现的模糊查询还是有一定潜力的。

posted on 2007-11-01 00:38:00 by ipark  评论(8) 阅读(7474)

 
2007年06月07日

今天听的两个Session很有意思,正好解答了我在前两天的两个疑问,一个是关于Excel Services的定位问题,一个是关于BizTalk和SharePoint的问题。

1)ARC 317:How to Select the Right Combination of Microsoft Office SharePoint Server, Windows Workflow Foundation, and BizTalk for All Your Workflow and Orchestration Needs

关键字:Biztalk,complex BPM,WF,Stand-alone workflow,SharePoint,User Fouced

摘要:当在SharePoint,Biztalk和WF之间做选择的时候,关键的是要看你的应用场景,我们的原则是:只选择最合适的,不选择最复杂的!不是说BizTalk就最好,WF就最不好。首先,要了解这三个东西的优势各在什么地方。SharePoint的优势在于其与用户的交互性,Biztalk则在于其处理各种系统之间的互连和内在的复杂的流程的管理,biztalk不把可交互性作为其考虑范围,他要做的是在企业的各种系统间路由信息。截取一张ppt可以让大家看到这个比较。

image

2)OFC345:Excel Services Architecture and Developer Senarios

关键字:Excel Services solution Overview,OBA

摘要:今天这个Session的内容虽然我比较熟悉,但是,讲师的演讲技巧很好,让我很受启发,他在这个Session中完全没有提到BI的东西。强调的是Excel的计算服务,商业逻辑,UDF这些东西。Demo了如何利用这些特性构建一个报表生成解决方案的每个环节。让我明白了Excel Services的精髓在Excel Calculation Services,虽然这是很明显的事情,但我们好像一直都过于强调Excel Services的Web展现效果,做DashBoard怎么怎么酷炫,而把根本的东西忘记了。基于Excel Services的解决方案应该更多的在于基于Excel文件的解决方案上,应该更多的归入OBA的范围。Excel Services对BI的支持更多的是在商业逻辑和计算方面,而不是在Excel的Web展现上。总而言之,Excel Services是面向Excel文档的技术,核心是Excel Calculation Services。

不要一讲到Excel Services,就一下子想到了Dashboard的各种指示灯。

前两天,我困惑PerformancePoint和Excel Services的问题,现在看来,自己也感觉有点可笑,这两个东西完全没有可比性。

 

另外

今天的一个特点是会场好多地方都在免费发放书,Session免费发书,站台送书,搞得会场在中午时段几个地方同时排起了浩浩荡荡的长队。我和李辉同学毫不犹豫的加入了其中,并成功获取到了几本书,一些可以当作礼物在OTEC活动的时候送给大家。

我这里多一本《Windows Server 2008》,李辉同学那里多两本《Begnning Excel Services》

posted on 2007-06-07 14:30:00 by ipark  评论(4) 阅读(6468)

 
【第1页/共2页,23条】
首页
前页
1

Powered by: Joycode.MVC引擎 0.5.1.8