一:定义表单页面
1.新建StartInstance.aspx页面,修改页面类继承至BasePage
该页面显示所有的流程模板,选择模板提交后进入启动页(第一个活动项),该页面表单如下:
Start按钮事件定义如下:
protected void btnStart_Click(object sender, EventArgs e) { if (ddlVersion.SelectedIndex > -1) { //根据流程类型,名称和板本,得到流程模板 OThinker.H3.WorkflowTemplate.WorkflowTemplate workflow = OThinker.H3.Server.Engine.WorkflowManager.GetWorkflow(ddlFlowType.Text, ddlFlowName.Text, Convert.ToInt32(ddlVersion.Text)); // 开始节点(活动项) OThinker.H3.WorkflowTemplate.ActivityTemplate startActivity = workflow.GetActivity(workflow.StartActivity); // 开始的表单 OThinker.H3.WorkflowTemplate.Sheet startSheet = workflow.GetSheet(startActivity.SheetName); // URL参数,传入流程类型,名称和版本,以及操作 System.Text.StringBuilder instanceParamBuilder = new System.Text.StringBuilder(); foreach (string key in this.Request.QueryString.Keys) { string lowerKey = key.ToLower(); if (lowerKey != "mode" && lowerKey != "workflowpackage" && lowerKey != "workflowname" && lowerKey != "workflowversion") { if (instanceParamBuilder.Length > 0) { instanceParamBuilder.Append("&"); } instanceParamBuilder.Append(key + "=" + this.Request.QueryString[key]); } } string url = GetFlowSheetUrl(startSheet); this.Response.Redirect( url + "?" + Param_Mode + "=" + SheetMode.Originate + "&" + "workflowpackage=" + System.Web.HttpUtility.UrlEncode(workflow.WorkflowPackageName) + "&" + "workflowname=" + System.Web.HttpUtility.UrlEncode(workflow.WorkflowName) + "&" + "workflowversion=" + workflow.WorkflowVersion + (instanceParamBuilder.Length == 0 ? null : ("&" + instanceParamBuilder.ToString()))); } }
其中GetFlowSheetUrl在BasePage中定义:
public string GetFlowSheetUrl(OThinker.H3.WorkflowTemplate.Sheet sheet) { if (string.IsNullOrEmpty(sheet.SheetAddress)) throw new ArgumentNullException(sheet.SheetName + "没有定义表单", "SheetAddress"); string m_rootUrl = "http://" + HttpContext.Current.Request.Url.Authority; if (!string.IsNullOrEmpty(HttpContext.Current.Request.ApplicationPath)) { m_rootUrl += HttpContext.Current.Request.ApplicationPath; } if (sheet.SheetAddress[0] == '/') { m_rootUrl += sheet.SheetAddress; } else { m_rootUrl += "/" + sheet.SheetAddress; } return m_rootUrl; }
2.创建表单页面放到Examples/WorkSheets下面,取名为ApplyLeave.aspx(路径和名称自便,这里只是以本人的习惯取的)
修改页面类继承至BasePage,设计页面如下,全部用Asp.net自带的控件,不用H3的WorkSheet里的控件,怕不好扩展
提交事件定义如下:
protected void btnSubmit_Click(object sender, EventArgs e) { if (string.IsNullOrEmpty(WorkflowName) || WorkflowVersion < 0) { return; } DateTime tempTime; //验证数据... if (!DateTime.TryParse(txtStartDate.Text, out tempTime)) { return; } if (!DateTime.TryParse(txtEndDate.Text, out tempTime)) { return; } //保存到流程引擎 string InstanceName = base.UserValidator.UserName + "的请假申请";//实例名称 //获取流程模板 OThinker.H3.WorkflowTemplate.WorkflowTemplate workflow = OThinker.H3.Server.Engine.WorkflowManager.GetWorkflow(WorkflowPackage, WorkflowName, WorkflowVersion); string InstanceId=null; string workItemId = null; //创建流程实例 OriginateInstance(workflow, InstanceName, ref InstanceId, ref workItemId); //保存到业务库(这里有个问题,如果业务库的操作失败了怎么办,但该方法又不能写在前面,因为WorkItemId得从H3的接口返回) Microsoft.Practices.EnterpriseLibrary.Data.Database dataBase = Microsoft.Practices.EnterpriseLibrary.Data.DatabaseFactory.CreateDatabase(); string sql = string.Format("insert into [ApplyLeaveInfo] ([startDate],[endDate] ,[ApplyResult],[WorkItemId]) values('{0}','{1}','false','{2}')", txtStartDate.Text, txtEndDate.Text, workItemId); dataBase.ExecuteNonQuery(System.Data.CommandType.Text, sql); //返回待处理 Response.Redirect("../../default.aspx"); }其中OriginateInstance为创建流程实例的方法,该方法里保存了实例记录,并且通过Soket通知H3服务一个实例创建的消息,服务接到消息后会在WorkItem中插入一条发起的消息,不过还没完,还得要记录下一步的操作数据,要不然下一步的用户在待处理列表里就看不到了
/// <summary> /// 启动一个流程实例,并且提交起始活动项 /// </summary> /// <param name="Workflow">流程模板对象</param> /// <param name="InstanceName">实例名称</param> /// <param name="InstanceId">实例编号</param> /// <param name="workItemId">起始流动项在OT_WorkItem的ID</param> public void OriginateInstance(OThinker.H3.WorkflowTemplate.WorkflowTemplate Workflow, string InstanceName, ref string InstanceId, ref string workItemId) { OThinker.H3.Acl.UserValidator userValidator = this.UserValidator; if (Workflow == null) { throw new ArgumentNullException("流程模板不存在", "Workflow"); } //开始一个流程实例 InstanceId = OThinker.H3.Server.Engine.InstanceManager.CreateInstance(WorkflowPackage, WorkflowName, WorkflowVersion, InstanceName, userValidator.UserID, null, userValidator.Department, false, "", null, -1L); OThinker.H3.Messages.MessageEmergencyType normal = OThinker.H3.Messages.MessageEmergencyType.Normal; if (Workflow.StartWithSheet) { normal = OThinker.H3.Messages.MessageEmergencyType.High; } //发送实例消息给服务 OThinker.H3.Messages.StartInstanceMessage message = new OThinker.H3.Messages.StartInstanceMessage( normal, InstanceId, null, OThinker.H3.Instance.PriorityType.Normal, false, 0L, -1L, null); OThinker.H3.Server.Engine.InstanceManager.SendMessage(message); //记录WorkItem,失败后尝试10次 string[] strArray = null; for (int i = 0; i < 10; i++) { System.Threading.Thread.Sleep(1500); strArray = OThinker.H3.Server.Engine.WorkItemManager.Query(null, new string[] { InstanceId }, new string[] { userValidator.UserID }, DateTime.MinValue, DateTime.MaxValue, OThinker.H3.WorkItem.WorkItemState.Unfinished ); if ((strArray != null) && (strArray.Length != 0)) { break; } } if ((strArray == null) || (strArray.Length == 0)) { throw new Exception("发起流程失败"); } workItemId = strArray[0]; //提交起始活动项 SubmitWorkItem(Workflow, workItemId); } /// <summary> /// 提交流程步骤 /// </summary> /// <param name="Workflow">流程模板对象</param> /// <param name="workItemId">活动项ID</param> public void SubmitWorkItem(OThinker.H3.WorkflowTemplate.WorkflowTemplate Workflow, string workItemId) { OThinker.H3.Acl.UserValidator userValidator = this.UserValidator; OThinker.H3.WorkItem.WorkItem workItem = OThinker.H3.Server.Engine.WorkItemManager.GetWorkItem(workItemId); workItem.State = OThinker.H3.WorkItem.WorkItemState.Finished; //完成活动 OThinker.H3.Server.Engine.WorkItemManager.FinishWorkItem(workItemId, this.UserValidator.UserID, null, OThinker.Data.BoolMatchValue.Unspecified, null); // 设置操作描述(Portal有这一步骤,不知道去掉后会有影响没) string description = "submit"; OThinker.H3.Server.Engine.TokenPool.AppendDescription(workItem.InstanceId, workItem.TokenId, description); OThinker.H3.WorkflowTemplate.ActivityTemplate destActivityTemplate = Workflow.GetActivity(DestActivityName); //如果地址栏没有传入下一活动名称 if (destActivityTemplate == null) { // 需要通知实例事件管理器结束事件 OThinker.H3.Messages.AsyncEndMessage endMessage = new OThinker.H3.Messages.AsyncEndMessage( OThinker.H3.Messages.MessageEmergencyType.Normal, workItem.InstanceId, workItem.ActivityName, workItem.ReplyID, true, this.UserValidator.UserID, OThinker.Data.BoolMatchValue.Unspecified, null, null); OThinker.H3.Server.Engine.InstanceManager.SendMessage(endMessage); } else { // 准备触发后面Activity的消息 OThinker.H3.Messages.ActivateActivityMessage activateMessage = new OThinker.H3.Messages.ActivateActivityMessage( OThinker.H3.Messages.MessageEmergencyType.Normal, workItem.InstanceId, destActivityTemplate.Name, OThinker.H3.Instance.Token.UnspecifiedID, null, new long[] { workItem.TokenId }, false, OThinker.H3.Messages.ActivateType.Normal, null); // 通知该活动已经完成 OThinker.H3.Messages.AsyncEndMessage endMessage = new OThinker.H3.Messages.AsyncEndMessage( OThinker.H3.Messages.MessageEmergencyType.Normal, workItem.InstanceId, workItem.ActivityName, workItem.ReplyID, false, userValidator.UserID, OThinker.Data.BoolMatchValue.Unspecified, activateMessage, null); OThinker.H3.Server.Engine.InstanceManager.SendMessage(endMessage); } }源码下源:FlowSite