客户端WCF Datacontract从服务中具有空/null值
-
22-09-2019 - |
题
我有一个简单的WCF服务,可以返回服务器的时间。我已经确认通过与提琴手核对发送数据。这是我的服务发送的结果对象XML。
<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客户端上,返回的对象的所有成员均为空,空白或默认Vaule。如您所见,服务器返回当前日期和时间。但是在Silverlight中,我对象上的TheTime属性设置为1/1/0001 12:00 AM(默认值)。
SOOO METHINK可以使数据合同在服务器和Silverlight客户端之间不匹配。这是服务器的数据合同
[DataContract]
public class Time
{
[DataMember]
public DateTime theTime { get; set; }
}
非常简单。这是我的Silverlight客户端上的数据合同。
[DataContract]
public class Time
{
[DataMember]
public DateTime theTime { get; set; }
}
从字面上看,唯一的区别是应用程序中的名称空间。但是,返回的值仍然为空,空或.NET默认值。
感谢您的帮助!
更新
这是我所有服务通过的客户库。我读了一本 在这里很棒的文章 构造它。
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 );
}
现在,我有了我的服务类,可以使用此接口通过我的基础服务类进行呼叫。
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 );
}
}
最后,这是实际调用所有内容并完成工作的代码。
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 );
} );
哇....我希望没有人从我发布的所有代码中丢失:P
解决方案
因为你不设定 名称空间属性 在您的datacontractAttribute上,名称空间将从.NET类/名称空间中进行序列化。您可以在您发布的肥皂消息示例中看到这一点:
http://schemas.datacontract.org/2004/07/TestService.DataObjects
为了将合同视为平等,您必须将数据合同上的名称空间属性设置为双方的相同值。看起来可能有点像这样:
[DataContract(Namespace="urn:my-test-namespace")]
其他提示
扩展了Drew Marsh的正确答案(+1 -THX),我有一个生成的服务参考,但是当我尝试使用WCF客户端工厂时,一个实现正确接口(但是名称空间是不同的)时,我正在遇到问题描述。
我没有简单的方法来确定“正确”的名称空间应该是什么,而只是简单地将以下属性从服务参考的数据合同实体复制到WCF客户端出厂实施中的一个属性解决了问题;
[System.Runtime.Serialization.DataContractAttribute(Name = "BOSPrice", Namespace = "http://schemas.datacontract.org/2004/07/BOSDataService")]
[System.SerializableAttribute()]