2016-12-26 289 views
2

我在寫一個爲WCF休息服務生成客戶端的小型庫。但是我遇到了可空值的問題:由於不明原因,我的定製QueryStringConverter永遠不會被調用,我在調試器中看到WCF調用它的CanConvert方法。這裏是代碼:QueryStringConverter不能正常工作

public class NullableQueryStringConverter : QueryStringConverter 
{ 
    public static NullableQueryStringConverter Instance { get; } = new NullableQueryStringConverter(); 
    public override bool CanConvert(Type type) 
    { 
     if (base.CanConvert(type)) 
      return true; 
     var underlyingType = Nullable.GetUnderlyingType(type); 
     var canConvert = underlyingType != null && base.CanConvert(underlyingType); 
     return canConvert; 
    } 

    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); 
    } 
} 

,這裏是WCF服務開放:

public void Start(Uri baseAddress) 
{ 
    var serviceInterface = _serviceType.GetInterfaces() 
             .First(i => i.GetCustomAttribute<ServiceContractAttribute>(true) != null); 
    var attribute = _serviceType.GetCustomAttribute<ServiceBehaviorAttribute>(true); 
    if (attribute?.InstanceContextMode == InstanceContextMode.Single) 
    { 
     var singleton = Activator.CreateInstance(_serviceType); 
     ServiceHost = new WebServiceHost(singleton, baseAddress.Concat(_subAddress)); 
    } 
    else 
    { 
     ServiceHost = new WebServiceHost(_serviceType, baseAddress.Concat(_subAddress)); 
    } 
    ServiceHost.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true }); 
    var debugBehavior = ServiceHost.Description.Behaviors.OfType<ServiceDebugBehavior>().FirstOrDefault(); 
    if (debugBehavior != null) 
    { 
     debugBehavior.IncludeExceptionDetailInFaults = true; 
    } 
    else 
    { 
     ServiceHost.Description.Behaviors.Add(new ServiceDebugBehavior { IncludeExceptionDetailInFaults = true }); 
    } 

    var webHttpBinding = new WebHttpBinding 
    { 
     MaxReceivedMessageSize = int.MaxValue, 
     MaxBufferSize = int.MaxValue, 
     MaxBufferPoolSize = int.MaxValue, 
     ReaderQuotas = 
       new XmlDictionaryReaderQuotas 
       { 
        MaxArrayLength = int.MaxValue, 
        MaxStringContentLength = int.MaxValue, 
        MaxDepth = 32 
       } 
    }; 

    webHttpBinding.ContentTypeMapper = new NewtonsoftJsonContentTypeMapper(); 
    ServiceHost.AddServiceEndpoint(serviceInterface, webHttpBinding, string.Empty); 

    foreach (var endpoint in ServiceHost.Description.Endpoints) 
    { 
     endpoint.Behaviors.Add(new NullableWebHttpBehavior 
     { 
      HelpEnabled = false, 
      DefaultBodyStyle = WebMessageBodyStyle.Bare, 
      DefaultOutgoingRequestFormat = WebMessageFormat.Json, 
      DefaultOutgoingResponseFormat = WebMessageFormat.Json, 
      FaultExceptionEnabled = true 
     }); 

     endpoint.Behaviors.Add(new NewtonsoftJsonBehavior()); 
    } 

    ServiceHost.Open(); 
} 

正如你所看到的,我加入NullableWebHttpBehavior這是被稱爲(至少CanConvert方法),但WCF劇照後要求參數可以由基類轉換。

以下鏈接至github上的項目:link。這是bizzare,因爲我在另一個工作正常的項目中有非常類似的代碼。

也許我錯過了一些東西,我不知道。包含所有要檢查的邏輯的文件是:NullableWebHttpBehavior.csServiceManager.cs。你可以很容易地運行一個測試(這是唯一的一個測試)並面臨同樣的問題。

回答

1

經過一番研究,我發現,這種方法會導致異常是日正:

protected override IDispatchMessageFormatter GetRequestDispatchFormatter(OperationDescription operationDescription, ServiceEndpoint endpoint) 
    { 
     if (operationDescription.IsGetOrDeleteOperation()) 
     { 
      // no change for GET operations 
      return base.GetRequestDispatchFormatter(operationDescription, endpoint); 
     } 

     if (operationDescription.Messages[0].Body.Parts.Count == 0) 
     { 
      // nothing in the body, still use the default 
      return base.GetRequestDispatchFormatter(operationDescription, endpoint); 
     } 

     return new NewtonsoftJsonDispatchFormatter(operationDescription, true); 
    } 

對於一些說理base.GetRequestDispatchFormatter將返回原來的QueryStringConverter會拋出一個錯誤。所以我剛剛刪除這些if s,並始終使用我的自定義NewtonsoftJsonDispatchFormatter,它有一些開銷,但工作正常。