WCF 를 이용한 통신채널을 구성할때, 일반적인 방법으로 인터페이스를 선언하고 웹 참조 혹은 DLL 참조, Svcutil 로 생성된 레퍼런스 정보를 사용할 때는 별 문제가 없다. 하지만 WCF 3.5 부터 제공되기 시작한 REST 형태의 호출 지원을 사용하는 경우에는 파라메터의 데이터 형태에 따라 BodyStyle 속성을 지정해야 하는 경우가 빈번하다.

예> IService.cs

[ServiceContract]

public interface IService

{

    [OperationContract]

    [WebInvoke(UriTemplate = "Counter", Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped)]

    int Counter(CounterList counterValues, int tryCount); 

 
그런데 문제는 서비스의 인터페이스 선언에 이렇게 WebInvoke Attirbute 와 BodyStyle 을 지정했음에도 클라이언트에서 서비스를 호출할 때 BodyStyle 이 Wrapped 로 지정되지 않았다는 에러가 발생할 때가 간혹 있다는 점이다. 특히 svcutil 을 이용해서 매뉴얼하게 레퍼런스 클래스를 만드는 경우에 이런 일이 많이 발생한다. (웹참조로 추가하는 경우에도 발생한다는 보고가 있다)

예> 클라이어트에서 서비스 호출시 에러 메세지

'IService' 계약의 'Counter' 작업에서 래퍼 요소 없이 직렬화할 여러 개의 요청 본문 매개 변수를 지정합니다. 최대 하나의 본문 매개 변수가 래퍼 요소 없이 직렬화될 수 있습니다. 추가 본문 매개 변수를 제거하거나 WebGetAttribute/WebInvokeAttribute의 BodyStyle 속성을 Wrapped로 설정하십시오.


이런 경우 서비스쪽을 자꾸 살피게 되는데 원인은 서비스가 아니라 레퍼런스 클래스의 생성에 있기 때문에 트러블슈팅이 쉽지 않다. svcutil 명령을 이용해서 만든 레퍼런스 클래스를 확인해 보면 WebInvoke 로 지정한 내용이 전혀 들어가있지 않은 걸 쉽게 발견할 수 있다. 해당 부분에 동일한 선언을 추가해주면 에러를 가볍게 제거할 수 있다.

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]

[System.ServiceModel.ServiceContractAttribute(ConfigurationName="IService")]

public interface IService

{

[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IService/Counter", ReplyAction="http://tempuri.org/IService/CounterResponse")]

    [WebInvoke(UriTemplate = "Counter", Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped)]

    int Counter(Counters counterValues, int tryCount);


비동기 형태로 호출하기 위해 만든 레퍼런스 클래스의 경우에도 Beginxxx 와 같은 비동기 메소드를 선언하는 부분에는 지정해줄 필요가 없다. 원래 함수의 속성으로만 지정하면 문제는 해결된다. 혹시 비슷한 어려움을 겪는 사람들을 위해서 공유해둔다.

- NoPD -



 

 
신고
Posted by 노피디
근래 몇 년간 웹서비스로 개발된 API 들은 항상 웹폼에서만 호출했었습니다. 이번에 개인적으로 사용할 서버 모니터링 프로그램을 만들면서 웹서비스를 사용하고 있었는데, 윈폼에서 호출이 1회 이상 되지 않는 문제가 발생하더군요.

처음 프로그램이 웹서비스를 호출하면 값을 잘 받아오지만, 이후부터는 값을 받아오지 못하는 문제더군요. 에러 메시지는 "기본 연결이 닫혔습니다" (영어로는 The Underlying Connection was Closed 더군요. 번역이 괜찮게 된건지 모르겠군요) 개발자의 친구, 구글신에게 물어보니 역시 좋은 해결 방안들이 있었습니다.


웹서비스 Proxy 를 생성하면 reference.cs 파일이 생기는데요, 일단 이 파일을 열어서 아래의 코드를 추가해 줍니다. 환경에 따라 다른 것인지 모르겠으나, keepalive 를 true 로 해서 해결이 된다는 이야기도 있었는데 제 경우에는 해당사항이 없었습니다.


해결 방법이 조금 꽁수이긴 하나 (ConnectionGroup 이름을 계속 새로운 GUID 로 할당해주는 -_-;;) 일단 해결이 되었고 크게 누군가에게 부담을 주는 방식이 아니라 일단 사용하기로 했습니다. 유경상님의 블로그에 이 에러와 관련하여 WCF와 Fiddler의 문제를 언급한 글도 한번 읽어 보시면 유사한 상황에서 도움이 되실 것 같습니다.

 
- NoPD -
신고
Posted by 노피디

티스토리 툴바