返回首页

目录{A}
注意:这篇文章已被写入使用
建立一个事件驱动的应用解决方案,基于逻辑连接模型(LCM)从物理连接的终端到终端的业务层封装,需要使用适当的技术,在所有层。典型的多层架构与私人中间层顺利转变为分布式的面向服务的架构(SOA)为基础的中间层。
在浏览器中的ActiveX托管调度和处理,而不需要回发在异步方式从服务器的请求和响应对象,如最新的技术。
的XmlHttpRequest使用(JavaScript对象符号)格式,可大大简化其执行任务,而不是使用XML文档导向的风格。
因此,AJAX / JSON的流行语是经常使用的现代Web事件驱动架构。 AJAX / JSON支持的网页,使页面为小部分分离,并以异步方式逐一处理。换句话说,组用户控制器可以异步处理,而不需要回发到Web服务器的所有页面更新过程。
从服务器端,服务必须启用AJAX / JSON的通信。这是在旁边的。NET Framework} {A9称为3.5版本,目前在beta版本。本文是基于这个beta版本,使用新的WebHttpBinding和JSON编码。以后你会看到更多的细节。
我以为你会读到大约的更多细节,了解自己的风格,结构和位置在前端层,特别是在浏览器上的客户端。现在,它的时间来解释WCF和WF技术的作用,在浏览器/工作流系统连接。
下面的图片将帮助我在事件驱动的企业解决方案显示了这些技术中的地位:
{S0}
上面的解决方案是由包含一个终端到结束活动,如业务逻辑背后的WCF服务,网页的介绍与定义的组件,接口和数据合约定义的描述元数据。每个网页在其自己的条目定义知识库工厂的页面,并启用其组件事件驱动的任务。当然,最重要的是,可以有一个根定义导航的所有网站 - 产品等在页面激活,状态机工作流实例标识符发送给浏览器发送的事件消息基于事件的兴趣。它是如何工作?当用户创建一个页面上的特定组件的事件(例如,点击一个按钮),通过JavaScript实现其逻辑将创建一个请求对象(事件消息)为代表的JSON格式的文本,这个过程中激活一个Ajax回调服务响应和调用神奇的XMLHttpRequest对象请求派遣一个特定端点。在服务器端,我们有一个WCF服务端点启用AJAX / JSON的通信。传入的​​消息后,转发到的JSON反序列化的接口契约为基础的工作流实例队列。请注意,所有层也配置的知识基础。在一个非阻塞的过程中的AJAX回调处理程序接收来自服务的响应。
主机和管道的WCF和WF的模型是非常顺利实施的。NET Framework 3.5(测试版)。有两个额外的上下文驱动的工作流活动的发送和接收基于接口合约的消息。
从视图的逻辑连接点,从浏览器的事件感兴趣交付跨越到业务逻辑的AJAX / JSON / WCF / WF的技术 - 工作流活动为代表的事件接收器。这种沟通是完全透明和出版商之间的事件的兴趣和其消费的配置。
的商业活动背后的WCF服务的可重用性是通过增加额外的端点(S)的服务。在我的文章A11}中详细描述发射WF活动背后的WCF服务的概念,本次大会将在这篇文章中使用。
本文的主要目标是通过WCF服务(如另一个客户端)上发射的AJAX / JSON启用页事件的工作流程活动的重点。注意,没有太多的实施为神奇的可重用的代码已经在我上面的在这里完成。
好,让我们开始。
下面的图片显示位于浏览器客户端的工作流活动和事件源所代表的事件接收器之间的逻辑连接。在这种情况下,浏览器是一个长期运行的工作流程,要提出一个事件在fireamp;忘记的方式:

为了接收由事件驱动的活动的事件消息,ExternalDataExchange接口契约必须声明与应用程序特定的事件处理程序。
事件委托有一个标准NET签名显示在下面的行。

public void EventHandler(object sender, ExternalDataEventArgs eventArgs);

EventArgs的代表INSTANCEID,标识,应用程序特定的数据,等如工作流事件的兴趣
事件处理程序,以JSON格式,将有以下符号:{C}
正如你可以看到,事件消息,可以很容易地创建在浏览器端和交付服务端点的反序列化到CLR。
我们需要执行3个简单步骤,以实现AJAX / JSON / WCF / WF的连接:步骤1:服务器 - 主机和管道WCF WF的技术使用svc文件(内联代码)。
JSON启用服务:
{S2}
@ ServiceHost指令可以调用主机的激活类型工厂属性声明。请注意,此自定义类必须从ServiceHostFactoryBase类派生以创建ServiceHost和WorkflowRuntime的对象调用它的抽象方法。有关此指令的更多细节,可以发现
有没有源代码的属性,因此,所有的实施是位于(行)在运行时编译的。svc文件。服务合约,在这个例子中,类ServiceTest1是一个普通的WCF服务的一个操作方法,传入(单程)消息请求。装饰这个自定义属性RKiss.​​WorkflowEventService.WorkflowFireEventAttribute的方法,操作调用将消息转发给接口合同和e.InstanceId价值为基础的工作流队列。注意,该方法的参数可以是任何可序列化的ExternalDataEventArgs派生的复杂类型。有关调用工作流,并通过其队列中的消息的更多细节,是我以前的文章中描述{A14};在这里,我们使用的是其装配。
这是所有这一步。下一步是创建的AJAX / JSON启用服务端点的配置节。第2步:服务配置 - 创建AJAX / JSON的端点
{S3}
我们需要使用的WebHttpBinding结合,使AJAX / JSON使用在端点行为的EnableWebScript对话的端点和反序列化的服务的JSON编码的数据格式设置,以便在JavaScript的eval函数的用法响应。注意,fireamp;忘记事件消息(没有返回值)不需要设置messageEncoding属性。
现在,我们已经在服务端完成所有的事情,我们准备接受一个AJAX / JSON请求。
让我们做的最后一步 - 客户端浏览器。第三步:客户端 - AJAX / JSON启用JavaScript
下面的代码片段显示了一个简单的AJAX / JSON的Web页面使用JavaScript实现。有5个步骤来处理射击事件,目标端点:
// 1: AJAX enabled client

 var xmlHttp ;

 try {xmlHttp=new XMLHttpRequest();}

  catch (e) {try {xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");}

    catch (e) {try {xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");}

      catch (e) {alert("This sample only works in browsers with AJAX support");

        return false;}}}



 // 2: callback

 xmlHttp.onreadystatechange=function()

 {

   if(xmlHttp.readyState==4 /*complete*/)

   {

     // todo - for example: var response=(eval("("+xmlHttp.responseText+")").d);

   }

 }



 // 3: endpoint

 var url = "service11.svc/ajaxEndpoint/Approve";



 // 4: message

 var body =

   '{"sender":"AjaxClient",

     "e":{"batchworkHandler":null,

    "batchworkItem":null,

    "identity":null,

    "instanceId":"2c6b451e-0d7d-4e8b-bc71-8f51e5bf54b0",

     "waitForIdle":true

     }

    }';



 // 5: action

 xmlHttp.open("POST",url,true);

 xmlHttp.setRequestHeader("Content-type","application/json");

 xmlHttp.send(body);

首先,我们需要创建一个ActiveX对象,来处理所有的魔术的请​​求和响应在异步方式(回调)的数据交换。下一步,将创建的JavaScript如URL,以JSON格式的请求体通信参数和设置JSON转换的内容类型标头。在此之后,发送方法被调用。请注意,该方法将立即返回响应号召,这就是为什么我们设置的回调函数的线程不阻塞。换句话说,浏览器已准备就绪,使页面上的另一个事件等。
正如你可以看到,所有的步骤是非常轻量级的。基于这个AJAX / JSON / WCF / WF水暖,我们可以看到更多的功能,浏览器客户端上。例如:页内逻辑的交谈过程中发射组事件(如广播消息(S)一些特定的服务合同),并等待在一个事件接收器(回调函数)的所有响应的集合,然后分发给内页。这种情况是在长期运行的工作流程情况下非常有用。前/后处理进行实弹射击工作流程
转发事件消息从事件源(浏览器)的工作流实例队列,需要了解的实例标识符(GUID)和接口契约来创建工作流队列名称。 ExternalDataEventArgs已为此INSTANCEID财产的,因此,事件源应该以某种方式获得这"票证ID"。否则,服务有责任,触发一个事件的工作流程之前插入票ID。 WorkflowFireEventAttribute前或后发射一个过程,通过经营合同执行逻辑能力。
下面的代码片段显示了如何可以实现基于类型的工作流程前处理射击。注意,浏览器之间的操作和服务合同可以有更多的应用程序特定的参数,以执行特定的前处理。
前处理触发的事件:
{S4}的
正如你可以看到,有一个选项,准备射击上面的代码片断中的工作流事件的过程。在这个例子中,工作流实例已创建基于特定的工作流类型。
我们也可以通过一些初始参数的工作流程,在其服务或从浏览器创建。从服务的返回值是返回给浏览器,转发事件后的工作流程。此操作可视为工作流业务逻辑的谈话开始。
任何其他触发事件可以在fireamp;忘记的方式,直到最后的工作合同将关闭此对话,并返回一个响应从工作流程。
下面的图片显示了一个状态机工作流的事件驱动的AJAX页面的例子:
{五}
和执行的事件之间的AJAX和工作流程驱动的交谈的例子可以像它在下面的代码片段所示:
[ServiceContract]

public class ServiceTest12

{

  // PRE-PROCESS

  [WorkflowFireEvent(Option = WorkflowFireEventOption.After,

    EventName = "Approve",

    EventType = typeof(IWorkflowSimpleEvents))]

  [OperationContract]

  public string BeginApprove(object sender, ExternalDataEventArgs e)

  {

    // Get a reference to the WorkflowRuntime

    WorkflowRuntime wr =

        OperationContext.Current.Host.Extensions.Find<WorkflowRuntime>();



    // Create workflow

    WorkflowInstance wi = wr.CreateWorkflow(typeof(Workflow1));



    // instance id

    e.InstanceId = wi.InstanceId;



    // done

    return e.InstanceId.ToString();

  }



  // PROCESS

  [WorkflowFireEvent(EventType = typeof(IWorkflowSimpleEvents))]

  [OperationContract(IsOneWay = true)]

  public void Approve(object sender, ExternalDataEventArgs e)

  {

  }



  // POST-PROCESS

  [WorkflowFireEvent(Option = WorkflowFireEventOption.Before,

    EventName = "Approve",

    EventType = typeof(IWorkflowSimpleEvents))]

  [OperationContract]

  public string EndApprove(object sender, ExternalDataEventArgs e)

  {

    string retVal = "error";

    AutoResetEvent waitHandle = new AutoResetEvent(false);





    // Get a reference to the WorkflowRuntime

    WorkflowRuntime wr =

        OperationContext.Current.Host.Extensions.Find<WorkflowRuntime>();



    // events from workflow runtime

    wr.WorkflowTerminated += delegate {waitHandle.Set();};

    wr.WorkflowCompleted += delegate(object sender1, 

                WorkflowCompletedEventArgs e1)

    {

      if(e1.WorkflowInstance.InstanceId.Equals(e.InstanceId))

      {

        int counter = (int)e1.OutputParameters["Counter"];

        retVal = string.Format("{0}, counter={1}", 

                e.InstanceId.ToString(), counter);

        waitHandle.Set();

      }

    };



    // wait for finish a job in the workflow

    waitHandle.WaitOne();



    // done

    return retVal;

  }

}

浏览器和工作流程之间的对话有可能出现的情况,但让我们看看在单独的程序集在WCF服务的管道。AJAX / WF {A15}
从连接点的看法,工作流事件接收器和WCF客户端的事件源(用户利益)。下面的图片显示了这个逻辑的模式:
{中六}
有两个如AJAX,服务和工作流的三个层次之间的实际连接。服务是一个普通的WCF服务与一个或多个端点。每个端点可以配置为一个特定的目的地址,绑定,合同和行为的基础上。
第一AJAX和服务之间的连接(1),是在我们的例子描述IFireEventTest经营合同(方法)。我们可以使用本合同由服务接收一个事件消息。装饰为AJAX连接的端点使用的的WebHttpBinding将使接收来自AJAX功能的浏览器的请求,并派遣到服务操作(方法)。
第二个接口合同是通过工作流。请注意,这些合同是完全独立的,他们不希望彼此工作。他们分别在自己的技术而设计的 - 看到他们的装饰品,如ServiceContract和ExternalDataExchange。事件驱动的工作流活动(HEEA)创建一个接口上的合约元数据和工作流实例ID的工作流队列。这是我们的管道概念的关键点,允许传递一个消息体,通过接口合约。
装饰由WorkflowFireEventAttribute的具体经营合同,将定期操作调用所取代WorkflowFireEventOperationInvoker对象以透明的方式处理传入事件信息的工作流。
集成WCF和WF的第一步是必要的,使他们的托管。 。svc文件下面的代码片段显示了一个托管ServiceTest2的例子:
{七}
工厂属性描述的类型将创建ServiceHost和WorkflowRuntime的实例。可通过主机扩展在WorkflowRuntime参考:
WorkflowRuntime wr = 

    OperationContext.Current.Host.Extensions.Find<WorkflowRuntime>();

正如我前面提到的,有两个接口合同和一个服务。下面的代码片段显示了这些项目,包括自定义ExternalDataEventArgs的例子。
上面的代码片段显示,管道大多需要申报的接口和它们的属性。马工作是在{A16}。
的所有有关AJAX / JSON / WCF管道标准。NET Framework 3.0的工作流与HandleExternalEventActivity。
让我们的测试管道的概念。{A17}
射击从AJAX功能的浏览器的工作流程,可以通过以下的解决方案表明:
{S8}
有四个Web测试页面和服务,在上述溶液中不同的场景。在实际测试之前,确保所有的服务都安装在虚拟目录WFService。在成功编译后的解决方案,可以处理下列检查:每个服务应该是通过浏览器打开Workflow1应开放由设计师
要看到什么是在服务器端(包括工作流),请下载此工具将显示所有跟踪消息。此外,我注意到,有一个从我以前的文章在〜/ bin文件夹的大会WorkflowEventService。当然,必须安装,包括SQL脚本。
确定,现在我们要火AjaxClient12页的事件。下图显示了一个事件源和工作流状态机:
{S9}
出于测试目的,测试解决方案有三个国家的简单工作流状态机。事件驱动两个国家,最后一个是超时的状态来完成这个过程时,有10秒没有活动。
上面的测试页会产生一个批准(对象发件人,发送ExternalDataEventArgs)事件Worfklow1。该页面将允许修改事件消息的一些参数。当BeginFireEvent是按下时,核准对象创建JSON格式(见文本框),并通过XMLHttpRequest发送的service12.svc。基于e.InstancedId(什么是初始为空),该服务将之前插入一个前处理呼叫的射击事件。这火处理前,有责任创造一个工作流实例。烧成后的事件的工作流程,工作流实例ID给客户端返回,并显示在文本框中。上面的图片显示此状态。
的射击事件的过程中,可以看到在DebugView中表格一样,它是在如下图所示:
{S11}
现在,我们应该按FireEvent按钮生成另一个火灾事件的工作流程。请注意,从客户端的发射事件的十(10)秒的寿命,否则状态机完成的工作流程 - 见DebugView中跟踪。每点击FireEvent按钮,将发送一个事件消息。
要完成这次谈话与工作流程,按下EndFireEvent按钮。在这种情况下,火处理后调用将调用等待在非阻塞方式在服务端的工作流程响应。超时后,工作流将输出页面上的文本信息发送到工作流的事件数量。
我们可以开始一个工作流的新发射的谈话,通过点击"清除"按钮。
基于此测试,打开其他客户端,例如类似的测试网页,网页AjaxClient2.htm,事件消息有一个自定义的对象。
我们的测试已经完成。{A19}
这篇文章描述了一个引发事件的工作流程,使用微软尖端技术能力。在这个解决方案中,我们可以使用内置与常规的工作流程。NET Framework 3.0的。即将到来的新版本都知道,逆戟鲸(。NET框架3.5)将使在工作流程的情况下开枪事件。 AJAX / JSON / WCF / WF代表一个业务层的正确封装和部署基于业务需求的元数据驱动的连接模式。参考和有用的链接{A20}{A21}{A22}{A23}{A24}{A25}{A26}{A27} {A28}{A29}{A30}

回答

评论会员:VagifAbilov 时间:2011/12/14
大文章,我的5投
评论会员:VagifAbilov 时间:2011/12/14
您好罗马,

我碰到你(一切照常)优秀文章,试图找出整合与WF4中的工作流程Web客户端的最佳途径。
您的文章涵盖WF3,所以我不知道事情如何在.NET/WF4改变。
该方案很简单:用户打开一个Web浏览器会话,并启动工作流。虽然正在执行的工作流程是,它可能需要给一些反馈的网页,例如更新页面的部分或移动到另一个网页。
标准WF4中调出的情况是使用发送活动,但是这将使Web客户端的WCF服务。
请问你推荐为WF4?
ВагифАбилов
MCPD(企业应用程序开发)
挪威的奥斯陆,

如果你在战争的时候,而不是在敌人投掷了一枚手榴弹,抛出这些小南瓜之一。也许它会让所有人都认为战争是多么愚蠢,而他们所思所想,你可以向他们扔一个真正的手榴弹。
杰克Handey
评论会员:。巴勃罗Cibraro 时间:2011/12/14
嘿罗马,你有一个相当不错的工作,本文的。感谢!!

的问候,
巴勃罗Cibraro
http://weblogs.asp.net/cibrax
评论会员:罗马吻 时间:2011/12/14
感谢巴勃罗,我很欣赏它

罗马

p.s.
退房{A31}]的文章,也。感谢

微软的MVP - 连接系统开发

评论会员:游客 时间:2011/12/14
安东尼中号Kancidrowski
伟大的文章,你让我5。您的链接需要改变。ASP,ASPX,但我怀疑该网站已改变,因为你的战后初期。 {S12}
蚂蚁。
我辛苦,但软。
我有色,目前尚不清楚。
我圆润甜美。
我果冻,我是什么?缪斯进一步,我会回报! - 大卫Walliams(小英)
评论会员:AndyCLon 时间:2011/12/14
是一个链接"消防WorfklowEvents从WCF"
评论会员:罗马吻 时间:2011/12/14
感谢安迪

罗马

微软MVP / Windows服务器系统 - 连接系统开发