通过JSON将继承对象传递给WCF服务
我有两个类,下面列出了它们。
public Class Vehicle
{
int wheels { get ; set}
}
public Class Car:Vehicle
{
int topspeed { get; set ;}
}
//This is the container class
public Class Message
{
string ConatinerName { get; set;}
Vehicle Container;
}
我定义了一个服务合同,样子如下。这个网络服务有两个接口,一个是SOAP,另一个是Json。
//this function gets a message object, looks into the container
public Message GetMessage(Message Input)
{
Car mycar = (Car)Message.Container;
mycar.topspeed = 200;
Message retMessage = new Message();
retMessage.ContainerName ="Adjusted Car Speed";
retMessage.Container = mycar;
return retMessage;
}
当我运行WCF网络服务时,Visual Studio自带的测试客户端能够用一个消息对象调用这个服务,并且提供了选项,可以在消息容器中传入一个汽车对象或者一个车辆对象。VS客户端根据传入的原始数据使用SOAP接口。
为了测试服务的Json接口,我使用了一个用Python写的简单客户端,它通过Json数据格式调用上面的网络服务的GetMessage()
方法。我传入了一个Car
对象,但当服务实际接收到数据时,
这个网络服务方法获取到的数据,容器里面只包含了车辆对象。我检查了web方法接收到的请求上下文,显示接收到了正确的Json字符串(和发送的一样),但.NET不知怎么的却把Car
类的属性去掉了,只传入了Vehicle
属性。所以在GetMessage()
里面尝试将其转换为汽车时,就抛出了一个异常,提示你试图将一个车辆转换为汽车,这是不合法的转换。
现在我明白了,Message
里面的Container
是Vehicle
类型的,但对于SOAP接口,我可以传入汽车对象和车辆对象,而对于Json接口,只能通过Message
容器传入一个车辆对象。
我的问题是,如何让.NET运行时识别我想传入的是Car
而不是Vehicle
呢?
我的Json客户端代码如下。
import urllib2, urllib, json
def get_json(url):
f = urllib2.urlopen(url)
resp = f.read()
f.close()
return json.loads(resp)
def post(url, data):
headers = {'Content-Type': 'application/json'}
request = urllib2.Request(url, data, headers)
f = urllib2.urlopen(request)
response = f.read()
f.close()
return response
geturl = 'http://localhost:24573/Service1.svc/json/GetMessage'
sendurl = 'http://localhost:24573/Service1.svc/json/SendMessage'
msg = get_json(geturl)
print 'Got', msg
print 'Sending...'
retval = post(sendurl, json.dumps(msg))
print 'POST RESPONSE', retval
2 个回答
在车辆类中添加这个属性
[KnownType(typeof("Car"))]
我在用Python调用WCF服务时遇到了类似的问题,使用JSON格式的数据。让我惊讶的是,解决这个问题的方法是确保在发送请求时,__type
这个键放在最前面。
举个例子,使用json.dumps(data, sort_keys=True)
会返回类似这样的结果。WCF服务不喜欢这个,因为__type
没有放在Container
的最前面。所以,我的建议是确保__type
是第一个。还有,我挺惊讶sort_keys
这个选项并不是递归的。
错误示例:
{"Container": {"Model": "El Camino", "TopSpeed": 150, "Wheels": 0, "__type": "Car:#WcfService1"},"WrapperName": "Car Wrapper"}
正确示例:
{"Container": {"__type": "Car:#WcfService1", "Model": "El Camino", "TopSpeed": 150, "Wheels": 0},"WrapperName": "Car Wrapper"}
这是一个简单的Python测试客户端。
import urllib2, urllib, json
def get_json(url):
f = urllib2.urlopen(url)
resp = f.read()
f.close()
return json.loads(resp)
def post(url, data):
headers = {'Content-Type': 'application/json'}
request = urllib2.Request(url, data, headers)
f = urllib2.urlopen(request)
response = f.read()
f.close()
return response
geturl = 'http://localhost:24573/Service1.svc/json/GetMessage'
sendurl = 'http://localhost:24573/Service1.svc/json/SendMessage'
msg = get_json(geturl)
print 'Got', msg
print 'Sending...'
retval = post(sendurl, json.dumps(msg))
print 'POST RESPONSE', retval