我的wcf网络服务使用webhttpbinding(msdn)来公开REST界面。有些方法接受枚举作为参数; e.g:
[ServiceContract]
public partial interface IStrangeEnumDemo
{
[OperationContract]
[WebGet(UriTemplate = "DefaultEnumName?q={val}")]
string DefaultEnumName(DefaultNumberEnum val);
}
DefaultNumberEnum
:
// Note values in this Enum are not annotated with [System.RunTime.Serialization.EnumMember] or [System.Runtim.Serialization.DataContract], both are not needed
public enum DefaultNumberEnum
{
APPLE,
PEAR,
BANANA
}
该操作的实现是:
public partial class StrangeEnumDemo : IStrangeEnumDemo
{
public string DefaultEnumName(DefaultNumberEnum val)
{
return $"Fruit: {val.ToString()}";
}
}
根据MSDN documentation of QueryStringConverter
,Ohad Schneider's answer至Can I pass non-string to WCF RESTful service using UriTemplate?和Carlos Figueira's MSDN blog,QueryStringConverter
应将枚举名称转换为其值。< / p>
通过以下方式调用网络服务:
http://localhost:16772/StrangeEnumDemo.svc/DefaultEnumName?q=PEAR
按预期产生响应 1 :
“水果:梨子”
我想用作参数的另一个枚举由byte
支持; e.g:
public enum ByteEnum: byte
{
ALIGATOR,
BEAR,
ZEBRA
}
操作声明和实现几乎与DefaultNumber
enum:
[ServiceContract]
public partial interface IStrangeEnumDemo
{
[OperationContract]
[WebGet(UriTemplate = "ByteEnumName?q={val}")]
string ByteEnumName(ByteEnum val);
}
和
public partial class StrangeEnumDemo : IStrangeEnumDemo
{
public string ByteEnumName(ByteEnum val)
{
return $"Animal: {val.ToString()}";
}
}
然而,在致电时:
http://localhost:16772/StrangeEnumDemo.svc/ByteEnumName?q=BEAR
我收到:
<Fault xmlns="http://schemas.microsoft.com/ws/2005/05/envelope/none">
<Code>
<Value>Receiver</Value>
<Subcode>
<Value xmlns:a="http://schemas.microsoft.com/net/2005/12/windowscommunicationfoundation/dispatcher">a:InternalServiceFault</Value>
</Subcode>
</Code>
<Reason>
<Text xml:lang="nl-NL">Input string was not in a correct format.</Text>
</Reason>
<Detail>
<ExceptionDetail xmlns="http://schemas.datacontract.org/2004/07/System.ServiceModel" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<HelpLink i:nil="true"/>
<InnerException i:nil="true"/>
<Message>Input string was not in a correct format.</Message>
<StackTrace> at System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal)
at System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info)
at System.Byte.Parse(String s, NumberStyles style, NumberFormatInfo info)
at System.ServiceModel.Dispatcher.QueryStringConverter.ConvertStringToValue(String parameter, Type parameterType)
at System.ServiceModel.Dispatcher.UriTemplateDispatchFormatter.DeserializeRequest(Message message, Object[] parameters)
at System.ServiceModel.Dispatcher.DispatchOperationRuntime.DeserializeInputs(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)</StackTrace>
<Type>System.FormatException</Type>
</ExceptionDetail>
</Detail>
</Fault>
为了完整性,这是我的service.svc:
<%@ ServiceHost Language="C#" Debug="true" Service="StrangeEnumBehavior.StrangeEnumDemo" CodeBehind="StrangeEnumDemo.svc.cs" %>
这是我的web.config:
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true"/>
</appSettings>
<!--
For a description of web.config changes see http://go.microsoft.com/fwlink/?LinkId=235367.
The following attributes can be set on the <httpRuntime> tag.
<system.Web>
<httpRuntime targetFramework="4.7" />
</system.Web>
-->
<system.web>
<compilation debug="true" targetFramework="4.7"/>
<httpRuntime targetFramework="4.7"/>
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior>
<webHttp automaticFormatSelectionEnabled="true" faultExceptionEnabled="true"/>
</behavior>
</endpointBehaviors>
</behaviors>
<protocolMapping>
<add binding="webHttpBinding" scheme="http"/>
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="false" multipleSiteBindingsEnabled="false"/>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<!--
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
是否有办法让QueryStringConverter
解析字节枚举值的名称与使用隐式后备存储解析枚举的方法相同?
我提出的解决方案是使用具有隐式后备存储的不同枚举,并使用数据合同并手动转换(或使用data contract surrogate进行自动转换);但我宁愿不复制枚举。
原始枚举必须存储为一个字节。
1 我使用标头Accept: application/json
让服务返回JSON数据。