从System.SystemModel.Channels.Message中检索JSON主体

本文关键字:检索 JSON 主体 Message System SystemModel Channels | 更新日期: 2023-09-27 17:51:12

我的服务合同原件:

[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查看,我看到某种纯xml混合JSON括号:

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

我怎么能得到输入消息包含纯JSON而不是JSON和XML的这种奇怪的混合?

谢谢你的帮助。

从System.SystemModel.Channels.Message中检索JSON主体

我做过类似的事情,在这种情况下,我确实使用了message.GetBody,它工作得很好。对于较年轻的。net版本,可以考虑使用message.GetReaderAtBodyContents。我没有在服务器端设置任何特殊的序列化。

尝试将主体作为流读入字符串。你可以将这个字符串传递给json反序列化器。注意,我没有指定任何特殊的RequestFormat。这里有一些示例代码在服务器端(使用行为webhttp &完全:)

[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'" }");
    }
}
编辑:

message.GetBody方法在使用小于。net4.5的版本时似乎工作得很糟糕。这里是另一个与。net一起工作的解决方案。在你的service方法中,这样做:

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