Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Web Api 2具有多个参数的通用传递方法_C#_.net_Asp.net Web Api - Fatal编程技术网

C# Web Api 2具有多个参数的通用传递方法

C# Web Api 2具有多个参数的通用传递方法,c#,.net,asp.net-web-api,C#,.net,Asp.net Web Api,我正在寻找一种在WebAPI2中生成一组通用方法的方法,可以与http客户机一起使用,以连接到另一台服务器 首先,解释一下我的基础设施。我公司通常采用的简化设置(省略数据库服务器和其他内容)由两个主服务器组成。有一个用于托管应用程序和站点的web层服务器,还有一个包含服务/API等的应用层服务器 内部规则规定,坐在web服务器上的应用程序如果不首先通过代理或代理服务,就不能直接与应用服务器上的任何东西进行对话 我目前对此问题的解决方案是创建一个SDK web api服务,其中包含api中所有路由

我正在寻找一种在WebAPI2中生成一组通用方法的方法,可以与http客户机一起使用,以连接到另一台服务器

首先,解释一下我的基础设施。我公司通常采用的简化设置(省略数据库服务器和其他内容)由两个主服务器组成。有一个用于托管应用程序和站点的web层服务器,还有一个包含服务/API等的应用层服务器

内部规则规定,坐在web服务器上的应用程序如果不首先通过代理或代理服务,就不能直接与应用服务器上的任何东西进行对话

我目前对此问题的解决方案是创建一个SDK web api服务,其中包含api中所有路由的副本。应用程序(在本例中为angular应用程序)通过REST api调用调用此SDK服务,此中间服务的任务是使用.NET HttpClient将此调用转换为对另一台服务器上运行的“实际”api服务的调用

这很好用,到目前为止我还没有遇到任何问题,但我觉得可能有更好的方法来做这类事情。我曾在网上搜索过描述这类事情的文章,但结果很短,而且我绝对不是使用.NET或web api的专家

我将给出一个刚才解决方案的示例—调用以获取当前存储在我的数据库中的所有客户端

public class ClientsController: ApiController
{
    // http client used to translate calls to api service
    private HttpClient httpClient = new HttpClient()
    {
        BaseAddress = new Uri(ConfigurationManager.AppSettings["apiUrl"])
    };

    [Route("clients")]
    [HttpGet]
    public IHttpActionResult GetClients()
    {
        httpClient.DefaultRequestHeaders.Accept.Clear();
        httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json");

        List<Client> clients = null;

        try
        {
            HttpResponseMessage result = httpClient.GetAsync("clients").Result;

            if (result.IsSuccessStatusCode)
            {
                clients = result.Content.ReadAsAsync<List<Client>>().Result;
                return Content(result.StatusCode, clients);
            }

            // return the failed reason code
            return Content(result.StatusCode, result.ReasonPhrase);
        }
        catch (Exception e)
        {
            return Content(HttpStatusCode.InternalServerError, e.Message);
        }
    }
}
公共类客户端控制器:ApiController
{
//用于将调用转换为api服务的http客户端
私有HttpClient HttpClient=新HttpClient()
{
BaseAddress=新Uri(ConfigurationManager.AppSettings[“apiUrl”])
};
[路线(“客户”)]
[HttpGet]
公共IHttpActionResult GetClient()
{
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(新的MediaTypeWithQualityHeaderValue(“应用程序/json”);
列表客户端=null;
尝试
{
HttpResponseMessage结果=httpClient.GetAsync(“客户端”).result;
if(结果。IsSuccessStatusCode)
{
clients=result.Content.ReadAsAsync().result;
返回内容(result.StatusCode、客户端);
}
//返回失败的原因代码
返回内容(result.StatusCode、result.ReasonPhrase);
}
捕获(例外e)
{
返回内容(HttpStatusCode.InternalServerError,e.Message);
}
}
}
然后在另一台服务器上运行的my api服务中实现此路由,并从数据库检索客户端,将客户端列表返回到此服务,然后返回到要在屏幕上显示的我的应用程序

api中的每个路由都有一对方法(如上所示的方法加上实际实现)

理想情况下,我希望我的sdk服务为每个HTTP谓词包含一个方法,其中它采用传递给它的路由,从api服务调用该路由,并处理返回给它的项或结果代码,类似于它现在所做的,只是我能够向api添加一组新的端点,而不必在两个端点中添加它们地方

这就是我被困的地方。任何关于如何做到这一点或任何我可能没有探索过的替代方案的见解都将是非常棒的


感谢您花时间阅读这个长问题。

您可以使用ASP.NET模块(实现IHttpModule)。这样您就可以随意阅读和更改请求/响应

给你一个想法:几年前,我写了一个模块,将收到的请求广播给多个侦听器。其中一个侦听器将处理响应(或者如果没有定义,模块将以200 OK响应)。接收到的url参数或对象很容易传递给侦听器

处理非常简单。将请求传递给所有侦听器,但忽略响应(激发并忘记),处理程序除外(如果已定义)。收到响应后,将其作为模块的响应传递。如果需要很长时间,您将自动获得超时

在配置中,我描述了所有已接受的路由(因此所有谓词只需一个方法),这些路由映射到(多个)其他路由,包括协议、谓词以及侦听器是否应处理响应。这意味着您甚至可以将https POST转换为http GET+url参数

有一点值得关注的是安全性。仅传递接收到的任何内容可能不安全。此外,我不会将代理连接到数据库。在发送之前,您可以进行一些检查和清理

请注意,您可能还需要发送头。例如,如果发送了令牌

我希望这能给你一个想法。互联网上有足够的信息,但这里有一些链接:


对这个问题的回答很晚,但我因为一些更紧急的事情被取消了项目,我回来完成了这个项目-设法找到了一个对我有效的解决方案-所以我想我会把它贴在这里,以防它对其他人有帮助

在我的设置中-我的传递服务以“SDK”的名义提供,我完全控制SDK和我将称之为“API”的其他服务之间的端点

public class SdkController : ApiController
{

    private HttpClient httpClient = new HttpClient()
    {
        BaseAddress = new Uri(ConfigurationManager.AppSettings["apiUrl"])
    };

    [HttpGet, HttpPost, HttpPut, HttpDelete, Route("v2/{*url}")]
    public HttpResponseMessage PerformRequest(string url)
    {
        httpClient.DefaultRequestHeaders.Accept.Clear();
        httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

        try
        {
            HttpResponseMessage response = null;
            HttpContent requestBody = null;
            string requestUrl = Request.RequestUri.LocalPath.Replace("/SDK/v2/", "");
            string requestMethod = Request.Method.ToString();

            switch (requestMethod)
            {
                case "GET":
                    response = httpClient.GetAsync(requestUrl).Result;
                    break;
                case "POST":
                    requestBody = Request.Content;
                    response = httpClient.PostAsync(requestUrl, requestBody).Result;
                    break;
                case "PUT":
                    requestBody = Request.Content;
                    response = httpClient.PutAsync(requestUrl, requestBody).Result;
                    break;
                case "DELETE":
                    response = httpClient.DeleteAsync(requestUrl).Result;
                    break;
            }

            return response;
        }
        catch
        {
            return new HttpResponseMessage()
            {
                StatusCode = HttpStatusCode.InternalServerError,
                ReasonPhrase = "Internal Server Error"
            };
        }
    }

}
我之所以能够做到这一点,是因为我对SDK的所有端点请求都有一个通用的“v2/”前缀,而且我不必在这个传递方法中关心请求将去哪里,请求返回或发送什么——因为处理这一问题的所有逻辑都位于更庞大的API服务中


这里不太好的地方是我的错误处理——尽管我将对其进行修复,以便更准确地预测可能从API返回的任何错误。

因此,简单地说,您有两个Web API服务器,其中一个是真正的服务器,另一个是更严格的中介