Pregunta

Tengo un servicio de WCF simple que devuelve la hora del servidor. He confirmado que los datos se envían mediante la comprobación con el violinista. Aquí está el objeto XML resultado de que mi servicio envía.

    <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>

Por lo tanto, en lo que puedo decir, no hay nada malo en el extremo del servidor. Es la recepción de solicitudes y devolver resultados.

Pero en mi cliente de Silverlight, todos los miembros del objeto devuelto o son nulos, en blanco o una vaule defecto. Como se puede ver el servidor devuelve la fecha y hora actual. Pero en Silverlight, thetime propiedad en mi objeto se establece en 1/1/0001 12:00a.m. (valor por defecto).

Sooo Me parece que los DataContracts no coinciden entre el servidor y el cliente de Silverlight. Aquí está la DataContract para el servidor

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

Increíblemente simple. Y aquí está la DataContract en mi cliente de Silverlight.

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

Literalmente, la única diferencia es los espacios de nombres dentro de la aplicación. Pero aún así los valores que se devuelven son nulos, vacío o un defecto .NET.

Gracias por su ayuda!

Actualizar

Esta es la ClientBase que todos mis servicios se ejecutan a través. Leí un excelente artículo aquí para construirlo .

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; }
    }
}

Aquí está mi interfaz

 [ServiceContract]      

    public interface ITestService
            {

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

                Time EndGetTime( IAsyncResult result );

            }

Ahora tengo mi clase de servicio que hace que las llamadas a través de mi clase BaseService utilizando esta interfaz.

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 );
    }
}

Finalmente aquí está el código que realmente llama a todo y hace el trabajo.

    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 );

            } );

Uf .... espero que nadie se pierde del todo el código que he publicado: P

¿Fue útil?

Solución

Debido a que no se establece la propiedad Espacio de nombres en su DataContractAttribute, el espacio de nombres se sythesized de la clase .NET / espacio de nombres. Esto se puede ver en el ejemplo de mensaje SOAP informados:

http://schemas.datacontract.org/2004/07/ TestService.DataObjects

Con el fin de que los contratos se consideran iguales, debe establecer la propiedad de espacio de nombres en el DataContract al mismo valor en ambos lados. Esto podría parecer un poco algo como esto:

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

Otros consejos

Extendiéndose sobre la respuesta correcta de Drew Marsh (1 - THX) que tenía una referencia de servicio generada la que estaba trabajando, pero cuando traté de utilizar el WCF fábrica del cliente una implementación de la interfaz correcta (pero el espacio de nombres era diferente) entonces yo estaba experimenten el problema descrito.

No tenía manera fácil de averiguar lo que el espacio de nombres "correcta" debería haber sido sino simplemente copiando los siguientes atributos de entidad DataContract de la referencia de servicio a la de la aplicación WCF fábrica Cliente resuelto el problema;

[System.Runtime.Serialization.DataContractAttribute(Name = "BOSPrice", Namespace = "http://schemas.datacontract.org/2004/07/BOSDataService")]
  [System.SerializableAttribute()]
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top