通过Enum&使用UriTemplate自定义WCF RESTful服务的类

时间:2015-07-02 12:29:14

标签: c# web-services wcf rest enums

我使用以下[WebGet(UriTemplate = "/foo?id={Id}&flags={flags}&filter={filter}", ResponseFormat = WebMessageFormat.Xml, BodyStyle = WebMessageBodyStyle.Wrapped)] [OperationContract] DataTable GetFoo(string id, FlaggedEnum flags, SomeClass filter = null);

创建了一个WCF服务
FlaggedEnum

DataContract已被标记为[DataContract] [Flags] public enum FlaggedEnum { [EnumMember] Book = 1, [EnumMember] Product = 2, [EnumMember] TenorGroup = 4, [EnumMember] Tenor = 8, [EnumMember] Trade = 16 } 成员

Unit player = Unit("something",100,1);

我已阅读Can I pass non-string to WCF RESTful service using UriTemplate?,但在将枚举移至查询部分后,它仍然无法正常工作。我错过了什么?

错误消息: 合同中的GetFoo操作' IFooProvider'有一个名为' flags'的路径变量。没有类型'字符串'。 UriTemplate路径段的变量必须具有类型'字符串'

对于第3个参数(传递类),是否只能通过使用自定义QueryStringConverter来实现?

1 个答案:

答案 0 :(得分:2)

枚举在查询字符串中工作正常。对于自定义类,是的,您需要使用查询字符串转换器。下面的代码显示了它的一个例子。

如果您在查询字符串中使用枚举时仍然遇到问题,请提供显示问题的Short, Self-Contained, Compilable Example,我们应该可以提供帮助。

public class StackOverflow_31184719
{
    [ServiceContract]
    public interface ITest
    {
        [WebGet(UriTemplate = "/foo?id={Id}&flags={flags}&filter={filter}", ResponseFormat = WebMessageFormat.Xml, BodyStyle = WebMessageBodyStyle.Wrapped)]
        [OperationContract]
        string GetFoo(string id, FlaggedEnum flags, SomeClass filter = null);
    }
    [Flags]
    public enum FlaggedEnum
    {
        [EnumMember]
        Book = 1,
        [EnumMember]
        Product = 2,
        [EnumMember]
        TenorGroup = 4,
        [EnumMember]
        Tenor = 8,
        [EnumMember]
        Trade = 16
    }
    public class SomeClass
    {
        public string SomeProperty { get; set; }
    }
    public class MyWebHttpBehavior : WebHttpBehavior
    {
        protected override QueryStringConverter GetQueryStringConverter(OperationDescription operationDescription)
        {
            return new MyConverter(base.GetQueryStringConverter(operationDescription));
        }

        class MyConverter : QueryStringConverter
        {
            QueryStringConverter inner;
            public MyConverter(QueryStringConverter inner)
            {
                this.inner = inner;
            }

            public override bool CanConvert(Type type)
            {
                return type == typeof(SomeClass) || this.inner.CanConvert(type);
            }

            public override object ConvertStringToValue(string parameter, Type parameterType)
            {
                if (parameterType == typeof(SomeClass))
                {
                    return new SomeClass { SomeProperty = parameter };
                }
                else
                {
                    return base.ConvertStringToValue(parameter, parameterType);
                }
            }
        }
    }
    public class Service : ITest
    {
        public string GetFoo(string id, FlaggedEnum flags, SomeClass filter = null)
        {
            return string.Format("{0} - {1} - {2}", id, flags, filter == null ? "<<NULL>>" : filter.SomeProperty);
        }
    }
    public static void Main()
    {
        string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
        ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
        ServiceEndpoint endpoint = host.AddServiceEndpoint(typeof(ITest), new WebHttpBinding(), "");
        endpoint.Behaviors.Add(new MyWebHttpBehavior());
        host.Open();
        Console.WriteLine("Host opened");

        WebClient c = new WebClient();
        Console.WriteLine(c.DownloadString(baseAddress + "/foo?id=MyId&flags=Book,Product&filter=MyFilter"));

        Console.Write("Press ENTER to close the host");
        Console.ReadLine();
        host.Close();
    }
}