2016-12-26 5 views
2

Ich schreibe eine kleine Bibliothek, die Clients für WCF Rest Services generiert. Aber ich stieß auf ein Problem mit Nullable-Werten: Aus unbekannten Gründen wird meine benutzerdefinierte QueryStringConverter niemals aufgerufen, durchgehend sehe ich im Debugger, dass WCF seine CanConvert Methode aufruft. Hier ist der Code:QueryStringConverter funktioniert nicht aus unbekannten Grund

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

und hier ist WCF Serviceöffnung:

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

Wie Sie sehen, ich bin NullableWebHttpBehavior Zugabe, die (zumindest CanConvert Verfahren) genannt wird, aber nach, dass WCF Stills Parameter müssen nach Basisklasse konvertierbar sein.

Hier ist Link zum Projekt auf GitHub: link. Es ist bizzare, weil ich sehr ähnlichen Code in einem anderen Projekt habe, das gut funktioniert.

Vielleicht vermisse ich etwas, ich weiß nicht. Dateien, die die gesamte zu untersuchende Logik enthalten, sind: NullableWebHttpBehavior.cs und ServiceManager.cs. Sie können problemlos einen Test durchführen (der hier der einzige ist) und mit demselben Problem konfrontiert werden.

Antwort

1

Nach einigen Recherchen fand ich, dass diese Methode Ausnahme Rizen sein Ursachen:

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

Für einige reaon base.GetRequestDispatchFormatter ist original QueryStringConverter Rückkehr, die einen Fehler auslöst. Also entfernte ich diese if s und immer meine benutzerdefinierte NewtonsoftJsonDispatchFormatter, die einige Overhead hat aber funktioniert gut.

Verwandte Themen