부록 A: 주문 응용 프로그램 개발

이 부록에서는 개발자가 Contoso Order service를 빌드하기 위한 세부 단계를 제공합니다. 이 부록은 개발자가 Visual Studio 2010 및 .NET Framework 4를 사용하여 .NET Framework 4를 사용하여 WCF(Windows Communication Foundation) 및/또는 Windows WF(Workflow Foundation) 서비스가 포함된 응용 프로그램을 개발하는 과정을 숙지하도록 하는 데 목적이 있습니다. 자습서의 주요 부분에서는 이 응용 프로그램을 사용하여 시스템 관리자나 응용 프로그램 소유자에게, Windows Server AppFabric을 사용하여 WCF 및/또는 WF 서비스가 포함된 응용 프로그램을 배포, 모니터링하고 관련 문제를 해결하는 방법을 보여 줍니다.

이 Contoso Order service는 다음과 같은 4개의 응용 프로그램으로 구성됩니다.

  • 주문 처리 서비스: 웹 서비스 인터페이스를 통해 기존 주문 처리 응용 프로그램을 호출하는 작업을 시뮬레이션하는 WCF서비스입니다.

  • 배송 서비스: API를 통해 기존 배송 응용 프로그램을 호출하는 작업을 시뮬레이션하는 WCF 서비스입니다.

  • 주문 워크플로 서비스: 주문 수신, 주문 처리 및 주문 배송을 포함하여 주문 프로세스를 관리하는 WF 워크플로 서비스입니다.

  • 주문 클라이언트: Order service에 대한 프런트 엔드의 역할을 하는 Windows Form 응용 프로그램입니다.

참고

이 부록을 사용하기 위해 Windows Server AppFabric을 설치할 필요는 없지만 이 부록을 올바르게 빌드할 수 있도록 먼저 Windows Server AppFabric 인터페이스 사용 자습서 파일을 설치하여 적절한 파일 구조를 만들어야 합니다. 이때 Windows Server AppFabric 인터페이스 사용 자습서 파일을 실행하여 완료할 필요는 없으며 해당 파일을 설치하기만 하면 됩니다. Windows Server AppFabric 인터페이스 사용 자습서 파일의 설치 절차에 대해서는 제 1과: 시작을 참조하십시오. C:\DublinTutorial\OrderServiceSolution\Completed 폴더에 전체 솔루션 복사본이 포함되어 있습니다.

절차

응용 프로그램을 만들려면 다음 단계를 진행합니다.

  1. 주문 처리 WCF 서비스 개발

  2. 배송 WCF 서비스 개발

  3. 주문 워크플로 WF 서비스 개발

  4. 주문 처리 WCF 서비스 완료

  5. 배송 WCF 서비스 완료

  6. 주문 클라이언트 응용 프로그램 개발

  7. Order service 패키징

주문 처리 WCF 서비스 개발

주문 처리 응용 프로그램은 Contoso가 구입한 응용 프로그램입니다. 이 응용 프로그램에는 다른 응용 프로그램이 통신할 수 있는 웹 서비스가 함께 제공됩니다. Contoso 개발자는 주문 처리 응용 프로그램과 상호 작용하는 OrderProcessingService라는 WCF 서비스를 개발해야 합니다.

OrderProcessingService에 대한 WCF Service Application과 Visual Studio 솔루션을 만들려면

  1. 시작을 클릭하고 모든 프로그램, Microsoft Visual Studio 2010을 차례로 가리킨 다음 Microsoft Visual Studio 2010을 클릭합니다.

  2. 파일 메뉴에서 새로 만들기, 새 프로젝트를 차례로 클릭합니다.

  3. 새 프로젝트에서 다음 값을 선택하거나 입력한 후 확인을 클릭합니다.

    속성

    Project types

    Visual C#/Web

    Templates

    WCF Service Application

    Name

    OrderProcessingService

    Location

    C:\DublinTutorial\OrderServiceSolution

    Solution Name

    OrderService

    Create directory for solution

    (선택됨)

  4. 솔루션 탐색기에서 OrderProcessingService를 확장하고 IService1.cs를 마우스 오른쪽 단추로 클릭한 다음 삭제를 클릭합니다.

  5. 확인을 클릭하여 파일 영구 삭제를 확인합니다.

  6. 솔루션 탐색기에서 OrderProcessingService를 확장하고 Service1.svc를 마우스 오른쪽 단추로 클릭한 다음 삭제를 클릭합니다.

  7. 확인을 클릭하여 파일 영구 삭제를 확인합니다.

WCF 서비스를 만들려면 우선 계약을 정의합니다. 이 계약에서 서비스가 지원하는 작업이 지정됩니다. 작업은 웹 서비스 메서드로 생각할 수 있습니다. 인터페이스의 각 메서드는 특정 서비스 작업에 해당합니다. OrderProcessingService에서 ProcessOrder 및 CancelOrderProcess의 2개 메서드를 정의합니다.

주문 처리 서비스에 대한 서비스 계약과 데이터 계약을 정의하려면

  1. 솔루션 탐색기에서 OrderProcessService를 마우스 오른쪽 단추로 클릭하고 추가를 가리킨 다음 새 항목을 클릭합니다.

  2. 새 항목 추가 - OrderProcessService에서 다음 값을 선택하거나 입력한 후 추가를 클릭합니다.

    속성

    Categories

    Visual C#/Web

    Template

    WCF Service

    Name

    OrderProcessing.svc

    솔루션에 IOrderProcessing.cs 및 OrderProcessing.svc의 2개 파일이 추가됩니다.

  3. 솔루션 탐색기에서 IOrderProcessing.cs를 두 번 클릭하여 엽니다.

  4. OrderProcessingService 네임스페이스를 마우스 오른쪽 단추로 클릭하고 리팩터링, 이름 바꾸기를 차례로 클릭하여 이름 바꾸기 대화 상자를 엽니다.

  5. 새 이름Microsoft.Samples.Dublin.Tutorials.OrderService.OrderProcessingService를 입력하고 확인을 클릭합니다.

  6. 적용을 클릭한 다음 를 클릭합니다.

  7. OrderProcessing.svc 원본 코드를 다음과 같이 수정합니다.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.Serialization;
    using System.ServiceModel;
    using System.Text;
    
    namespace Microsoft.Samples.Dublin.Tutorials.OrderService.OrderProcessingService
    {
        [ServiceContract]
        public interface IOrderProcessing
        {
            [OperationContract]
            string ProcessOrder(PurchaseOrder po);
    
            [OperationContract]
            string CancelOrderProcess(string orderID);
        }
    
        [DataContract]
        public class PurchaseOrder
        {
            [DataMember]
            public string POID;
            [DataMember]
            public string FirstName;
            [DataMember]
            public string LastName;
            [DataMember]
            public string EmailAddress;
            [DataMember]
            public string TelephoneNumber;
            [DataMember]
            public string AddressLine1;
            [DataMember]
            public string AddressLine2;
            [DataMember]
            public string City;
            [DataMember]
            public string State;
            [DataMember]
            public string ZipCode;
            [DataMember]
            public string Description;
            [DataMember]
            public int Quantity;
            [DataMember]
            public string UnitPrice;
        }
    }
    

    이 파일에서 데이터 계약과 서비스 계약을 정의합니다. 클라이언트가 서비스를 호출하여 주문을 처리하고 주문 처리를 취소할 수 있습니다.

인터페이스를 사용하여 정의된 계약을 만든 후 다음 단계에서 이 인터페이스를 구현합니다. 이 작업에는 사용자 정의 IOrderProcessing 인터페이스를 구현하는 OrderProcessService라는 클래스 만들기 과정이 포함됩니다.

주문 처리 서비스 계약을 구현하려면

  1. 솔루션 탐색기에서 IOrderProcessing.cs를 두 번 클릭하여 엽니다.

  2. 원본 코드를 다음과 같이 수정합니다.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.Serialization;
    using System.ServiceModel;
    using System.Text;
    using System.Threading;
    using System.IO;
    
    namespace Microsoft.Samples.Dublin.Tutorials.OrderService.OrderProcessingService
    {
        class WorkItem
        {
            private Thread workThread;
            private object workItemLock;
            private bool completeFlag;
    
            public Thread WorkThread { get { return workThread; } set { workThread = value; } }
            public object WorkItemLock { get { return workItemLock; } }
            public bool CompleteFlag { get { return completeFlag; } }
    
            public WorkItem(Thread WorkThread)
            {
                workThread = WorkThread;
                workItemLock = new object();
                completeFlag = false;
            }
    
            public void Complete()
            {
                completeFlag = true;
            }
        }
    
        public class OrderProcessing : IOrderProcessing
        {
            private static Dictionary<String, WorkItem> WorkItemMap = new Dictionary<String, WorkItem>();
    
            public string ProcessOrder(PurchaseOrder po)
            {
                //run the code from a different thread to simulate asynchronized call
                ThreadPool.QueueUserWorkItem(SendProcessResult, po);
                return ("The request for processing order[" + po.POID + "] has been received.");
            }
    
            private void SendProcessResult(object state)
            {
                PurchaseOrder po = (PurchaseOrder)state;
    
                WorkItem workItem = new WorkItem(Thread.CurrentThread);
                WorkItemMap.Add(po.POID, workItem);
    
                //Simulating the order processing process
                Thread.Sleep(120000);
    
                //The following code will be uncommented later in the process
                //OrderWorkflowService.ProcessServiceResult reply = new OrderWorkflowService.ProcessServiceResult();
                //reply.POID = po.POID;
                //reply.Message = "The order has been processed successfully.";
    
                //lock (workItem.WorkItemLock)
                //{
                //    using (OrderWorkflowService.MicrosoftSamplesDublinTutorialsOrderServiceOrderWorkflowServiceIOrderWorkflowServiceClient client = new OrderWorkflowService.MicrosoftSamplesDublinTutorialsOrderServiceOrderWorkflowServiceIOrderWorkflowServiceClient())
                //    {
                //        client.SubmitProcessResult(reply);
                //    }
    
                //    workItem.Complete();
                //    WorkItemMap.Remove(po.POID);
                //}
    
            }
    
            public string CancelOrderProcess(string poID)
            {
                string ret = "Cancel unavailable for this order.";
    
                //=====================================================//
                //===[ Attempt to get a work item for the order Id 
                //=====================================================//
                WorkItem workItem;
                if (WorkItemMap.TryGetValue(poID, out workItem) == true)
                {
                    //===========================================================
                    //=== Slight race condition here. Workitem could complete
                    //=== before we aquire its lock. So we check the          
                    //=== completion flag inside the lock.                    
                    //===========================================================
                    lock (workItem.WorkItemLock)
                    {
                        if ((!workItem.CompleteFlag) && (workItem.WorkThread.IsAlive))
                        {
                            workItem.WorkThread.Abort();
                            WorkItemMap.Remove(poID);
                            ret = "The order process has been terminated successfully.";
                        }
                    }
                }
                return ret;
            }
        }
    }
    

구성 파일을 사용하면 디자인 시점이 아니라 배포할 때 끝점 및 서비스 동작 데이터를 유연하게 제공할 수 있습니다. 이 구성 파일에서는 2개의 끝점을 정의합니다.

구성 파일을 사용하여 주문 처리 서비스를 구성하려면

  1. 솔루션 탐색기에서 OrderProcessingService를 확장하고 Web.config를 두 번 클릭하여 엽니다. <services> 태그를 <system.serviceModel> 태그 내부에 추가합니다.

        <services>
          <service name="Microsoft.Samples.Dublin.Tutorials.OrderService.OrderProcessingService.OrderProcessing">
            <endpoint address="" binding="basicHttpBinding" contract="Microsoft.Samples.Dublin.Tutorials.OrderService.OrderProcessingService.IOrderProcessing" />
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
          </service>
        </services>
    

주문 처리 WCF 서비스를 컴파일하려면

  1. 솔루션 탐색기에서 OrderProcessingService 프로젝트를 마우스 오른쪽 단추로 클릭하고 다시 빌드를 클릭합니다. 출력 창에서 프로젝트가 성공적으로 컴파일되었는지 확인하십시오.

주문 처리 WCF 서비스를 테스트하려면

  1. 솔루션 탐색기에서 OrderProcessingService 프로젝트를 마우스 오른쪽 단추로 클릭하고 브라우저에서 보기를 클릭합니다. Internet Explorer 창이 열리고 디렉터리 파일이 나열됩니다.

  2. Internet Explorer 창에서 OrderProcessing.svc를 클릭합니다. 오류가 표시되지 않는지 확인하십시오.

배송 WCF 서비스 개발

배송 서비스는 SQL Server 저장소를 호출하는 WCF 서비스입니다. 시뮬레이션에서는 실제로 데이터베이스 호출을 수행하지 않습니다.

솔루션에 새 WCF Service Application프로젝트를 추가하려면

  1. 솔루션 탐색기에서 **솔루션 ‘OrderService’**를 마우스 오른쪽 단추로 클릭하고 추가를 가리킨 다음 새 프로젝트를 클릭합니다.

  2. 새 프로젝트 추가에서 다음 값을 선택하거나 입력한 후 확인을 클릭합니다.

    속성

    Project types

    Visual C#/Web

    Templates

    WCF Service Application

    Name

    ShippingService

    Location

    C:\DublinTutorial\OrderServiceSolution\OrderService

  3. 솔루션 탐색기에서 ShippingService를 확장하고 IService1.cs를 마우스 오른쪽 단추로 클릭한 다음 삭제를 클릭합니다.

  4. 확인을 클릭하여 파일 영구 삭제를 확인합니다.

  5. 솔루션 탐색기에서 ShippingService를 확장하고 Service1.svc를 마우스 오른쪽 단추로 클릭한 다음 삭제를 클릭합니다.

  6. 확인을 클릭하여 파일 영구 삭제를 확인합니다.

ShipOrder 및 CancelShipping의 2개 작업 계약을 포함하는 IShipping이라는 하나의 서비스 계약을 정의합니다.

배송 WCF 서비스 계약을 정의하려면

  1. 솔루션 탐색기에서 ShippingService를 마우스 오른쪽 단추로 클릭하고 추가를 가리킨 다음 새 항목을 클릭합니다.

  2. 새 항목 추가 - ShippingService에서 다음 값을 선택하거나 입력한 후 추가를 클릭합니다.

    속성

    Categories

    Visual C#/Web

    Template

    WCF Service

    Name

    Shipping.svc

    IShipping.cs 및 Shipping.svc의 2개 파일이 프로젝트에 추가됩니다.

  3. 솔루션 탐색기에서 IShipping.cs를 두 번 클릭하여 엽니다.

  4. ShippingService 네임스페이스를 마우스 오른쪽 단추로 클릭하고 리팩터링, 이름 바꾸기를 차례로 클릭하여 이름 바꾸기 대화 상자를 엽니다.

  5. 새 이름Microsoft.Samples.Dublin.Tutorials.OrderService.ShippingService를 입력하고 확인을 클릭합니다.

  6. 적용을 클릭한 다음 를 클릭합니다.

  7. 원본 코드를 다음과 같이 수정합니다.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.Serialization;
    using System.ServiceModel;
    using System.Text;
    
    namespace Microsoft.Samples.Dublin.Tutorials.OrderService.ShippingService
    {
        [ServiceContract]
        public interface IShipping
        {
            [OperationContract]
            string ShipOrder(string poID);
    
            [OperationContract]
            string CancelShipping(string poID);
        }
    }
    

배송 WCF 서비스 계약을 구현하려면

  1. 솔루션 탐색기에서 Shipping.svc를 두 번 클릭하여 엽니다.

  2. 원본 코드를 다음과 같이 수정합니다.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.Serialization;
    using System.ServiceModel;
    using System.Text;
    using System.Threading;
    
    namespace Microsoft.Samples.Dublin.Tutorials.OrderService.ShippingService
    {
        class WorkItem
        {
            private Thread workThread;
            private object workItemLock;
            private bool completeFlag;
    
            public Thread WorkThread { get { return workThread; } set { workThread = value; } }
            public object WorkItemLock { get { return workItemLock; } }
            public bool CompleteFlag { get { return completeFlag; } }
    
            public WorkItem(Thread WorkThread)
            {
                workThread = WorkThread;
                workItemLock = new object();
                completeFlag = false;
            }
    
            public void Complete()
            {
                completeFlag = true;
            }
        }
    
        public class Shipping : IShipping
        {
            private static Dictionary<String, WorkItem> WorkItemMap = new Dictionary<String, WorkItem>();
    
            public string ShipOrder(string poID)
            {
                //run the code from a different thread to simulate asynchronized call
                ThreadPool.QueueUserWorkItem(SendShippingResult, poID);
                return ("The request for processing order[" + poID + "] has been received.");
            }
    
            private void SendShippingResult(object state)
            {
                string poID = state.ToString();
    
                WorkItem workItem = new WorkItem(Thread.CurrentThread);
                WorkItemMap.Add(poID, workItem);
    
                //Simulating the order processing process
                Thread.Sleep(60000);
    
                //The following portion will be uncommented after referencing OrderWorkflowService
                //OrderWorkflowService.ShippingServiceResult reply = new OrderWorkflowService.ShippingServiceResult();
                //reply.POID = poID;
                //reply.Message = "The order has been shipped.";
    
                //lock (workItem.WorkItemLock)
                //{
                //    using (OrderWorkflowService.MicrosoftSamplesDublinTutorialsOrderServiceOrderWorkflowServiceIOrderWorkflowServiceClient client = new OrderWorkflowService.MicrosoftSamplesDublinTutorialsOrderServiceOrderWorkflowServiceIOrderWorkflowServiceClient())
                //    {
                //        client.SubmitShippingResult(reply);
                //    }
    
                //    workItem.Complete();
                //    WorkItemMap.Remove(poID);
                //}
            }
    
            public string CancelShipping(string poID)
            {
                string ret = "Cancel unavailable for this order.";
    
                //=====================================================//
                //===[ Attempt to get a work item for the order Id 
                //=====================================================//
                WorkItem workItem;
                if (WorkItemMap.TryGetValue(poID, out workItem) == true)
                {
                    //===========================================================
                    //=== Slight race condition here. Workitem could complete
                    //=== before we aquire its lock. So we check the          
                    //=== completion flag inside the lock.                    
                    //===========================================================
                    lock (workItem.WorkItemLock)
                    {
                        if ((!workItem.CompleteFlag) && (workItem.WorkThread.IsAlive))
                        {
                            workItem.WorkThread.Abort();
                            WorkItemMap.Remove(poID);
                            ret = "The shipping process has been terminated successfully.";
                        }
                    }
                }
                return ret;
            }
        }
    }
    

이 구성 파일에서는 2개의 끝점을 정의합니다.

구성 파일을 사용하여 배송 WCF 서비스를 구성하려면

  1. 솔루션 탐색기에서 ShippingService를 확장하고 Web.config를 두 번 클릭하여 엽니다. <services> 태그를 <system.serviceModel> 태그 내부에 추가합니다.

        <services>
          <service name="Microsoft.Samples.Dublin.Tutorials.OrderService.OrderProcessingService.Shipping">
            <endpoint address="" binding="basicHttpBinding" contract="Microsoft.Samples.Dublin.Tutorials.OrderService.OrderProcessingService.IShipping" />
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
          </service>
        </services>
    

배송 WCF 서비스를 컴파일하려면

  1. 솔루션 탐색기에서 ShippingService 프로젝트를 마우스 오른쪽 단추로 클릭하고 다시 빌드를 클릭합니다. 출력 창에서 프로젝트가 성공적으로 컴파일되었는지 확인하십시오.

주문 워크플로 WF 서비스 개발

주문 워크플로 서비스 응용 프로그램은 전체 서비스의 주요 부분으로서 전체 비즈니스 프로세스를 오케스트레이션합니다. 이 응용 프로그램은 구매 주문을 수신하고 OrderProcessingService 및 ShippingService를 호출한 다음 마지막으로 구매 주문 상태에 대한 전자 메일 메시지를 고객에게 보냅니다.

솔루션에 새 WCF Workflow Service Application 프로젝트를 추가하려면

  1. 솔루션 탐색기에서 **솔루션 ‘OrderService’**를 마우스 오른쪽 단추로 클릭하고 추가를 가리킨 다음 새 프로젝트를 클릭합니다.

  2. 새 프로젝트 추가에서 다음 값을 선택하거나 입력한 후 확인을 클릭합니다.

    속성

    Project types

    Visual C#/Workflow

    Templates

    WCF Workflow Service Application

    Name

    OrderWorkflowService

    Location

    C:\DublinTutorial\OrderServiceSolution\OrderService

OrderWorkflowService는 OrderProcessingService 및 ShippingService를 사용합니다. 이 2개 서비스를 참조해야 합니다.

서비스 참조를 추가하려면

  1. 솔루션 탐색기에서 OrderWorkflowService를 마우스 오른쪽 단추로 클릭하고 서비스 참조 추가를 클릭합니다.

  2. 서비스 참조 추가에서 검색을 클릭합니다. Visual Studio가 2개 서비스를 모두 검색해야 합니다.

  3. 다음 값을 입력 및 선택하고 확인을 클릭하여 서비스 참조를 만듭니다.

    속성

    Services

    OrderProcessing.svc

    Namespace

    OrderProcessService

  4. 단계를 반복하여 다음 값을 갖는 다른 서비스 참조를 추가합니다.

    속성

    Services

    Shipping

    Namespace

    ShippingService

전자 메일 알림 보내기를 시뮬레이션하는 데 사용할 사용자 지정 워크플로 활동을 정의해야 합니다.

워크플로 코드 활동을 만들려면

  1. 솔루션 탐색기에서 OrderWorkflowService를 마우스 오른쪽 단추로 클릭하고 추가를 가리킨 다음 새 항목을 클릭합니다.

  2. 새 항목 추가 - OrderWorkflowService에서 다음 값을 선택하거나 입력한 후 추가를 클릭합니다.

    속성

    Categories

    Visual C#/Workflow

    Template

    Code Activity

    Name

    SendNotification.cs

  3. 솔루션 탐색기에서 SendNotification.cs를 두 번 클릭하여 엽니다.

  4. OrderWorkflowService 네임스페이스를 마우스 오른쪽 단추로 클릭하고 리팩터링, 이름 바꾸기를 차례로 클릭하여 이름 바꾸기 대화 상자를 엽니다.

  5. 새 이름Microsoft.Samples.Dublin.Tutorials.OrderService.OrderWorkflowService를 입력하고 확인을 클릭합니다.

  6. 적용을 클릭한 다음 를 클릭합니다.

  7. 원본 코드를 다음과 같이 수정합니다.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Activities;
    using System.IO;
    
    namespace Microsoft.Samples.Dublin.Tutorials.OrderService.OrderWorkflowService
    {
        public class SendNotification : CodeActivity
        {
            InArgument<string> to;
            InArgument<string> subject;
            InArgument<string> body;
            string pathRoot = @"C:\DublinTutorial\Inbox\";
    
            public InArgument<string> To { get { return this.to; } set { this.to = value; } }
            public InArgument<string> Subject { get { return this.subject; } set { this.subject = value; } }
            public InArgument<string> Body { get { return this.body; } set { this.body = value; } }
            public SendNotification() { }
    
            public SendNotification(InArgument<string> To, InArgument<string> Subject, InArgument<string> Body)
            {
                this.to = To; this.subject = Subject; this.body = Body;
            }
    
            protected override void Execute(CodeActivityContext context)
            {
                string filename;
                string content;
    
                try
                {
                    filename = this.to.Get<String>(context) + "~~" + this.subject.Get<string>(context) + "_" + DateTime.Now.ToFileTime() + ".txt";
                    content = String.Format("To: {0}" + Environment.NewLine
                        + "From: {1}" + Environment.NewLine
                        + "Subject: {2}" + Environment.NewLine
                        + Environment.NewLine
                        + "{3}",
                        this.to.Get<String>(context), "CustomerRelations@Contoso.com", this.subject.Get<String>(context), this.body.Get<String>(context));
    
                    File.WriteAllText((pathRoot + filename), content);
                }
                catch (Exception Ex)
                {
                    context.SetValue(Body, Ex.Message);
                }
    
            }
        }
    }
    

    경로는 "C:\DublinTutorial\Inbox\"로 하드 코드됩니다.

다음 절차에서는 데이터 유형을 정의합니다. 이러한 데이터 유형은 OrderProcessingService 및 ShippingService가 결과를 다시 OrderWorkflowService로 보내는 데 사용됩니다.

데이터 유형을 정의하려면

  1. 솔루션 탐색기에서 OrderWorkflowService를 마우스 오른쪽 단추로 클릭하고 추가를 가리킨 다음 새 항목을 클릭합니다.

  2. 새 항목 추가 - OrderWorkflowService에서 다음 값을 선택하거나 입력한 후 추가를 클릭합니다.

    속성

    Categories

    Visual C#/Code

    Template

    Code File

    Name

    DataTypes.cs

  3. 솔루션 탐색기에서 DataTypes.cs를 두 번 클릭하여 엽니다.

  4. 원본 코드를 다음과 같이 수정합니다.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.Serialization;
    using System.ServiceModel;
    using System.Text;
    
    namespace Microsoft.Samples.Dublin.Tutorials.OrderService.OrderWorkflowService
    {
        [DataContract]
        public class ProcessServiceResult
        {
            [DataMember]
            public string POID;
            [DataMember]
            public string Message;
        }
    
        [DataContract]
        public class ShippingServiceResult
        {
            [DataMember]
            public string POID;
            [DataMember]
            public string Message;
        }
    }
    
  5. 솔루션 탐색기에서 OrderWorkflowService를 마우스 오른쪽 단추로 클릭하고 다시 빌드를 클릭합니다. 다음 단계에서 개발하는 워크플로에서 코드 활동에 액세스할 수 있도록 프로젝트를 빌드해야 합니다. 컴파일을 수행하면 워크플로에 참조된 WCF 서비스 끝점이 노출될 수도 있습니다.

다음 단계에서는 워크플로를 정의합니다. 워크플로에는 여러 개의 상태가 있습니다. 먼저 상태를 정의한 다음 상태 세부 정보를 정의합니다. 개발의 각 부분에 다음 단계가 포함될 수 있습니다.

  1. 활동을 사용하여 워크플로를 작성합니다.

  2. 변수를 정의합니다.

  3. 활동을 구성합니다.

워크플로를 정의하려면

  1. 솔루션 탐색기에서 OrderWorkflowService를 확장하고 Service1.xamlx를 마우스 오른쪽 단추로 클릭한 다음 이름 바꾸기를 클릭합니다. 파일 이름을 OrderWorkflow.xamlx로 바꿉니다.

  2. 솔루션 탐색기에서 OrderWorkflow.xamlx를 두 번 클릭하여 엽니다. 순차적 서비스에 ReceiveRequest 및 SendResponse라는 2개 활동이 나열되어 있습니다.

  3. 순차적 서비스 활동을 마우스 오른쪽 단추로 클릭하고 삭제를 클릭합니다.

  4. 워크플로에서 여기에 활동 놓기를 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    configurationName

    Microsoft.Samples.Dublin.Tutorials.OrderService.OrderWorkflowService.OrderWorkflow

    Name

    Microsoft.Samples.Dublin.Tutorials.OrderService.OrderWorkflowService.OrderWorkflow

  5. 창의 왼쪽에 있는 도구 상자를 클릭하여 도구 상자 패널을 열고 창의 왼쪽에 고정합니다.

  6. 다음 활동을 도구 상자에서 "여기에 활동 놓기"라고 표시된 워크플로로 끌어서 놓습니다.

    범주 활동 참고

    Flowchart

    Flowchart

    Flowchart 활동은 기본적으로 시작이 포함된 복합 활동입니다. 다음 단계에서 해당 활동에 다른 활동을 추가합니다.

  7. 표시된 순서대로 다음 활동을 도구 상자에서 워크플로로 끌어서 놓습니다.

    범주 활동 참고

    Messaging

    ReceiveAndSendReply

    "주문 대기" 상태입니다.

    Control Flow

    Sequence

    두 번째 상태인 "주문 시작됨"이 포함됩니다.

    Flowchart

    FlowDecision

    FlowDecision 활동은 상태 사이에서 전환하는 데 도움이 됩니다.

    Control Flow

    Sequence

    세 번째 상태인 "주문 처리됨"이 포함됩니다.

    Flowchart

    FlowDecision

    FlowDecision 활동은 상태 사이에서 전환하는 데 도움이 됩니다.

    Control Flow

    Sequence

    마지막 상태인 "주문 완료됨"이 포함됩니다.

  8. 마우스 포인터를 사용하여 다음과 같이 활동을 연결합니다.

    67e7c9dd-77e7-43be-ad5a-797b3b46f6e8

  9. 워크플로 아래쪽에 있는 변수를 클릭하여 변수 패널을 엽니다.

  10. 변수 패널에서 변수 만들기를 클릭하고 다음 변수를 만듭니다.

    변수 이름 변수 유형 범위 참고

    poID

    String

    Flowchart

    poID는 GUID 번호입니다. poID는 상관 관계에도 사용됩니다.

    isProcessed

    Boolean

    Flowchart

    주문이 성공적으로 처리되었는지 나타내는 플래그입니다.

    isShipped

    Boolean

    Flowchart

    주문이 배송되었는지 나타내는 플래그입니다.

    isUpdated

    Boolean

    Flowchart

    고객이 주문을 업데이트했는지 나타내는 플래그입니다.

    po

    PurchaseOrder

    Flowchart

    OrderProcessingService에 정의되는 사용자 지정 데이터 유형입니다. PO 정보가 포함됩니다.

    poUpdate

    PurchaseOrder

    Flowchart

    고객이 PO를 업데이트하려고 하면 업데이트된 PO 정보가 포함됩니다.

    correlationorderWorkflow

    CorrelationHandle

    Flowchart

    서비스에 연결되는 클라이언트와 OrderProcessService 및 ShippingService에 연결되는 서비스에 모두 사용되는 상관 관계 핸들입니다.

    다음 스크린 샷과 같은 변수가 생성됩니다.

    9208977f-710c-460f-afd8-5c6bd8a792d9

  11. 워크플로에서 Flowchart 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    DisplayName

    Order service

  12. 워크플로에서 첫 번째 Sequence 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    DisplayName

    Wait for order

  13. 워크플로에서 두 번째 Sequence 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    DisplayName

    Order opened

  14. 워크플로에서 세 번째 Sequence 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    DisplayName

    Order processed

  15. 워크플로에서 네 번째 Sequence 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    DisplayName

    Order completed

  16. 워크플로에서 첫 번째 FlowDecision 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    Condition

    isProcessed

    FalseLabel

    Updated

    TrueLabel

    Processed

  17. 워크플로에서 두 번째 FlowDecision 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    Condition

    isShipped

    FalseLabel

    Updated

    TrueLabel

    Shipped

    상태 시스템 워크플로의 기본 구조를 정의했습니다. 이제 각 상태를 정의합니다.

  18. 워크플로에서 Wait for order를 두 번 클릭합니다. 경로가 탭 아래에 표시됩니다. Order service를 클릭하여 전체 상태 시스템 워크플로가 표시되는 페이지로 돌아갈 수 있습니다.

  19. 표시된 순서대로 다음 활동을 도구 상자에서 워크플로로 끌어서 놓습니다.

    범주 활동 참고

    Primitives

    Assign

    이 Assign 활동은 주문 또는 주문 ID(GUID)를 가져옵니다.

    Microsoft.Samples.Dublin.Tutorials.OrderService.OrderWorkflowSerivce

    SendNotification

    이 사용자 지정 활동은 전자 메일 알림을 클라이언트로 보냅니다.

    Primitives

    Assign

    이 Assign 활동은 구매 주문 제품을 모니터링할 수 있도록 사용됩니다.

    Primitives

    Assign

    이 Assign 활동은 구매 주문 수량을 모니터링할 수 있도록 사용됩니다.

  20. 다음과 같이 활동을 다시 정렬합니다.

    주문 상태 활동 대기

  21. 워크플로 아래쪽에 있는 변수를 클릭하여 변수 패널을 엽니다.

  22. 변수 패널에서 변수 만들기를 클릭하고 다음 변수를 만듭니다.

    변수 이름 변수 유형 범위 참고

    product

    String

    Wait for order

    AppFabric은 워크플로 변수를 추적할 수 있습니다. 이 변수를 만들어야 제품 이름을 추적할 수 있습니다.

    quantity

    Int32

    Wait for order

    이 변수는 추적에 사용됩니다.

  23. 워크플로에서 Receive 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    Content

    Message; Message data: po; Message type: Microsoft.Samples.Dublin.Tutorials.OrderService.OrderWorkflowService.OrderProcessingService.Purchaseorder

    DisplayName

    Receive PO

    OperationName

    SubmitPO

    SerivceContractName

    Microsoft.Samples.Dublin.Tutorials.OrderService.OrderWorkflowService.IOrderWorkflowService

    CanCreateInstance

    (선택됨)

  24. 워크플로에서 첫 번째 Assign 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    DisplayName

    Assign PO ID

    To

    po.POID

    Value

    System.Guid.NewGuid().ToString()

  25. 워크플로에서 SendReplyToReceive 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    Content

    Message; Message data: po.POID; Message type: string

    CorrelationInitializers

    CorrelationOrderWorkflow;Query correlation initialize; key1=sm:body()/xg0:string

    237be300-a94d-4b8e-a707-83f4d2041f6e

    참고

    지금 수행한 활동을 상관 관계라고 합니다. 이 워크플로에는 구매 주문 수신 1개, 처리 서비스 결과 수신 1개, 배송 서비스 결과 수신 1개, 클라이언트 업데이트 수신 2개 및 클라이언트 취소 수신 2개의 총 7개 수신 활동이 있습니다. 구매 주문을 수신한 후 워크플로 서비스가 주문 번호로 GUID 번호를 생성합니다. 워크플로 서비스가 동시에 여러 구매 주문을 수신한다고 가정해 봅니다. 워크플로 엔진이 각 구매 주문 요청에 대해 워크플로 인스턴스를 만듭니다. 워크플로 엔진은 다른 6개 요청을 워크플로 인스턴스에 일치시키거나 상관 관계를 지정해야 합니다. 이를 수행하기 위해 워크플로 엔진은 각 상관 관계에 대해 고유 식별자가 필요합니다. 이 샘플에서 고유 식별자는 주문 번호(GUID)입니다. 첫 번째 SendReplyToReceive 활동에서 CorrelationInitializer를 정의합니다. 쿼리 상관 관계 이니셜라이저 쿼리 유형을 선택하면 고유 식별자가 수신 활동으로 전달되는 메시지에 포함됩니다. 또한 필드에 대한 xPath를 지정합니다. 상관 관계 이니셜라이저 이외에 CorrelateWith 필드에서 상관 관계 핸들도 지정해야 합니다. 상관 관계 핸들은 상관 관계 데이터를 저장할 컨테이너이므로 상관 관계 데이터는 워크플로 내에서 어디서나 검색할 수 있습니다. 후속 수신에서는 동일한 상관 관계 핸들을 지정합니다. 또한 CorrelateOn 필드에서는 수신된 메시지에서 주문 번호를 검색하는 방법을 지정합니다.

  26. 워크플로에서 SendNotification 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    Body

    "We have received your order.  Your order number is " + po.POID

    DisplayName

    Send client notification

    Subject

    "Contoso.com Order#" + po.POID + "~~Order Received"

    To

    po.EmailAddress

  27. 워크플로에서 두 번째 Assign 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    DisplayName

    Assign product name

    To

    proudct

    Value

    po.Description

  28. 워크플로에서 세 번째 Assign 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    DisplayName

    Assign quantity

    To

    quantity

    Value

    po.Quantity

    주문 대기 상태 구현을 완료했습니다.

  29. 탭 이름 아래에서 Order service를 클릭하여 "Order service" Flowchart 활동을 표시합니다.

  30. 워크플로에서 주문 시작됨 Sequence 활동을 두 번 클릭하여 상태를 구현합니다.

  31. 표시된 순서대로 다음 활동을 도구 상자에서 워크플로로 끌어서 놓습니다.

    범주 활동 참고

    Primitives

    Assign

    Control Flow

    Parallel

  32. 다음 활동을 Parallel 활동 내부로 끌어서 놓습니다.

    범주 활동 참고

    Control Flow

    Sequence

  33. 다음 활동을 Sequence 활동 내부로 끌어서 놓습니다.

    범주 활동 참고

    Microsoft.Samples.Dublin.Tutorials.OrderService.OrderProcessingService.Activities

    ProcessOrder

    Runtime

    Persist

    Messaging

    Receive

    Microsoft.Samples.Dublin.Tutorials.OrderService.orderWorkflowService

    SendNotification

    Primitives

    Assign

  34. 다음 활동을 Parallel 활동 내부 및 기존 Sequence 활동 오른쪽으로 끌어서 놓습니다.

    범주 활동 참고

    Messaging

    ReceiveAndSendReply

    ReceiveAndSendReply 활동은 하나의 Sequence 활동이 Receive 활동과 SendReplyToReceive 활동을 래핑하는 복합 활동입니다.

  35. 다음 활동을 새로 추가된 Sequence 활동 내부 및 Receive 및 SendReplyToReceive의 두 개 활동 아래에 끌어서 놓습니다.

    범주 활동 참고

    Microsoft.Samples.Dublin.Tutorials.OrderService.OrderProcessingService.Activities

    CancelOrderProcess

    Control Flow

    If

  36. 다음 활동을 If 활동의 Then 분기 내부로 끌어서 놓습니다.

    범주 활동 참고

    Control Flow

    Sequence

  37. 다음 활동을 새로 추가된 Sequence 활동 내부로 끌어서 놓습니다.

    범주 활동 참고

    Primitives

    Assign

    Primitives

    Assign

    Microsoft.Samples.Dublin.Tutorials.OrderService.OrderWorkflowService

    SenNotification

  38. 다음 활동을 If 활동의 Else 분기 내부로 끌어서 놓습니다.

    범주 활동 참고

    Microsoft.Samples.Dublin.Tutorials.OrderService.OrderWorkflowService

    SenNotification

  39. 다음 활동을 Parallel 활동 내부로 끌어서 놓아 맨 오른쪽 분기로 만듭니다.

    범주 활동 참고

    Messaging

    ReceiveAndSendReply

  40. 다음 활동을 새로 추가된 Sequence 활동 내부 및 Receive 및 SendReplyToReceive의 두 개 활동 아래에 끌어서 놓습니다.

    범주 활동 참고

    Microsoft.Samples.Dublin.Tutorials.OrderService.OrderProcessingService.Activities

    CancelOrderProcess

    Control Flow

    If

  41. 다음 활동을 If 활동의 Then 분기 내부로 끌어서 놓습니다.

    범주 활동 참고

    Control Flow

    Sequence

  42. 다음 활동을 새로 추가된 Sequence 활동 내부로 끌어서 놓습니다.

    범주 활동 참고

    Microsoft.Samples.Dublin.Tutorials.OrderService.OrderWorkflowService

    SenNotification

    Runtime

    TerminateWorkflow

  43. 다음 활동을 If 활동의 Else 분기 내부로 끌어서 놓습니다.

    범주 활동 참고

    Microsoft.Samples.Dublin.Tutorials.OrderService.OrderWorkflowService

    SenNotification

    활동을 추가하면 주문 시작됨 상태는 다음과 같이 표시됩니다.

    주문 열림 상태

  44. Parallel 활동의 맨 왼쪽 분기에서 Sequence 활동을 클릭하고 워크플로 아래쪽에서 변수를 클릭하여 변수 패널을 엽니다.

  45. 변수 패널에서 변수 만들기를 클릭하고 다음 변수를 만듭니다.

    변수 이름 변수 유형 범위 참고

    cancelOrderProcessAcknowledgement

    String

    Parallel

    ProcessServiceResult

    Microsoft.Samples.Dublin.Tutorials.OrderService.OrderWorkflowService.ProcessServiceResult

    Sequence

    processServiceAcknowledgement

    String

    Sequence

  46. 워크플로의 Parallel 활동 맨 위에서 Assign 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    DisplayName

    Initialize isUpdated

    To

    isUpdated

    False

  47. 워크플로에서 Parallel 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    Completion

    isUpdated Or isProcessed

    DisplayName

    Process order

  48. 워크플로의 Parallel 활동 맨 왼쪽 분기에서 Sequence 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    DisplayName

    Processing

  49. 워크플로의 Parallel 활동 맨 왼쪽 분기에서 ProcessOrder 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    DisplayName

    Process order

    po

    po

    ProcessOrderResult

    processServiceAcknowledgement

  50. 워크플로의 Parallel 활동 맨 왼쪽 분기에서 Receive 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    Content

    Message; Message data:processServiceResult; Message type: Microsoft.Samples.Dublin.Tutorials.OrderService.OrderWorkflowService.ProcessServiceResult

    DisplayName

    Receive process result

    OperationName

    SubmitProcessResult

    ServiceContractName

    Microsoft.Samples.Dublin.Tutorials.OrderService.OrderWorkflowService.IOrderWorkflowService

    CanCreateInstance

    (선택 취소)

    CorrelationOn

    CorrelationWith: correlationOrderWorkflow; XPath Queries: key1=sm:body()/xg0:ProcessServiceResult/sg0:POID

    CorrelationWith

    correlationOrderWorkflow

  51. 워크플로의 Parallel 활동 맨 왼쪽 분기에서 SendNotification 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    Body

    "Order with order#" + po.POID + " has been processed, and is ready for shipping."

    DisplayName

    Send client notification

    Subject

    "Contoso.com Order#" + po.POID + "~~Order Processed"

    To

    po.EmailAddress
  52. 워크플로의 Parallel 활동 맨 왼쪽 분기에서 Assign 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    DisplayName

    Set isProcessed flag

    To

    isProcessed

    Value

    True

    Parallel 활동의 맨 왼쪽 분기 구성을 완료했습니다.

  53. 워크플로의 Parallel 활동 중간 분기에서 Sequence 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    DisplayName

    Waiting for update

  54. 워크플로의 Parallel 활동 중간 분기에서 Receive 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    Content

    Message; Message data:poUpdate; Message type: Microsoft.Samples.Dublin.Tutorials.OrderService.OrderWorkflowService.OrderProcessingService.PurchaseOrder

    DisplayName

    Receive update

    OperationName

    SubmitUpdate

    ServiceContractName

    Microsoft.Samples.Dublin.Tutorials.OrderService.OrderWorkflowService.IOrderWorkflowService

    CanCreateInstance

    (선택 취소)

    CorrelationOn

    CorrelationWith: correlationOrderWorkflow; XPath Queries: key1=sm:body()/xg0:PurchaseOrder/xg0:POID

    CorrelationWith

    correlationOrderWorkflow

  55. 워크플로의 Parallel 활동 중간 분기에서 SendReplyToReceive 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    Content

    Message; Message data: “PO update received”; Message type: String

    DisplayName

    Acknowledge receiving update

  56. 워크플로의 Parallel 활동 중간 분기에서 CancelOrderProcess 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    CancelOrderProcessResult

    cancelOrderProcessAcknowledgement

    DisplayName

    Cancel order processing

    orderID

    po.POID
  57. 워크플로의 Parallel 활동 중간 분기에서 If 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    Condition

    cancelOrderProcessAcknowledgement = "The order process has been terminated successfully."

    DisplayName

    Check cancellation status

  58. 워크플로의 If 활동 Then 분기에서 Sequence 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    DisplayName

    Cancellation succeed sequence

  59. 워크플로의 If 활동 Then 분기에서 첫 번째 Assign 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    DisplayName

    Refresh PO

    To

    po

    Value

    poUpdate
  60. 워크플로의 If 활동 Then 분기에서 두 번째 Assign 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    DisplayName

    Set isUpdated flag

    To

    isUpdated

    Value

    True
  61. 워크플로의 If 활동 Then 분기에서 SendNotification 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    Body

    "Your order has updated upon your request. The order is under processing."

    DisplayName

    Send client notification

    Subject

    "Contoso.com Order#" + po.POID + "~~Order Updated (by customer)"

    To

    po.EmailAddress
  62. 워크플로의 If 활동 Else 분기에서 SendNotification 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    Body

    "Your order update request cannot be processed. Please try again."

    DisplayName

    Send client notification

    Subject

    "Contoso.com Order#" + po.POID + "~~Order Update (by customer) Failed"

    To

    po.EmailAddress

    Parallel 활동의 중간 분기 구성을 완료했습니다.

  63. 워크플로의 Parallel 활동 맨 오른쪽 분기에서 Sequence 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    DisplayName

    Waiting for cancellation

  64. 워크플로의 Parallel 활동 맨 오른쪽 분기에서 Receive 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    Content

    Message; Message data:poID; Message type:String

    DisplayName

    Receive cancellation

    OperationName

    SubmitCancellation

    ServiceContractName

    Microsoft.Samples.Dublin.Tutorials.OrderService.OrderWorkflowService.IOrderWorkflowService

    CanCreateInstance

    (선택 취소)

    CorrelationOn

    CorrelationWith: correlationOrderWorkflow; XPath Queries: key1=sm:body()/xg0:string

    CorrelationWith

    correlationOrderWorkflow

  65. 워크플로의 Parallel 활동 맨 오른쪽 분기에서 SendReplyToReceive 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    Content

    Message; Message data: “PO cancellation received”; Message type: String

    DisplayName

    Acknowledge receiving cancellation

  66. 워크플로의 Parallel 활동 맨 오른쪽 분기에서 CancelOrderProcess 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    CancelOrderProcessResult

    cancelOrderProcessAcknowledgement

    DisplayName

    Cancel order processing

    orderID

    po.POID
  67. 워크플로의 Parallel 활동 맨 오른쪽 분기에서 If 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    Condition

    cancelOrderProcessAcknowledgement = "The order process has been terminated successfully."

    DisplayName

    Check cancellation status

  68. 워크플로의 If 활동 Then 분기에서 Sequence 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    DisplayName

    Cancellation succeed sequence

  69. 워크플로의 If 활동 Then 분기에서 SendNotification 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    Body

    "Your order has been cancelled upon your request."

    DisplayName

    Send client notification

    Subject

    "Contoso.com Order#" + po.POID + "~~Order Cancelled (by customer)"

    To

    po.EmailAddress
  70. 워크플로의 If 활동 Then 분기에서 TerminateWorkflow 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    DisplayName

    Terminate workflow

    Reason

    “Client cancellation”
  71. 워크플로의 If 활동 Else 분기에서 두 번째 SendNotification 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    Body

    "Your order cancellation request cannot be processed. Please try again."

    DisplayName

    Send client notification

    Subject

    "Contoso.com Order#" + po.POID + "~~Order Cancellation(by customer) Failed"

    To

    po.EmailAddress

    Parallel 활동의 맨 오른쪽 분기 구성을 완료했습니다.

  72. 탭 이름 아래에서 Order service를 클릭하여 "Order service" Flowchart 활동을 표시합니다.

  73. 워크플로에서 주문 처리됨 Sequence 활동을 두 번 클릭하여 상태를 구현합니다.

  74. 표시된 순서대로 다음 활동을 도구 상자에서 워크플로로 끌어서 놓습니다.

    범주 활동 참고

    Primitives

    Assign

    Control Flow

    Parallel

  75. 다음 활동을 Parallel 활동 내부로 끌어서 놓습니다.

    범주 활동 참고

    Control Flow

    Sequence

  76. 다음 활동을 Sequence 활동 내부로 끌어서 놓습니다.

    범주 활동 참고

    Microsoft.Samples.Dublin.Tutorials.OrderService.ShippingService.Activities

    ShipOrder

    Runtime

    Persist

    Messaging

    Receive

    Primitives

    Assign

  77. 다음 활동을 Parallel 활동 내부 및 기존 Sequence 활동 오른쪽으로 끌어서 놓습니다.

    범주 활동 참고

    Messaging

    ReceiveAndSendReply

    ReceiveAndSendReply 활동은 하나의 Sequence 활동이 Receive 활동과 SendReplyToReceive 활동을 래핑하는 복합 활동입니다.

  78. 다음 활동을 새로 추가된 Sequence 활동 내부 및 Receive 및 SendReplyToReceive의 두 개 활동 아래에 끌어서 놓습니다.

    범주 활동 참고

    Microsoft.Samples.Dublin.Tutorials.OrderService.ShippingService.Activities

    CancelShipping

    Control Flow

    If

  79. 다음 활동을 If 활동의 Then 분기 내부로 끌어서 놓습니다.

    범주 활동 참고

    Control Flow

    Sequence

  80. 다음 활동을 새로 추가된 Sequence 활동 내부로 끌어서 놓습니다.

    범주 활동 참고

    Primitives

    Assign

    Primitives

    Assign

    Microsoft.Samples.Dublin.Tutorials.OrderService.OrderWorkflowService

    SendNotification

  81. 다음 활동을 If 활동의 Else 분기 내부로 끌어서 놓습니다.

    범주 활동 참고

    Microsoft.Samples.Dublin.Tutorials.OrderService.OrderWorkflowService

    SendNotification

  82. 다음 활동을 Parallel 활동 내부로 끌어서 놓아 맨 오른쪽 분기로 만듭니다.

    범주 활동 참고

    Messaging

    ReceiveAndSendReply

  83. 다음 활동을 새로 추가된 Sequence 활동 내부 및 Receive 및 SendReplyToReceive의 두 개 활동 아래에 끌어서 놓습니다.

    범주 활동 참고

    Microsoft.Samples.Dublin.Tutorials.OrderService.ShippingService.Activities

    CancelShipping

    Control Flow

    If

  84. 다음 활동을 If 활동의 Then 분기 내부로 끌어서 놓습니다.

    범주 활동 참고

    Control Flow

    Sequence

  85. 다음 활동을 새로 추가된 Sequence 활동 내부로 끌어서 놓습니다.

    범주 활동 참고

    Microsoft.Samples.Dublin.Tutorials.OrderService.OrderWorkflowService

    SendNotification

    Runtime

    TerminateWorkflow

  86. 다음 활동을 If 활동의 Else 분기 내부로 끌어서 놓습니다.

    범주 활동 참고

    Microsoft.Samples.Dublin.Tutorials.OrderService.OrderWorkflowService

    SenNotification

    활동을 추가하면 주문 처리됨 상태는 다음과 같이 표시됩니다.

    주문 처리됨 상태

  87. Parallel 활동의 맨 왼쪽 분기에서 Sequence 활동을 클릭하고 워크플로 아래쪽에서 변수를 클릭하여 변수 패널을 엽니다.

  88. 변수 패널에서 변수 만들기를 클릭하고 다음 변수를 만듭니다.

    변수 이름 변수 유형 범위 참고

    cancelShippingAcknowledgement

    String

    Parallel

    ShippingServiceResult

    Microsoft.Samples.Dublin.Tutorials.OrderService.OrderWorkflowService.ShippingServiceResult

    Sequence

    shippingServiceAcknowledgement

    String

    Sequence

  89. 워크플로의 Parallel 활동 맨 위에서 Assign 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    DisplayName

    Initialize isUpdated

    To

    isUpdated

    Value

    False

  90. 워크플로에서 Parallel 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    Completion

    isUpdated Or isShipped

    DisplayName

    Ship order

  91. 워크플로의 Parallel 활동 맨 왼쪽 분기에서 Sequence 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    DisplayName

    Shipping

  92. 워크플로의 Parallel 활동 맨 왼쪽 분기에서 ShipOrder 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    DisplayName

    Ship order

    poID

    po.POID

    ShipOrderResult

    shippingServiceAcknowledgement

  93. 워크플로의 Parallel 활동 맨 왼쪽 분기에서 Receive 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    Content

    Message; Message data:shippingServiceResult; Message type: Microsoft.Samples.Dublin.Tutorials.OrderService.OrderWorkflowService.ShippingServiceResult

    DisplayName

    Receive shipping result

    OperationName

    SubmitShippingResult

    ServiceContractName

    Microsoft.Samples.Dublin.Tutorials.OrderService.OrderWorkflowService.IOrderWorkflowService

    CanCreateInstance

    (선택 취소)

    CorrelationOn

    CorrelationWith: correlationOrderWorkflow; XPath Queries: key1=sm:body()/xg0:ShippingServiceResult/xg0:POID

    CorrelationWith

    correlationOrderWorkflow

  94. 워크플로의 Parallel 활동 맨 왼쪽 분기에서 Assign 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    DisplayName

    Set isShipped flag

    To

    isShipped

    Value

    True

    Parallel 활동의 맨 왼쪽 분기 구성을 완료했습니다.

  95. 워크플로의 Parallel 활동 중간 분기에서 Sequence 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    DisplayName

    Waiting for update

  96. 워크플로의 Parallel 활동 중간 분기에서 Receive 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    Content

    Message; Message data:poUpdate; Message type: Microsoft.Samples.Dublin.Tutorials.OrderService.OrderWorkflowService.OrderProcessingService.PurchaseOrder

    DisplayName

    Receive update

    OperationName

    SubmitUpdate

    ServiceContractName

    Microsoft.Samples.Dublin.Tutorials.OrderService.OrderWorkflowService.IOrderWorkflowService

    CanCreateInstance

    (선택 취소)

    CorrelationOn

    CorrelationWith: correlationOrderWorkflow; XPath Queries: key1=sm:body()/xg0:PurchaseOrder/xg0:POID

    CorrelationWith

    correlationOrderWorkflow

  97. 워크플로의 Parallel 활동 중간 분기에서 SendReplyToReceive 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    Content

    Message; Message data: “PO update received”; Message type: String

    DisplayName

    Acknowledge receiving update

  98. 워크플로의 Parallel 활동 중간 분기에서 CancelShipping 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    CancelShippingResult

    cancelShippingAcknowledgement

    DisplayName

    Cancel shipping

    orderID

    poUpdate.POID
  99. 워크플로의 Parallel 활동 중간 분기에서 If 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    Condition

    cancelShippingAcknowledgement = "The shipping process has been terminated successfully."

    DisplayName

    Check cancellation status

  100. 워크플로의 If 활동 Then 분기에서 Sequence 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    DisplayName

    Cancellation succeed sequence

  101. 워크플로의 If 활동 Then 분기에서 첫 번째 Assign 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    DisplayName

    Refresh PO

    To

    po

    Value

    poUpdate
  102. 워크플로의 If 활동 Then 분기에서 두 번째 Assign 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    DisplayName

    Set isUpdated flag

    To

    isUpdated

    Value

    True
  103. 워크플로의 If 활동 Then 분기에서 SendNotification 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    Body

    "Your order has updated upon your request. The order is under processing."

    DisplayName

    Send client notification

    Subject

    "Contoso.com Order#" + po.POID + "~~Order Updated (by customer)"

    To

    po.EmailAddress
  104. 워크플로의 If 활동 Else 분기에서 SendNotification 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    Body

    "Your order update request cannot be processed. The order has been shipped."

    DisplayName

    Send client notification

    Subject

    "Contoso.com Order#" + po.POID + "~~Order Update (by customer) Failed"

    To

    po.EmailAddress

    Parallel 활동의 중간 분기 구성을 완료했습니다.

  105. 워크플로의 Parallel 활동 맨 오른쪽 분기에서 Sequence 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    DisplayName

    Waiting for cancellation

  106. 워크플로의 Parallel 활동 맨 오른쪽 분기에서 Receive 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    Content

    Message; Message data:poID; Message type:String

    DisplayName

    Receive cancellation

    OperationName

    SubmitCancellation

    ServiceContractName

    Microsoft.Samples.Dublin.Tutorials.OrderService.OrderWorkflowService.IOrderWorkflowService

    CanCreateInstance

    (선택 취소)

    CorrelationOn

    CorrelationWith: correlationOrderWorkflow; XPath Queries: key1=sm:body()/xg0:string

    CorrelationWith

    correlationOrderWorkflow

  107. 워크플로의 Parallel 활동 맨 오른쪽 분기에서 SendReplyToReceive 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    Content

    Message; Message data: “PO cancellation received”; Message type: String

    DisplayName

    Acknowledge receiving cancellation

  108. 워크플로의 Parallel 활동 맨 오른쪽 분기에서 CancelShipping 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    CancelshippingResult

    cancelShippingAcknowledgement

    DisplayName

    Cancel shipping

    poID

    po.POID
  109. 워크플로의 Parallel 활동 맨 오른쪽 분기에서 If 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    Condition

    cancelShippingAcknowledgement = "The shipping process has been terminated successfully."

    DisplayName

    Check cancellation status

  110. 워크플로의 If 활동 Then 분기에서 Sequence 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    DisplayName

    Cancellation succeed sequence

  111. 워크플로의 If 활동 Then 분기에서 SendNotification 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    Body

    "We are sorry you chose to cancel your order. If there is anything we can do to help you with our order process or with our products or services please do not hesitate to contact us."

    DisplayName

    Send client notification

    Subject

    "Contoso.com Order#" + po.POID + "~~Order Cancelled (by cusotmer)"

    To

    po.EmailAddress
  112. 워크플로의 If 활동 Then 분기에서 TerminateWorkflow 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    DisplayName

    Terminate workflow

    Reason

    “Client cancellation”
  113. 워크플로의 If 활동 Else 분기에서 두 번째 SendNotification 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    Body

    "Your order cancellation request cannot be processed. The order has been shipped.

    DisplayName

    Send client notification

    Subject

    "Contoso.com Order#" + po.POID + "~~Order Cancellation(by customer) Failed"

    To

    po.EmailAddress

    Parallel 활동의 맨 오른쪽 분기 구성을 완료했습니다.

  114. 탭 이름 아래에서 Order service를 클릭하여 "Order service" Flowchart 활동을 표시합니다.

  115. 워크플로에서 주문 완료됨 Sequence 활동을 두 번 클릭하여 상태를 구현합니다.

  116. 표시된 순서대로 다음 활동을 도구 상자에서 워크플로로 끌어서 놓습니다.

    범주 활동 참고

    Microsoft.Samples.Dublin.Tutorials.OrderService.OrderWorkflowService

    SendNotification

  117. 워크플로의 If 활동 Else 분기에서 두 번째 SendNotification 활동을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    Body

    "Your order has been shipped.  Thank you for shopping at contoso.com."

    DisplayName

    Send client notification

    Subject

    "Contoso.com Order#" + po.POID + "~~ Order Shipped"

    To

    po.EmailAddress

    워크플로 개발을 완료했습니다.

이 구성 파일에서는 2개의 끝점과 1개의 동작 요소를 정의합니다.

구성 파일을 사용하여 주문 워크플로 서비스를 구성하려면

  1. 솔루션 탐색기에서 OrderWorkflowService를 확장하고 Web.config를 두 번 클릭하여 엽니다.

  2. <services> 태그를 <system.serviceModel> 태그 내부에 추가합니다.

        <services>
          <service name="Microsoft.Samples.Dublin.Tutorials.OrderService.OrderWorkflowService.OrderWorkflow">
            <endpoint address="" binding="basicHttpBinding" contract="Microsoft.Samples.Dublin.Tutorials.OrderService.OrderWorkflowService.IOrderWorkflowService" />
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
          </service>
        </services>
    

주문 워크플로 서비스를 컴파일하려면

  1. 솔루션 탐색기에서 OrderWorkflowService 프로젝트를 마우스 오른쪽 단추로 클릭하고 다시 빌드를 클릭합니다. 출력 창에서 프로젝트가 성공적으로 컴파일되었는지 확인하십시오.

주문 처리 서비스 완료

OrderProcessingService 및 OrderWorkflowService는 서로를 참조합니다. 따라서 OrderWorkflowService를 완료한 후 OrderProcessingService를 완료해야 합니다.

서비스 참조를 추가하려면

  1. 솔루션 탐색기에서 OrderProcessingService를 마우스 오른쪽 단추로 클릭하고 서비스 참조 추가를 클릭합니다.

  2. 서비스 참조 추가에서 검색을 클릭합니다. Visual Studio가 2개 서비스를 모두 검색해야 합니다.

  3. 다음 값을 입력 및 선택하고 확인을 클릭하여 서비스 참조를 만듭니다.

    속성

    Services

    OrderWorkflow.xamlx

    Namespace

    OrderWorkflowService

OrderProcess.svc를 수정하려면

  1. 솔루션 탐색기에서 OrderProcessingService를 확장하고 OrderProcessing.svc를 두 번 클릭하여 엽니다.

  2. 다음과 같이 SendProcessResult 함수 내부의 섹션에 대한 주석 처리를 제거합니다.

    
    private void SendProcessResult(object state)
    {
        PurchaseOrder po = (PurchaseOrder)state;
    
        WorkItem workItem = new WorkItem(Thread.CurrentThread);
        WorkItemMap.Add(po.POID, workItem);
    
        //Simulating the order processing process
        Thread.Sleep(120000);
    
        //The following portion will be uncommented after referencing OrderWorkflowService
        OrderWorkflowService.ProcessServiceResult reply = new OrderWorkflowService.ProcessServiceResult();
        reply.POID = po.POID;
        reply.Message = "The order has been processed successfully.";
    
        lock (workItem.WorkItemLock)
        {
            using (OrderWorkflowService.MicrosoftSamplesDublinTutorialsOrderServiceOrderWorkflowServiceIOrderWorkflowServiceClient client = new OrderWorkflowService.MicrosoftSamplesDublinTutorialsOrderServiceOrderWorkflowServiceIOrderWorkflowServiceClient())
            {
                client.SubmitProcessResult(reply);
            }
    
            workItem.Complete();
            WorkItemMap.Remove(po.POID);
        }
    
    }
    

주문 처리 서비스를 컴파일하려면

  1. 솔루션 탐색기에서 OrderProcessingService 프로젝트를 마우스 오른쪽 단추로 클릭하고 다시 빌드를 클릭합니다. 출력 창에서 프로젝트가 성공적으로 컴파일되었는지 확인하십시오.

배송 서비스 완료

ShippingService 및 OrderWorkflowService는 서로를 참조합니다. 따라서 OrderWorkflowService를 완료한 후 ShipingService를 완료해야 합니다.

서비스 참조를 추가하려면

  1. 솔루션 탐색기에서 ShipingService를 마우스 오른쪽 단추로 클릭하고 서비스 참조 추가를 클릭합니다.

  2. 서비스 참조 추가에서 검색을 클릭합니다. Visual Studio가 2개 서비스를 모두 검색해야 합니다.

  3. 다음 값을 입력 및 선택하고 확인을 클릭하여 서비스 참조를 만듭니다.

    속성

    Services

    OrderWorkflow.xamlx

    Namespace

    OrderWorkflowService

Shipping.svc를 수정하려면

  1. 솔루션 탐색기에서 ShippingService를 확장하고 Shipping.svc를 두 번 클릭하여 엽니다.

  2. 다음과 같이 SendShippingResult 함수 내부의 섹션에 대한 주석 처리를 제거합니다.

    private void SendShippingResult(object state)
    {
        string poID = state.ToString();
    
        WorkItem workItem = new WorkItem(Thread.CurrentThread);
        WorkItemMap.Add(poID, workItem);
    
        //Simulating the order processing process
        Thread.Sleep(60000);
    
        //The following portion will be uncommented after referencing OrderWorkflowService
        OrderWorkflowService.ShippingServiceResult reply = new OrderWorkflowService.ShippingServiceResult();
        reply.POID = poID;
        reply.Message = "The order has been shipped.";
    
        lock (workItem.WorkItemLock)
        {
            using (OrderWorkflowService.MicrosoftSamplesDublinTutorialsOrderServiceOrderWorkflowServiceIOrderWorkflowServiceClient client = new OrderWorkflowService.MicrosoftSamplesDublinTutorialsOrderServiceOrderWorkflowServiceIOrderWorkflowServiceClient())
            {
                client.SubmitShippingResult(reply);
            }
    
            workItem.Complete();
            WorkItemMap.Remove(poID);
        }
    }
    

배송 서비스를 컴파일하려면

  1. 솔루션 탐색기에서 ShippingService 프로젝트를 마우스 오른쪽 단추로 클릭하고 다시 빌드를 클릭합니다. 출력 창에서 프로젝트가 성공적으로 컴파일되었는지 확인하십시오.

주문 클라이언트 응용 프로그램 개발

이 단계에서는 Windows Form 클라이언트 응용 프로그램을 개발합니다.

솔루션에 Windows Form 응용 프로그램 프로젝트를 추가하려면

  1. 솔루션 탐색기에서 **솔루션 ‘OrderService’**를 마우스 오른쪽 단추로 클릭하고 추가를 가리킨 다음 새 프로젝트를 클릭합니다.

  2. 새 프로젝트 추가에서 다음 값을 선택하거나 입력한 후 확인을 클릭합니다.

    속성

    Project types

    Visual C#/Windows

    Templates

    Windows Forms Application

    Name

    OrderClient

    Location

    C:\DublinTutorial\OrderServiceSolution\OrderService

주문 클라이언트는 워크플로 서비스에 대한 인터페이스입니다. 워크플로 서비스에 서비스 참조를 추가해야 합니다.

서비스 참조를 추가하려면

  1. 솔루션 탐색기에서 OrderClient를 마우스 오른쪽 단추로 클릭하고 서비스 참조 추가를 클릭하여 서비스 참조 추가 대화 상자를 엽니다.

  2. 서비스 참조 추가에서 검색을 클릭합니다.

  3. 다음 값을 입력 및 선택하고 확인을 클릭하여 서비스 참조를 만듭니다.

    속성

    Services

    OrderWorkflow.xamlx

    Namespace

    OrderWorkflowService

Windows Form을 개발하려면

  1. 솔루션 탐색기에서 OrderClient를 확장하고 Form1.cs를 두 번 클릭하여 엽니다.

  2. Form1.cs를 마우스 오른쪽 단추로 클릭하고 이름 바꾸기를 클릭한 다음 OrderForm.cs를 입력합니다.

  3. 프롬프트에서 를 클릭합니다.

  4. 도구 상자에서 양식에 레이블 컨트롤 4개, 텍스트 상자 컨트롤 5개 및 단추 컨트롤 3개를 추가하고 다음 스크린 샷과 같이 컨트롤을 정렬합니다.

    주문 클라이언트 양식

  5. 워크플로에서 양식을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    Name

    OrderForm

    Text

    Contoso.com Order Form

  6. 워크플로에서 label1을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    Name

    lblOrderNumber

    Text

    Order number:

  7. 워크플로에서 label2를 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    Name

    lblEmail

    Text

    Email:

  8. 워크플로에서 label3을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    Name

    lblDescription

    Text

    설명:

  9. 워크플로에서 label4를 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    Name

    lblQuantity

    Text

    Quantity:

  10. 워크플로에서 textbox1을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    Name

    txtOrderNumber

    Enabled

    False

  11. 워크플로에서 textbox2를 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    Name

    txtEmail

    Text

    JohnDole@fabrikam.com

  12. 워크플로에서 textbox3을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    Name

    txtDescription

    Text

    Windows 7

  13. 워크플로에서 textbox4를 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    Name

    txtQuantity

    Text

    10

  14. 워크플로에서 textbox5를 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    Name

    txtStatus

    Anchor

    Bottom, Left, Right

    Enabled

    False

    Text

    “”

  15. 워크플로에서 button1을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    Name

    btnSubmit

    Anchor

    Bottom, Right

    Text

    제출

    Click(이벤트 탭 아래)

    btnSubmit_Click

  16. 워크플로에서 button2를 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    Name

    btnUpdate

    Anchor

    Bottom, Right

    Text

    Update

    Click(이벤트 탭 아래)

    btnUpdate_Click

  17. 워크플로에서 button3을 클릭하고 속성 패널에서 다음 값을 설정합니다.

    속성

    Name

    btnCancel

    Anchor

    Bottom, Right

    Text

    Cancel

    Click(이벤트 탭 아래)

    btnCancel_Click

  18. 솔루션 탐색기에서 OrderForm.cs를 마우스 오른쪽 단추로 클릭하고 코드 보기를 클릭합니다.

  19. OrderClient 네임스페이스를 마우스 오른쪽 단추로 클릭하고 리팩터링, 이름 바꾸기를 차례로 클릭하여 이름 바꾸기 대화 상자를 엽니다.

  20. 이름 바꾸기에서 Microsoft.Samples.Dublin.Tutorials.OrderService.OrderClient를 입력하고 확인을 클릭합니다.

  21. 적용을 클릭합니다.

  22. 코드를 다음으로 바꿉니다.

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    
    namespace Microsoft.Samples.Dublin.Tutorials.OrderService.OrderClient
    {
        public partial class OrderForm : Form
        {
            //Delegates to make all service calls on a secondary thread
            private delegate void SubmitOrderDelegate();
            private delegate void CancelOrderDelegate();
            private delegate void UpdateOrderDelegate();
            private delegate void CallbackDelegate(string poID, string str);
    
            private SubmitOrderDelegate SubmitOrderHandler;
            private CancelOrderDelegate CancelOrderHandler;
            private UpdateOrderDelegate UpdateOrderHandler;
            private CallbackDelegate CallbackHandler;
    
            public OrderForm()
            {
                InitializeComponent();
            }
    
            private void OrderForm_Load(object sender, EventArgs e)
            {
                btnUpdate.Enabled = false;
                btnCancel.Enabled = false;
                btnSubmit.Focus();
            }
    
            #region Submit button
            private void btnSubmit_Click(object sender, EventArgs e)
            {
                btnSubmit.Enabled = false;
                btnCancel.Enabled = false;
                btnUpdate.Enabled = false;
                txtEmail.Enabled = false;
    
                txtStatus.Text = "Connecting to the Order service ...";
    
                //Executed on secondary thread so the UI thread is not blocked
                SubmitOrderHandler = new SubmitOrderDelegate(this.SubmitOrder);
                SubmitOrderHandler.BeginInvoke(null, null);
            }
    
            private void SubmitOrder()
            {
                string strMessage = "Your order has been received.";
                string strPOID = "";
    
                OrderWorkflowService.PurchaseOrder po = new OrderWorkflowService.PurchaseOrder();
                po.EmailAddress = txtEmail.Text;
                po.Description = txtDescription.Text;
                po.Quantity = System.Int32.Parse(txtQuantity.Text);
    
                //A Blocking service call executed on secondary thread
                try
                {
                    OrderWorkflowService.MicrosoftSamplesDublinTutorialsOrderServiceOrderWorkflowServiceIOrderWorkflowServiceClient client = new OrderWorkflowService.MicrosoftSamplesDublinTutorialsOrderServiceOrderWorkflowServiceIOrderWorkflowServiceClient();
                    strPOID = client.SubmitPO(po);
                    client.Close();
                }
                catch (Exception Ex)
                {
                    strMessage = "Error: " + Ex.Message;
                }
    
                //Make UI updates back on the primary thread
                CallbackHandler = new CallbackDelegate(this.SubmitOrderCallBack);
                this.BeginInvoke(CallbackHandler, strPOID, strMessage);
    
            }
    
            private void SubmitOrderCallBack(string strPOID, string strMessage)
            {
                //UI updates back on the primary thread
                btnUpdate.Enabled = true;
                btnCancel.Enabled = true;
    
                txtOrderNumber.Text = strPOID;
                txtStatus.Text = strMessage;
            }
            #endregion
    
            #region Update button
            private void btnUpdate_Click(object sender, EventArgs e)
            {
                btnUpdate.Enabled = false;
                btnCancel.Enabled = false;
    
                txtStatus.Text = "Connecting to the Order service ...";
    
                //Executed on secondary thread so the UI thread is not blocked
                UpdateOrderHandler = new UpdateOrderDelegate(this.UpdateOrder);
                UpdateOrderHandler.BeginInvoke(null, null);
    
            }
    
            private void UpdateOrder()
            {
                string strMessage = "Your order update request has been received.";
                string strPOID = "";
    
                OrderWorkflowService.PurchaseOrder po = new OrderWorkflowService.PurchaseOrder();
                po.POID = txtOrderNumber.Text;
                po.EmailAddress = txtEmail.Text;
                po.Description = txtDescription.Text;
                po.Quantity = System.Int32.Parse(txtQuantity.Text);
    
                try
                {
                    OrderWorkflowService.MicrosoftSamplesDublinTutorialsOrderServiceOrderWorkflowServiceIOrderWorkflowServiceClient client = new OrderWorkflowService.MicrosoftSamplesDublinTutorialsOrderServiceOrderWorkflowServiceIOrderWorkflowServiceClient();
                    strMessage = client.SubmitUpdate(po);
                    client.Close();
                }
                catch (Exception Ex)
                {
                    strMessage = "Error: " + Ex.Message;
                }
    
                //Make UI updates back on the primary thread
                CallbackHandler = new CallbackDelegate(this.UpdateOrderCallback);
                this.BeginInvoke(CallbackHandler, strPOID, strMessage);
    
            }
    
            private void UpdateOrderCallback(string strPOID, string strMessage)
            {
                //UI updates back on the primary thread
                btnUpdate.Enabled = true;
                btnCancel.Enabled = true;
    
                txtStatus.Text = strMessage;
            }
            #endregion
    
            #region Cancel button
            private void btnCancel_Click(object sender, EventArgs e)
            {
                btnUpdate.Enabled = false;
                btnCancel.Enabled = false;
    
                txtStatus.Text = "Connecting to the Order service ...";
    
                //Executed on secondary thread so the UI thread is not blocked
                CancelOrderHandler = new CancelOrderDelegate(this.CancelOrder);
                CancelOrderHandler.BeginInvoke(null, null);
            }
    
            private void CancelOrder()
            {
                string strInOut = txtOrderNumber.Text;
    
                try
                {
                    OrderWorkflowService.MicrosoftSamplesDublinTutorialsOrderServiceOrderWorkflowServiceIOrderWorkflowServiceClient client = new OrderWorkflowService.MicrosoftSamplesDublinTutorialsOrderServiceOrderWorkflowServiceIOrderWorkflowServiceClient();
                    client.SubmitCancellation(ref strInOut);
                    client.Close();
                }
                catch (Exception Ex)
                {
                    strInOut = "Error: " + Ex.Message;
                }
    
                //Make UI updates back on the primary thread
                CallbackHandler = new CallbackDelegate(this.CancelOrderCallback);
                this.BeginInvoke(CallbackHandler, txtOrderNumber.Text, strInOut);
            }
    
            private void CancelOrderCallback(string strPOID, string strMessage)
            {
                //UI updates back on the primary thread
                //btnUpdate.Enabled = true;
                //btnCancel.Enabled = true;
    
                txtStatus.Text = strMessage;
            }
            #endregion
        }
    }
    

주문 클라이언트를 컴파일하려면

  1. 솔루션 탐색기에서 OrderClient 프로젝트를 마우스 오른쪽 단추로 클릭하고 다시 빌드를 클릭합니다. 출력 창에서 프로젝트가 성공적으로 컴파일되었는지 확인하십시오.

Order Service 테스트

Order service를 테스트하려면

  1. 솔루션 탐색기에서 OrderClient를 마우스 오른쪽 단추로 클릭하고 시작 프로젝트로 설정을 클릭합니다.

  2. Visual Studio에서 디버그 메뉴를 클릭한 다음 디버깅 시작을 클릭합니다. Windows Form이 열렸는지 확인해야 합니다.

  3. 양식에서 제출을 클릭합니다.

  4. Windows 탐색기를 열고 C:\DublinTutorial\Inbox 폴더로 이동합니다.

  5. 3개 전자 메일 알림이 모두 표시될 때까지 기다립니다. 3개 파일이 모두 표시되려면 3-4분 정도가 걸립니다.

Order Service 패키징

OrderProcessingService WCF 서비스를 패키징하려면

  1. 솔루션 탐색기에서 OrderProcessingService 프로젝트를 마우스 오른쪽 단추로 클릭하고 패키징/게시 설정을 클릭합니다.

  2. 다음 값을 입력합니다.

    속성

    ZIP 파일로 웹 패키지 만들기

    (선택됨)

    패키지가 만들어지는 위치

    C:\DublinTutorial\DeploymentPackages\OrderProcessingService.zip

    대상 서버에 사용되는 IIS 웹 사이트/응용 프로그램 이름

    OrderService/OrderProcessingService

  3. 솔루션 탐색기에서 OrderProcessingService 프로젝트를 마우스 오른쪽 단추로 클릭하고 패키지 만들기를 클릭합니다.

  4. 마지막 절차를 반복하여 다음 설정으로 다른 3개 프로젝트에 대한 패키지를 만듭니다.

    프로젝트 이름 패키지가 만들어지는 위치 대상 서버에 사용되는 IIS 웹 사이트/응용 프로그램 이름

    OrderWorkflowService

    C:\DublinTutorial\DeploymentPackages\OrderWorkflowService.zip

    OrderService/OrderWorkflowService

    ShippingService

    C:\DublinTutorial\DeploymentPackages\ShippingService.zip

    OrderService/ShippingService

    참고

    서비스를 패키징하기 전에 패키지를 배포할 서버를 반영하기 위해 Web.config 파일에서 종속 서비스의 끝점 주소를 업데이트하는 것을 고려할 수 있습니다.

참고 항목

개념

Windows Server AppFabric 인터페이스 사용 자습서
Windows PowerShell 사용 자습서

  2011-12-05