Consuming JSON in WCF service method
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)
.
Related videos on Youtube
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, 2020Comments
-
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 about 13 yearsThanks but it is on TotalScore which is the method in question.
-
Simon Rigby about 13 yearsThank 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 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 ofBodyStyle
attribute. I hope it will also help you. -
Simon Rigby about 13 yearsMany 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 about 13 years@Simon Rigby:
DateTime
orDate
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 JqvqScriptDate
to the server to be easy converted toDateTime
? I could post you some examples or probably this post solve you problem. -
Simon Rigby about 13 yearsMany thanks, I ended up using a variation on Rick Strahl's Service Proxy that uses JSON2 stringify(). Thanks for all your help. :)