how to pass json string and deserialize in WCF

2019-08-07 03:34发布

I am having a json string

json1 = "{\"Shops\":[{\"id\":\"1\",\"title\":\"AAA\"},{\"id\":\"2\",\"title\":\"BBB\"}],\"movies\":[{\"id\":\"1\",\"title\":\"Sherlock\"},{\"id\":\"2\",\"title\":\"The Matrix\"}]}";

want to deserialize and get values in two classes shops and movies inside requestcollectionclass.

 [WebInvoke(
               Method = "POST",
               UriTemplate = "SubmitRequest",
               RequestFormat = WebMessageFormat.Json,
               ResponseFormat = WebMessageFormat.Json
               )
        ]
  string SubmitRequest(string RequestDetailsjson);

and in the service.cs

JavaScriptSerializer serializer = new JavaScriptSerializer();
            RequestDetailsCollection requestdetailscoll = serializer.Deserialize<RequestDetailsCollection>(RequestDetailsjson);

Getting error

The server encountered an error processing the request. The exception message is 'There was an error deserializing the object of type System.String. End element 'root' from namespace '' expected. Found element 'request' from namespace ''.'. See server logs for more details. The exception stack trace is:

I changed the parameter type to stream

string SubmitRequest(Stream RequestDetailsjson);

And changed the code

StreamReader sr = new StreamReader(RequestDetailsjson);
JavaScriptSerializer serializer = new JavaScriptSerializer();
RequestDetailsCollection requestdetailscoll = (RequestDetailsCollection)serializer.DeserializeObject(sr.ReadToEnd());

And getting error

The server encountered an error processing the request. The exception message is 'Incoming message for operation 'SubmitRequest' (contract 'IService1' with namespace 'http://tempuri.org/') contains an unrecognized http body format value 'Json'. The expected body format value is 'Raw'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details.'. See server logs for more details. The exception stack trace is:

Help me to resolve this issue

4条回答
小情绪 Triste *
2楼-- · 2019-08-07 03:47

Since there is no code for the RequestDetailsCollection I used json2csharp to convert your json to an object:

public class Shop
{
    public string id { get; set; }
    public string title { get; set; }
}

public class Movie
{
    public string id { get; set; }
    public string title { get; set; }
}

public class RequestDetailsCollection
{
    public List<Shop> Shops { get; set; }
    public List<Movie> movies { get; set; }
}


Deserializing like this:

JavaScriptSerializer serializer = new JavaScriptSerializer();
var requestdetailscoll = serializer.Deserialize<RequestDetailsCollection>(jsonString);


Returned:

enter image description here

查看更多
再贱就再见
3楼-- · 2019-08-07 04:02

I was getting this error too, here's how I fixed it:

I wanted a Stream too and when a Content-Type: application/json is sent it was breaking (was ok if no content-type specified i.e. Raw). I wanted it to work if the other party specified the content-type or not.

So create this file RawContentTypeMapper.cs and paste the following in

using System.ServiceModel.Channels;

namespace Site.Api
{

    public class RawContentTypeMapper : WebContentTypeMapper
    {
        public override WebContentFormat GetMessageFormatForContentType(string contentType)
        {
            // this allows us to accept XML (or JSON now) as the contentType but still treat it as Raw
            // Raw means we can accept a Stream and do things with that (rather than build classes to accept instead)
            if (
                contentType.Contains("text/xml") || contentType.Contains("application/xml")
                || contentType.Contains("text/json") || contentType.Contains("application/json")
                )
            {
                return WebContentFormat.Raw;
            }
            return WebContentFormat.Default;
        }
    }
}

In your web.config you need to specify it to be used (all the following in the <system.serviceModel> section):

 <bindings>
    <binding name="RawReceiveCapableForHttps">
        <webMessageEncoding webContentTypeMapperType="Site.Api.RawContentTypeMapper, Site, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
        <httpsTransport manualAddressing="true" maxReceivedMessageSize="524288000" transferMode="Streamed"/>
    </binding>
</bindings>

you'll need to update your service to use this too:

<services>
    <service behaviorConfiguration="XxxBehaviour" name="Site.Api.XXXX">
        <endpoint address="" behaviorConfiguration="web" binding="customBinding" bindingConfiguration="RawReceiveCapableForHttps" contract="Site.Api.IXXXX" />
    </service>
</services>

here's my behaviours section too for completeness

<behaviors>
  <serviceBehaviors>
    <behavior name="XxxBehaviour">
      <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
      <serviceDebug includeExceptionDetailInFaults="true"/>
    </behavior>
  </serviceBehaviors>
  <endpointBehaviors>
    <behavior name="web">
      <webHttp/>
    </behavior>
  </endpointBehaviors>
</behaviors>
查看更多
劫难
4楼-- · 2019-08-07 04:03

Long question short, you wanted to know how to deserialise your json message. This is how to do it.

 var json1 = "{\"Shops\":[{\"id\":\"1\",\"title\":\"AAA\"},{\"id\":\"2\",\"title\":\"BBB\"}],\"movies\":[{\"id\":\"1\",\"title\":\"Sherlock\"},{\"id\":\"2\",\"title\":\"The Matrix\"}]}";
 var requestDetailsCollection = JsonConvert.DeserializeObject<RequestDetailsCollection>(json1);

Your entity classes should be like this. (Code Generated using Paste Special)

public class RequestDetailsCollection 
{
    public Shop[] Shops { get; set; }
    public Movie[] movies { get; set; }
}

public class Shop
{
    public string id { get; set; }
    public string title { get; set; }
}

public class Movie
{
    public string id { get; set; }
    public string title { get; set; }
}
查看更多
Fickle 薄情
5楼-- · 2019-08-07 04:12

Thanks for the reply . I have two list<> of different classes inside one class i want to pass json string and serialize .

[WebInvoke(
               Method = "POST",
               UriTemplate = "SubmitRequest",
               RequestFormat = WebMessageFormat.Json,
               ResponseFormat = WebMessageFormat.Json
               )
        ]
         string SubmitRequest(string RequestDetailsjson);

And in service code JavaScriptSerializer serializer = new JavaScriptSerializer(); RequestDetailsCollection requestdetailscoll = serializer.Deserialize(RequestDetailsjson);

Getting error in POSTMAN REST Client The server encountered an error processing the request. The exception message is 'There was an error deserializing the object of type System.String. End element 'root' from namespace '' expected. Found element 'request' from namespace ''.'. See server logs for more details. The exception stack trace is:

Passing stream param like string SubmitRequest(Stream RequestDetailsjson); Getting Below error

The server encountered an error processing the request. The exception message is 'Incoming message for operation 'SubmitRequest' (contract 'IService1' with namespace 'http://tempuri.org/') contains an unrecognized http body format value 'Json'. The expected body format value is 'Raw'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details.'. See server logs for more details. The exception stack trace is:

查看更多
登录 后发表回答