我正在尝试托管一个可以用作代理/网关的服务,以通用的方式调用各种其他服务。该服务将采用标识要调用的服务的参数以及它简单地传递给“实现”的有效负载字符串。 “网关”负责外部客户端的身份验证,并将用户身份和其他“上下文”信息提供给“实现”。
我希望外部客户端提供无效请求以获取指示错误的错误。但由于“网关”服务不知道请求(或响应)应该是什么样子,因此必须依赖“真实”服务来提供可靠地指示“错误请求”的响应。还需要提供错误消息(人们可读的描述请求的错误)。在某些情况下,“实现”具有自己的授权逻辑,所以类似地它也必须能够指示“未授权”,我认为具有状态403的HttpException可以很好地表示。
所有实现者都将用.net编写为WCF服务。
我认为我可以通过指定服务合同来逃避并让实现抛出HttpException,状态代码为400或403,以便将错误信息提供回“网关” - 没有必要指定错误合同(isn)有一些通用的SOAP错误,这不至少允许错误代码和消息字符串??)。
现在我试图建立一个POC。请求有效并且实现正常返回的“正常”情况可以正常工作。但是当出现问题时,我无法看到任何获取错误信息的方法。
在用于测试一个服务实现的控制台应用程序中:
private string GetResponse(string req)
{
try
{
using (var proxy = new MapperProxy())
{
return proxy.Map(null, req);
}
}
catch (FaultException fe)
{
int status = GetStatus(fe);
switch (status)
{
case 400:
return "400 BAD REQUEST - " + fe.Message;
case 403:
return "403 FORBIDDEN - " + fe.Message;
default:
return "501 INTERNAL SERVER ERROR";
}
}
catch (Exception ex)
{
return "Exception caught: " + ex.ToString();
}
}
假设WCF服务抛出了状态代码为400的HttpException。(服务实现配置为“包含故障中的异常详细信息”。)如何实现GetStatus(FaultException ex)?
答案 0 :(得分:0)
我找到了答案。我可以通过让实现者抛出指示FaultCode和消息的SoapFaultException来使用泛型SOAP错误。我应该设置Action和属性来指示它是客户端还是服务器故障,但是这样做:
服务器端:
public string Map(MapperContext context, string payLoad)
{
string verb = GetFirstWord(payLoad).ToUpper();
switch (verb)
{
case "ECHO":
return payLoad.Substring(verb.Length).TrimStart();
case "COP":
throw new FaultException("Only cops may use this service.", new FaultCode("FORBIDDEN"));
case "BUG":
throw new NullReferenceException();
}
throw new FaultException("Invalid request; first word must be 'ECHO', 'COP' or 'BUG'.", new FaultCode("BAD REQUEST"));
}
private string GetFirstWord(string request)
{
for (int i = 0; i < request.Length; i++)
{
if (char.IsWhiteSpace(request[i]))
{
return request.Substring(0, i);
}
}
return request;
}
修改后的客户端(我的控制台应用程序来测试它):
private string GetResponse(string req)
{
try
{
using (var proxy = new MapperProxy())
{
return proxy.Map(null, req);
}
}
catch (FaultException fe)
{
switch (fe.Code.Name)
{
case "BAD REQUEST":
return "400 BAD REQUEST - " + fe.Message;
case "FORBIDDEN":
return "403 FORBIDDEN - " + fe.Message;
default:
return "501 INTERNAL SERVER ERROR: " + fe.Message;
}
}
catch (Exception ex)
{
return "Exception caught: " + ex.ToString();
}
}
我认为这对我的目的来说已经足够了。