RESTful Web Service - 在何处以及如何使用其他元数据返回错误?

时间:2011-12-14 00:15:00

标签: .net wcf rest

这个问题说明了一切。我正在处理一个复杂的RESTful Web服务,并且我希望返回的响应包含的信息不仅仅是400-something或500-something。我需要添加请求失败的原因。

如何使用WCF 4.0实现此目的?

谢谢!

2 个答案:

答案 0 :(得分:1)

典型的方法是返回一个特定代码以及一个响应正文,其中包含更详细地描述错误的人类可读信息。

WCF中的一种技术是抛出this form of WebFaultException,它允许您指定响应主体详细信息和状态代码作为构造函数参数。

答案 1 :(得分:0)

我的方法是尽量保持简单。您并不总是保证客户端将知道如何处理HTTP错误代码,因此我尝试保持始终确保我的服务返回200的承诺。确保客户端能够知道发生的坏事我将元数据注入到我们的所有服务响应中。考虑以下结构:

[DataContract(Namespace = Constants.DataContractNamespace)]
public class ResponseMetadata : IExtensibleDataObject
{
    [DataMember(Order = 1, Name = "HasError", IsRequired = true, EmitDefaultValue = true)]
    public bool HasError { get; set; }

    [DataMember(Order = 2, Name = "ServiceMessage", IsRequired = true, EmitDefaultValue = true)]
    public string ServiceMessage { get; set; }

    [DataMember(Order = 3, Name = "IdentityContext", IsRequired = true, EmitDefaultValue = true)]
    public IdentityContext IdentityContext { get; set; }

    [DataMember(Order = 4, Name = "Environment", IsRequired = true, EmitDefaultValue = true)]
    public string Environment { get; set; }

    [DataMember(Order = 5, Name = "Host", IsRequired = true, EmitDefaultValue = true)]
    public string Host { get; set; }

    [DataMember(Order = 6, Name = "Pulse", IsRequired = true, EmitDefaultValue = true)]
    public string Pulse { get; set; }

    public virtual ExtensionDataObject ExtensionData { get; set; }
}

我们所有的服务repsonse类型都包含ResponseMetadata:

[DataContract(Namespace = Constants.DataContractNamespace)]
public class EchoResponse
{     
    public EchoResponse(ResponseMetadata meta, string echo)
    {
        Metadata = meta;
        EchoText = echo;
    }

    [DataMember(Order = 1)]
    public ResponseMetadata Metadata { get; set; }

    [DataMember(Order = 2)]
    public string EchoText { get; set; }
}

现在在服务实现中:

public EchoResponse GetEcho(string echo)
{
    try
    {
        // Implement your service operation

        var res = string.Empty;
        var response = new EchoResponse(new ResponseMetadata(false, string.Empty, Pulse), res);

        return response;
    }
    catch (WebException ex)
    {
        var err = StringHelper.FormatException(MethodBase.GetCurrentMethod(), ex, Pulse, true, ex.Status.ToString());
        Log.Error(err, ex);

        return new EchoResponse(new ResponseMetadata(true, err, Pulse), null);
    }
    catch (ArgumentOutOfRangeException ex)
    {
        var err = StringHelper.FormatException(MethodBase.GetCurrentMethod(), ex, Pulse, true);
        Log.Warn(err);

        return new EchoResponse(new ResponseMetadata(true, err, Pulse), null);
    }
    catch (Exception ex)
    {
        var err = StringHelper.FormatException(MethodBase.GetCurrentMethod(), ex, Pulse, true);
        Log.Error(err, ex);

        return new EchoResponse(new ResponseMetadata(true, err, Pulse), null);
    }
}

因为您可以看到这种方法可以保证通过设置HasError标志并将有意义的文本填充到ServiceMessage中来捕获和处理任何错误或异常。

IdentityContext结构用于确保我的服务响应始终报告身份信息,Pulse是一种关联相关操作的方法。我已从示例中删除了日志记录代码。

我们已经为iPad,iPhone,WebSphere和.NET客户端使用这种技术构建了数百种服务。