将复杂对象传递到 WCF Rest 服务

Posted

技术标签:

【中文标题】将复杂对象传递到 WCF Rest 服务【英文标题】:Passing complex objects into a WCF Rest Service 【发布时间】:2011-01-04 22:41:18 【问题描述】:

我有一个接受复杂对象的操作契约,我通过 jQuery 调用操作。如何使用 jQuery 传递复杂类型的对象。下面是操作签名:

public Resolution CreateNewResolution(Resolution NewResolution);

我需要在客户端传递一个 Resolution 对象,但我不知道如何做一些事情,比如使用 jQuery。有什么帮助吗?

谢谢

【问题讨论】:

【参考方案1】:

首先请参阅Denny's post,尽管我不同意他使用 GET 并在查询字符串中传递 JSON 以获取复杂参数。这似乎真的不对。


data 使用的参数是任何分辨率类型的 json 表示。例如,假设类型和操作在服务器端是这样定义的:

[DataContract( Namespace = "urn:brandon.michael.hunter/ws/2010/01", 
               Name = "Resolution" )]
public class Resolution

    [DataMember( IsRequired = true, Name = "Name" )]
    public string Name      get; set;  

    [DataMember( IsRequired = true, Name = "Rank" )]
    public int Rank  get; set; 

    [DataMember( IsRequired = true, Name = "SerialNumber" )]
    public int SerialNumber  get; set;  

    [DataMember( IsRequired = false, Name = "Id" )]
    public int Id  get; set;  


[OperationContract]
[WebInvoke(Method = "PUT",
           RequestFormat=WebMessageFormat.Json,
           ResponseFormat = WebMessageFormat.Json,
           UriTemplate = "new")]
public Resolution CreateNewResolution(Resolution r)

    // your logic here
    r.Id = System.Guid.NewGuid();
    return r;

然后,在 javascript 中,您使用的代码可能如下所示:

var resolution = r:  Name : "Fred", Rank : 2,  SerialNumber : 17268 ;

// convert object to JSON string  (See http://jollytoad.googlepages.com/json.js)
var objectAsJson = $.toJSON(resolution);
// result is a string:  '"Name":"Fred","Rank":"2","SerialNumber":"17268"'

$.ajax(
  type        : "PUT",              // must match Method in WebInvoke
  contentType : "application/json",
  url         : "Service.svc/new",  // must match UriTemplate in WebInvoke
  data        : objectAsJson, 
  dataFilter  : function (data, type) 
      // convert from "\/Date(nnnn)\/" to "new Date(nnnn)"
      return data.replace(/"\\\/(Date\([0-9-]+\))\\\/"/gi, 'new $1');
  ,
  processData : false,              // do not convert outbound data to string (already done)
  success     : function(msg) ... ,
  error       : function(xhr, textStatus, errorThrown) ...  
 );

注意事项:

您需要将变量 (r) 的名称作为要传递的 JSON 中的第一个对象,至少在 WCF 4 中是这样。当我使用前面的示例时,它直到我放入变量名开头。 要在 JSON 中传递复杂对象,请使用 PUT 或 POST 作为请求的类型(HTTP 方法) 您需要将复杂对象转换为 JSON 字符串。有a nice, tiny jquery plugin to do this。 Denny 提供了他自己的实现。 我发现如果我使用processData=true,那么发送到服务的结果字符串是查询字符串格式,而不是JSON。不是我想要传递复杂对象的东西。所以我把它设置为假。对于您正在执行 WebGet 的更简单的非 JSON 请求,使用 true 会很好,并且所有参数都在查询字符串中。 dataFilter 允许正确反序列化 DateTime 对象 传递给成功回调的msg 参数包含返回的json。 您可能希望使用 URL 重写器来隐藏请求 URL 中的 .svc 标记 在这种情况下,WCF 服务使用 webHttp 行为,而不是 enableWebScript。后者动态生成 Javascript 代理来调用服务,但是您提出问题的方式让您看起来不想要那样。

【讨论】:

你会更新这个以显示 POST 而不是 PUT 吗? POST 被普遍认为是避免跨站脚本问题的最安全方法【参考方案2】:

查看 Gil Fink 关于组合 WCF 数据服务、JSONP 和 jQuery 的博客

http://blogs.microsoft.co.il/blogs/gilf/archive/2011/04/24/combining-wcf-data-services-jsonp-and-jquery.aspx

在 Mike Flasko 在 MIX11 的 session 期间,他展示了如何使用 JSONPSupportBehavior 属性创建一个支持 JSONP 的 WCF 数据服务,该属性可用于 MSDN 代码库中的download(并且应该是 Microsoft.Data 的一部分) .Services.Extensions 命名空间)。在这篇文章中,我将展示一个使用属性和 jQuery 的简单示例,以便对 WCF 数据服务进行 JSONP 跨域调用。

设置环境

首先,我创建了两个不同的 ASP.NET Web 应用程序。第一个应用程序包括调用页面,第二个应用程序包括 WCF 数据服务。然后,我在第二个 Web 应用程序中创建了一个实体框架模型和来自该模型的 WCF 数据服务。我还添加了之前提供的link 中存在的 JSONPSupportBehavior.cs 类。该类包括实现 WCF IDispatchMessageInspector 接口的 JSONPSupportBehavior 的实现。它还包括我在代码中使用的 JSONPSupportBehaviorAttribute。代码很简单,看起来像:

[JSONPSupportBehavior] 
public class SchoolDataService : DataService<SchoolEntities>

  // This method is called only once to initialize service-wide policies.
  public static void InitializeService(DataServiceConfiguration config)
        
    config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);      
    config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
  

进行 JSONP 调用

在第二个 Web 应用程序中,我创建了一个包含 JSONP 调用示例的 Web 表单。这是进行调用的代码:

<!DOCTYPE html>
<html>
<head runat="server">
    <title>JSONP Call</title>
    <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.5.1.js" type="text/javascript"></script>
</head>
<body>
    <form id="form1" runat="server">
    <output id="result">
    </output>
    </form>
    <script type="text/javascript">
        $.getJSON('http://localhost:23330/SchoolDataService.svc/Courses?$format=json&$callback=?', 
        function (response)  
            $.each(response.d, function (index, value) 
                var div = document.createElement('div');
                div.innerHTML = value.Title;
                $('#result').append(div);
            )
        );        
    </script>
</body>
</html>

让我们探索网络表单代码: 起初,我使用 Microsoft CDN 来检索 jQuery 库。然后,我创建了一个 HTML5 输出元素,以便将调用的输出附加到它。在主脚本中,我使用 jQuery 的 getJSON 函数来调用 WCF 数据服务。请注意,为了从 WCF 数据服务获取 JSON 响应,您需要使用 $format=json 查询字符串参数。检索数据后,我迭代并为检索到的每个课程标题创建一个 div 元素。这是在我连接到 getJSON 函数调用的成功函数中完成的。下面是运行代码的输出:

总结

在帖子中,我提供了一个使用 jQuery 对 WCF 数据服务进行 JSONP 调用的简单示例。这种解决方案可以帮助您从客户端使用存在于其他域中的 WCF 数据服务。在后续文章中,我将展示使用新的 datajs 库的相同示例

【讨论】:

以上是关于将复杂对象传递到 WCF Rest 服务的主要内容,如果未能解决你的问题,请参考以下文章

是否可以使用 jQuery 方法 getJSON 跨域将复杂对象传递给 WCF 服务?

ksoap2 将复杂对象数组发送到 WCF 服务

为 Rest Web 服务创建 WCF 代理

将 REST 方法添加到 WCF 数据服务?

WCF REST 服务流式传输 JSON 对象

如何同时使用 SOAP WCF 服务和 REST API