接上篇文章 “状态机工作流.实列.报销审批流程(一) ” 有代码下载
本文主要讲述,在web上实际应用上篇文章中设计的工作流。。。。
涉及技术
在Web.config 配置
取得工作流结构
动态加签
动态取得审批方式
启动工作流流转等(这个好多列子中都有不再详细描述)
Web 项目文件主要功能描述
Web.Config配置了一些工作流服务
WorkflowRuntime 加载的,ManualWorkflowSchedulerService 和 ExternalDataExchangeService
ExternalDataExchangeService 加载的,上篇文章中的 MyWorkflows.BillServer
Global.asax,App_Code\Global.asax.cs
启动 WorkflowRuntime,加载 FileWorkflowPersistenceService(自定义的状态保存服务,下篇文章详细讲解)
代码
protectedvoidApplication_Start(objectsender,EventArgse)
{
Console.WriteLine("Application_Start:");
System.Workflow.Runtime.WorkflowRuntimeworkflowRuntime=newSystem.Workflow.Runtime.WorkflowRuntime(MyWorkHelpr.WorkflowRuntimeName);
//加载状态保持服务(自己的类),构造函数设置保存状态的路径
FileWorkflowPersistenceServicef28s=newFileWorkflowPersistenceService(Server.MapPath("~/App_Data/XOM.WFDB/"));
workflowRuntime.AddService(f28s);
Application[MyWorkHelpr.WorkflowRuntimeName]=workflowRuntime;
//映射事件没用上
workflowRuntime.WorkflowCompleted+=newEventHandler<System.Workflow.Runtime.WorkflowCompletedEventArgs>(workflowRuntime_WorkflowCompleted);
workflowRuntime.WorkflowTerminated+=newEventHandler<System.Workflow.Runtime.WorkflowTerminatedEventArgs>(workflowRuntime_WorkflowTerminated);
workflowRuntime.WorkflowSuspended+=newEventHandler<System.Workflow.Runtime.WorkflowSuspendedEventArgs>(workflowRuntime_WorkflowSuspended);
workflowRuntime.WorkflowPersisted+=newEventHandler<System.Workflow.Runtime.WorkflowEventArgs>(workflowRuntime_WorkflowPersisted);
workflowRuntime.StartRuntime();
//重状态保存读取所有没执行完的了类.
foreach(Guididinf28s.GetAllWorkflows())
{
workflowRuntime.GetWorkflow(id);
}
}
Default.aspx(用户登陆)
导航页面,可以模拟各种角色登陆,可以显示全部正在进行的工作流信息、可以查看工作流的结构
代码说明
取得工作流结构
protectedvoidGridView1_RowCommand(objectsender,GridViewCommandEventArgse)
{
inti=0;
if(mandName.ToLower()=="select")
{//就想取两级就不递归了
i=Convert.ToInt32(mandArgument);
stringsguid=GridView1.Rows[i].Cells[1].Text.Trim();
GuidinstanceId=newGuid(sguid);
WorkflowInstanceworkInstance=(Application[MyWorkHelpr.WorkflowRuntimeName]asWorkflowRuntime).GetWorkflow(instanceId);
StateMachineWorkflowActivityMainActivity=workInstance.GetWorkflowDefinition()asStateMachineWorkflowActivity;
TreeView1.Nodes.Clear();
TreeNodeMainNode=newTreeNode();
TreeNodeNodeL1=null;
TreeNodeNodeL2=null;
MainNode.Text=sguid;
foreach(StateActivitystateinMainActivity.Activities)
{
NodeL1=newTreeNode();
NodeL1.NavigateUrl="#";
NodeL1.Text=state.Name+":"+state.Description;
foreach(CompositeActivitycactiveinstate.Activities)
{
NodeL2=newTreeNode();
NodeL2.NavigateUrl="#";
NodeL2.Text=cactive.Name+":"+cactive.Description;
NodeL1.ChildNodes.Add(NodeL2);
}
MainNode.ChildNodes.Add(NodeL1);
}
MainNode.ExpandAll();
TreeView1.Nodes.Add(MainNode);
//btnReadGuid_Click(btnReadGuid,null);
}
}
CreateBill.aspx(创建修改报销单)
填写表单,根据金额判断跳转到老板,还是财务(跳转是在程序中控制的,其实也可以在工作流里控制,有情趣的可以自己改改)
代码
protectedvoidbtnOk_Click(objectsender,EventArgse)
{
if(TextBox1.Text.Length>0)
{
GuidInstanceId=newGuid(TextBox1.Text);
BillServerbillserver=(Application[MyWorkHelpr.WorkflowRuntimeName]asWorkflowRuntime).GetService<BillServer>();
ManualWorkflowSchedulerServicescheduler=(Application[MyWorkHelpr.WorkflowRuntimeName]asWorkflowRuntime).GetService<ManualWorkflowSchedulerService>();
decimalmoney=decimal.Parse(txt3.Text);
if(money<1)return;
stringwsPath=HttpContext.Current.Server.MapPath("~/App_Data/WorkflowSave/");
//如果已经有数据取得
BillModelmodel=FileTools.XmlDeserializeObject(wsPath
,InstanceId
,typeof(BillModel))asBillModel;
if(model==null)model=newBillModel();
model.BillId=txt1.Text;
model.Money=money;
model.UserName=txt2.Text;
if(model.Money>1000)
{//流转到老板
billserver.RaiseEvent("BillInitMoneyMax",InstanceId);
}
else
{//流转到财务
billserver.RaiseEvent("BillInitMoneyMin",InstanceId);
}
//流转工作流
scheduler.RunWorkflow(InstanceId);
TextBox1.Text="";
//保存更改的数据
FileTools.XmlSerializeObject(wsPath
,InstanceId
,model);
//this.Response.Redirect("default.aspx",false);
}
}
Finance.aspx(财务)
页面加载显示财务应该处理的流程,选择一个正在进行的流程进行审批,动态取得审批方式到下拉框(审批方式是工作流设计器上设计的)、如果需要可以动态增加一个老板加签
代码说明
动态取得审批方式到下拉框的代码
protectedvoidbtnReadGuid_Click(objectsender,EventArgse)
{
strings=txtGuid.Text.Trim();
if(s.Length>0)
{
GuidinstanceId=newGuid(s);
//取得当前工作流里正在进行的StateMachineWorkflow(这里是stateFinance)
StateMachineWorkflowInstancestateInstance=newStateMachineWorkflowInstance(Application[MyWorkHelpr.WorkflowRuntimeName]asWorkflowRuntime,instanceId);
using(DataTabledt=newDataTable())
{
//创建一个下拉框用的DataTable
dt.Columns.Add("NID",typeof(string));//保存EventDrivenActivity的名字,在确定时使用
dt.Columns.Add("NTEXT",typeof(string));//保存EventDrivenActivity的说明
dt.Rows.Add("-1","==请选择==");
inti=0;
foreach(ActivityactinstateInstance.CurrentState.EnabledActivities)
{//循环当前流程可以用的Activitie(在本步骤就是设计器里的stateFinance中的那些EventDrivenActivity)
if(actisEventDrivenActivity)
{
EventDrivenActivityedact=(EventDrivenActivity)act;
if(edact.EnabledActivities.Count>0&&edact.EnabledActivities[0]isHandleExternalEventActivity)
{//取得每个EventDrivenActivity中第一个HandleExternalEventActivity把名字和说明放到dt中
dt.Rows.Add(edact.Name,act.Description);
}
}
i++;
}
//DataBind
DropDownList1.DataValueField="NID";
DropDownList1.DataTextField="NTEXT";
DropDownList1.DataSource=dt;
DropDownList1.DataBind();
}
}
}
动态加签的代码
protectedvoidButton2_Click(objectsender,EventArgse)
{
strings=txtGuid.Text.Trim();
if(s.Length>0)
{
GuidinstanceId=newGuid(s);
WorkflowInstanceworkInstance=(Application[MyWorkHelpr.WorkflowRuntimeName]asWorkflowRuntime).GetWorkflow(instanceId);
//取得整个工作流对象
StateMachineWorkflowActivityactivity=(StateMachineWorkflowActivity)workInstance.GetWorkflowDefinition();
//用WorkflowChanges榜定activity
WorkflowChangeswfc=newWorkflowChanges(activity);
//取得财务的StateActivity
StateActivitystate=(StateActivity)wfc.TransientWorkflow.Activities["stateFinance"];
if(state.Activities["eveToBoss"]!=null)return;
//声明一个外部事件
HandleExternalEventActivityexternalEveTmp=newHandleExternalEventActivity();
externalEveTmp.EventName="BillInsert";
externalEveTmp.InterfaceType=typeof(MyWorkflows.IBILLService);
externalEveTmp.Name="externalEveTmp";
//设置一个跳转
SetStateActivitysetActTmp=newSetStateActivity();
setActTmp.Name="setActTmp";
setActTmp.TargetStateName="stateBoss";
EventDrivenActivityEventDrivenTmp=newEventDrivenActivity();
EventDrivenTmp.Activities.Add(externalEveTmp);
EventDrivenTmp.Activities.Add(setActTmp);
EventDrivenTmp.Description="*老板加签*";
EventDrivenTmp.Name="eveToBoss";
//挂起
workInstance.Suspend("正在加签");
//财务的StateActivity中加入一个EventDrivenActivity
state.Activities.Add(EventDrivenTmp);
ValidationErrorCollectionerr=wfc.Validate();
//应用更改
workInstance.ApplyWorkflowChanges(wfc);
//恢复
workInstance.Resume();
btnReadGuid_Click(btnReadGuid,newEventArgs());
}
}
确定按扭时使用 下拉框 里的审批方式
protectedvoidButton1_Click(objectsender,EventArgse)
{
strings=txtGuid.Text.Trim();
if(s.Length>0&&DropDownList1.SelectedValue!="-1")
{
//取得下拉框选择的valuebtnReadGuid_Click中取得的
stringnid=DropDownList1.SelectedValue;
GuidinstanceId=newGuid(s);
BillServerbillserver=(Application[MyWorkHelpr.WorkflowRuntimeName]asWorkflowRuntime).GetService<BillServer>();
ManualWorkflowSchedulerServicescheduler=(Application[MyWorkHelpr.WorkflowRuntimeName]asWorkflowRuntime).GetService<ManualWorkflowSchedulerService>();
StateMachineWorkflowInstancestateInstance=newStateMachineWorkflowInstance(Application[MyWorkHelpr.WorkflowRuntimeName]asWorkflowRuntime,instanceId);
//通过名称取得EventDrivenActivity
EventDrivenActivityedact=(EventDrivenActivity)stateInstance.CurrentState.Activities[nid];
//和第一个HandleExternalEventActivity
HandleExternalEventActivityheva=(HandleExternalEventActivity)edact.EnabledActivities[0];
//WorkflowInstanceworkInstance=stateInstance.WorkflowInstance;
//BillWorkflowact=stateInstance.WorkflowInstance.GetWorkflowDefinition()asBillWorkflow;
stringwsPath=HttpContext.Current.Server.MapPath("~/App_Data/WorkflowSave/");
BillModelmodel=FileTools.XmlDeserializeObject(wsPath
,instanceId
,typeof(BillModel))asBillModel;
model.LastRemark=model.Fremark=string.Concat("财务:",DropDownList1.SelectedItem.Text,":",txtRemark.Text);
//通过HandleExternalEventActivity.EventName调用BillServer.RaiseEvent触发外部事件使工作流向前运行
//这就是我为上一章何在BillServer重写那些事件的原因
billserver.RaiseEvent(heva.EventName,instanceId);
//工作流向下流转
scheduler.RunWorkflow(instanceId);
FileTools.XmlSerializeObject(wsPath,instanceId,model);
DropDownList1.Items.Clear();
txtGuid.Text="";
//stateInstance.CurrentStateName
return;
////如果用过一次要删除
//if(edact.Name=="eveToBoss")//删除加签
//{
////WorkflowInstanceworkInstance=(Application[MyWorkHelpr.WorkflowRuntimeName]asWorkflowRuntime).GetWorkflow(instanceId);
//workInstance.Suspend("正在删除加签");
//StateMachineWorkflowActivityactivity=workInstance.GetWorkflowDefinition()asStateMachineWorkflowActivity;
//WorkflowChangeswfc=newWorkflowChanges(activity);
////StateActivitysa=wfc.TransientWorkflow.Activities["stateFinance"]asStateActivity;
//StateActivitystate=(StateActivity)wfc.TransientWorkflow.Activities["stateFinance"];
//state.Activities.Remove(state.Activities["eveToBoss"]);
//ValidationErrorCollectionerr=wfc.Validate();
//workInstance.ApplyWorkflowChanges(wfc);
//workInstance.Resume();
////this.Response.Redirect("");
//}
}
}
Boss.aspx(老板)
页面加载显示老板应该处理的流程,选择一个正在进行的流程进行审批,动态取得审批方式到下拉框
PayBox.aspx(出纳)
页面加载显示出纳应该处理的流程,选择一个正在进行的流程进行审批,动态取得审批方式到下拉框
OutMoney.aspx(取钱确认)
页面加载子显示出纳审批Ok 的流程,选择一个正在进行的流程确认以读取,动态取得审批方式到下拉框
说明
其实重财务以后的页面处理方式都基本是一样的,界面也都类似,不再多说...