2009-09-08 25 views
12

Bunun gibi bir sözleşme var:WCF servis sözleşmesi null bir giriş parametresine sahip olabilir mi?

[OperationContract] 
[WebGet(UriTemplate = "/GetX?myStr={myStr}&myX={myX}", BodyStyle = WebMessageBodyStyle.Wrapped)] 
string GetX(string myStr, int? myX); 

Bir istisna alıyorum: [InvalidOperationException: 'IMyGet' sözleşmesindeki 'GetX' işlemi 'System.Nullable 1[System.Int32]', but type 'System.Nullable türünde' myX 'adlı bir sorgu değişkenine sahiptir. [System.Int32] ',' QueryStringConverter 'tarafından dönüştürülemiyor. UriTemplate sorgu değerleri için değişkenler, 'QueryStringConverter' tarafından dönüştürülebilen türlere sahip olmalıdır. Xzx23

, aşağıdaki bağlantı dışında bu hata hakkında bir şey bulamadı: http://blog.rolpdog.com/2007/07/webget-and-webinvoke-rock.html ki bu biraz eski ve bir çözüm değil zaten.

neyin dışında neyin yapılabilir parametreden kurtulmak için ne yapacağınız?

teşekkürler.

cevap

1

Evet, WCF ile nealable parametreleri olabilir. Bence senin problemin QueryStringConverter'ın null parametrelerle çalışmadığı.

Ne yapmalı? UriTemplate özelliğini kullanmanız mı gerekiyor? Bunu 'klasik web hizmeti' olarak yayınladıysanız, bu sorunu yaşamayacaksınız.

Diğer seçenek, sağladığınız bağlantıdaki tavsiyeyi takip etmektir - yani, myX parametresini string olarak alın ve daha sonra int (?) N neyin boş olduğu bir int'ye aktarın. Güzel değil.

8

Aslında ... ... kesinlikle null parametreler veya kutudan QueryStringConverter tarafından desteklenmeyen diğer herhangi bir parametre olabilir. Tek yapmanız gereken, ihtiyacınız olan herhangi bir türü desteklemek için QueryStringConverter'u uzatmaktır. herhangi kesmek gerektirmeyen bu soruna bir çözüm vardır bu yazı ==>

In the WCF web programming model, how can one write an operation contract with an array of query string parameters (i.e. with the same name)?

+0

Yukarıdaki kod referansında, QueryStringConverter türetilmiş sınıfları, framework 4'te kullanılamaz hale getiren bir hata vardır. Bunu denemeden önce hatayı gözden geçirdiğinizden emin olun. Pratikte işe yaramadığını keşfetmeden önce çok zaman harcadım. – Jim

32

kabul yanıta bakın. Çok fazla iş gibi görünebilir, ancak gerçekten okuyamıyor ve okumanız çok mantıklı. Sorunun özü, unresolved bug (.NET 4'ten itibaren) olduğundan, WebServiceHost özel QueryStringConverters kullanmadığı anlamına gelir. Bu yüzden biraz fazladan çalışmaya ihtiyaç duyuyorsunuz ve WebHttpEndpoints için WCF yapılandırmasının nasıl çalıştığını anlıyorsunuz. Aşağıda sizin için çözüm yatıyor.

Öncelikle nulls boş dize bunları ihmal ya sağlayarak sorgu dizesinde sağlanacak olanak sağlayan özel QueryStringConverter:

public class NullableQueryStringConverter : QueryStringConverter 
{ 
    public override bool CanConvert(Type type) 
    { 
     var underlyingType = Nullable.GetUnderlyingType(type); 

     return (underlyingType != null && base.CanConvert(underlyingType)) || base.CanConvert(type); 
    } 

    public override object ConvertStringToValue(string parameter, Type parameterType) 
    { 
     var underlyingType = Nullable.GetUnderlyingType(parameterType); 

     // Handle nullable types 
     if (underlyingType != null) 
     { 
      // Define a null value as being an empty or missing (null) string passed as the query parameter value 
      return String.IsNullOrEmpty(parameter) ? null : base.ConvertStringToValue(parameter, underlyingType); 
     } 

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

Şimdi özel WebHttpBehavior özel ayarlar Standart olan yerine kullanılacak QueryStringConverter. Not biz REST son nokta için gerekli davranışı devralması için önemlidir WebHttpBehaviorbu davranış derivces: bu yüzden o WebHttpEndpoint özel davranışı ekler

public class NullableWebHttpBehavior : WebHttpBehavior 
{ 
    protected override QueryStringConverter GetQueryStringConverter(OperationDescription operationDescription) 
    { 
     return new NullableQueryStringConverter(); 
    } 
} 

Şimdi özel ServiceHost Özel QueryStringConverter kullanır.Bu kodda dikkat edilmesi gereken önemli nokta, ServiceHost ve WebServiceHost'dan türetilmesidir. Biz türeyen olmadığından

public sealed class NullableWebServiceHost : ServiceHost 
{ 
    public NullableWebServiceHost() 
    { 
    } 

    public NullableWebServiceHost(object singletonInstance, params Uri[] baseAddresses) : base(singletonInstance, baseAddresses) 
    { 
    } 

    public NullableWebServiceHost(Type serviceType, params Uri[] baseAddresses) : base(serviceType, baseAddresses) 
    { 
    } 

    protected override void OnOpening() 
    { 
     if (this.Description != null) 
     { 
      foreach (var endpoint in this.Description.Endpoints) 
      { 
       if (endpoint.Binding != null) 
       { 
        var webHttpBinding = endpoint.Binding as WebHttpBinding; 

        if (webHttpBinding != null) 
        { 
         endpoint.Behaviors.Add(new NullableWebHttpBehavior()); 
        } 
       } 
      } 
     } 

     base.OnOpening(); 
    } 
} 

bunu bir iş yapmak ve bizim yapılandırma için doğru olduğundan emin olmak gerekir WebServiceHost: Aksi yukarıda belirtilen hata kullanılmaktan özel QueryStringConverter önleyecektir Bu önemlidir, çünkü REST servisinin çalışacağından emin olun. İhtiyacınız olan şey aşağıdaki gibi bir şey. Bu yapılandırmada, her iki C# (WS HTTP'yi daha güzel kullanarak) ve mobil aygıtlardan (REST kullanarak) bu hizmete erişmem gerektiğinden, bir WS HTTP son nokta kurulumuna da sahibim. İhtiyacınız yoksa, bu son nokta için yapılandırmayı atlayabilirsiniz. Dikkat edilmesi gereken önemli bir nokta, artık özel uç nokta davranışına ihtiyaç duymamanızdır. Bu, artık özel QueryStringConverter'u bağlayan kendi özel son nokta davranışımızı eklediğimiz içindir. Yapılandırmanın eklendiği WebHttpBehavior'dan türetilmiştir, bu da artık yedekli hale gelmektedir.

<system.serviceModel> 
    <services> 
    <service behaviorConfiguration="ServiceBehavior" name="MyNamespace.Service1"> 
     <endpoint binding="webHttpBinding" bindingConfiguration="WebHttpBinding" contract="MyNamespace.IService1" /> 
     <endpoint address="ws" binding="wsHttpBinding" bindingConfiguration="WsHttpBinding" contract="MyNamespace.IService1" /> 
     <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> 
    </service> 
    </services> 

    <bindings> 
    <webHttpBinding> 
     <binding name="WebHttpBinding"> 
     <security mode="Transport"> 
      <transport clientCredentialType="None" /> 
     </security> 
     </binding> 
    </webHttpBinding> 

    <wsHttpBinding> 
     <binding name="WsHttpBinding"> 
     <security mode="Transport"> 
      <transport clientCredentialType="None" /> 
     </security> 
     </binding> 
    </wsHttpBinding> 
    </bindings> 

    <behaviors> 
    <serviceBehaviors> 
     <behavior name="ServiceBehavior"> 
     <serviceMetadata httpGetEnabled="false" httpsGetEnabled="true" /> 
     <serviceDebug includeExceptionDetailInFaults="true" httpHelpPageEnabled="false" httpsHelpPageEnabled="true" /> 
     <dataContractSerializer maxItemsInObjectGraph="2147483647" /> 
     </behavior> 
    </serviceBehaviors> 
    </behaviors> 
</system.serviceModel> 

yapılacak son şey, özel bir ServiceHostFactory oluşturmak ve tüm özel kodu kullanılacak neden olur, kullanmak için svc dosyası söylemek. Tabii ki, davranışı konfigürasyona eklemenize izin veren bir özel eleman da yaratabilirsiniz, fakat bu davranış için kod tabanlı bir yaklaşımın daha iyi olduğunu düşünüyorum çünkü olası olmayan türleri işlemek olasılığını ortadan kaldırmak isteyeceksiniz. o hizmetinizi kıracak şekilde:

public sealed class NullableWebServiceHostFactory : ServiceHostFactory 
{ 
    protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses) 
    { 
     return new NullableWebServiceHost(serviceType, baseAddresses); 
    } 
} 

Değiştir sizin Service.svc biçimlendirme dosyasını, aşağıdaki:

<%@ ServiceHost Service="MyNamespace..Service1" CodeBehind="Service1.svc.cs" Factory="MyNamespace.NullableWebServiceHostFactory" %> 

Artık sadece tarafından, herhangi bir sorun olmadan servis arayüzünde null türlerini kullanabilirsiniz Parametreyi atlamak veya boş bir dizeye ayarlamak. Aşağıdaki kaynaklar size daha fazla yardım olabilir:

Umut bu yardımcı olur!

+1

Bu çözümü beğendim. – Sawyer

+4

Bu, Microsoft tarafından uygulanacak bir nobrainer olması gereken bir şey için çok fazla iş. – crush

+2

Microsoft, karmaşık bir şeye ağrılı bir şekilde kolay bir şey olması gereken bir şey yapar ... İyi bir yanıt olsa da – Jim

1

Hızlı çözüm (gayet hoş olmayan), WCF'nin ilgili Arabirim ve Servis kodlarında bir dizge olarak null parametresini kabul etmektir.

İlgili konular