转:工作流服务Workflow Service(1):ReceiveActivity

转:http://www.cnblogs.com/carysun/archive/2009/01/11/receiveactivity.html

在.NET3.5中WF提供了和WCF的整合,就是工作流服务,即使用工作流创作的 WCF服务。服务协定的实现是通过一个或多个 ReceiveActivity 活动处理的。
在WCF中提供了三种消息交换模式分别为One-Way Calls,Request/Response和Duplex,在工作流服务中只支持One-Way Calls和Request/Response两种模式。

下面就举例说明,新建一个顺序工作流库CaryWFLib项目

1.先定义服务契约接口,我们建立的是一个无状态的工作流服务,所以要设置如下SessionMode = SessionMode.NotAllowed

namespace CaryWFLib
{[ServiceContract(Namespace = "http://CaryWF",SessionMode = SessionMode.NotAllowed)]public interface IAddService{[OperationContract]Double Add(Double num1, Double num2);}
}

2.在工作流设计器中拖入ReceiveActivity,设置ServiceOperationInfo属性,该属性来实现的协定和服务操作,如下图:

WFService1

3.设置该活动的CanCreateInstance属性为true,当服务客户端调用时,服务将创建工作流的新实例。 如果设置为 false,客户端无法使用服务操作调用来创
建工作流的新实例,只能使用关联的 WorkflowRuntime 对象的 CreateWorkflow 方法可以创建。

在IIS中宿主工作流服务

主要通过以下步骤:

1.创建AddServiceWorkflow.svc放到IIS虚拟目录中,代码如下:

<%@ServiceHost language=c# Debug="true" Service="CaryWFLib.AddWorkflow" 
Factory="System.ServiceModel.Activation.WorkflowServiceHostFactory" %>
 

2.增加web.config文件,在web.config中我加载了持久化服务,当然我已经建立好了持久化数据库,代码如下:

<?xml version="1.0" encoding="utf-8" ?>
<configuration><system.serviceModel><services><service name="CaryWFLib.AddWorkflow"behaviorConfiguration="ServiceBehavior"><endpoint address="" binding="wsHttpContextBinding" contract="CaryWFLib.IAddService"/></service></services><behaviors><serviceBehaviors><behavior name="ServiceBehavior"><serviceMetadata httpGetEnabled="true"/><serviceDebug includeExceptionDetailInFaults="true"/><workflowRuntime name="WorkflowServiceHostRuntime"validateOnCreate="true"enablePerformanceCounters="true"><services><add type="System.Workflow.Runtime.Hosting.SqlWorkflowPersistenceService,System.Workflow.Runtime,Version=3.0.00000.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35"connectionString="Initial Catalog=WorkflowPersistence;Data Source=localhost\SQLEXPRESS; Integrated Security=SSPI; Trusted_Connection=True;"LoadIntervalSeconds="1" UnLoadOnIdle="true" /></services></workflowRuntime></behavior></serviceBehaviors></behaviors></system.serviceModel><system.web><compilation><assemblies><add assembly="System.WorkflowServices,Version=3.5.0.0,Culture=neutral,PublicKey Token=31bf3856ad364e35"/></assemblies></compilation></system.web>
</configuration>

3.将编译后生成的CaryWFLib.dll放到IIS的虚拟目录的bin目录下

4.然后你就可以在浏览器中输入http://localhost/CaryWFWCF/AddServiceWorkflow.svc来测试是否部署成功了。

5.有几点要注意的:

5.1.在使用iis承载wcf时,如果遇到无法访问iis元数据的权限的错误,可以使用如下命令

      aspnet_regiis –ga <WindowsUserAccount>来给制定用户权限。

5.2.无法打开登录所请求的数据库 "WorkflowPersistence"。登录失败。用户 XXXX\ASPNET' 登录失败。

这个时候需要给aspnet用户访问持久化数据库的权限,可以将aspnet用户添加到state_persistence_users角色中,该角色是随着持久化数据库创建
而产生的。我使用的是express版,我的方法是利用sql server 2005外围应用配置器的添加新管理员,将aspnet账户添加为管理员。

5.3.如果在安装 WCF之后安装了 IIS,必须运行以下命令:

"%WINDIR%\Microsoft.Net\Framework\v3.0\Windows Communication Foundation\ServiceModelReg.exe" -r

这将在 IIS 中注册所需的脚本映射。 还必须确保将 .svc 文件类型映射到 aspnet_isapi.dll。  

创建客户端测试

1.在你的项目中添加服务引用,添加完成后,项目中会自动添加System.ServiceModel和System.Runtime.Serialization引用,和App.config配置文件。

测试代码如下:

namespace AddServiceConsole
{class Program{static void Main(string[] args){try{AddServiceClient client = new AddServiceClient();Console.WriteLine("Server endpoint: {0}", client.Endpoint.Address.ToString());Double result = client.Add(1, 2);Console.WriteLine("1加2的结果为:{0}", result);client.Close();}catch (Exception exception){Console.WriteLine("未处理的异常: {0} - {1}", exception.GetType().Name, exception.Message);}Console.WriteLine("Press any key to exit");Console.ReadKey();}}
}

2.结果如下:

WFService2

手动宿主工作流服务

1.代码如下:

WorkflowServiceHost serviceHost = null;try{               serviceHost = new WorkflowServiceHost(typeof(CaryWFLib.AddWorkflow));  
serviceHost.Description.Behaviors.Find<WorkflowRuntimeBehavior>().WorkflowRuntime.WorkflowCompleted
+= delegate(object sender, WorkflowCompletedEventArgs e) { Console.WriteLine("WorkflowCompleted: " + e.WorkflowInstance.InstanceId.ToString()); };
              serviceHost.Open();if (serviceHost.Description.Endpoints.Count > 0){Console.WriteLine("Contract: {0}",serviceHost.Description.Endpoints[0].Contract.ContractType);Console.WriteLine("Endpoint: {0}",serviceHost.Description.Endpoints[0].Address);}Console.WriteLine("Press any key to exit");Console.ReadKey();}catch (Exception exception){Console.WriteLine("Exception hosting service: {0}",exception.Message);}finally{try{                    if (serviceHost != null){serviceHost.Close(new TimeSpan(0, 0, 10));}}catch (CommunicationObjectFaultedException exception){Console.WriteLine("CommunicationObjectFaultedException on close: {0}",exception.Message);}catch (TimeoutException exception){Console.WriteLine("TimeoutException on close: {0}",exception.Message);}}

2.手动宿主要使用WorkflowServiceHost类为基于工作流的服务提供主机。使用 WorkflowServiceHost 对象可加载工作流服务、配置终结点、应用
安全设置并启动侦听器来处理传入的请求。

3.可以通过如下代码来得到WorkflowRuntime:

serviceHost.Description.Behaviors.Find<WorkflowRuntimeBehavior>().WorkflowRuntime 

4.然后要配置app.config文件,如下:

<?xml version="1.0" encoding="utf-8" ?>
<configuration><system.serviceModel><services><service name="CaryWFLib.AddWorkflow"behaviorConfiguration="ServiceBehavior" ><host><baseAddresses><add baseAddress=http://localhost:8802/CaryWFWCF/AddServiceWorkflow.svc /></baseAddresses></host><endpoint address="" binding="basicHttpBinding"contract="CaryWFLib.IAddService" /></service></services><behaviors><serviceBehaviors><behavior name="ServiceBehavior"  ><serviceMetadata httpGetEnabled="true" /><serviceDebug includeExceptionDetailInFaults="true" /><workflowRuntime name="WorkflowServiceHostRuntime"validateOnCreate="true"enablePerformanceCounters="true"><services><add type="System.Workflow.Runtime.Hosting.SqlWorkflowPersistenceService, System.Workflow.Runtime, Version=3.0.00000.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"connectionString="Initial Catalog=WorkflowPersistence;Data Source=localhost\SQLEXPRESS;Integrated Security=SSPI;"LoadIntervalSeconds="1" UnLoadOnIdle= "true" /></services></workflowRuntime></behavior></serviceBehaviors></behaviors></system.serviceModel>
</configuration>

运行自己host的程序后,就可以使用前面的测试程序来再次测试,测试得到的结果是一样。

工作流服务创作样式

协定优先

协定优先的工作流服务是一种使用预先存在的服务协定信息的工作流。 我们上面的例子使用的都是这种方式,他的服务契约部分和WCF是一样的方式。

工作流优先

WF还支持另一种叫做工作流优先的模型,在ReceiveActivity的ServiceOperationInfo属性对话框中可以直接添加约定就是这种方式。在自动生成的代码中
是使用 ContractName 属性定义的,而操作名称是使用 Name 参数设置的。 操作的参数(包括返回值)是使用 OperationParameterInfo 类并将每个参数
添加到 OperationInfo 对象的参数集合中。下面的例子我就将使用这种方式。

工作流服务中的安全性

工作流服务为服务提供两个级别的安全性。 在第一个级别中,您可对操作指定原则权限安全性。 服务运行时会在将消息传递到工作流之前检查权限。 如果消息不满足原则权限安全性,则不会将消息发送到工作流。 第二个级别是“操作验证条件”,OperationValidation事件在ReceiveActivity活动即将收到消息时激发。可以使用关联的处理程序来执行基于 ClaimSet 的安全检查,以对由 ReceiveActivity活动实现的服务操作的客户端调用进行授权,如果OperationValidationEventArgs.IsValid设置为 false 会拒绝服务操作调用,并且客户会收到 FaultException。如果将 OperationValidationEventArgs.IsValid设置为 true,则服务操作调用将成功完成,并且 ReceiveActivity活动将接收并处理消息。下面我就举例说明:
1.我们新建一个WFFirstWorkflow并实现同样的加法运算的功能,这次我们使用的是工作流优先的创作样式,并指定只允许 Administrators 组中的用户调用此操作。具体如下图所示:

WFService3

ReceiveActivity的OperationValidation事件的代码如下:

public string owner;
private void AddValidate(object sender, OperationValidationEventArgs e){           if (string.IsNullOrEmpty(owner)){owner = ExtractCallerName(e.ClaimSets);e.IsValid = true;Console.WriteLine("Owner: " + owner);}if (owner.Equals(ExtractCallerName(e.ClaimSets)))e.IsValid = true;}private string ExtractCallerName(ReadOnlyCollection<ClaimSet> claimSets){string owner = string.Empty;foreach (ClaimSet claims in claimSets){foreach (Claim claim in claims){if (claim.ClaimType.Equals(ClaimTypes.Name) && claim.Right.Equals(Rights.PossessProperty)){owner = claim.Resource.ToString();break;}}}return owner;}

2.AddValidate方法的OperationValidationEventArgs 参数的ClaimSets属性中存储ClaimSet对象的集合,这些对象包含已添加到操作的授权上下文的声明。 我们就使用这些声明集来完成消息验证。 注意,此时实际的消息正文参数尚不可用。 ExtractCallerName 方法从 Name 声明中提取调用方名称并将其存储起来。 在后续请求中,将根据传入消息的 Name 声明检查调用方名称,以便验证发送第一个消息(导致实例创建)和发送后续消息的是否是同一个人。

可以使用上面的方面来宿主并进行相关测试。

作者:生鱼片
    
出处:http://carysun.cnblogs.com/
    
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

转载于:https://www.cnblogs.com/ookami/p/3969899.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/290717.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

论敏捷管理与团队文化的契合度

前言说到敏捷管理&#xff0c;很多程序员或者软件开发公司的管理人员第一反应就是“小步快跑&#xff0c;频繁发布”。这令公司决策层&#xff08;老板&#xff09;觉得敏捷能解决一切问题&#xff0c;想啥时候上线就啥时候上线。其实这只是一种表象。要深刻理解敏捷的本质和内…

Echart..js插件渲染报错 data.length1?

问题 getJSON提交 返回数据正常&#xff0c;在传入参数进行序列化&#xff0c;渲染报表时报错 option.data.length < 1. 分析 1.可能情况一: . 可自己明明是getJSON()把渲染放在成功回调函数里面了&#xff0c;所以显然不是这个错误 2.可能情况二 &#xff1a; 序列化数据没…

LeetCode之Valid Parentheses

1、题目 Given a string containing just the characters (, ), {, }, [ and ], determine if the input string is valid. The brackets must close in the correct order, "()" and "()[]{}" are all valid but "(]" and "([)]" are…

《JavaScript专家编程》——第1章 对象和原型 1.1鸟瞰JavaScript

本节书摘来自异步社区《JavaScript专家编程》一书中的第1章&#xff0c;第1.1节&#xff0c;作者&#xff1a;【美】Mark Daggett&#xff08;达格特&#xff09;著&#xff0c;更多章节内容可以访问云栖社区“异步社区”公众号查看 第1章 对象和原型 练习不会造就完美&#xf…

c#使用PdfiumViewer展示、打印pdf文档

1:简介PdfiumViewer 是一个 WinForms 控件&#xff0c;它承载一个 PdfRenderer 控件并添加一个工具栏来保存或打印 PDF 文件2:兼容性除了常规的win7 win10 也支持xp win83:对比Spire.Pdf和Adobe PDF ReaderSpire.Pdf收费且免费版只能打印三页的pdfAdobe PDF Reader每台电脑都必…

apache 静态编译和动态编译参考

apache-2.2.22 编译安装笔记 一、静态编译 在使用./configure 编译的时候&#xff0c;即没有使用--enable-mods-shared[module]或者--enable-[module]shared这2个中的一个&#xff0c;那么所有的默认模块为静态。何谓静态&#xff1f; 其实就是编译的时候所有的模块自己编译进h…

jQuery插件ASP.NET应用之AjaxUpload

本次使用AJAXUPLOAD做为上传客户端无刷上传插件&#xff0c;其最新版本为3.9&#xff0c;官方地址&#xff1a;http://valums.com/ajax-upload/ 在页面中引入 jquery.min.1.4.2.js 和 ajaxupload.js Html代码 <script src"Scripts/jquery-1.4.2.min.js" type&quo…

LeetCode之Remove Element

1、题目 Given an array and a value, remove all instances of that value in place and return the new length. Do not allocate extra space for another array, you must do this in place with constant memory. The order of elements can be changed. It doesnt matter…

运维前线:一线运维专家的运维方法、技巧与实践导读

前  言为什么要写这本书《运维前线&#xff1a;一线运维专家的运维方法、技巧与实践》&#xff08;以下简称《运维前线》&#xff09;是前线系列的一个子集&#xff0c;前线系列图书的出版理念是邀请多位业界专家&#xff0c;总结所在行业的最新理念或深度实践经验。前线系列…

Avalonia跨平台入门第十一篇之自定义Window

在前面分享的几篇中咱已经玩耍了Popup、ListBox多选、Grid动态分、RadioButton模板、控件的拖放效果、控件的置顶和置底、控件的锁定;今天趁着周末接着去摸索自定义Window样式,毕竟自带的样式不太让人满意;最终实现的效果如下图:前台Window样式:后台Window代码:咱也基于AvalonS…

开发文档收集

http://docs.jboss.org/hibernate/orm/4.1/manual/en-US/html_single/ http://docs.jboss.org/hibernate/orm/4.1/devguide/en-US/html_single 转载于:https://www.cnblogs.com/happyday56/p/4709045.html

ie8下修改input的type属性报错

摘要&#xff1a; 现在有一个需求如图所示&#xff0c;当用户勾选显示明文复选框时&#xff0c;要以明文显示用户输入的密码&#xff0c;去掉勾选时要变回密文&#xff0c;刚开始想到的就是修改输入框的type来决定显示明文还是密文&#xff0c;使用jQuery的attr来做试验&#x…

LeetCode之Count and Say

1、题目 The count-and-say sequence is the sequence of integers with the first five terms as following: 1. 1 2. 11 3. 21 4. 1211 5. 1112211 is read off as "one 1" or 11.11 is read off as "two 1s" or 21.21 is read off …

《SAP入门经典(第4版•修订版)》——2.5 4种视角相互结合

本节书摘来自异步社区《SAP入门经典&#xff08;第4版•修订版&#xff09;》一书中的第2章&#xff0c;第2.5节&#xff0c;作者&#xff1a;【美】George Anderson著&#xff0c;更多章节内容可以访问云栖社区“异步社区”公众号查看 2.5 4种视角相互结合 SAP入门经典&#x…

dotNet Core使用SignalR实现websocket

前言:最近有一个公司项目做一个排队叫号系统&#xff0c;系统功能不复杂&#xff0c;所以后端就我一人&#xff0c;难点在于消息推送到安卓屏上&#xff0c;最近有点时间&#xff0c;把我工作中使用的技术分享出来&#xff01;整个技术架构:前端使用vue uniapp&#xff0c;后端…

JPA和hibernate的关系

实际上&#xff0c;JPA的标准的定制是hibernate作者参与定制的&#xff0c;所以JPA是hibernate的一个总成&#xff0c;可以这么理解转载于:https://www.cnblogs.com/cyh2009/p/4709465.html

nagios监控mysql(check_mysql)及内存使用率(check_mem)

一、监控本地&#xff08;localhost&#xff09;内存1、上传监控脚本 check_mem 到/usr/local/nagios/libexec# chown -R nagios.nagios check_mem # chmod x check_mem2、修改commands配置# vim /usr/local/nagios/etc/objects/commands.cfg define command{command_name …

Android之jni编译报错comparsion between signed and unsigned integer expressions解决办法

1、问题 jni编译报错comparsion between signed and unsigned integer expressions 2、原因 在for循环里面&#xff0c;不能用无符号32整形数据作为判断条件 2、解决办法 先把无符号32整形数据强转为整型数据&#xff0c;然后再去作为条件

《手机测试Robotium实战教程》——导读

本节书摘来自异步社区《手机测试Robotium实战教程》一书中的导读&#xff0c;作者 杨志伟&#xff0c;更多章节内容可以访问云栖社区“异步社区”公众号查看 目 录前 言第1章 自动化测试简介 1.1节何为自动化测试1.2节自动化测试和手动测试的对比1.3节移动端自动化测试工具的选…

linux内核的冒险md来源释义# 14raid5非条块读

linux内核的冒险md来源释义&#xff03; 14raid5非条块读转载请注明出处&#xff1a;http://blog.csdn.net/liumangxiong假设是非条块内读。那么就至少涉及到两个条块的读&#xff0c;这就须要分别从这两个条块内读出数据。然后再凑成整个结果返回给上层。接下来我们将看到怎样…