使用WCF使用REST服务 - 可选的查询字符串参数?

时间:2012-05-10 18:35:43

标签: c# .net wcf

我在尝试使用WCF使用简单服务时遇到问题。到目前为止,除了实现可选的查询字符串参数之外,一切都进展顺利。界面看起来有点像这样:

[ServiceContract]
[XmlSerializerFormat]
public interface IApi
{
    [OperationContract]
    [WebGet(UriTemplate = "/url/{param}?top={top}&first={first}")]
    object GetStuff(string param, int top, DateTime first);
}

然后通过创建继承ClientBase<IApi>的类来消耗它。我尝试了几种方法使参数可选:

1)使参数可以为空

这不起作用。我收到来自QueryStringConverter的消息,就像另一个问题:Can a WCF service contract have a nullable input parameter?

2)网址末尾的一个参数

因此,我考虑将UriTemplate更改为更通用,构建查询字符串并将其作为参数传递。这似乎也不起作用,因为传入的值被编码,使得它不被服务器识别为查询字符串。

示例:

[WebGet(UriTemplate = "/url/{query}")]

3)Hackish Solution

到目前为止我发现的唯一方法就是将所有参数更改为字符串,这里似乎允许使用NULL。

示例:

[WebGet(UriTemplate = "/url/{param}?top={top}&first={first}")]
object GetStuff(string param, string top, string first);

此接口的使用仍接受正确的变量类型,但使用ToString。这些查询字符串参数仍然出现在实际请求中。

那么,当使用WCF 消费 REST服务时,有没有办法使查询字符串参数可选?

更新 - 修复方法

采取了建立服务行为的建议。这继承自WebHttpBehaviour。它看起来如下:

public class Api : ClientBase<IApi>
{
    public Api() : base("Binding")
    {
        Endpoint.Behaviors.Add(new NullableWebHttpBehavior());
    }
}

可以在以下Stackoverflow问题中找到NullableWebHttpBehaviorCan a WCF service contract have a nullable input parameter?。唯一的问题是,ConvertValueToString没有超载,所以我快速地掀起了一个:

    public override string ConvertValueToString(object parameter, Type parameterType)
    {
        var underlyingType = Nullable.GetUnderlyingType(parameterType);

        // Handle nullable types
        if (underlyingType != null)
        {
            var asString = parameter.ToString();

            if (string.IsNullOrEmpty(asString))
            {
                return null;
            }

            return base.ConvertValueToString(parameter, underlyingType);
        }

        return base.ConvertValueToString(parameter, parameterType);
    }

这可能不完美,但似乎按预期工作。

2 个答案:

答案 0 :(得分:1)

您的选项1)可以用于WCF客户端,因为WebHttpBehavior可以应用于ClientBase(或ChannelFactory)派生类,如此SO question & answer.所示。只需合并您在1中引用的代码使用捕获500响应问题中显示的配置,它显示工作。

答案 1 :(得分:0)

您是否尝试过使用可空类型?

object GetStuff(string param, int? top, DateTime? first);