【Moss开发系列】WF+Aspx进行Moss工作流开发(1)

Moss平台下工作流设计分一般三种模式:

一、根据Moss系统本身提供的一些流程模版,如审批工作流、三态工作流等进行定制。

二、利用SharePoint Designer进行流程设计。

三、前两种流程设计方式我们称之为流程定制,这种方式一般用于一些简单流程的处理,现实中有很多流程都需要专门的开发,对于这些复杂的流程,我们可以选用第三方流程开发工具(如K2),也可以选用标准的VS环境下的WF进行开发。

Moss平台下流程开发最常规的做法是:用InfoPath设计表单,然后利用WF设计流程并收集数据,然后与列表关联,最后发布流程。

这种方式看似简单,但做起来并不那么容易,因为InfoPath有其先天的不足,用InfoPath做过复杂流程的可能都经历过以下几点:

(1) 界面数据与流程交互比较麻烦,界面本身定制也比较麻烦,常见的情况:客户觉得InfoPath不好看,结果有好多东西是改不了的

(2) 界面上数据互动也较麻烦,比如常见的三级联动,仿Ajax验证,做起来也是很麻烦的事情

(3) 大表单与项目清单的显示与控制方面,常见的情况有,客户要求审批界面上半部分显示项目的详细信息,下面是审批信息,而且不同审批人能看到的项目信息字段权限不同

(4) 表单与表单代码的封装与重用,现实中的流程并不只简单的审批那么简单,一个复杂的流程涉及到的表单可能有上百个,难道都要从头设计,重用和表单管理本身是一个大的问题

那么如果我们能用Aspx表单来取代InfoPath表单的话,所有问题都可以轻易解决,一切都变得随心所欲了,下面切入正题,如何使用Aspx界面来替换InfoPath表单:

首先我们新建一个自定义列表“请假信息单”和一个“请假审批”任务类型列表

然后打开VS2008,新建一个WEB应用程序,注意:不要建成网站类型,建WEB应用程序,Moss环境下部署较麻烦,而WEB应用程序生成单一程序集,易于程序集的签名与部署。

然后对该WEB应用程序签名,以便于程序集可以部署在GAC中

新建一目录“_Layouts”,复制 C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\LAYOUTS 下的application.master到该目录下。

删除默认的Default.aspx,新建一个审批页面 Approve.aspx,删除页面中原有HTML代码

将 前台页面的 Inherits节改为该web应用程序集强命名程序集的名称,Inherits="Janet.AspxWorkflow.Forms.Approve,Janet.AspxWorkflow.Forms, Version=1.0.0.0, Culture=neutral, PublicKeyToken=4af1d7891f28970c" 具体名字可以使用reflector查看。

然后改写添加 MasterPageFile="~/_layouts/application.master" 使继承母版页”application.master” ,最终页面代码如下: 

1 <%@ Page Language="C#" MasterPageFile="~/_layouts/application.master" AutoEventWireup="true"
2 CodeBehind="Approve.aspx.cs" Inherits="Janet.AspxWorkflow.Forms.Approve,Janet.AspxWorkflow.Forms, Version=1.0.0.0, Culture=neutral, PublicKeyToken=4af1d7891f28970c" %>
3
4  <%@ Import Namespace="Microsoft.SharePoint" %>
5  <%@ Register TagPrefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls"
6 Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
7  <asp:Content ID="Content1" ContentPlaceHolderID="PlaceHolderPageTitle" runat="server">
8 请假审批流程
9  </asp:Content>
10  <asp:Content ID="Content2" ContentPlaceHolderID="PlaceHolderTitleBreadcrumb" runat="server">
11 &nbsp;
12  </asp:Content>
13  <asp:Content ID="Content3" ContentPlaceHolderID="PlaceHolderPageTitleInTitleArea"
14 runat="server">
15  </asp:Content>
16  <asp:Content ID="Content5" ContentPlaceHolderID="PlaceHolderMain" runat="server">
17 <TABLE width="650" style="font-size:12px;color:#369;BORDER-BOTTOM-STYLE: solid; BORDER-RIGHT-STYLE: solid; BORDER-COLLAPSE: collapse; BORDER-TOP-STYLE: solid; BORDER-LEFT-STYLE: solid" border="1" rules="all" cellSpacing="0" cellPadding="4">
18 <tr>
19 <td>请假人</td>
20 <td>
21 <%= this.UserName%>
22 </td>
23 </tr>
24 <tr>
25 <td>请假原因</td>
26 <td>
27 <%=this.UserMsg %>
28 </td>
29 </tr>
30 <tr>
31 <td>请假天数</td>
32 <td>
33 <%= this.Days%>
34 </td>
35 </tr>
36 <tr>
37 <td>审批意见</td>
38 <td>
39 <asp:TextBox ID="txtMsg" runat="server" TextMode="MultiLine" Rows="5" Columns="40"></asp:TextBox>
40 </td>
41 </tr>
42 <tr>
43 <td>是否通过</td>
44 <td>
45 <asp:RadioButtonList ID="radioPass" runat="server">
46 <asp:ListItem Value="true" Selected="True">通过</asp:ListItem>
47 <asp:ListItem Value="false">拒绝</asp:ListItem>
48 </asp:RadioButtonList>
49 </td>
50 </tr>
51 <tr><td></td>
52 <td><asp:Button Text="提交" runat="server" ID="BtnSubmit" onclick="BtnSubmit_Click" /></td>
53 </tr>
54 </table>
55  </asp:Content>
56  

  

项目中添加对Microsoft.SharePoint的引用,修改后台代码,改变页面继承自 Microsoft.SharePoint.WebControls.LayoutsPageBase

编写提交处理事件,页面后台代码如下:

代码
1
2  namespace Janet.AspxWorkflow.Forms
3 {
4 public partial class Approve : Microsoft.SharePoint.WebControls.LayoutsPageBase
5 {
6 protected SPList taskList; //请假审批任务列表
7 protected SPListItem taskItem; //当前任务
8
9 public string UserName; //请假人
10 public string UserMsg; //请假原因
11 public string Days; //请假天数
12
13 protected void Page_Load(object sender, EventArgs e)
14 {
15 string strListID = Request.QueryString["List"];
16 if (strListID != null)
17 {
18 taskList = Web.Lists[new Guid(strListID)];
19 taskItem = taskList.GetItemById(Convert.ToInt32(Request.Params["ID"]));
20 if (!Page.IsPostBack)
21 {
22 Guid workflowId = new Guid((string)taskItem["WorkflowInstanceID"]);
23 SPWorkflow workflow = new SPWorkflow(Web, workflowId);
24 SPListItem projectItem = workflow.ParentItem; //当前请假项目
25
26 this.UserName = projectItem["Author"].ToString();
27 this.UserMsg=projectItem["请假原因"].ToString();
28 this.Days = projectItem["请假天数"].ToString();
29 }
30 }
31 }
32
33
34
35 protected void BtnSubmit_Click(object sender, EventArgs e)
36 {
37 try
38 {
39 if (taskItem != null)
40 {
41 SPWeb web = SPContext.Current.Web;
42 web.AllowUnsafeUpdates = true;
43 Hashtable taskHash = new Hashtable();
44 taskHash["ApproveMsg"] = this.txtMsg.Text; //审批信息
45 taskHash["approved"] = this.radioPass.SelectedValue; //审批状态,WF中获取用来判断,是否回退....
46 SPWorkflowTask.AlterTask(taskItem, taskHash, true); //提交任务审批结果
47 SPUtility.Redirect(taskList.DefaultViewUrl, SPRedirectFlags.UseSource, HttpContext.Current);
48 }
49 }
50 catch (Exception ex)
51 {
52 Response.Write(ex.ToString());
53 }
54 }
55 }
56 }

   

编写Feature配置文件,

Feathre.xml 

代码
1 <?xml version="1.0" encoding="utf-8"?>
2  <Feature Id="1161B2A1-FDED-47a2-B3FE-7C97DD6CC743" Title="请假审批内容类型" Scope="Site" Version="1.0.0.0" Hidden="FALSE" DefaultResourceFile="core" xmlns="http://schemas.microsoft.com/sharepoint/">
3 <ElementManifests>
4 <ElementManifest Location="form.xml" />
5 </ElementManifests>
6  </Feature>

form.xml  

代码
1 <?xml version="1.0" encoding="utf-8"?>
2  <Elements Id="D9170A70-D733-4886-9117-12410DF5A8B2" xmlns="http://schemas.microsoft.com/sharepoint/">
3 <ContentType ID="0x0108010023070ff45efd410a8bb9252cbabc1211"
4 Name="请假审批页面"
5 Group="我的审批页面"
6 Description="请假审批表单内容类型"
7 Version="0">
8 <FieldRefs>
9 </FieldRefs>
10 <XmlDocuments>
11 <XmlDocument NamespaceURI="http://schemas.microsoft.com/sharepoint/events">
12 <Receivers />
13 </XmlDocument>
14 <XmlDocument NamespaceURI="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms/url">
15 <FormUrls xmlns="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms/url">
16 <New>_layouts/MyAspxTask/Approve.aspx</New>
17 <Display>_layouts/MyAspxTask/Approve.aspx</Display>
18 <Edit>_layouts/MyAspxTask/Approve.aspx</Edit>
19 </FormUrls>
20 </XmlDocument>
21 </XmlDocuments>
22 </ContentType>
23 </Elements>

 注意:上面文件中的 _layouts/MyAspxTask/Approve.aspx 指向的是你的审批页面。    

在C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\FEATURES 下面建一目录 MyAspxTask ,然后把这两个XML文件放入该目录中。执行命令:STSADM -o InstallFeature -filename MyAspxTask\feature.xml -force   注册该Feature。

注册成功后在“网站集功能”中能看到该内容类型,然后激活该内容类型

 

 然后进入“请假审批”任务列表的设置页,选择“高级设置”启用内容类型管理,如下图所示:

 然后在“请假审批”列表中添加刚才我们创建的那个内容类型:

 

 把我们的审批页面 approve.aspx 文件复制到 C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\LAYOUTS\MyAspxTask 目录下,然后把WEB应用程序的dll文件,拖到GAC中(C:\WINDOWS\assembly文件夹),到这里,页面部分设计完成,下面进行WF部分开发。

该流程仅涉及到一级审批:

 注意:创建任务活动在这里要使用“CreateTaskWithContentType”,在该活动的"ContentTypeID"属性中输入 0x0108010023070ff45efd410a8bb9252cbabc1211,即form.xml中的ContentType节的ID中的值,整个流程的代码如下: 

代码
1 public sealed partial class Workflow1 : SequentialWorkflowActivity
2 {
3 public Workflow1()
4 {
5 InitializeComponent();
6 }
7
8 public Guid workflowId = default(System.Guid);
9 public SPWorkflowActivationProperties workflowProperties = new SPWorkflowActivationProperties();
10 public Guid taskId1 = default(System.Guid);
11 public SPWorkflowTaskProperties taskProperties1 = new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();
12
13 private void onWorkflowActivated1_Invoked(object sender, ExternalDataEventArgs e)
14 {
15
16 }
17
18 private void createTaskWithContentType1_MethodInvoking(object sender, EventArgs e)
19 {
20 this.taskId1 = Guid.NewGuid();
21 this.taskProperties1.AssignedTo = "jasper\\moss";
22 this.taskProperties1.Title = string.Format("请审批【{0}】", this.workflowProperties.Item.DisplayName);
23 }
24
25 private void onTaskChanged1_Invoked(object sender, ExternalDataEventArgs e)
26 {
27 bool approve = bool.Parse(this.taskProperties1.ExtendedProperties["approved"].ToString());
28 string msg = approve ? "审批通过:" : "审批拒绝:";
29 msg += this.taskProperties1.ExtendedProperties["ApproveMsg"].ToString();
30 this.workflowProperties.Workflow.CreateHistoryEvent(approve ? 2 : 8, 0, this.workflowProperties.OriginatorUser, msg, "", ""); //写入工作流历史记录
31 }
32 }

  

启动该工作流:

 审批该任务,看到我们熟悉的Aspx页面:

 审批结束: 

 

 请假审批结束,历史记录记录了该请假中间的审批过程,可以看到我的回家看老婆的希望已经破灭了......

 总结:这个只是一个简单的演示,很多细节没有进行处理。用Aspx做表单,一个流程的第一次使用感觉麻烦了点,后期经过一系列封装之后,做起来就简单的多了。

 示例项目下载

 下一篇将对aspx+wf进行一系列封装,使之能够轻易完成wf+infopath中的task1, task2 ... taskn的功能。

原文地址:https://www.cnblogs.com/janet/p/1719315.html