由于WCF路由不支持REST服务的路由,因此我创建了一个REST服务,该服务有一个接受所有传入请求的enpoint,而不是根据查询参数重定向这些请求。
我是按照这篇文章http://blog.tonysneed.com/2012/04/24/roll-your-own-rest-ful-wcf-router/完成的。
此方法适用于传递请求并返回结果。问题是每当我从实际服务中得到错误(如404)时,返回给客户端的消息是400(错误请求)。
我想要的是一个路由代理,实际上只是根据查询将调用重定向到真实服务,并将所有错误返回给客户端,因为它们来自真实服务。
这是否是我尝试完成的正确方法,还是有更简单或更好的解决方案?
任何帮助表示赞赏!
在下面我添加了我的代码的样子 app.config:
<!--
System.net
-->
<system.net>
<settings>
<servicePointManager expect100Continue="false" useNagleAlgorithm="false" />
</settings>
<connectionManagement>
<add address="*" maxconnection="24" />
</connectionManagement>
</system.net>
<!--
System.ServiceModel
-->
<system.serviceModel>
<!--
Services
-->
<services>
<service name="RoutingGateway.RoutingService">
<endpoint address="/api/routing" binding="webHttpBinding" bindingConfiguration="secureWebHttpBinding" contract="RoutingGateway.IRoutingService" behaviorConfiguration="RESTBehaviour" />
</service>
</services>
<client>
<endpoint binding="webHttpBinding" bindingConfiguration="secureWebHttpBinding" contract="RoutingGateway.IRoutingService" name="routingService" behaviorConfiguration="RESTBehaviour" />
</client>
<!--
Bindings
-->
<bindings>
<webHttpBinding>
<binding name="secureWebHttpBinding" hostNameComparisonMode="StrongWildcard" maxReceivedMessageSize="2147483647" transferMode="Streamed">
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
</binding>
</webHttpBinding>
</bindings>
<!--
Behaviors
-->
<behaviors>
<endpointBehaviors>
<behavior name="RESTBehaviour">
<dispatcherSynchronization asynchronousSendEnabled="true" />
<webHttp helpEnabled="true" />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false before deployment -->
<serviceMetadata httpsGetEnabled="false" />
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false" />
<!-- Enable Throttling -->
<serviceThrottling maxConcurrentCalls="100" maxConcurrentInstances="100" maxConcurrentSessions="100" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
IRoutingService.cs:
[ServiceContract(Namespace = "https://test/api/routing")]
public interface IRoutingService
{
[OperationContract(Action = "*", ReplyAction = "*")]
[WebInvoke(UriTemplate = "*", Method = "*")]
Message ProcessRequest(Message requestMessage);
}
RoutingService.cs:
public Message ProcessRequest(Message requestMessage)
{
ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true;
Uri originalRequestUri = WebOperationContext.Current.IncomingRequest.UriTemplateMatch.RequestUri;
// Gets the URI depending on the query parameters
Uri uri = GetUriForRequest(requestMessage);
// Select rest client endpoint
string endpoint = "routingService";
// Create channel factory
var factory = new ChannelFactory<IRoutingService>(endpoint);
Uri requestUri = new Uri(uri, originalRequestUri.PathAndQuery);
factory.Endpoint.Address = new EndpointAddress(requestUri);
requestMessage.Headers.To = requestUri;
// Create client channel
_client = factory.CreateChannel();
// Begin request
Message result = _client.ProcessRequest(requestMessage);
return result;
}
答案 0 :(得分:1)
我最终捕获了所有的CommunicationExceptions,然后使用适当的消息和状态代码重新抛出WebFaultExceptions。
以下是代码:
Message result = null;
try
{
result = _client.ProcessRequest(requestMessage);
}
catch (CommunicationException ex)
{
if (ex.InnerException == null ||
!(ex.InnerException is WebException))
{
throw new WebFaultException<string>("An unknown internal Server Error occurred.",
HttpStatusCode.InternalServerError);
}
else
{
var webException = ex.InnerException as WebException;
var webResponse = webException.Response as HttpWebResponse;
if (webResponse == null)
{
throw new WebFaultException<string>(webException.Message, HttpStatusCode.InternalServerError);
}
else
{
var responseStream = webResponse.GetResponseStream();
string message = string.Empty;
if (responseStream != null)
{
using (StreamReader sr = new StreamReader(responseStream))
{
message = sr.ReadToEnd();
}
throw new WebFaultException<string>(message, webResponse.StatusCode);
}
else
{
throw new WebFaultException<string>(webException.Message, webResponse.StatusCode);
}
}
}
}