Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
184 views
in Technique[技术] by (71.8m points)

javascript - Consuming JSON in WCF service method

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...