• WF4.0实战(三):WCF服务


        这篇文章,通过一个简单的WCF交互,讲解一下WF4.0中一组重要活动:Messaging,它包括:Receive
    、ReceiveAndSendReply、Send、SendAndReceiveReply。这里将详细讲解ReceiveAndSendReply和SendAndReceiveReply两个活动的配置以及使用,以及它与普通的WCF的区别。

        如果你了解WCF,你一定知道WCF可以缩略为ABC。A :Address (服务在哪里?),B: Binding (怎么才能访问服务?),C: Contract (提供了哪些服务?)。既然同样也是WCF服务,WF4.0中WCF服务同样也存在ABC的概念。我将一步一步通过实现WF中的wcf服务的ABC来实现这个Demo,请你注意它与普通的WCF的区别。

         首先,我们定义一下用于数据交换的实体。

         定义Request消息ReservationRequest

    代码
     1  [MessageContract(IsWrapped = false)]
     2     public class ReservationRequest
     3     {
     4         private String _ISBN;
     5         private String _Title;
     6         private String _Author;
     7         private Guid _RequestID;
     8         private Branch _Requester;
     9         private Guid _InstanceID;
    10 
    11         #region Constructors
    12         public ReservationRequest()
    13         {
    14         }
    15 
    16         public ReservationRequest(String title, String author, String isbn,
    17             Branch requestor)
    18         {
    19             _Title = title;
    20             _Author = author;
    21             _ISBN = isbn;
    22             _Requester = requestor;
    23             _RequestID = Guid.NewGuid();
    24         }
    25 
    26         public ReservationRequest(String title, String author, String isbn,
    27             Branch requestor, Guid id)
    28         {
    29             _Title = title;
    30             _Author = author;
    31             _ISBN = isbn;
    32             _Requester = requestor;
    33             _RequestID = id;
    34         }
    35         #endregion Constructors
    36 
    37         #region Public Properties
    38         [MessageBodyMember]
    39         public String Title
    40         {
    41             get { return _Title; }
    42             set { _Title = value; }
    43         }
    44 
    45         [MessageBodyMember]
    46         public String ISBN
    47         {
    48             get { return _ISBN; }
    49             set { _ISBN = value; }
    50         }
    51 
    52         [MessageBodyMember]
    53         public String Author
    54         {
    55             get { return _Author; }
    56             set { _Author = value; }
    57         }
    58 
    59         [MessageBodyMember]
    60         public Guid RequestID
    61         {
    62             get { return _RequestID; }
    63             set { _RequestID = value; }
    64         }
    65 
    66         [MessageBodyMember]
    67         public Branch Requester
    68         {
    69             get { return _Requester; }
    70             set { _Requester = value; }
    71         }
    72 
    73         [MessageBodyMember]
    74         public Guid InstanceID
    75         {
    76             get { return _InstanceID; }
    77             set { _InstanceID = value; }
    78         }
    79         #endregion Public Properties
    80     }

    定义Response消息ReservationResponse:

    代码
     1  [MessageContract(IsWrapped = false)]
     2     public class ReservationResponse
     3     {
     4         private bool _Reserved;
     5         private Branch _Provider;
     6         private Guid _RequestID;
     7 
     8         #region Constructors
     9         public ReservationResponse()
    10         {
    11         }
    12 
    13         public ReservationResponse(ReservationRequest request, bool reserved,
    14             Branch provider)
    15         {
    16             _RequestID = request.RequestID;
    17             _Reserved = reserved;
    18             _Provider = provider;
    19         }
    20         #endregion Constructors
    21 
    22         #region Public Properties
    23         [MessageBodyMember]
    24         public bool Reserved
    25         {
    26             get { return _Reserved; }
    27             set { _Reserved = value; }
    28         }
    29 
    30         [MessageBodyMember]
    31         public Branch Provider
    32         {
    33             get { return _Provider; }
    34             set { _Provider = value; }
    35         }
    36 
    37         [MessageBodyMember]
    38         public Guid RequestID
    39         {
    40             get { return _RequestID; }
    41             set { _RequestID = value; }
    42         }
    43         #endregion Public Properties
    44     }

    服务端的实现

    一、C(Contract )

    定义这个服务具体提供了哪些服务:

    1     [ServiceContract]
    2     public interface ILibraryReservation
    3     {
    4         [OperationContract]
    5         void RequestBook(ReservationRequest request);
    6 
    7         [OperationContract]
    8         void RespondToRequest(ReservationResponse response);
    9     }

    这里定义了两个方法:RequestBook、RespondToRequest。在普通的WCF中,一般做法是:通过一个类继承这个接口。在类中实现wcf的具体内容。而在WF4.0中,这里我将使用Messaging中的活动:ReceiveAndSendReply。

    1、新建一个控制台应用程序WF3Demo:

    注意:这里创建的是Console Application。而不是WorkflowConsoleApplication。

    2、添加下面这些引用:

        System.Activities.dll

        System.ServiceModel.dll

        System.ServiceModel.Activities.dll

    3、创建一个自定义活动CreateResponse,它用于创建返回给客户端的ReservationResponse对象,代码如下:

     1  //这种是一个自定义的活动,用于创建一个ReservationResponse对象
     2     public sealed class CreateResponse : CodeActivity
     3     {
     4         public InArgument<ReservationRequest> Request { getset; }
     5         public InArgument<bool> Reserved { getset; }
     6         public OutArgument<ReservationResponse> Response { getset; }
     7 
     8         protected override void Execute(CodeActivityContext context)
     9         {
    10             // 打开配置文件
    11             Configuration config = ConfigurationManager
    12                 .OpenExeConfiguration(ConfigurationUserLevel.None);
    13             AppSettingsSection app =
    14                 (AppSettingsSection)config.GetSection("appSettings");
    15 
    16             // 创建ReservationResponse对象
    17             ReservationResponse r = new ReservationResponse
    18                 (
    19                     Request.Get(context),
    20                     Reserved.Get(context),
    21                     new Branch
    22                     {
    23                         BranchName = app.Settings["Branch Name"].Value,
    24                         BranchID = new Guid(app.Settings["ID"].Value),
    25                         Address = app.Settings["Address"].Value
    26                     }
    27                 );
    28             // 将Response保存到OutArgument
    29             Response.Set(context, r);
    30         }
    31     }

    5、添加一个名字为ProcessRequest工作流,在其中拖放一个ReceiveAndSendReply。

        在ProcessRequest添加如下变量:

    设置Receive活动:

        OperationName:RequestBook

        Content: 设置Message data为request、设置Message type为ReservationRequest

        ServiceContractName:ILibraryReservation

        ILibraryReservation:true

    设置SendReply

    Content: 设置Message data为response、设置Message type 为ReservationResponse,如下图:

    6、为了更好的诠释服务,在Receive活动和SendReply活动之间加入如下图活动,详细见代码。

    这样我们定义好了 Contract

    二、B(Binding)和A(Address )

        C实现之后,Binding和Address就简单了。这里Binding使用BasicHttpBinding,使用如下代码实现B和A:

     1  WorkflowService service = new WorkflowService
     2             {
     3                 Name = "LibraryReservation",
     4                 Body = new ProcessRequest(),
     5                 Endpoints =
     6                 {
     7                     new Endpoint
     8                     {
     9                         ServiceContractName="ILibraryReservation",
    10                         AddressUri = new Uri("http://localhost:" + adr + 
    11                             "/LibraryReservation"),
    12                         Binding = new BasicHttpBinding(),
    13                     }
    14                 }
    15             };
    16 
    17             System.ServiceModel.Activities.WorkflowServiceHost wsh =
    18                 new System.ServiceModel.Activities.WorkflowServiceHost(service);
    19 
    20             wsh.Open();

    至此,WF4中的wcf服务就这样简单的配置好了。

    客户端调用:

        对于调用一般的WCF,可以通过添加service引用或者通过命令自动生成调用wcf的代码。这与WF4.0不同,这里我使用SendAndReceiveReply活动来调用WCF服务。

    1、首先自定义一个活动CreateRequest,用于创建一个提交wcf服务ReservationRequest对象。

     1     public sealed class CreateRequest : CodeActivity
     2     {
     3         public InArgument<string> Title { getset; }
     4         public InArgument<string> Author { getset; }
     5         public InArgument<string> ISBN { getset; }
     6         public OutArgument<ReservationRequest> Request { getset; }
     7         public OutArgument<string> RequestAddress { getset; }
     8 
     9         protected override void Execute(CodeActivityContext context)
    10         {
    11             // 打开配置文件,得到请求的地址
    12             Configuration config = ConfigurationManager
    13                 .OpenExeConfiguration(ConfigurationUserLevel.None);
    14             AppSettingsSection app =
    15                 (AppSettingsSection)config.GetSection("appSettings");
    16 
    17             // 使用输入参数创建一个ReservationRequest对象
    18             ReservationRequest r = new ReservationRequest
    19                 (
    20                     Title.Get(context),
    21                     Author.Get(context),
    22                     ISBN.Get(context),
    23                     new Branch
    24                     {
    25                         BranchName = app.Settings["Branch Name"].Value,
    26                         BranchID = new Guid(app.Settings["ID"].Value),
    27                         Address = app.Settings["Address"].Value
    28                     }
    29                 );
    30 
    31             //将request保存到OutArgument中 
    32             Request.Set(context, r);
    33 
    34             // 将address保存到OutArgument
    35             RequestAddress.Set(context, app.Settings["Request Address"].Value);
    36         }
    37     }

    2、添加一个名字为SendRequest的工作流,在其中拖放一个SendAndReceiveReply活动,以及一个CreateRequest活动,将CreateRequest活动拖放到Send前面。

    3、在ProcessRequest添加如下变量:

     在ProcessRequest添加如下参数:

    4、设置Send:

        OperationName:RequestBook

        Content: 设置Message data为request、设置Message type为ReservationRequest

        ServiceContractName:ILibraryReservation

        Endpoint:Endpoint

        Endpoint.Binding:BasicHttpBinding

        EndpointAddress:New Uri("http://localhost/:" + requestAddress + "/LibraryReservation")

    5、设置ReceiveReplyForSend

        将ReceiveReplyForSend的Content的Message data设为response,将ReceiveReplyForSend的Content的Message type设为ReservationResponse

    6、为了便于观察,添加几个WriteLine用于输出,如下图,详见代码:

    这样设置好了客户端。

    使用wcf服务:

    我们只需启动ProcessRequest这个工作流来调用wcf服务:

     1             IDictionary<stringobject> input = new Dictionary<stringobject> 
     2             {
     3                 { "Title" , "Gone with the Wind" },
     4                 { "Author""Margaret Mitchell" },
     5                 { "ISBN""9781416548898" }
     6             };
     7 
     8             IDictionary<stringobject> output =
     9                 WorkflowInvoker.Invoke(new SendRequest(), input);
    10             ReservationResponse resp = (ReservationResponse)output["Response"];

    运行程序:

    启动WCF服务。等待客户端的调用,如下图:

    输入回车,启动客户端的工作流,来调用WCF服务,输入结果如下:

    整个运行的过程

    如下图:

    总结:

        这篇文章讲述了在WF4.0中使用WCF服务。WF中的WCF与普通的WCF,在原理上是一致的,但是在形式上区别很大。WF4.0中提供了一组活动,这样比直接使用WCF更加简单和直观。

    欢迎加入博客园WF4.0技术交流群:51262864

    下载1:XMAL工作流代码

    下载2:CS工作流代码下载



    (全文完)


    以下为广告部分

    您部署的HTTPS网站安全吗?

    如果您想看下您的网站HTTPS部署的是否安全,花1分钟时间来 myssl.com 检测以下吧。让您的HTTPS网站变得更安全!

    SSL检测评估

    快速了解HTTPS网站安全情况。

    安全评级(A+、A、A-...)、行业合规检测、证书信息查看、证书链信息以及补完、服务器套件信息、证书兼容性检测等。

    SSL证书工具

    安装部署SSL证书变得更方便。

    SSL证书内容查看、SSL证书格式转换、CSR在线生成、SSL私钥加解密、CAA检测等。

    SSL漏洞检测

    让服务器远离SSL证书漏洞侵扰

    TLS ROBOT漏洞检测、心血漏洞检测、FREAK Attack漏洞检测、SSL Poodle漏洞检测、CCS注入漏洞检测。

  • 相关阅读:
    Tomcat单独部署,控制台乱码解决方法
    mysql授权访问数据库
    Arrays.binarySearch采坑记录及用法
    使用Spring Ehcache二级缓存优化查询性能
    Redis批量删除缓存数据
    Java并发包之Semaphore用法
    Java并发包之CountDownLatch用法
    如何用Xshell导出文件到桌面本地
    Semaphore信号量原理
    老应用链接替换到新链接
  • 原文地址:https://www.cnblogs.com/zhuqil/p/wfserver.html
Copyright © 2020-2023  润新知