Es gibt eine Lösung für dieses Problem ist, dass kein Hacks erfordert. Es sieht vielleicht nach viel Arbeit aus, aber es ist nicht wirklich und macht viel Sinn, wenn man es durchliest. Der Kern des Problems besteht darin, dass es tatsächlich eine unresolved bug (ab .NET 4) gibt, die WebServiceHost nicht benutzerdefinierte AbfrageStringConverter verwendet. Sie müssen also etwas mehr arbeiten und verstehen, wie die WCF-Konfiguration für WebHttpEndpoints funktioniert. Das Folgende beschreibt die Lösung für Sie.
Zuerst wird eine benutzerdefinierte Querystringconverter, die NULL-Werte können durch Weglassen sie in die Query-String zur Verfügung gestellt werden, oder eine leere Zeichenfolge bereitstellt:
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);
}
}
Jetzt eine benutzerdefinierte WebHttpBehavior, die die benutzerdefinierte gesetzt wird QueryStringConverter anstelle des Standard-verwendet werden. Beachten Sie, dass dieses Verhalten derivces von WebHttpBehavior was wichtig ist, so dass wir das Verhalten, die für einen REST-Endpunkt erben:
public class NullableWebHttpBehavior : WebHttpBehavior
{
protected override QueryStringConverter GetQueryStringConverter(OperationDescription operationDescription)
{
return new NullableQueryStringConverter();
}
}
Jetzt ein benutzerdefinierten Servicehost, die das benutzerdefinierte Verhalten des WebHttpEndpoint fügt, so dass es wird den benutzerdefinierten QueryStringConverter verwenden.Die wichtige Sache in diesem Code zu beachten, ist, dass es von ServiceHost und nicht WebServiceHost abgeleitet ist. Dies ist wichtig, weil sonst die oben genannten Fehler werden die benutzerdefinierten Querystringconverter verhindern, verwendet:
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();
}
}
Weil wir Ableitung nicht aus Webservicehost wir es Arbeit tun müssen, und sicherstellen, dass unsere Konfiguration korrekt ist Stellen Sie sicher, dass der REST-Service funktioniert. So etwas wie das Folgende ist alles was Sie brauchen. In dieser Konfiguration habe ich auch eine WS-HTTP-Endpunkt-Einrichtung, weil ich auf diesen Dienst sowohl von C# (unter Verwendung von WS HTTP als dessen netter) als auch von mobilen Geräten (unter Verwendung von REST) zugreifen musste. Sie können die Konfiguration für diesen Endpunkt weglassen, wenn Sie ihn nicht benötigen. Eine wichtige Sache zu beachten ist, dass Sie nicht mehr das benutzerdefinierte Endpunktverhalten benötigen. Dies liegt daran, dass wir jetzt unser eigenes benutzerdefiniertes Endpunktverhalten hinzufügen, das den benutzerdefinierten QueryStringConverter bindet. Es stammt von WebHttpBehavior was ist die Konfiguration hinzugefügt, so dass es jetzt überflüssig.
<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>
Das letzte, was zu tun ist, eine benutzerdefinierte Servicehost erstellen und die SVC-Datei sagen, es zu benutzen, die alle benutzerdefinierten Code verursacht verwendet werden. Natürlich könnten Sie auch ein benutzerdefiniertes Element erstellen, mit dem Sie das Verhalten in der Konfiguration hinzufügen können, aber ich denke, für dieses Verhalten ist ein code-basierter Ansatz besser, da es unwahrscheinlich ist, dass Sie die Fähigkeit zum Verarbeiten von Nullwerten entfernen möchten. wie es Ihren Dienst brechen:
public sealed class NullableWebServiceHostFactory : ServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
return new NullableWebServiceHost(serviceType, baseAddresses);
}
}
ändern Sie den Markup Ihrer Service.svc auf die folgende Datei:
<%@ ServiceHost Service="MyNamespace..Service1" CodeBehind="Service1.svc.cs" Factory="MyNamespace.NullableWebServiceHostFactory" %>
Jetzt können Sie Nullable-Typen in Ihrem Service-Schnittstelle ohne Probleme verwenden, einfach durch den Parameter weglassen oder ihn auf eine leere Zeichenfolge setzen. Die folgenden Ressourcen können Sie von mehr Hilfe sein:
hoffe, das hilft!
Es gibt einen Fehler in der obigen Code-Referenz, der die von QueryStringConverter abgeleiteten Klassen in Framework 4 unbrauchbar macht. Stellen Sie sicher, dass Sie sich den Fehler angesehen haben, bevor Sie dies versuchen. Ich habe viel Zeit verschwendet, bevor ich entdeckt habe, dass es in der Praxis nicht funktioniert. – Jim