2008-12-10 13 views
13

Sử dụng mô hình lập trình web WCF ai có thể chỉ định một hợp đồng hoạt động như sau:Trong mô hình lập trình web WCF, làm cách nào để có thể viết một hợp đồng hoạt động với một mảng tham số chuỗi truy vấn (tức là có cùng tên)?

[OperationContract] 
[WebGet(ResponseFormat = WebMessageFormat.Xml, UriTemplate = "SomeRequest?qs1={qs1}&qs2={qs2}")] 
XElement SomeRequest1(string qs1, string qs2); 

Bây giờ nếu chúng ta có để thực hiện một hợp đồng chấp nhận một loạt các thông số có cùng tên (trong trường hợp này qs1) hợp đồng như vậy ...

[OperationContract] 
[WebGet(ResponseFormat = WebMessageFormat.Xml, UriTemplate = "SomeRequest?qs1={qs1}&qs1={qs2}")] 
XElement SomeRequest2(string qs1, string qs2); 

chúng tôi nhận được thông báo lỗi tại thời gian chạy khi chúng tôi làm cho gọi đến phương pháp:

chuỗi truy vấn phải có cặp 'name = value' với các tên duy nhất. Lưu ý rằng các tên không phân biệt chữ hoa chữ thường. Xem tài liệu cho UriTemplate để biết thêm chi tiết.

Làm cách nào để xác định dịch vụ HTTP hiển thị tài nguyên với một mảng thông số mà không cần đến giao diện lỏng lẻo?

Trả lời

28

Tôi đã thực hiện một QueryStringConverter tùy chỉnh đơn giản để bạn có thể làm cho qs1 một string [] sau đó có biến chuỗi truy vấn có dấu phẩy phân cách (ví dụ http://server/service/SomeRequest?qs1=val1,val2,val3,val4)

[OperationContract] 
[WebGet(ResponseFormat = WebMessageFormat.Xml, 
     UriTemplate = "SomeRequest?qs1={qs1}")] 
XElement SomeRequest2(string[] qs1); 

Trước tiên, bạn cần một lớp kế thừa từ WebHttpBehavior để chúng tôi có thể tiêm QueryStringConverter tùy chỉnh của chúng tôi:

public class CustomHttpBehavior : System.ServiceModel.Description.WebHttpBehavior 
{ 
    protected override System.ServiceModel.Dispatcher.QueryStringConverter GetQueryStringConverter(System.ServiceModel.Description.OperationDescription operationDescription) 
    { 
     return new CustomQueryStringConverter(); 
    } 
} 

Sau đó CustomQueryStringConverter của chúng tôi để xử lý string [] thông số:

public class CustomQueryStringConverter : System.ServiceModel.Dispatcher.QueryStringConverter 
{ 
    public override bool CanConvert(Type type) 
    { 
     if (type == typeof(string[])) 
     { 
      return true; 
     } 

     return base.CanConvert(type); 
    } 

    public override object ConvertStringToValue(string parameter, Type parameterType) 
    { 
     if (parameterType == typeof(string[])) 
     { 
      string[] parms = parameter.Split(','); 
      return parms; 
     } 

     return base.ConvertStringToValue(parameter, parameterType); 
    } 

    public override string ConvertValueToString(object parameter, Type parameterType) 
    { 
     if (parameterType == typeof(string[])) 
     { 
      string valstring = string.Join(",", parameter as string[]); 
      return valstring; 
     } 

     return base.ConvertValueToString(parameter, parameterType); 
    } 
} 

Điều cuối cùng bạn cần làm là tạo tiện ích cấu hình hành vi để mà bộ thực thi có thể nhận được một thể hiện của các CustomWebHttpBehavior:

public class CustomHttpBehaviorExtensionElement : System.ServiceModel.Configuration.BehaviorExtensionElement 
{ 
    protected override object CreateBehavior() 
    { 
     return new CustomHttpBehavior(); 
    } 

    public override Type BehaviorType 
    { 
     get { return typeof(CustomHttpBehavior); } 
    } 
} 

Bây giờ chúng ta thêm yếu tố để mở rộng cấu hình của chúng tôi để CustomWebHttpBehavior của chúng tôi được sử dụng, chúng tôi sử dụng tên của phần mở rộng thay vì <webHttp /> trong hành vi của chúng tôi:

<system.serviceModel> 
    <services> 
    <service name="NameSpace.ServiceClass"> 
     <endpoint address="" behaviorConfiguration="MyServiceBehavior" 
     binding="webHttpBinding" contract="NameSpace.ServiceClass" /> 
    </service> 
    </services> 
    <behaviors> 
    <endpointBehaviors> 
    <behavior name="MyServiceBehavior"> 
     <customWebHttp/> 
    </behavior> 
    </endpointBehaviors> 
    </behaviors> 
    <extensions> 
    <behaviorExtensions> 
     <add name="customWebHttp" type="NameSpace.CustomHttpBehaviorExtensionElement, MyAssemblyName" /> 
    </behaviorExtensions> 
    </extensions> 
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" /> 
</system.serviceModel> 

Bây giờ bạn cũng có thể mở rộng CustomQueryStringConverter của bạn để xử lý các loại khác mà mặc định trên e không, chẳng hạn như các loại giá trị nullable.

LƯU Ý: Có lỗi được ghi lại ở kết nối microsoft có liên quan trực tiếp đến mã này. Mã này không thực sự hoạt động trong hầu hết các trường hợp mà bạn cố gắng truy vấn Chuyển đổi các loại khác nhau.

http://connect.microsoft.com/VisualStudio/feedback/details/616486/bug-with-getquerystringconverter-not-being-called-by-webservicehost#tabs

Hãy chắc chắn rằng bạn đọc cẩn thận trước khi lãng phí thời giờ của bạn tạo tùy chỉnh REST của chuỗi truy vấn chuyển đổi mà không thể nào làm việc. (Áp dụng cho Framework 4.0 trở xuống).

+0

Bất kỳ ý tưởng nào về cách chúng tôi có thể có giao diện như vậy: http: // server/service/SomeRequest? Qs1 = val1 & qs1 = val2 & qs1 = val3 & qs1 = val4? Chúng tôi có thể ofcourse hack nó để trả về một chuỗi định dạng với tên tham số thay vì dấu phẩy. –

+0

Tuyệt vời! Tôi chạy vào một vấn đề mà phần mở rộng hành vi của tôi sẽ không tải trừ khi tôi hoàn toàn đủ điều kiện tên loại với phiên bản lắp ráp, chìa khóa, vv Xem http://nayyeri.net/configuration-error-for-custom-behavior-extensions-in -wcf –

+4

Có một lỗi trong WCF 4 với WebServiceHost không gọi phương thức GetQueryStringConverter bị ghi đè. Xem https://connect.microsoft.com/VisualStudio/feedback/details/616486/bug-with-getquerystringconverter-not-being-called-by-webservicehost?wa=wsignin1.0 – Daniel

5

Để đáp ứng với nhận xét của bạn về câu trả lời khác của tôi:

Bạn có thể làm một số ký tự đại diện vào cuối của chuỗi truy vấn như

[WebGet(ResponseFormat = WebMessageFormat.Xml, 
     UriTemplate = "SomeRequest?qs1={*qs1}")] 
XElement SomeRequest2(string qs1); 

Bằng cách này, tham số chuỗi qs1 sẽ là toàn bộ chuỗi truy vấn liệu sau qs1 =, bạn có thể phân tích cú pháp thủ công trong mã của mình.

QueryStringConverter dựa trên định dạng của chuỗi truy vấn để làm điều gì đó chính xác như bạn muốn là không thể mà không có khả năng viết lại QueryStringConverter thay vì các ghi đè nhỏ mà chúng tôi đã làm trong câu trả lời khác.

Từ MSDN:

đoạn ký tự đại diện phải tuân theo các quy tắc sau:

  • Có thể có nhiều nhất một phân khúc wildcard tên cho mỗi mẫu chuỗi.
  • Phân đoạn ký tự đại diện được đặt tên phải xuất hiện ở phân khúc ngoài cùng bên phải trong đường dẫn.
  • Phân đoạn ký tự đại diện được đặt tên không thể cùng tồn tại với phân đoạn ký tự đại diện ẩn danh trong cùng một chuỗi mẫu.
  • Tên của phân đoạn ký tự đại diện được đặt tên phải là duy nhất.
  • Phân đoạn ký tự đại diện được đặt tên không được có giá trị mặc định.
  • Phân đoạn ký tự đại diện được đặt tên không thể kết thúc bằng “/”.
2

Hãy nhận biết rằng trong WCF 3.5 bạn phải ghi rõ tên lắp ráp đủ tiêu chuẩn đầy đủ trong:

<extensions> 
    <behaviorExtensions> 
     <add name="customWebHttp" type="NameSpace.CustomHttpBehaviorExtensionElement, MyAssemblyName, NOT SUFFICIENT HERE" /> 
    </behaviorExtensions> 
    </extensions> 

Chỉ cần như thế này: SampleService.CustomBehavior, SampleService, Version = 1.0.0.0, Culture = trung tính, PublicKeyToken = null

Nếu không, bạn sẽ nhận được ngoại lệ:

Cấu hình Lỗi
Mô tả: Đã xảy ra lỗi trong khi xử lý tệp cấu hình cần thiết để phục vụ yêu cầu này. Vui lòng xem lại chi tiết lỗi cụ thể bên dưới và sửa đổi tệp cấu hình của bạn một cách thích hợp.

Thông báo lỗi trình phân tích cú pháp: Phần tử không hợp lệ trong cấu hình. Tên tiện ích 'CustomWebHttp' không được đăng ký trong bộ sưu tập tại system.serviceModel/extensions/behaviorExtensions.