작업 2: 워크플로 서비스 클라이언트 만들기
이 작업에서는 작업 1: 워크플로 서비스 만들기에서 만든 워크플로 서비스에서 정의되고 구현된 작업을 호출하는 기본 워크플로 서비스 클라이언트를 만듭니다. 클라이언트는 콘솔 창에 각 수학 연산 호출에 전달한 값과 서비스에서 응답으로 보낸 값을 표시합니다.
참고
이 클라이언트는 이 자습서의 나머지 연습에서 사용됩니다.
참고
Visual Studio Workflow Designer를 사용하여 워크플로 서비스를 만들거나 관리할 경우 의사 유효성 검사 오류가 발생할 수 있습니다. 프로젝트를 성공적으로 빌드할 수 있으면 유효성 검사 오류를 무시해도 됩니다.
워크플로 서비스 클라이언트를 만들려면
WorkflowServiceTutorial 솔루션이 현재 열려 있지 않으면 Visual Studio 2008을 열고 파일을 클릭한 다음 열기를 강조 표시하고 WorkflowServiceTutorial 솔루션으로 이동합니다.
WcfSvcHost.exe가 실행 중이 아닌 경우 Ctrl+F5를 눌러 WorkflowServiceTutorial 서비스를 빌드하고 실행합니다. 이 작업의 단계를 완료하려면 이 서비스가 실행 중이어야 합니다. 서비스 목록에서 WorkflowServiceTutorial.ServerWorkflow를 마우스 오른쪽 단추로 클릭한 다음 메타데이터 주소 복사를 선택합니다.
파일을 클릭하고 추가를 강조 표시한 다음 새 프로젝트를 선택합니다.
새 프로젝트 대화 상자의 워크플로 아래에서 순차 워크플로 콘솔 응용 프로그램을 선택합니다.
프로젝트 이름을 WorkflowServiceClient로 지정하고 확인을 클릭합니다.
솔루션 탐색기에서 WorkflowServiceClient 노드를 마우스 오른쪽 단추로 클릭하고 **서비스 참조 추가...**를 선택합니다.
서비스 참조 추가 대화 상자의 주소 상자에 이전 단계에서 복사한 메타데이터 주소를 붙여 넣고 이동을 클릭합니다. ServerWorkflow가 서비스 상자에 나타나면 확인을 클릭하여 서비스 참조를 추가합니다.
워크플로에 대한 Workflow Designer 페이지를 열고 도구 상자 창을 사용하여 SendActivity 활동을 워크플로에 추가합니다.
Workflow Designer에서 SendActivity 활동을 강조 표시합니다.
속성 창으로 이동하고 ServiceOperationInfo 속성 아래에서 줄임표를 클릭하여 작업 선택 대화 상자를 엽니다.
오른쪽 위 모퉁이에서 가져오기를 클릭합니다.
형식 탭 아래에서 **<현재 프로젝트>**를 강조 표시합니다.
형식 목록에서 IWorkflow1을 선택하고 확인을 클릭합니다.
작업 선택 대화 상자가 템플릿에서 정의되고 WorkflowServiceTutorial 프로젝트에서 구현된 계약과 작업에 대한 정보로 채워집니다.
사용 가능한 작업에서 StartupService를 강조 표시하고 확인을 클릭합니다.
디자이너는 TypedOperationInfo 개체를 만든 다음 계약 및 작업 정보로 채우고 ServiceOperationInfo 속성을 통해 SendActivity 활동과 연결하여 SendActivity 활동을
StartupService
작업과 연결합니다.Workflow Designer에서 속성 창으로 이동합니다.
ChannelToken 속성에서 ChannelToken 개체의 이름을 만들고 Enter 키를 누릅니다.
ChannelToken 속성을 확장합니다.
EndpointName 속성의 경우 클라이언트의 App.config 파일로 이동합니다. 서비스에 액세스하는 데 사용할 끝점의 이름을 복사하여 붙여 넣습니다. 예를 들어, 다음 코드에서 끝점 이름은 "WSHttpContextBinding_IWorkflow1"입니다.
<client> <endpoint address="https://localhost:8080/ServerWorkflow" binding="wsHttpContextBinding" bindingConfiguration="WSHttpContextBinding_IWorkflow1" contract="ServiceReference.IWorkflow1" name="WSHttpContextBinding_IWorkflow1"> <identity> <userPrincipalName value="someone@example.com" /> </identity> </endpoint> </client>
참고
App.config 파일의 EndpointName 속성과 이름 특성은 동일해야 합니다. 동일하지 않은 경우에는 클라이언트 응용 프로그램을 실행할 때 오류가 발생합니다.
OwnerActivityName 속성의 경우 비워 둡니다. 이름을 선택하지 않으면 루트 활동의 이름이 컴파일 타임에 자동으로 선택됩니다.
속성 창에서 이벤트 단추를 클릭합니다.
AfterResponse 이벤트의 텍스트 상자를 두 번 클릭하여 이벤트 처리기를 생성합니다.
다음 코드를 입력하여 StartupService 작업이 호출된 후 사용자에게 다음 메시지를 표시합니다.
Private Sub sendActivity1_AfterResponse(ByVal sender As System.Object, ByVal e As System.Workflow.Activities.SendActivityEventArgs) Console.WriteLine("A service instance has successfully been created.") End Sub
private void sendActivity1_AfterResponse(object sender, SendActivityEventArgs e) { Console.WriteLine("A service instance has successfully been created."); }
Workflow Designer에서 SendActivity 활동을 5개 더 추가합니다.
각 SendActivity 활동을 한 작업 및 13-17단계에서 사용한 동일한 클라이언트 채널 토큰과 연결합니다.
수학 연산(더하기, 빼기, 곱하기, 나누기)은 n1이라는 int를 사용하므로 n1에 대한 활동 바인딩을 만들거나 값을 설정해야 합니다. 이 자습서에서는 워크플로의 기존 속성에 바인딩합니다. 이렇게 하려면 Workflow1.cs(또는 Visual Basic 솔루션을 만든 경우 Workflow1.vb)를 열고 다음 단계를 수행합니다.
Workflow1 클래스의 이름을 ClientWorkflow로 바꿉니다.
ClientWorkflow
클래스 정의에서 다음 예제와 같이 public 속성을 만듭니다.Public class ClientWorkflow Inherits SequentialWorkflowActivity Public inputValue As Integer = Nothing Private Sub sendActivity1_AfterResponse(ByVal sender As System.Object, ByVal e As System.Workflow.Activities.SendActivityEventArgs) Console.WriteLine("A service instance has successfully been created.") End Sub End Class
public sealed partial class ClientWorkflow: SequentialWorkflowActivity { public int inputValue = default(int); public ClientWorkflow() { InitializeComponent(); } private void sendActivity1_AfterResponse(object sender, SendActivityEventArgs e) { Console.WriteLine("A service instance has successfully been created."); } }
Workflow Designer를 열고 더하기 연산을 호출하여 연결된 SendActivity 활동에 대한 속성 창의 기존 멤버에 바인딩 탭에서 줄임표를 클릭하고 inputValue를 선택하여 inputValue를 n1 활동 속성에 바인딩합니다.
서비스에 보낼 메시지를 만들도록 BeforeSend 이벤트에 대한 이벤트 처리기를 구현합니다.
Private Sub sendActivity2_BeforeSend(ByVal sender As System.Object, ByVal e As System.Workflow.Activities.SendActivityEventArgs) inputValue = 1 Console.WriteLine("The initial input value is {0}", inputValue) End Sub
private void sendActivity2_BeforeSend(object sender, SendActivityEventArgs e) { inputValue = 1; Console.WriteLine("The initial input value is {0}", inputValue); }
서비스에서 받은 결과를 표시하려면 작업이 성공할 때 반환 값을 저장할 변수를 만들어야 합니다. 이렇게 하려면 Workflow1.cs(또는 Visual Basic 솔루션을 만든 경우 Workflow1.vb)를 열고 다음 단계를 수행합니다.
ClientWorkflow
클래스 정의에서 다음 예제와 같이returnedValue
라는 public 속성을 만듭니다.Public class ClientWorkflow Inherits SequentialWorkflowActivity Public inputValue As Integer = Nothing Public returnedValue As Integer = Nothing ... End Class
public sealed partial class ClientWorkflow: SequentialWorkflowActivity { public int inputValue = default(int); public int returnedValue = default(int); public ClientWorkflow() { InitializeComponent(); } ... }
Workflow Designer를 열고 속성 창의 기존 멤버에 바인딩 탭에서 줄임표를 클릭하고 returnedValue를 선택하여 returnedValue를 (ReturnValue) 활동 속성에 바인딩합니다.
서비스에서 전송된 메시지를 표시하도록 AfterResponse 이벤트에 대한 이벤트 처리기를 구현합니다.
private void sendActivity2_AfterResponse(object sender, SendActivityEventArgs e) { Console.WriteLine("The value after invoking the Add operation is {0}", returnedValue); }
다른 각 수학 연산에 대해 inputValue 및 returnedValue를 각각 n1 및 **(ReturnValue)**에 바인딩합니다.
24c 및 25c 단계와 같은 방법으로 수학 연산에 연결된 나머지 각 SendActivity 활동의 BeforeSend 및 AfterResponse 이벤트에 대한 이벤트 처리기를 구현합니다. 다음 예제에서는
ShutdownService
작업에 연결된 SendActivity 활동에 대한 이벤트 처리기를 비롯하여 모든 이벤트 처리기에 대한 구현을 보여 줍니다.Private Sub sendActivity1_AfterResponse(ByVal sender As System.Object, ByVal e As System.Workflow.Activities.SendActivityEventArgs) Console.WriteLine("A service instance has successfully been created.") End Sub Private Sub sendActivity2_BeforeSend(ByVal sender As System.Object, ByVal e As System.Workflow.Activities.SendActivityEventArgs) inputValue = 1 Console.WriteLine("The initial input value is {0}", inputValue) End Sub Private Sub sendActivity2_AfterResponse(ByVal sender As System.Object, ByVal e As System.Workflow.Activities.SendActivityEventArgs) Console.WriteLine("The value after invoking the Add operation is {0}", returnedValue) End Sub Private Sub sendActivity3_BeforeSend(ByVal sender As System.Object, ByVal e As System.Workflow.Activities.SendActivityEventArgs) inputValue = 2 Console.WriteLine("The new input value is {0}", inputValue) End Sub Private Sub sendActivity3_AfterResponse(ByVal sender As System.Object, ByVal e As System.Workflow.Activities.SendActivityEventArgs) Console.WriteLine("The value after invoking the Subtract operation is {0}", returnedValue) End Sub Private Sub sendActivity4_BeforeSend(ByVal sender As System.Object, ByVal e As System.Workflow.Activities.SendActivityEventArgs) inputValue = 6 Console.WriteLine("The new input value is {0}", inputValue) End Sub Private Sub sendActivity4_AfterResponse(ByVal sender As System.Object, ByVal e As System.Workflow.Activities.SendActivityEventArgs) Console.WriteLine("The value after invoking the Multiply operation is {0}", returnedValue) End Sub Private Sub sendActivity5_BeforeSend(ByVal sender As System.Object, ByVal e As System.Workflow.Activities.SendActivityEventArgs) inputValue = 3 Console.WriteLine("The new input value is {0}", inputValue) End Sub Private Sub sendActivity5_AfterResponse(ByVal sender As System.Object, ByVal e As System.Workflow.Activities.SendActivityEventArgs) Console.WriteLine("The value after invoking the Divide operation is {0}", returnedValue) End Sub Private Sub sendActivity6_AfterResponse(ByVal sender As System.Object, ByVal e As System.Workflow.Activities.SendActivityEventArgs) Console.WriteLine("The workflow service instance has been successfully shut down.") End Sub
private void sendActivity1_AfterResponse(object sender, SendActivityEventArgs e) { Console.WriteLine("A service instance has successfully been created."); } private void sendActivity2_BeforeSend(object sender, SendActivityEventArgs e) { inputValue = 1; Console.WriteLine("The initial input value is {0}", inputValue); } private void sendActivity2_AfterResponse(object sender, SendActivityEventArgs e) { Console.WriteLine("The value after invoking the Add operation is {0}", returnedValue); } private void sendActivity3_BeforeSend(object sender, SendActivityEventArgs e) { inputValue = 2; Console.WriteLine("The new input value is {0}", inputValue); } private void sendActivity3_AfterResponse(object sender, SendActivityEventArgs e) { Console.WriteLine("The value after invoking the Subtract operation is {0}", returnedValue); } private void sendActivity4_BeforeSend(object sender, SendActivityEventArgs e) { inputValue = 6; Console.WriteLine("The new input value is {0}", inputValue); } private void sendActivity4_AfterResponse(object sender, SendActivityEventArgs e) { Console.WriteLine("The value after invoking the Multiply operation is {0}", returnedValue); } private void sendActivity5_BeforeSend(object sender, SendActivityEventArgs e) { inputValue = 3; Console.WriteLine("The new input value is {0}", inputValue); } private void sendActivity5_AfterResponse(object sender, SendActivityEventArgs e) { Console.WriteLine("The value after invoking the Divide operation is {0}", returnedValue); } private void sendActivity6_AfterResponse(object sender, SendActivityEventArgs e) { Console.WriteLine("The workflow service instance has been successfully shut down."); }
Program.cs(또는 Visual Basic의 경우 Module1.vb)에서 ChannelManagerService를 WorkflowRuntime에서 사용되는 서비스의 목록에 추가하여 채널과 채널 팩터리를 캐시합니다. ChannelManagerService는 선택적으로 사용할 수 있지만 사용하지 않으면 채널이 캐시되지 않고 워크플로의 각 SendActivity 활동이 서비스와 통신할 때 새 채널 인스턴스를 사용합니다.
Shared WaitHandle As New AutoResetEvent(False) Shared Sub Main() Using workflowRuntime As New WorkflowRuntime() AddHandler workflowRuntime.WorkflowCompleted, AddressOf OnWorkflowCompleted AddHandler workflowRuntime.WorkflowTerminated, AddressOf OnWorkflowTerminated ' Add ChannelManagerService to the list of services used by the WorkflowRuntime. Dim cms As ChannelManagerService = New ChannelManagerService()workflowRuntime.AddService(cms) Dim workflowInstance As WorkflowInstance workflowInstance = workflowRuntime.CreateWorkflow(GetType(ClientWorkflow)) workflowInstance.Start() WaitHandle.WaitOne() End Using End Sub Shared Sub OnWorkflowCompleted(ByVal sender As Object, ByVal e As WorkflowCompletedEventArgs) Console.WriteLine("The client workflow has completed." + vbLf + "Press <Enter> to exit the client application.") Console.ReadLine() WaitHandle.Set() End Sub Shared Sub OnWorkflowTerminated(ByVal sender As Object, ByVal e As WorkflowTerminatedEventArgs) Console.WriteLine(e.Exception.Message) WaitHandle.Set() End Sub
using(WorkflowRuntime workflowRuntime = new WorkflowRuntime()) { AutoResetEvent waitHandle = new AutoResetEvent(false); // Add ChannelManagerService to the list of services used // by the WorkflowRuntime. ChannelManagerService cms = new ChannelManagerService(); workflowRuntime.AddService(cms); workflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e) { Console.WriteLine("The client workflow has completed. \nPress <Enter> to exit the client application."); Console.ReadLine(); waitHandle.Set(); }; workflowRuntime.WorkflowTerminated += delegate(object sender, WorkflowTerminatedEventArgs e) { Console.WriteLine(e.Exception.Message); waitHandle.Set(); }; WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(WorkflowServiceClient.ClientWorkflow)); instance.Start(); waitHandle.WaitOne(); }
연습 1에서 만든 WorkflowServiceTutorial 솔루션에서 워크플로 서비스와 함께 클라이언트를 사용하려면 WorkflowServiceTutorial 프로젝트 속성에서 명령줄 인수를 삭제해야 합니다. 이렇게 하려면 다음 단계를 수행하십시오.
- WorkflowServiceTutorial 프로젝트 노드를 마우스 오른쪽 단추로 클릭하고 속성을 선택합니다.
- 디버그 탭을 선택하고 시작 옵션 아래의 세부 정보 창에 있는 텍스트 상자에서 /client:"WfcTestClient.exe"를 제거합니다.
WorkflowServiceTutorial 솔루션 노드를 마우스 오른쪽 단추로 클릭하고 속성을 선택합니다.
속성 페이지 대화 상자에서 여러 개의 시작 프로젝트를 선택합니다.
WorkflowServiceTutorial이 목록의 맨 위 항목으로 표시되지 않으면 목록 상자 측면의 화살표를 사용하여 맨 위 항목으로 만듭니다. 이 작업은 클라이언트 응용 프로그램이 서비스에서 작업을 호출하려고 하기 전에 서비스의 실행이 시작되도록 하는 데 필요합니다.
목록에 있는 각 프로젝트의 동작을 없음에서 시작으로 변경합니다.
적용, 확인을 차례로 클릭합니다.
Visual Basic 솔루션을 만든 경우 솔루션 탐색기 창에서 WorkflowServiceClient 프로젝트 노드를 마우스 오른쪽 단추로 클릭하고 속성을 선택합니다.
응용 프로그램 탭을 선택하고 WorkflowServiceClient를 루트 네임스페이스 텍스트 상자에서 제거합니다. 이렇게 하지 않으면 클라이언트가 잘못된 네임스페이스를 참조하기 때문에 워크플로 서비스에 연결할 수 없습니다.
워크플로 서비스 솔루션을 빌드하고 실행합니다.
서비스가 시작된 후 클라이언트 응용 프로그램이 실행됩니다. 명령 프롬프트에서 클라이언트 응용 프로그램을 실행하면 다음이 표시됩니다.
A workflow service instance has successfully been created. The initial input value is 1 The value after invoking the Add operation is 1 The new input value is 2 The value after invoking the Subract operation is -1 The new input value is 6 The value after invoking the Multiply operation is -6 The new input value is 3 The value after invoking the Divide operation is -2 The workflow service instance has been successfully shut down. The client workflow has completed. Press <Enter> to exit the client application.
참고 항목
기타 리소스
Copyright © 2007 by Microsoft Corporation. All rights reserved.