J'ai un service WCF simple qui renvoie l'heure du serveur. J'ai confirmé que les données sont envoyées en vérifiant avec Fiddler. Voici l'objet de résultat xml que mon service envoie.Le client WCF DataContract a des valeurs vides/nulles du service
<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>
Donc, autant que je sache, il n'y a rien de mal à la fin du serveur. Il reçoit des demandes et renvoie des résultats.
Mais sur mon client Silverlight, tous les membres de l'objet retourné sont soit null, vide ou une valeur par défaut. Comme vous pouvez le voir, le serveur renvoie la date et l'heure actuelles. Mais dans Silverlight, la propriété Time sur mon objet est définie sur 1/1/0001 12:00 AM (valeur par défaut).
Sooo suggère que les DataContracts ne correspondent pas entre le serveur et le client Silverlight. Voici le DataContract pour le serveur
[DataContract]
public class Time
{
[DataMember]
public DateTime theTime { get; set; }
}
Incroyablement simple. Et voici le contrat de données sur mon client Silverlight. Littéralement, la seule différence réside dans les espaces de noms au sein de l'application. Mais toujours les valeurs retournées sont nulles, vides ou un .NET par défaut.
Merci pour votre aide!
MISE À JOUR
Voici le ClientBase que tous mes services traversent. J'ai lu un excellent article here pour le construire.
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; }
}
}
Voici mon interface
[ServiceContract]
public interface ITestService
{
[OperationContract(AsyncPattern = true)]
IAsyncResult BeginGetTime(AsyncCallback callback, object state);
Time EndGetTime(IAsyncResult result);
}
Maintenant, j'ai ma classe de service qui fait des appels dans ma classe BaseService utilisant cette interface.
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);
}
}
Enfin, voici le code qui appelle réellement tout et fait le travail.
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);
});
Ouf .... J'espère que personne ne se perd de tout ce code que j'ai posté: P
Pouvez-vous publier le code pour la méthode de service et le code client que vous utilisez? En outre, vous devez formater votre code correctement dans votre question. Modifiez la question, sélectionnez le code et appuyez sur Ctrl + K. –
eek! Je ne sais pas comment cela est arrivé. Tout est fixé. Je vais poster mon client de service dans un peu – Matt