如何在代码中设置WCF错误消息返回格式?

时间:2012-05-07 15:58:06

标签: wcf

我有这样的服务合同:

[WebGet(UriTemplate = "getdata?key={key}&format={format}")]
Event[] GetIncidentsXml(string key, string format);

在代码中,我正在切换响应格式:

var selectedFormat = ParseWebMessageFormat(format);
WebOperationContext.Current.OutgoingResponse.Format = selectedFormat;

(ParseWebMessageFormat是一个包装Enum解析类型的方法)

这部分按预期工作,我得到XML或JSON,具体取决于传递的参数。

它丢失的地方是我抛出异常的时候。如果传入的(API)密钥无效,我这样做:

var exception = new ServiceResponse
{
    State = "fail", 
    ErrorCode = new ErrorDetail { Code = "100", Msg = "Invalid Key" }
};

throw new WebProtocolException(HttpStatusCode.BadRequest, "Invalid Key.", exception, null);

抛出异常时,返回类型始终 XML:

<ServiceResponse xmlns="http://schemas.datacontract.org/2004/07/IBI.ATIS.Web.ServiceExceptions" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <ErrorCode>
        <Code>100</Code>
        <Msg>Invalid Key</Msg>
    </ErrorCode>
    <State>fail</State>
</ServiceResponse>

返回类型更改是服务方法中的第一行代码,因此在抛出异常之前就会发生。

我知道我可以根据请求格式设置WCF返回类型,但是要求使用通过查询字符串传入的类型。

在配置中关闭自动消息类型:

<standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="false" />

1 个答案:

答案 0 :(得分:0)

因为您需要以某种方式指定默认响应格式。您看到的行为是标准的。您需要查看特定标头并确定响应格式应该是什么。然后,您可以实现请求拦截器以确定传出响应格式需要的内容。

因此,要回答您的问题,如果没有提及,则需要坚持使用默认格式类型或返回错误请求。与SOAP不同,REST更像是一种范式。

更新:为了澄清起见。你可以这样做。

[ServiceContract()]
public interface ICustomerService
{
   [OperationContract]
   [WebGet(UriTemplate ="?format={formatType}",BodyStyle = WebMessageBodyStyle.Bare)]
   IResponseMessage GetEmCustomers(string formatType);

}

public class CustomerService : ServiceBase
{
  IResponseMessage GetEmCustomers(string formatType)
  {
    try
    {
      var isValid  = base.validateformatspecification(formatType);// check to see if format is valid and supported
      if(!isValid) return base.RespondWithError(formatType,new Error {Msg= "Dude we dont support this format"});
      var customers = CustomerProvider.GetAll();
      return base.Respond(formatType,customer);// This method will format the customers in desired format,set correct status codes and respond.
    }catch(Exception ex)
    {
      // log stuff and do whatever you want
      return base.RespondWithError(formatType,new Error{Msg = "Aaah man! Sorry something blew up"});// This method will format the customers in desired format,set correct status codes and respond.

    }      
  }    
}

public class ServiceBase
{
  public IResponseMessage Respond<T>(string format,T entity);
  public IResponseMessage RespondWithError<T>(string format, T errorObject);

}

public class Error:IResponseMessage {/*Implementation*/}

public class GetEmCustomerResponseResource:List<Customer>,IResponseMessage {/* Implementation*/}

public class GetEmCustomerErrorResponse: IResponseMessage {/* Implementation   */}