在WCF服务方法中使用JSON
在一个较大的项目中,我在获取 WCF 服务方法来使用 JSON 参数时遇到问题。所以我制作了一个较小的测试用例,并且行为得到了回应。如果我调试服务,我可以看到服务调用时参数值为空。 Fiddler 确认 JSON 正在发送,而 JsonLint 确认它是有效的。
下面的代码带有调试注释。
[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);
}
...及其实现
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();
}
}
调用前三个方法中的任何一个都可以正常工作(但您会注意到没有参数)。使用此客户端代码调用最后一个方法 (TotalScore) ...
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"); }
});
}
... 导致 ...
尝试反序列化参数 http://tempuri.org/:player。 InnerException 消息是“期望状态“元素”。遇到名称为“”、命名空间“”的“文本”。 '。
我尝试发送 JSON 的未包装版本...
{"Name":"Simon","Score":"100","Club":"Rigby"}
但在服务中参数为 null,并且没有格式化程序例外情况。
这是服务 web.config 的 system.serviceModel 分支:
<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>
这是玩家数据合约。
[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; } }
}
非常感谢任何帮助,如果需要任何其他信息,请告诉我。
非常感谢。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您以错误的方式对方法
TotalScore
的输入参数player
进行编码。我建议您使用 json2.js 中的
JSON.stringify
函数将任何 JavaScript 对象转换为JSON。如果将
TotalScore
方法的BodyStyle = WebMessageBodyStyle.Wrapped
属性更改为BodyStyle = WebMessageBodyStyle.WrappedRequest
,则可以更改alert( data.TotalScoreResult)
位于success
句柄中alert(data)
。You encode the input parameter
player
of the methodTotalScore
in the wrong way.I recommend you to use
JSON.stringify
function from json2.js to convert any JavaScript objects to JSON.If you change the
BodyStyle = WebMessageBodyStyle.Wrapped
attribute of theTotalScore
method toBodyStyle = WebMessageBodyStyle.WrappedRequest
you can change thealert(data.TotalScoreResult)
in thesuccess
handle toalert(data)
.您尚未在 Web 调用上指定 Method 参数。请参阅:http://msdn.microsoft.com/ en-us/library/bb472541(v=vs.90).aspx
You have not sepcified the Method parameter on web invoke. See: http://msdn.microsoft.com/en-us/library/bb472541(v=vs.90).aspx
我使用 WCF POST JSON 数据遇到了同样的问题(不允许 405 方法)。我在下面的这篇文章中找到了
http://blog.weareon.net/calling-wcf-rest-service-from-jquery-causes-405-method-not-allowed/
希望有帮助!
I got the same problems (405 methods not allowed) using WCF POST JSON data. I found on this article below
http://blog.weareon.net/calling-wcf-rest-service-from-jquery-causes-405-method-not-allowed/
Hope this help!