2011-08-01 48 views
10

随着合同:从jQuery的消费WCF的JSON

namespace ACME.FooServices 
{ 
    [ServiceContract] 
    public interface IFooService 
    { 
     [OperationContract] 
     [WebInvoke(Method = "POST", 
        ResponseFormat = WebMessageFormat.Json, 
        RequestFormat = WebMessageFormat.Json, 
        BodyStyle = WebMessageBodyStyle.Bare)]   
     FooMessageType Foo(string name); 
    } 

    [DataContract] 
    public class FooMessageType 
    { 
     string _name; 
     string _date; 

     [DataMember] 
     public string Name 
     { 
      get { return _name; } 
      set { _name = value; } 
     } 

     [DataMember] 
     public string Date 
     { 
      get { return _date; } 
      set { _date = value; } 
     } 
    } 
} 

与实现

using System; 
using System.ServiceModel.Activation; 

namespace ACME.FooServices 
{ 
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)] 
    public class FooService : IFooService 
    { 
     public FooMessageType Foo(string name) 
     { 
      string l_name = (String.IsNullOrWhiteSpace(name)) ? "Anonymous" : name; 

      return new FooMessageType {Name = l_name, Date = DateTime.Now.ToString("MM-dd-yyyy h:mm:ss tt")}; 
     } 
    } 
} 

在web.config配置为:

<system.serviceModel> 
    <services> 
     <service name="ACME.FooServices.FooService"> 
      <endpoint address="" behaviorConfiguration="ACME.FooBehaviour" binding="webHttpBinding" contract="ACME.FooServices.IFooService" /> 
     </service> 
    </services> 
    <behaviors> 
     <endpointBehaviors> 
      <behavior name="ACME.FooBehaviour"> 
       <webHttp /> 
      </behavior> 
     </endpointBehaviors> 
     <serviceBehaviors> 
      <behavior name=""> 
       <serviceMetadata httpGetEnabled="true" /> 
       <serviceDebug includeExceptionDetailInFaults="true" /> 
      </behavior> 
     </serviceBehaviors> 
    </behaviors> 
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" /> 
</system.serviceModel> 

我想通过jQuery从页面调用Foo:

<script type="text/javascript" language="javascript"> 
    $(document).ready(function() { 
     $("#msgButton").click(function() { 
      var params = {}; 
      params.name = $("#nameTextbox").val(); 

      $.ajax({ 
       type: 'POST', 
       url: "http://acme.com/wcfsvc/FooService.svc/Foo", 
       data: JSON.stringify(params), 
       contentType: 'application/json; charset=utf-8', 
       success: function (response, status, xhr) { alert('success: ' + response); }, 
       error: function (xhr, status, error) { alert("Error\n-----\n" + xhr.status + '\n' + xhr.responseText); }, 
       complete: function (jqXHR, status) { alert('Status: ' + status + '\njqXHR: ' + JSON.stringify(jqXHR)); } 
      }); 
     }); 
    });   
</script> 

但是我得到一个400 - 错误请求错误消息“服务器在处理请求时遇到错误。异常消息是'反序列化System.String类型的对象时出现错误。从期望的命名空间''结束元素'root'。从命名空间”找到元素 '名'。

我缺少的东西?

回答

15

params为对象,并将其形成{ "name" : "someValue" } JSON字符串。如果你说邮件正文样式是Bare我认为你的服务期望是这样的:

[DataContract] 
public class SomeDTO 
{ 
    [DataMember(Name = "name")] 
    public string Name { get; set; } 
} 

而且因为你的操作应该被定义定义为:如果你希望你当前的代码工作,你或许应该将其更改为

[OperationContract] 
[WebInvoke(Method = "POST", 
      ResponseFormat = WebMessageFormat.Json, 
      RequestFormat = WebMessageFormat.Json, 
      BodyStyle = WebMessageBodyStyle.Bare)]   
FooMessageType Foo(SomeDTO data); 

[OperationContract] 
[WebInvoke(Method = "POST", 
      ResponseFormat = WebMessageFormat.Json, 
      RequestFormat = WebMessageFormat.Json, 
      BodyStyle = WebMessageBodyStyle.WrappedRequest)]   
FooMessageType Foo(SomeDTO data); 
+0

我收集裸和DTO将是一个最好的请求实践? – Bullines

4

尝试设置BodyStyle=WebMessageBodyStyle.Wrapped

source

6

我得到了同样的问题。设置后BodyStyle = WebMessageBodyStyle.Wrapped它解决了。

[WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped)] 
+0

Ladislav Mrnka建议的是一项工作。但BodyStyle = WebMessageBodyStyle.Wrapped是一个正确的修复 –

0

BodyStyle = WebMessageBodyStyle.WrappedRequest工作对我来说,如果你是从小提琴手或其他休息客户 但如果你是从HTTPWebResponse裸请求将工作