Consuming JSON in WCF service method

23,830

You encode the input parameter player of the method TotalScore in the wrong way.

I recommend you to use JSON.stringify function from json2.js to convert any JavaScript objects to JSON.

var myPlayer = {
    Name: "Simon",
    Score: 1000,
    Club: {
        Name: "Tigers",
        Town: "Glenelg"
    }
};
$.ajax({
    type: "POST",
    url: "/wcfservice/wcfservice.svc/json/TotalScore",
    data: JSON.stringify({player:myPlayer}), // for BodyStyle equal to 
                                             // WebMessageBodyStyle.Wrapped or 
                                             // WebMessageBodyStyle.WrappedRequest
    // data: JSON.stringify(myPlayer), // for no BodyStyle attribute
                                       // or WebMessageBodyStyle.WrappedResponse
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    success: function(data, textStatus, xhr) {
        alert(data.TotalScoreResult); // for BodyStyle = WebMessageBodyStyle.Wrapped
                                      // or WebMessageBodyStyle.WrappedResponse
        // alert(data); // for BodyStyle = WebMessageBodyStyle.WrappedRequest
                        // or for no BodyStyle attributes
    },
    error: function (xhr, textStatus, ex) {
        alert("Not Done");
    }
});

If you change the BodyStyle = WebMessageBodyStyle.Wrapped attribute of the TotalScore method to BodyStyle = WebMessageBodyStyle.WrappedRequest you can change the alert(data.TotalScoreResult) in the success handle to alert(data).

Share:
23,830

Related videos on Youtube

Simon Rigby
Author by

Simon Rigby

Simon is a musician, composer, engineer and producer with a penchant for coding (ie it was a profession in a previous life). He still maintains a toe in the water as principle geek at Artscope Music and Management.

Updated on October 05, 2020

Comments

  • Simon Rigby
    Simon Rigby over 3 years

    In a larger project I am having trouble getting a WCF service method to consume a JSON parameter. So I produced a smaller test case and the behaviour is echoed. If I debug the service I can see the parameter value is null at the service call. Fiddler confirms that the JSON is being sent and JsonLint confirms it is valid.

    Code below with annotations from debugging.

    [ServiceContract]
    public interface IWCFService
    {
    
        [OperationContract]
        [WebInvoke(BodyStyle = WebMessageBodyStyle.WrappedRequest,
                ResponseFormat = WebMessageFormat.Json,
                UriTemplate = "getstring")]
    
        string GetString();
    
        [OperationContract]
        [WebInvoke(BodyStyle = WebMessageBodyStyle.WrappedRequest,
            ResponseFormat = WebMessageFormat.Json,
            UriTemplate = "getplayer")]
        //[WebGet(BodyStyle = WebMessageBodyStyle.WrappedRequest,
        //    ResponseFormat = WebMessageFormat.Json,
        //    UriTemplate = "getplayers")]
        Player GetPlayer();
    
        [OperationContract]
        [WebInvoke(BodyStyle = WebMessageBodyStyle.WrappedRequest,
            ResponseFormat = WebMessageFormat.Json,
            UriTemplate = "getplayers")]
        List<Player> GetPlayers();
    
        [OperationContract]
        [WebInvoke(
            Method = "POST",
            BodyStyle = WebMessageBodyStyle.Wrapped,
            ResponseFormat = WebMessageFormat.Json,
            RequestFormat = WebMessageFormat.Json,
            UriTemplate = "totalscore")]
        string TotalScore(Player player);
    
    }
    

    ... and its implementation

    public class WCFService : IWCFService
    {
        public string GetString()
        {
            return "hello from GetString";
        }
    
        public Player GetPlayer()
        {
            return new Player()
                    {
                        Name = "Simon", 
                        Score = 1000, 
                        Club = new Club()
                                {
                                    Name = "Tigers", 
                                    Town = "Glenelg"
                                }
                    };
        }
    
        public List<Player> GetPlayers()
        {
            return new List<Player>()
                {
                    new Player()
                        {
                            Name = "Simon", 
                            Score = 1000 , 
                            Club=new Club()
                                    {
                                        Name="Tigers", 
                                        Town = "Glenelg"
                                    }
                        }, 
                    new Player()
                        {
                            Name = "Fred", Score = 50,
                            Club=new Club()
                                    {
                                        Name="Blues",
                                        Town="Sturt"
                                    }
                        }
                };
        }
    
        public string TotalScore(Player player)
        {
            return player.Score.ToString();
        }
    }
    

    Calling any of the first three methods works correctly (but no parameters as you'll note). Calling the last method (TotalScore) with this client code ...

    function SendPlayerForTotal() {
            var json = '{ "player":{"Name":"' + $("#Name").val() + '"'
                + ',"Score":"' + $("#Score").val() + '"'
                + ',"Club":"' + $("#Club").val() + '"}}';
    
            $.ajax(
            {
                type: "POST",
                contentType: "application/json; charset=utf-8",
                url: "http://localhost/wcfservice/wcfservice.svc/json/TotalScore",
                data: json,
                dataType: "json",
                success: function (data) { alert(data); },
                error: function () { alert("Not Done"); }
            });
        }
    

    ... results in ...

    There was an error while trying to deserialize parameter http://tempuri.org/:player. The InnerException message was 'Expecting state 'Element'.. Encountered 'Text' with name '', namespace ''. '.

    I have tried sending an unwrapped version of the JSON ...

    {"Name":"Simon","Score":"100","Club":"Rigby"}

    but at the service the parameter is null, and no formatter exceptions.

    This is the system.serviceModel branch of the service web.config:

    <system.serviceModel>
    <services>
        <service name="WCFService.WCFService" behaviorConfiguration="WCFService.DefaultBehavior">
            <endpoint address="json" binding="webHttpBinding" contract="WCFService.IWCFService" behaviorConfiguration="jsonBehavior"/>
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
        </service>
    </services>
    
    <behaviors>
        <serviceBehaviors>
            <behavior name="WCFService.DefaultBehavior">
                <serviceMetadata httpGetEnabled="true"/>
                <serviceDebug includeExceptionDetailInFaults="true"/>
            </behavior>
        </serviceBehaviors>
    
        <endpointBehaviors>
            <behavior name="jsonBehavior">
                <webHttp/>
            </behavior>             
        </endpointBehaviors>
    </behaviors>
    

    And here is the Player DataContract.

    [DataContract(Name = "Player")]
        public class Player
        {
            private string _name;
            private int _score;
            private Club _club;
    
            [DataMember]
            public string Name { get { return _name; } set { _name = value; } }
    
            [DataMember]
            public int Score { get { return _score; } set { _score = value; } }
    
            [DataMember]
            public Club Club { get { return _club; } set { _club = value; } }
    
        }
    

    Any help greatly appreciated and if any other info is required, please let me know.

    Many thanks.

  • Simon Rigby
    Simon Rigby about 13 years
    Thanks but it is on TotalScore which is the method in question.
  • Simon Rigby
    Simon Rigby about 13 years
    Thank you so much .. that was the issue. Looking at the JSON in fiddler, I see that the int value is not quoted. I was under the impression that they should be. Many Thanks.
  • Oleg
    Oleg about 13 years
    @Simon Rigby: Yes it was one from the errors. The Club property you serialized also in the "Form" style which are also wrong. I modified my answer additionally to show the meaning of BodyStyle attribute. I hope it will also help you.
  • Simon Rigby
    Simon Rigby about 13 years
    Many thanks. How does stringify go with dates. My WCF service is tripping on them as it doesn't have the /date() wrapper around it. Is that something I'd need to address separately. I'm not sure how I'd hook into that as the object json'd in one call. I hope that makes sene.
  • Oleg
    Oleg about 13 years
    @Simon Rigby: DateTime or Date are not standard type which is supported by JSON. So you should either do some additional conversion on the client side (in JavaScript) or on the server side. Do you need to convert the date posted from the server to client or post the JqvqScript Date to the server to be easy converted to DateTime? I could post you some examples or probably this post solve you problem.
  • Simon Rigby
    Simon Rigby about 13 years
    Many thanks, I ended up using a variation on Rick Strahl's Service Proxy that uses JSON2 stringify(). Thanks for all your help. :)

Related