我原来的服务合同:
[ServiceContract(
Namespace = "http://my.framework/superservices/myservice",
Name = "IMyServiceContract")]
public interface IMyServiceContract
{
[OperationContract]
[FaultContract(typeof(MyFaultContract))]
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped,
RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json,
UriTemplate = "GetMyItemListJSONMC")]
GetListResponse GetMyItemListJSONMC(GetListRequest request);
// Other methods like this.
}
我想通过POST发送给我的服务的请求:
[MessageContract]
public class GetListRequest
{
[MessageBodyMember]
public int NbItems {get;set;}
[MessageBodyMember]
public DateTime? InputDate { get; set; }
[MessageBodyMember]
public string AnotherParameter { get; set; }
[MessageBodyMember]
public MyItem ACoolItem { get; set; }
}
[DataContract(
Namespace="http://my.framework/superservices/myservice/types",
Name="MyItem")]
public class MyItem
{
[DataMember]
public int BirthYear { get; set; }
[DataMember]
public string FirstName { get; set; }
[DataMember]
public string LastName { get; set; }
[DataMember]
public DateTime? BirthFullDate { get; set; }
}
我想从我的服务中获得的回复:
[MessageContract]
public class GetListResponse
{
[MessageBodyMember]
public List<MyItem> Result { get; set; }
[MessageBodyMember]
public string ReceivedUsername { get; set; }
[MessageBodyMember]
public string ReceivedPassword { get; set; }
}
客户代码:
private void CallService<TRequest, TResponse>()
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestedUri);
request.Method = "POST";
request.ContentType = "application/json; charset=utf-8";
DataContractJsonSerializer serRequest = new DataContractJsonSerializer(typeof(TRequest));
using (MemoryStream ms = new MemoryStream())
{
serRequest.WriteObject(ms, requestObject);
String json = Encoding.UTF8.GetString(ms.ToArray());
using (StreamWriter writer = new StreamWriter(request.GetRequestStream()))
{
writer.Write(json);
}
}
// Read Response
WebResponse response = request.GetResponse();
using (Stream stream = response.GetResponseStream())
{
if (stream != null)
{
string temp = new StreamReader(stream).ReadToEnd();
return Deserialize<TResponse>(temp);
}
return default(TResponse);
}
}
原始服务配置:
<endpoint address="" binding="webHttpBinding" bindingConfiguration="security"
name="HttpGetUseEndpoint" behaviorConfiguration="JSONBehavior"
contract="ServiceContracts.IMyServiceContract"/>
<endpointBehaviors>
<behavior name="JSONBehavior">
<webHttp faultExceptionEnabled="True"/>
<dataContractSerializer maxItemsInObjectGraph="20000000"/>
</behavior>
</endpointBehaviors>
<behavior name="InternalServiceBehavior">
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceMetadata httpGetEnabled="false"/>
<serviceThrottling maxConcurrentCalls="1500" maxConcurrentSessions="1500" maxConcurrentInstances="1500"/>
<dataContractSerializer maxItemsInObjectGraph="20000000"/>
</behavior>
使用此服务,我可以使用POST发送JSON请求,并在我的服务实现中处理它们,如下所示:
[ServiceBehavior(Name = "MyService",
Namespace = "http://my.framework/advertiserservices/myservice")]
public class MyService : IMyServiceContract
{
public GetListResponse GetMyItemListJSONMC(GetListRequest request)
{
// Do the Job and return the response.
}
}
现在,我想通过一种路由实现替换此服务实现,我可以捕获对合同的任何服务方法的所有请求。为此,我调整了配置:
<service name="ServiceImplementation.RoutingService"
behaviorConfiguration="InternalServiceBehavior">
<endpoint address="" binding="webHttpBinding" bindingConfiguration="security" name="HttpGetUseEndpoint" behaviorConfiguration="JSONBehavior" contract="ServiceContracts.IRouterService"/>
</service>
我实现了我的路由器接口:
[ServiceContract]
public interface IRouterService
{
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped,
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json, UriTemplate = "*")]
Message ProcessMessage(Message message);
}
和服务实现本身:
public Message ProcessMessage(Message message)
{
UriTemplateMatch uriTemplate = WebOperationContext.Current.IncomingRequest.UriTemplateMatch;
string methodName = uriTemplate.RelativePathSegments.First();
// Routing)
switch (methodName.ToUpper())
{
case "GETMYITEMLISTJSONMC":
// 1st try to retrieve the JSON from Message:
TypedMessageConverter converter = TypedMessageConverter.Create(typeof(GetListRequest), string.Empty, string.Empty);
GetListRequest typedMessage = (GetListRequest)converter.FromMessage(message);
// 2nd Try to retreive JSON from Message
GetListRequest request = message.GetBody<GetListRequest>();
return WebOperationContext.Current.CreateJsonResponse(new GetListResponse());
break;
}
}
现在终于来了我的问题和我的问题:
运行此代码和调试,我希望输入中的传入System.ServiceModel.Channels.Message包含纯JSON结构,但是看看QuickWatch,我看到某种带有JSON括号的纯XML:
{<root type="object">
<ACoolItem type="object">
<BirthFullDate type="null">
</BirthFullDate>
<BirthYear type="number">1981</BirthYear>
<FirstName type="string">Cool First Name</FirstName>
<LastName type="null">
</LastName>
</ACoolItem>
<AnotherParameter type="string">jsonPost</AnotherParameter>
<InputDate type="string">/Date(1395414903106+0100)/</InputDate>
<NbItems type="number">5</NbItems>
</root>}
这使我无法在服务端反序列化请求,因为代码中的两种技术都需要JSON。
如何让输入Message包含纯JSON而不是JSON和XML这种奇怪的混合?
感谢您的帮助。
答案 0 :(得分:0)
我做了类似的事情,在这种情况下我确实使用了message.GetBody
,它运行良好。对于.net的较新版本,请考虑使用message.GetReaderAtBodyContents
。我没有在服务器端设置任何特殊的序列化。
尝试将主体作为流读取,然后将其读入字符串。您可以将该字符串传递给json反序列化器。请注意,我没有指定任何特殊的RequestFormat。这是服务器端的一些示例代码(使用行为webhttp&amp; webhttpbinding:)
[ServiceContract]
public interface ITestService
{
[OperationContract]
[WebInvoke(Method = "POST",
UriTemplate = TestService.ROUTER_URL,
ResponseFormat = WebMessageFormat.Json
BodyStyle = WebMessageBodyStyle.Wrapped)]
Message Router(Message message);
}
public class TestClass
{
public string test { get; set; }
}
public class TestService : ITestService
{
public const string ROUTER_URL = "/Router/*";
public Message Router(Message message)
{
TestClass testClassInstance;
/*
(See further down for .net 4 solution)
using (var reader = new StreamReader(message.GetBody<Stream>()))
{
testClassInstance = Newtonsoft.Json.JsonConvert.DeserializeObject<TestClass>(reader.ReadToEnd());
}*/
return WebOperationContext.Current.CreateJsonResponse(new { Whatever = "yes"});
}
}
在客户端,我只是喜欢:
var webClient = new WebClient();
using (var upstream = webClient.OpenWrite(url, "POST"))
{
using (var writer = new StreamWriter(upstream))
{
writer.Write("{ \"test\" : \"json\" }");
}
}
修改:
使用小于.net4.5的版本时,message.GetBody
方法似乎工作得很糟糕。这是另一个与.net4一起使用的解决方案。在您的服务方法中,请改为:
using (var reader = message.GetReaderAtBodyContents())
{
reader.Read();
var whatever = System.Text.Encoding.UTF8.GetString(reader.ReadContentAsBase64());
testClassInstance = Newtonsoft.Json.JsonConvert.DeserializeObject<TestClass>(whatever);
Console.WriteLine("Server: testClassInstance.test = {0}", testClassInstance.test);
}