2010-03-18 37 views
25

Tôi đang cố gắng xây dựng một giao diện dịch vụ web chung bằng cách sử dụng WCF, để cho phép các nhà phát triển bên thứ ba móc vào phần mềm của chúng tôi. Sau nhiều khó khăn và đọc sách (this question đã giúp rất nhiều), cuối cùng tôi đã có SOAP, JSON và XML (POX) làm việc cùng nhau.Kết hợp SOAP/JSON/XML trong WCF, sử dụng UriTemplate

Để đơn giản hóa, đây là mã của tôi (để làm ví dụ này đơn giản, tôi không sử dụng giao diện - tôi đã thử cả hai cách này):

<ServiceContract()> _ 
Public Class TestService 
    Public Sub New() 
    End Sub 

    <OperationContract()> _ 
    <WebGet()> _ 
    Public Function GetDate() As DateTime 
     Return Now 
    End Function 


    '<WebGet(UriTemplate:="getdateoffset/{numDays}")> _ 
    <OperationContract()> _ 
    Public Function GetDateOffset(ByVal numDays As Integer) As DateTime 
     Return Now.AddDays(numDays) 
    End Function 

End Class 

và mã web.config:

<services> 
    <service name="TestService" 
      behaviorConfiguration="TestServiceBehavior"> 
    <endpoint address="soap" binding="basicHttpBinding" contract="TestService"/> 
    <endpoint address="json" binding="webHttpBinding" behaviorConfiguration="jsonBehavior" contract="TestService"/> 
    <endpoint address="xml" binding="webHttpBinding" behaviorConfiguration="poxBehavior" contract="TestService"/> 
    <endpoint address="mex" contract="IMetadataExchange" binding="mexHttpBinding" /> 
    </service> 
</services> 
<behaviors> 
    <endpointBehaviors> 
    <behavior name="jsonBehavior"> 
     <enableWebScript/> 
    </behavior> 
    <behavior name="poxBehavior"> 
     <webHttp /> 
    </behavior> 
    </endpointBehaviors> 
    <serviceBehaviors> 
    <behavior name="TestServiceBehavior"> 
     <serviceMetadata httpGetEnabled="true"/> 
     <serviceDebug includeExceptionDetailInFaults="false"/> 
    </behavior> 
    </serviceBehaviors> 
</behaviors> 

Điều này thực sự hiệu quả - Tôi có thể truy cập TestService.svc/xml/GetDate cho xml, TestService.svc/json/GetDate cho json và trỏ máy khách SOAP tại TestService.svc?wsdl và truy vấn SOAP hoạt động.

Phần tôi muốn khắc phục là các truy vấn. Tôi phải sử dụng TestService.svc/xml/GetDateOffset?numDays=4 thay vì TestService.svc/xml/GetDateOffset/4. Nếu tôi xác định UriTemplate, tôi nhận được lỗi:

Endpoints using 'UriTemplate' cannot be used with 'System.ServiceModel.Description.WebScriptEnablingBehavior'.

Nhưng tất nhiên mà không sử dụng <enableWebScript/>, JSON không hoạt động. Điều duy nhất tôi thấy rằng tôi sẽ làm việc là tạo 3 dịch vụ khác nhau (tệp .svc), tất cả đều triển khai giao diện chỉ định hợp đồng, nhưng trong các lớp chỉ định các thuộc tính WebGet/WebInvoke khác nhau trên mỗi lớp học. Điều này có vẻ như rất nhiều công việc phụ, mà thẳng thắn, tôi không thấy lý do tại sao khuôn khổ không xử lý cho tôi. Việc thực thi các lớp sẽ giống nhau, ngoại trừ các thuộc tính, có nghĩa là theo thời gian sẽ dễ dàng cho các lỗi/thay đổi để được sửa/thực hiện trong một triển khai thực hiện chứ không phải các lỗi khác, dẫn đến hành vi không nhất quán khi sử dụng JSON Ví dụ thực hiện SOAP.

Tôi có làm gì sai ở đây không? Tôi đang sử dụng một cách tiếp cận hoàn toàn sai lầm và lạm dụng WCF? Có cách nào tốt hơn để làm điều này?

Với kinh nghiệm làm công cụ web, tôi nghĩ có thể một số loại khung hình để xử lý việc này ... Tôi thậm chí còn có ý tưởng trong đầu về cách xây dựng nó. Có vẻ như WCF được cho là đang làm điều này, và tôi không thực sự muốn phát minh lại bánh xe.

+0

Ví dụ mã của bạn ở đây rất hữu ích! Tôi đã có chỉ ràng buộc JSON và thấy rằng tôi không thể tiêu thụ các dịch vụ từ một ứng dụng .net vì vậy đây chỉ là những gì tôi đã sau! :) – Shawson

+0

Lưu ý rằng tôi cho rằng điều này hoàn toàn bị lỗi thời với [ASP.NET Web API] (http://www.asp.net/web-api); mã đã khiến câu hỏi này được hỏi từ lâu đã được viết lại bằng API Web. Tôi rất muốn giới thiệu chống lại bằng cách sử dụng WCF cho tốt, bất cứ điều gì, trừ khi bạn đang [mắc kẹt trong thời đại tối tăm và thực sự cần SOAP] (http://stackoverflow.com/questions/11317572/asp-net-webapi-soap). – gregmac

Trả lời

27

Trên thực tế <enableWebScript />không phải là bắt buộc đối với hỗ trợ JSON "thuần túy". Chỉ cần WebScriptEnablingBehavior nếu bạn muốn hỗ trợ ASP.NET AJAX. Thường xuyên hơn không, nếu bạn đang cố gắng làm việc với thư viện tập lệnh chuẩn, bạn không muốn bật hỗ trợ này cho dịch vụ của mình.

Thay vào đó, những gì bạn muốn làm cho điểm cuối JSON của mình chỉ sử dụng số WebHttpBehavior và đặt DefaultOutgoingResponseFormat = "JSON". Vấn đề là, trong .NET 3.5, bạn không thể kiểm soát cài đặt này thông qua cấu hình vì WebHttpElement không hiển thị các thuộc tính này cho cấu hình. Để giải quyết vấn đề này trong 3.5, chúng tôi đã cung cấp một triển khai cho những gì tôi gọi là EnhancedWebHttpElementhere in this answer cho một câu hỏi StackOverflow khác.

May mắn là Microsoft đã nhận ra cấu hình ngắn gọn và được bật này của tất cả các cài đặt WebHttpBehavior qua WebHttpElement in 4.0.

4

Câu trả lời của Drew đã được phát hiện, nhưng tôi nghĩ câu hỏi vẫn đứng vững.Có cách nào để có JSON cho AJAX() và các phước lành của UriTemplate không?

Tôi nghĩ rằng điều đáng nói đến là JSON được trả lại bằng khác với JSON được tạo bằng [WebGet (ResponseFormat = WebMessageFormat.Json)]. Phần trước được bao quanh phần tử MS AJAX 'd', ví dụ: {"d": [{...}]}.

0

Bạn đã chỉ định các thông số nguyên trong hoạt động của mình. Mẫu URI không hoạt động tốt với các tham số int. Hãy thay đổi nó thành chuỗi, nó sẽ hoạt động.

Tôi nghĩ bạn phải viết QuerystringConverter của riêng mình để sử dụng int với URITemplate.

Các vấn đề liên quan