티스토리 툴바

블로그 이미지
오태겸(RuAA)

카테고리

분류 전체보기 (31)
RESEARCH (1)
Development (0)
.NET (24)
Android (0)
Ruby (0)
ITEM (1)
Book (2)
Diary (2)
etc (0)
Statistics Graph
Total8,113
Today7
Yesterday6
오태겸(RuAA)

REST 서비스 템플릿

.NET/WCF / 2011/05/02 09:00

이번 포스트에선 REST 서비스를 만들 수 있는 간단한 방법~ REST 서비스 템플릿에 대해 얘기를 해볼까 합니다.
이 주제로 세미나(Your Smarter Visual Studio 2010)를 한번 했었는데, 그 때 시간이 짧아 많은 얘기를 전달하지 못한 것 같아 그 때 차마 하지 못했던 얘기들을 이번 포스팅에서 한번 주절거려 보겠습니다. 
세미나를 한 지가 꽤 오래됐는데 이제서야 포스팅을 하네요~ ^^;;;


그럼 시작합니다~ ^^

REST 서비스에 대한 자세한 설명은 과감하게 생략하도록 하겠습니다. 최근엔 REST에 대한 정보가 많아서 글 솜씨가 부족한 제가 굳이 설명하지 않아도 REST에 대해 알기 쉽게 설명한 글들을 큰 힘 들이지 않아도 찾을 수 있으실 겁니다 ㅎ

그래서, 이번 포스팅의 시작은 REST 서비스 템플릿을 다운받는 것부터 시작하겠습니다.

Visual Studio 프로젝트 템플릿을 다운 받는 방법은 크게 두 가지가 있습니다. 첫째는 Visual Studio를 통해서 다운 받는 것이고, 둘째는 직접 템플릿 다운 사이트(Visual Studio 갤러리 사이트)를 방문하여 다운 받는 것입니다.
두 방법 모두 절대 어렵지 않습니다. 여기선 Visual Studio를 사용하는 방법에 대해 알아보겠습니다.

우선,Visual Studio를 열고, 새 프로젝트를 만들기 위한 창을 띄웁니다. 그리고 좌측 메뉴에서 "온라인 템플릿"을 선택합니다. 그러면 잠깐 동안의 검색 이미지가 나타났다가, 아래 그림과 같은 화면이 나타나는데, 우측 리스트에 보면 "WCF REST Service Template 40(CS)" 아이템이 보입니다. 

 
이 아이템을 선택하고 프로젝트를 생성할 이름과 위치를 지정한 후에 확인 버튼을 클릭하면, 해당하는 템플릿을 다운받고, 바로 새로운 프로젝트를 생성해줍니다. 너무 쉽습니다~ 그죠? ㅎ 

REST 서비스 프로젝트가 생성되면 기본 파일들이 함께 생성되는데, 이 파일 중에 Service1.cs 파일이 실제 REST 서비스를 구현하기 위한 파일입니다. 이 파일을 보면 Service1 이라는 이름의 클래스 밑에 다음과 같은 메서드들이 정의되어 있는 것을 보실 수 있으실 겁니다. 

[WebGet(UriTemplate = "")]
public List<SampleItem> GetCollection() { … }

[WebInvoke(UriTemplate = "", Method = "POST")]
public SampleItem Create(SampleItem instance) { … }

[WebGet(UriTemplate = "{id}")]
public SampleItem Get(string id) {… }

[WebInvoke(UriTemplate = "{id}", Method = "PUT")]
public SampleItem Update(string id, SampleItem instance) { … } 

[WebInvoke(UriTemplate = "{id}", Method = "DELETE")]
 
public void Delete(string id) { … }

 
REST 서비스에서 각 작업과의 상호 작용은 고유한 URIHTTP 표준 동사(GET, POST, PUT, DELETE) 를 통해 이루어 집니다. 기본적으로 만들어지는 위와 같은 메서드는 각 HTTP 표준 동사에 대한 메서드 특성 설정에 대한 예시를 보여줍니다.

WebGetAttribute 와 WebInvokeAttribute

WCF REST 서비스는 위와 같이 정의 된 메서드에 접근하기 위해 URI와 HTTP 동사를 메서드에 매핑해 주는데 이때 필요한 것이 WebGetAttributeWebInvokeAttribute 입니다.

WebGetAttribute는 메서드가 HTTP GET 요청에 대해 응답한다는 것을 알려줍니다. WebInvokeAttribute는 기본적으로 POST 요청에 응답하지만, PUT 과 DELETE 요청에 대한 응답도 지원합니다. PUT 및 DELETE 요청에 대해 응답하는 메서드를 정의하기 위해서는 WebInvokeAttribute.Method 속성을 설정해주면 됩니다. 설명이 좀 어려워 보이지만 위 코드를 보면 쉽게 이해할 수 있으실 겁니다. ^^


REST 서비스 구현

기본적인 부분은 모두 언급이 된 것 같습니다. 이제는 이를 이용하여 간단한 REST 서비스를 만들어보겠습니다.
만들려는 서비스는 회원 관리에 대한 것으로 새로운 회원의 입력, 회원 정보 조회, 회원 정보 수정 및 삭제를 할 수 있는 서비스를 구현해보도록 하겠습니다.

우선, 서비스에서 사용할 Member 클래스를 다음과 같이 정의하였습니다.

[DataContract]
public class Member
{
    [
DataMember(Order=0)]
   
public string Id { get; set; }
    [
DataMember(Order=1)]
   
public string Name { get; set; }
    [
DataMember(Order=2)]
   
public string Job { get; set; }
    [
DataMember(Name="PhoneNumber", Order=3)]
   
public string Phone { get; set; }
    [
DataMember(Order=4)]
   
public string Address { get; set; }
}

 
그리고, 실제 서비스의 구현은 다음과 같습니다.

[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class MemberService
{
    [WebGet(UriTemplate = "GetAll")]
    public MemberList GetCollection()
    {
        BizMember bizMember = new BizMember();
        return bizMember.GetAll();
    }

 
    [WebInvoke(UriTemplate = "Add", Method = "POST")]
    public void Create(Member instance)
    {
        BizMember bizMember = new BizMember();
        bizMember.Add(instance);
    }

 

    [WebGet(UriTemplate = "{id}", ResponseFormat=WebMessageFormat.Json)]
 
   public Member Get(string id)
    {
        BizMember bizMember = new BizMember();
        return bizMember.Get(id);
    }

 

    [WebInvoke(UriTemplate = "{id}", Method = "PUT")]
 
   public void Update(string id, Member instance)
    {
        BizMember bizMember = new BizMember();
        bizMember.Update(id, instance);
    }
 

    [WebInvoke(UriTemplate = "{id}", Method = "DELETE")]
    public void Delete(string id)
    {
        BizMember bizMember = new BizMember();
        bizMember.Delete(id);
    }
}


코드는 보시면 아시겠지만 그리 어렵지 않습니다. BizMember 라는 클래스에서 여러가지 작업이 이루어지는데 이 클래스 역시 그렇게 어려운 내용이 없기에 자세한 설명은 생략하겠습니다. 대신에 소스를 첨부시켜 놓을 테니 잠깐만 살펴보시면 알 수 있으실 겁니다. ^^;; BizMember 클래스에 대한 설명까지 하려면 내용이 너무 길어질 것 같아 그러니 양해 부탁드립니다~ 흠흠;;; 

앞에서 설명을 하지 않았는데 위 코드를 보면 WebGetAttribute와 WebInvokeAttribute에 UriTemplate 이라는 속성이 보이실겁니다. 이 속성은 서비스로 들어온 요청의 URI와 매핑을 시키는 속성이라고 생각하시면 됩니다.
예를 들어, 위의 코드에서 Create 메서드의 경우 UriTemplate 속성의 값이 "Add" 로 되어 있는데, 만약 이 서비스의 기본 주소가 "http://localhost:2853/MemberService"이라고 할 때, 요청 들어온 URI가 "http://localhost:2853/MemberService/Add" 일 때 Create 메서드를 호출 한다는 것입니다. 물론, Create 메소드의 WebInvokeAttribute에 정의되어 있듯이 "POST" 방식의 요청이어야 하겠죠~?

또한, 위 코드의 Get 메서드처럼 UriTemplate 속성의 값이 "{id}"인 경우가 있는데, 이는 메서드의 파라미터인 id의 값이 URI에 들어가는 형태가 되는 것입니다. 예를 들면, HTTP "GET" 방식으로 "http://localhost:2853/MemberService/ruaa" 의 주소로 요청이 들어오면, 위 코드에서의 Get 메서드가 호출되면서 Get 메서드의 id 파라미터 값으로 ruaa가 입력되는 것입니다.
 
그럼, 서비스의 기본 주소는 어떻게 설정할 수 있을까요? 궁금하지 않으신가요? ㅎ
기존 WCF 서비스에서는 web.config 파일을 사용했었는데, REST 서비스 템플릿은 조금 다릅니다.
global.asax 파일을 열어보시면 그 답을 찾을 수 있으실 겁니다.

private void RegisterRoutes()
{
    // Edit the base address of Service1 by replacing the "Service1" string below
    RouteTable.Routes.Add(new ServiceRoute("MemberService", new WebServiceHostFactory(),
                                            typeof(MemberService)));
}

 
위 코드를 보니 어디서 많이 봤다~ 싶으네요~ ㅎ
ASP.NET 4.0과 ASP.NET MVC 프로젝트를 한 번이라도 구현해보신 분들이라면 저랑 같은 생각을 하셨을겁니다. ASP.NET MVC 때 부터 사용한 라우팅 방법과 같은 방식을 사용하고 있네요~

아무튼, 위 코드 처럼 구현을 할 경우 서비스의 기본 주소는 "http://{서비스가 배포된 기본 주소}/MemberService"가 됩니다.


Help 페이지

이렇게 REST 서비스 템플릿을 이용하여 서비스를 구현하고, 빌드를 하면 기본적으로 서비스에 대한 help 페이지를 만날 수 있습니다. help 페이지의 주소는 서비스의 기본주소에 "/help" 가 붙는 형식입니다.
저 같은 경우, Visual Studio 개발 서버로 돌렸기 때문에 다음 그림에서 보듯이 help 페이지의 경로는 "http://localhost:2853/MemberService/Help" 가 되는 것입니다.


위 그림을 보시면 알겠지만, 각 서비스 끝점에 대한 간단한 설명을 볼 수 있고, 각 서비스 끝점의 메서드를 클릭하면 자세한 내용을 확인할 수 있습니다. 이는 WCF 서비스의 헬프 페이지와 아주 유사하죠~? 

자~ 이제 슬 마무리 지어 볼까요? ^^

이번 포스팅을 통해 REST 서비스의 많은 부분에 대해 알려드리진 못했지만 기본적인 부분은 모두 설명이 된 듯 합니다. 그리고 REST 서비스 템플릿을 이용하면 정말 쉽게 WCF를 이용한 RESTful 서비스를 구현할 수 있다는 것도 알게 되었습니다.

혹시나 추가적인 설명이 필요한 부분이나 질문이 있으신 분들은 댓글 남겨주시면 성심성의껏(?) 답변 해드리겠습니다.
그리고, 첨부한 소스 코드를 참조하시어 테스트 해보시면 이번 포스팅에서 설명한 많은 부분이 이해가 되실 것 같습니다. 

저작자 표시 비영리 변경 금지
Posted by 오태겸(RuAA)


Visual Studio 2010 공식 팀에서 세미나를 주최합니다.

Visual Studio를 좀 더 스마트하게 사용하기 위한 주제로 세션들을 구성하였습니다.
많은 관심 부탁드립니다.


세미나의 간략한 내용은 다음과 같습니다.

Visual Studio 공식 팀 세미나 (클릭!! 세미나 정보 페이지로 연결됩니다.)

- 주최 : 한국Visual Studio 공식 팀
- 일시 :2011 4 6일 수요일
- 시간 : 늦은 오후 7 30 ~ 9 30
- 장소 : 한국 Microsoft Korea 5
- 참가비 : 무료
- 
경품 : 삼성동 코엑스 바이킹 뷔페 식권 3

저작자 표시 비영리 변경 금지
Posted by 오태겸(RuAA)
오랜만에 인사 드립니다~
해가 바뀌고, 벌써 두 달이 거의 지나가고 있는 시점에 이제야 다시 글을 올리게 되었습니다.
참, 부끄럽기 그지 없군요~ ^^;;
부끄럽긴 하지만 인사는 드려야죠!! 새해 복!! 많이 받으쌉싸리와용~

두어 달 만에 포스팅을 이어가려니 정말 난감하기도 하고, 민망하기도 하고... 
하지만, 이 민망함 그냥 얼굴에 철판 깔고, 시작 해 보렵니다. 어차피 포스팅 기다린 사람도 없었을 테니깐,, ㅋㅋ

이번 포스팅은 Troubleshooting 의 세 번째 포스팅으로, Error Handler 에 대해 알아볼까 합니다.

서비스를 개발할 때, 서비스에서 예외가 발생하는 경우, 이 예외에 대해 어떤 공통적인 동작을 취하게끔 코드를 만들고 싶을 때가 있습니다. 예를 들면, 발생하는 모든 예외에 대한 정보를 로그로 남긴다거나, 클라이언트로 전송되는 fault message의 내용을 동일하게 한다거나, 등등등... 

이럴 때 사용할 수 있는 것이 바로 Error Handler 입니다.
명칭을 봐도 딱! 감이 오지 않습니까? "에러 핸들러!!!" ㅋ

그럼, Error Handler 를 사용하는 방법을 차근 차근 적어내려 가보겠습니다.

WCF의 에러 핸들러를 사용하기 위해 가장 먼저 해야하는 것은 IErrorHandler 인터페이스를 구현하는 서브 클래스를 만드는 것입니다.

IErrorHandler 인터페이스는 다음과 같은 두 개의 메서드를 제공합니다.
 Method  Description 
 HandleError  예외에 대해 어떤 공통적인 동작을 취할 수 있는 메서드입니다.
 (예 : 예외 정보 로깅)
 ProvideFault  클라이언트로 보내질 fault message 를 정의할 수 있는 메서드입니다. 

아하~ 그리 어렵지 않죠? ㅎ

그럼, 직접 한번 구현 해보겠습니다.

namespace ErrorHandler

{

    [DataContract]

    public class MyErrorInfo

    {

        [DataMember]

        public string Message { get; set; }

        [DataMember]

        public string ExceptionInfo { get; set; }

    }

}



public class SampleErrorHandler : IErrorHandler

{

    public bool HandleError(Exception error)

    {
        // 이곳에 발생한 예외에 대한 공통적인 작업을 구현할 수 있습니다.

        return true;

    }

 

    public void ProvideFault(Exception error, MessageVersion version, ref Message fault)

    {

        FaultReason reason = new FaultReason("내맘대로 무조건 예외");

        FaultException<MyErrorInfo> faultException = new FaultException<MyErrorInfo>(

                                                  new MyErrorInfo

                                                  {

                                                      Message = error.Message,

                                                      ExceptionInfo = error.ToString()

                                                  },

                                                  reason);

 

        MessageFault messageFault = faultException.CreateMessageFault();

 

        fault = Message.CreateMessage(

            version,

            messageFault,

            faultException.Action);

    }

}


이 예제에서는 HandleError 메서드에 별 다른 코드를 넣지 않았습니다. 앞에서 언급을 했었지만 HandleError 메서드에서는 발생한 예외에 대한 어떤 공통적인 행동에 대한 코드를 구현 해주시면 됩니다.

그리고, HandleError 메서드에서는  bool 형의 값을 반환 해주는 것이 보이네요~ 이 bool 형의 값은 예외가 적절하게 처리되었는지 여부를 나타내준다고 생각하시면 됩니다. 만약, false를 반환하게되면, 예외가 처리되지 않은 것으로 간주하고, 기본 응답이 사용됩니다. 이 경우 디스패처가 모든 세션을 중단하고, InstanceContext를 중단합니다.

MSDN의 HandleError 메서드 설명 페이지에도 나와 있지만, HandleError 메서드는 여러 다른 위치에서 호출될 수 있기 때문에 이 메서드에서 예외를 제대로 처리하지 못했다고 false를 반환하게 되면, 모든 상태가 손상된 것으로 간주되고, 서비스에 존재하는 모든 세션이 중단된다고 생각하시면 됩니다.

따라서, 예외가 발생했을 때 모든 세션이 중단되길 원치 않는다면 위 예제 코드처럼 true를 반환하는 것이 나을 것입니다.

ProvideFault 메서드의 코드도 그리 어려워 보이지 않는군요. 이 전 저의 포스팅을 보셨던 분이라면 같은 생각을 하실 것 같네요~ ^^

ProvideFault의 매개 변수에 대한 설명은 다음과 같습니다.

 Parameter  Description 
 error  서비스 작업 중에 던져지는 Exception 개체입니다.
 version  메시지의 SOAP 버전입니다. 
 fault  클라이언트로 보내지는 Message 개체입니다. 

위 예제 코드에선 ProvideFault 메서드 안에서 매개 변수로 받은 예외 개체(error)를 이용하여 사용자 정의 된 예외 메시지를 정의합니다. 이렇게 정의 된 예외 메시지를 매개 변수 fault에 할당만 해주면 이 메시지는 클라이언트로 전달 됩니다.
FaultException 와 FaultReason 에 관한 내용은 이 전 포스트를 확인 해주세요~ ^^

이제 ErrorHandler 구현은 끝이 났습니다.
이렇게 만든 ErrorHandler를 사용하기 위해서 다음으로 해야 할 것은 WCF 서비스에 사용할 수 있는 새로운 Behavior 를 만드는 것입니다. 
Custom Behavior 를 만들어 WCF를 확장하는 방법에 대해선 이 곳을 참고하시면 좋을 것 같습니다.

그럼 새로운 Behavior를 만들어 볼까요?


public sealed class ErrorBehaviorAttribute : Attribute, IServiceBehavior

{

    private List<Type> _errorHandler;

 

    public List<Type> ErrorHandlerType

    {

        get { return _errorHandler; }

    }

 

    public ErrorBehaviorAttribute(params Type[] errorHandler)

    {

        this._errorHandler = new List<Type>();

        foreach (var item in errorHandler)

        {

            _errorHandler.Add(item);

        }

    }

 

    public void AddBindingParameters(ServiceDescription serviceDescription,

                                        ServiceHostBase serviceHostBase,

                                        Collection<ServiceEndpoint> endpoints,

                                        BindingParameterCollection bindingParameters)

    {           

    }

 

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription,

                                        ServiceHostBase serviceHostBase)

    {

        List<IErrorHandler> errorHandler = new List<IErrorHandler>();

 

        ErrorHandlerType.ForEach(

            (item) =>

            {

                errorHandler.Add((IErrorHandler)Activator.CreateInstance(item));

            });

 

        foreach (ChannelDispatcherBase dispatcherBase in
                                                     serviceHostBase.ChannelDispatchers)

        {

            ChannelDispatcher dsp = dispatcherBase as ChannelDispatcher;

            errorHandler.ForEach(

                (item) =>

                {

                    dsp.ErrorHandlers.Add(item);

                });

        }

    }

 

    public void Validate(ServiceDescription serviceDescription,

                            ServiceHostBase serviceHostBase)

    {           

    }

}

이 코드를 보면 조금 복잡해 보일 것 같습니다. Behavior의 경우 설정파일(.config)에서 설정을 하거나 코드 상에서 설정을 할 수 있는데 서비스 클래스의 Attribute 특성을 사용하여 설정합니다.
그래서 이 클래스는 Attribute 시스템 클래스를 상속합니다. 또한, IServiceBehavior 인터페이스를 상속하여 Behavior 로 사용할 수 있는 클래스를 만듭니다.

위 클래스의 생성자를 보면 하나 이상의 클래스 타입을 매개 변수로 받습니다. 이렇게 받은 타입들을 List<Type> 인스턴스의 전역 변수에 저장을 합니다. 따로 예외 처리를 하진 않았지만 생성자에 매개변수로 넘겨주는 클래스 타입은 반드시 IErrorHandler 인터페이스를 구현한 타입이어야 합니다.

그리고, IServiceBehavior 인터페이스 메서드 중에 ApplyDispatchBehavior 메서드를 구현합니다. 이 메서드에서는 서비스에 존재하는 모든 channel dispatcher 에게 생성자에서 받았던 IErrorHandler 타입들의 인스턴스를 추가시켜줍니다.

말이 조금 어렵나요? ^^;;

참고로, channel dispatcher 는 WCF 서비스를 구현할 때 어떤 Binding을 사용하는냐에 따라 달라집니다. 물론 사용하는 Binding 의 수에 따라 disptcher의 수도 늘어가게 됩니다.
dispatcher에 대해 잘 알지 못하는 분들이 있을 것 같습니다. 정확한 설명을 이 포스팅에서 하기에는 이것 만으로도 내용이 길어질 것 같아 설명하긴 힘들지만, 이 곳(디스패처 확장)의 내용을 확인하시면 이해는 가시리라 생각합니다. ^^

이제 준비 작업은 모두 끝이 났습니다. 앞에서 만든 ErrorHandler 를 사용할 수 있을 것 같네요

ErrorHandler를 사용하기 위해 다음과 같이 간단한 서비스를 만들고 서비스 클래스에 ErrorBehavior 특성을 설정하였습니다.

// Service Contract
[
ServiceContract]

public interface ICalc

{

    [OperationContract]

    [FaultContract(typeof(MyErrorInfo))]

    int Add(int a, int b);

 

    [OperationContract]

    [FaultContract(typeof(MyErrorInfo))]

    int Sub(int a, int b);

 

    [OperationContract]

    [FaultContract(typeof(MyErrorInfo))]

    int Mul(int a, int b);

 

    [OperationContract]

    [FaultContract(typeof(MyErrorInfo))]

    int Div(int a, int b);

}


// Service 구현 클래스
[ErrorBehavior(typeof(SampleErrorHandler))]

public class Calculator : ICalc

{

    public int Add(int a, int b)

    {

        throw new InvalidOperationException("잘못된 Add 메서드 호출입니다.");

    }

 

    public int Sub(int a, int b)

    {

        throw new InvalidOperationException("잘못된 Sub 메서드 호출입니다.");

    }

 

    public int Mul(int a, int b)

    {

        throw new InvalidOperationException("잘못된 Mul 메서드 호출입니다.");

    }

 

    public int Div(int a, int b)

    {

        throw new InvalidOperationException("잘못된 Div 메서드 호출입니다.");

    }

}

모든 메서드를 호출하면 아~무 이유없이 예외를 던지고 있군요~!! ㅎ

이제 이 서비스를 빌드하고 테스트를 해보야겠죠.
이번에는 따로 Console 어플리케이션을 만들지 않고 WcfTestClient.exe를 사용해보도록 하겠습니다.
이 간단한 프로그램은 WCF 서비스를 테스트하기 위한 클라이언트 툴입니다.

Visual Studio 명령 프롬프트를 실행시키고 "WcfTestClient"를 치고 엔터를 클릭하면 실행시킬 수 있습니다. 또는 Visual Studio 에서 WCF 서비스 프로젝트를 F5 를 이용하여 실행해도 역시 이 툴을 사용할 수 있습니다.

이 툴을 실행시키면 다음과 같은 모습을 하고 있죠.


여기에서 간단히 호출하고자 하는 메서드를 왼쪽 창에서 마우스로 더블 클릭 "톡! 톡!" 해주시면 실행할 수 있습니다. 이건 너무 직관적인거라 자세한 설명을 하지 않더라도 모두 사용하실 수 있으실겁니다 ^^

아무 메서드를 하나 실행시키면 예외가 발생했다는 내용을 담고 있는 창이 뜨는 것을 보실 수 있습니다. 여기서 오류정보를 보면 위에 SampleErrorHandler 의 ProvideFault 메서드에서 정의한 내용들이 들어가 있는 것을 확인할 수 있습니다.

더 자세한 내용을 보고 싶다면, 예외 창을 닫고 오른쪽 창 밑에 있는 "XML" 탭을 클릭해보세요~ 그럼 다음과 같은 화면을 보실 수 있으실 겁니다.


응답에 있는 XML을 다시 보여드려볼까요?

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">

  <s:Header />

  <s:Body>

    <s:Fault>

      <faultcode>s:Client</faultcode>

      <faultstring xml:lang="ko-KR">내맘대로 무조건 예외</faultstring>

      <detail>

        <MyErrorInfo xmlns="http://schemas.datacontract.org/2004/07/ErrorHandler" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">

          <ExceptionInfo>

            System.InvalidOperationException: 잘못된 Sub 메서드 호출입니다.

            위치: ErrorHandler.Calculator.Sub(Int32 a, Int32 b) 파일 D:\Dev\Learning\WCF\ErrorHandler\ErrorHandler\Service1.svc.cs: 21

            위치: SyncInvokeSub(Object , Object[] , Object[] )

            위치: System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]&amp; outputs)

            위치: System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc&amp; rpc)

            위치: System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc&amp; rpc)

            위치: System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage41(MessageRpc&amp; rpc)

            위치: System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc&amp; rpc)

            위치: System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc&amp; rpc)

            위치: System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3(MessageRpc&amp; rpc)

            위치: System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2(MessageRpc&amp; rpc)

            위치: System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc&amp; rpc)

            위치: System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1(MessageRpc&amp; rpc)

            위치: System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)

          </ExceptionInfo>

          <Message>잘못된 Sub 메서드 호출입니다.</Message>

        </MyErrorInfo>

      </detail>

    </s:Fault>

  </s:Body>

</s:Envelope>



네~ XML 내용을 확인하니 좀 더 확실해 졌네요. 클라이언트가 받은 메시지에 ProvideFault 메서드에서 정의한 내용들이 들어가 있다는 것을요~ ㅎ

자~ 그럼 마무리 하겠습니다!!

이번 내용은 뭔가 조금 복잡했던 것 같지만 사실 그렇게 복잡하지 않습니다. 이 포스트를 찬찬히 되새기면서, 그리고 인터넷을 통해 다른 부가적인 내용들도 알아가면서 학습을 하시면 그리 어렵지 않다는 것을 느끼게 되실겁니다.
예외를 처리하는 방법은 실무에 꽤 많이 쓰일 수 있는 내용이니깐 제대로 알고 가는건 좋을 것 같습니다.

다음 포스팅에선 계속해서 Troubleshooting 에 관한 내용으로 찾아 뵙도록 하겠습니다.
WCF에서 제공하는 몇 가지 툴들이 있는데 이런 툴들에 대한 설명이 될 것 같습니다.

그럼 다음 포스팅때까지 안녕히~ ^^
저작자 표시 비영리 변경 금지
Posted by 오태겸(RuAA)

최근에 달린 댓글

최근에 받은 트랙백

글 보관함