如何为代理控制器设置 Web API 路由? [英] How to set up Web API Routing for a Proxy Controller?

查看:21
本文介绍了如何为代理控制器设置 Web API 路由?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的应用程序的一部分需要充当第三方 RESTful Web 服务的代理服务器.有没有办法设置 Web API 路由,让所有相同类型的请求都转到相同的方法?

Part of my application needs to act as a Proxy Server for a third party RESTful web service. Is there a way to set up Web API routing so that all requests of the same type will go to the same method?

例如,如果客户端发送这些 GET 请求中的任何一个,我希望它们进入单个 GET 操作方法,然后将请求发送到下游服务器.

For example, if the client sends in either of these GET requests I want them to go into a single GET action method that then sends on the request to the downstream server.

api/Proxy/Customers/10045
api/Proxy/Customers/10045/orders
api/Proxy/Customers?lastname=smith

GET 的单一操作方法会选择这三个请求中的任何一个并将它们发送到相应的服务(我知道如何使用 HttpClient 来有效地实现这一点):

The single action method for GET would pick up any one of these three requests and send them on to the respective service (I know how to work with HttpClient to make that happen effectively):

http://otherwebservice.com/Customers/10045
http://otherwebservice.com/Customers/10045/orders
http://otherwebservice.com/Customers?lastname=smith

我不想将我的 Web 服务与第三方 Web 服务紧密耦合,并将它们的整个 API 作为方法调用复制到我的内部.

I don't want to have to tightly couple my web service to the third party web service and replicate their entire API as method calls inside mine.

我想到的一种解决方法是在客户端用 JavaScript 简单地对目标 URL 进行编码,然后将其传递到 Web API 中,然后 Web API 只会看到一个参数.它会起作用,但如果可能的话,我更愿意使用 Web API 中的路由功能.

One workaround that I have thought of is to simply encode the target URL in JavaScript on the client and pass this into the Web API which will then only see one parameter. It would work, but I'd prefer to use the routing capabilities in Web API if possible.

推荐答案

这是我如何让它工作的.首先,为您要支持的每个动词创建一个带有方法的控制器:

Here's how I got this to work. First, create a controller with a method for each verb you want to support:

public class ProxyController : ApiController
{
    private Uri _baseUri = new Uri("http://otherwebservice.com");

    public async Task<HttpResponseMessage> Get(string url)
    {
    }

    public async Task<HttpResponseMessage> Post(string url)
    {
    }

    public async Task<HttpResponseMessage> Put(string url)
    {
    }

    public async Task<HttpResponseMessage> Delete(string url)
    {
    }
}

这些方法是异步的,因为它们将使用 HttpClient.像这样映射您的路线:

The methods are async because they're going to use an HttpClient. Map your route like this:

config.Routes.MapHttpRoute(
  name: "Proxy",
  routeTemplate: "api/Proxy/{*url}",
  defaults: new { controller = "Proxy" });

现在回到控制器中的 Get 方法.创建一个 HttpClient 对象,使用适当的 Url 创建一个新的 HttpRequestMessage 对象,从原始请求消息中复制所有(或几乎所有),然后调用 SendAsync():

Now back to the Get method in the controller. Create an HttpClient object, create a new HttpRequestMessage object with the appropriate Url, copy everything (or almost everything) from the original request message, then call SendAsync():

public async Task<HttpResponseMessage> Get(string url)
{
    using (var httpClient = new HttpClient())         
    {
        string absoluteUrl = _baseUri.ToString() + "/" + url + Request.RequestUri.Query;
        var proxyRequest = new HttpRequestMessage(Request.Method, absoluteUrl);
        foreach (var header in Request.Headers)
        {
            proxyRequest.Headers.Add(header.Key, header.Value);
        }

        return await httpClient.SendAsync(proxyRequest, HttpCompletionOption.ResponseContentRead);
    }
}

结合 的 URL 可能更复杂,但这是基本思想.对于 Post 和 Put 方法,您还需要复制请求正文

The URL combining could be more sophisticated, but that's the basic idea. For the Post and Put methods, you'll also need to copy the request body

另外请注意在SendAsync调用中传递的HttpCompletionOption.ResponseContentRead参数,因为如果没有它,如果内容是大(就我而言,它将 500KB 100 毫秒的请求更改为 60 秒的请求).

Also please note a HttpCompletionOption.ResponseContentRead parameter passed in SendAsync call, because without it, ASP.NET will spend an exremeley long time reading the content if the content is large (in my case, it changed a 500KB 100ms request into a 60s request).

这篇关于如何为代理控制器设置 Web API 路由?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆