2010-03-26 6 views
9

서버에서 시간을 반환하는 간단한 WCF 서비스가 있습니다. Fiddler를 확인하여 데이터가 전송되고 있음을 확인했습니다. 내 서비스에서 보내는 결과 개체 xml은 다음과 같습니다.클라이언트 WCF DataContract에 서비스의 빈 값/null 값이 있습니다.

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> 
    <s:Body> 
     <GetTimeResponse xmlns="http://tempuri.org/"> 
      <GetTimeResult xmlns:a="http://schemas.datacontract.org/2004/07/TestService.DataObjects" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> 
       <a:theTime>2010-03-26T09:14:38.066372-06:00</a:theTime> 
      </GetTimeResult> 
     </GetTimeResponse> 
    </s:Body> 
    </s:Envelope> 

그래서 내가 알 수있는 한, 서버쪽에 아무런 문제가 없습니다. 요청을 받고 결과를 반환합니다.

내 Silverlight 클라이언트에서 반환 된 개체의 모든 멤버는 null, 공백 또는 기본 vaule입니다. 보시다시피 서버는 현재 날짜와 시간을 반환합니다. 하지만 Silverlight에서 내 개체의 theTime 속성은 1/1/0001 12:00 AM (기본값)으로 설정됩니다.

Sooo는 서버와 Silverlight 클라이언트간에 DataContracts가 일치하지 않음을 알립니다. 서버용 DataContract는 다음과 같습니다.

[DataContract] 
public class Time 
{ 
    [DataMember] 
    public DateTime theTime { get; set; } 
} 

매우 간단합니다. 그리고 내 실버 클라이언트에서 datacontract이야.

[DataContract] 
public class Time 
{ 
    [DataMember] 
    public DateTime theTime { get; set; } 
} 

문자 그대로 유일한 차이점은 응용 프로그램 내의 네임 스페이스입니다. 그러나 여전히 반환되는 값은 null, 비어 있거나 .NET 기본값입니다.

도움 주셔서 감사합니다.

UPDATE 여기

내 모든 서비스를 통해 실행 ClientBase입니다. 나는 그것을 만들기 위해 excellent article here을 읽었다.

public class ClientBase<T> where T :class 
{ 
    private T Channel { get; set; } 

    private Type ContractType { get; set; } 

    private ClientBase() 
    { 
     ContractType = typeof(T); 
    } 

    public ClientBase(string endPointConfiguration) :this() 
    { 
     Channel = new ChannelFactory<T>(endPointConfiguration).CreateChannel(); 
    } 

    public ClientBase(EndpointAddress address, Binding binding):this() 
    { 
     Channel = new ChannelFactory<T>(binding, address).CreateChannel(); 
    } 

    public void Begin(string methodName, object state, params object[] parameterArray) 
    { 
     Begin(methodName, null, state, parameterArray); 
    } 

    public void Begin(string methodName, EventHandler<ClientEventArgs> callBack, object state, params object[] parameterArray) 
    { 
     if(parameterArray != null) 
     { 
      Array.Resize(ref parameterArray, parameterArray.Length + 2); 
     } 
     else 
     { 
      parameterArray = new object[2]; 
     } 

     parameterArray[ parameterArray.Length - 1 ] = new ObjectClientState {CallBack = callBack, MethodName = methodName, UserState = state}; 
     parameterArray[ parameterArray.Length - 2 ] = new AsyncCallback(OnCallBack); 
     ContractType.InvokeMember("Begin" + methodName, 
            System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.InvokeMethod | 
            System.Reflection.BindingFlags.Public, null, Channel, parameterArray); 

    } 

    private void OnCallBack(IAsyncResult result) 
    { 
     ObjectClientState state = result.AsyncState as ObjectClientState; 
     if(state == null) 
      return; 
     Object obj = ContractType.InvokeMember("End" + state.MethodName, 
               System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.InvokeMethod | 
               System.Reflection.BindingFlags.Public, null, Channel, new object[] {result}); 
     if(state.CallBack != null) 
     { 
      state.CallBack(this, new ClientEventArgs {Object = obj, UserState = state.UserState}); 
     } 
    } 

    public class ClientEventArgs : EventArgs 
    { 
     public object Object { get; set; } 
     public object UserState { get; set; } 

     public T LoadResult<T>() 
     { 
      if(Object is T) 
       return (T) Object; 
      return default(T); 
     } 
    } 

    private class ObjectClientState 
    { 
     public EventHandler<ClientEventArgs> CallBack { get; set; } 
     public string MethodName { get; set; } 
     public object UserState { get; set; } 
    } 
} 

여기

[ServiceContract]  

    public interface ITestService 
      { 

       [OperationContract(AsyncPattern = true)] 
       IAsyncResult BeginGetTime(AsyncCallback callback, object state); 

       Time EndGetTime(IAsyncResult result); 

      } 

이 지금은이 인터페이스를 사용하여 내 BaseService 클래스를 통해 호출을 내 서비스 클래스를 내 인터페이스입니다.

public class TestSiteService : ClientBase<ITestService> 
{ 
    public TestSiteService (string endPointConfiguration):base(endPointConfiguration) { } 

    public TestSiteService (EndpointAddress address, Binding binding) : base(address, binding) { } 

    public void GetTime(EventHandler<ClientEventArgs> callBack) 
    { 
     Begin("GetTime", callBack, null, null); 
    } 
} 

마지막으로 실제로 모든 것을 호출하고 작업을 수행하는 코드가 있습니다. P 당신이 당신의 DataContractAttribute에 the Namespace property를 설정하지 않기 때문에

+0

서비스 방법 및 사용중인 클라이언트 코드에 대한 코드를 게시 할 수 있습니까? 또한 질문에서 코드의 형식을 올바르게 지정해야합니다. 질문을 편집하고 코드를 강조 표시 한 다음 Ctrl + K를 누릅니다. –

+0

eek! 어떻게 된 일인지 잘 모르겠습니다. 모두 고정. 내 서비스 클라이언트를 조금 올리겠다. – Matt

답변

19

이 네임 스페이스는 .NET에서 sythesized됩니다

TestSiteService client = new TestSiteService (new EndpointAddress("http://localhost:3483/wcf/Service.svc"), new BasicHttpBinding()); 

client.GetTime(delegate(object res, ClientBase<ITestService>.ClientEventArgs e) 
      { 

       Dispatcher.BeginInvoke(() => lblDisplay.Text = "Welcome " + e.LoadResult<Time>().theTime); 

      }); 

휴 .... 나는 아무도 내가 게시 된 모든 코드에서 손실되지 않습니다 희망 클래스/네임 스페이스. 같은에 DataContract에 네임 스페이스 속성을 설정해야합니다

http://schemas.datacontract.org/2004/07/TestService.DataObjects 계약을하기 위해

동일한 것으로 간주한다 : 당신은 당신이 게시 된 SOAP 메시지의 예에서 볼 수 있습니다 양쪽에 가치.내가 구현하는 WCF 클라이언트 공장 하나를 사용하려고 할 때 - (THX +1) 내가 일하는 생성 된 서비스 참조를했지만,

[DataContract(Namespace="urn:my-test-namespace")] 
+0

이것들은 매우, 매우, 매우 그럴듯하게 보인다. 나는 그 다음 자유로운 순간을 시도 할 것이다. 감사. – Matt

+1

흥미 롭습니다. 각 응용 프로그램마다 다른 네임 스페이스가 있기 때문에 DataContracts가 작동하지 않습니다. 일부 네임 스페이스에 추가했는데 이제는 완벽하게 작동합니다! 고맙습니다!! – Matt

+0

정확합니다. 다행스럽게 도울 수있어! –

0

드류 마쉬의 정답에 확장 : 즉,이 같은 작은 선물을 보일 수 있습니다 올바른 인터페이스 (하지만 네임 스페이스가 다름)를 설명하면 문제가 발생했습니다.

"올바른"네임 스페이스가 있어야하는 작업을 쉽게 수행 할 수 없었지만 서비스 참조의 DataContract 엔터티에서 Wcf 클라이언트 팩토리 구현의 다음 특성을 단순히 복사하여 문제를 해결했습니다.

[System.Runtime.Serialization.DataContractAttribute(Name = "BOSPrice", Namespace = "http://schemas.datacontract.org/2004/07/BOSDataService")] 
    [System.SerializableAttribute()]