【问题标题】:Consuming JSON in WCF service method在 WCF 服务方法中使用 JSON
【发布时间】:2011-07-26 17:26:49
【问题描述】:

在一个较大的项目中,我无法让 WCF 服务方法使用 JSON 参数。所以我制作了一个较小的测试用例,并且行为得到了回应。如果我调试服务,我可以在服务调用中看到参数值为 null。 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 的解包版本...

{"姓名":"Simon","Score":"100","俱乐部":"Rigby"}

但在服务中参数为空,并且没有格式化程序异常。

这是服务 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>

这里是 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; } }

    }

非常感谢任何帮助,如果需要任何其他信息,请告诉我。

非常感谢。

【问题讨论】:

    标签: javascript jquery wcf json nullreferenceexception


    【解决方案1】:

    您尚未在 web 调用中指定 Method 参数。见:http://msdn.microsoft.com/en-us/library/bb472541(v=vs.90).aspx

    【讨论】:

    • 谢谢,但它在 TotalScore 上,这是有问题的方法。
    【解决方案2】:

    你对方法TotalScore的输入参数player进行了错误的编码。

    我建议您使用 json2.js 中的 JSON.stringify 函数将任何 JavaScript 对象转换为 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");
        }
    });
    

    如果将TotalScore 方法的BodyStyle = WebMessageBodyStyle.Wrapped 属性更改为BodyStyle = WebMessageBodyStyle.WrappedRequest,则可以将success 句柄中的alert(data.TotalScoreResult) 更改为alert(data)

    【讨论】:

    • 非常感谢......这就是问题所在。查看 fiddler 中的 JSON,我看到 int 值没有被引用。我的印象是他们应该是。非常感谢。
    • @Simon Rigby:是的,这是错误之一。您序列化的Club 属性也是“表单”样式,这也是错误的。我还修改了我的答案以显示BodyStyle 属性的含义。希望对你也有帮助。
    • 非常感谢。 stringify 如何处理日期。我的 WCF 服务正在绊倒它们,因为它没有 /date() 包装器。这是我需要单独解决的问题。我不确定如何在一次调用中将其作为对象 json'd 挂钩。我希望这是有道理的。
    • @Simon Rigby: DateTimeDate 是 JSON 支持的非标准类型。因此,您应该在客户端(在 JavaScript 中)或服务器端进行一些额外的转换。您需要将服务器发布的日期转换为客户端或将JqvqScript Date发布到服务器以便轻松转换为DateTime吗?我可以给你发一些例子或者this post 解决你的问题。
    • 非常感谢,我最终使用了 Rick Strahl 的服务代理的变体,它使用 JSON2 stringify()。感谢你的帮助。 :)
    【解决方案3】:

    我在使用 WCF POST JSON 数据时遇到了同样的问题(不允许使用 405 方法)。我在下面的这篇文章中找到了

    http://blog.weareon.net/calling-wcf-rest-service-from-jquery-causes-405-method-not-allowed/

    希望对您有所帮助!

    【讨论】:

      猜你喜欢
      • 2012-11-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多