接受的答案是有這個問題,不需要任何黑客的解決方案。它可能看起來像很多工作,但它不是真的,並且如果你仔細閱讀它就會很有意義。問題的核心是確實有一個unresolved bug(從.NET 4起),這意味着WebServiceHost不使用自定義QueryStringConverters。因此,您需要做一些額外的工作並瞭解WebHttpEndpoints的WCF配置是如何工作的。以下爲您找出解決方案。
首先,自定義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);
}
}
現在定製WebHttpBehavior將設置自定義QueryStringConverter被用來代替標準的。需要注意的是,從WebHttpBehavior這種行爲derivces讓我們繼承了一個REST端點所要求的行爲,這是很重要的:即增加了自定義行爲的WebHttpEndpoint
public class NullableWebHttpBehavior : WebHttpBehavior
{
protected override QueryStringConverter GetQueryStringConverter(OperationDescription operationDescription)
{
return new NullableQueryStringConverter();
}
}
現在定製ServiceHost的,使其將使用自定義QueryStringConverter。此代碼中要注意的重要一點是,它來自ServiceHost而不是WebServiceHost。這是很重要的,否則上面提到的bug會阻止自定義QueryStringConverter被使用:
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();
}
}
,因爲我們沒有從獲得WebServiceHost,我們需要做的工作,並確保我們的配置是正確的確保REST服務能夠正常工作。像下面這樣的東西就是你需要的。在這個配置中,我也有一個WS HTTP端點設置,因爲我需要從C#(使用WS HTTP作爲它的更好)和移動設備(使用REST)訪問此服務。如果不需要,可以省略此端點的配置。需要注意的一點是,您不再需要自定義端點行爲。這是因爲我們現在添加了我們自己的自定義端點行爲,該行爲綁定了自定義的QueryStringConverter。它來源於WebHttpBehavior這是什麼配置添加,使其現在是多餘的。
<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>
最後要做的是創建一個自定義ServiceHostFactory並告訴SVC文件來使用它,這將導致使用的所有的自定義代碼。當然,你也可以創建一個自定義元素,允許你在配置中添加行爲,但我認爲對於這種行爲,基於代碼的方法更好,因爲你不太可能想要去除處理可空類型的能力,因爲它會破壞你的服務:
public sealed class NullableWebServiceHostFactory : ServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
return new NullableWebServiceHost(serviceType, baseAddresses);
}
}
更改您的Service.svc的標記文件到以下幾點:
<%@ ServiceHost Service="MyNamespace..Service1" CodeBehind="Service1.svc.cs" Factory="MyNamespace.NullableWebServiceHostFactory" %>
現在你可以使用你的服務接口可空類型沒有任何問題,只要通過省略參數或將其設置爲空字符串。以下資源可能更多的援助,以你:
希望這有助於!
上面的代碼引用中存在一個錯誤,它使得QueryStringConverter派生類在框架4中不可用。請確保在嘗試此操作之前查看錯誤。在發現它在實踐中不起作用之前,我浪費了很多時間。 – Jim 2011-05-27 10:55:41