gpt4 book ai didi

c# - 在没有启动的情况下在旧的 ASP.NET MVC 应用程序中创建 HttpClient

转载 作者:太空狗 更新时间:2023-10-29 21:37:35 25 4
gpt4 key购买 nike

我有一个旧版本的 ASP.NET MVC 应用程序,它没有 Startup.cs。我想实现一种干净的方法来拥有一个 HttpClient,我将使用它来调用第三方的 API。

到目前为止,这是我根据针对此问题收到的一些想法/建议所做的工作。问题是,当我进行 API 调用时,它无处可去。我把它放在 try catch 中,但我什至没有得到异常。 API 提供商告诉我他们没有看到搜索参数。

首先,我创建了这个 HttpClientAccessor 用于延迟加载。

public static class HttpClientAccessor
{
public static Func<HttpClient> ValueFactory = () =>
{
var client = new HttpClient();

client.BaseAddress = new Uri("https://apiUrl.com");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.TryAddWithoutValidation("APIAccessToken", "token1");
client.DefaultRequestHeaders.TryAddWithoutValidation("UserToken", "token2");

return client;
};

private static Lazy<HttpClient> client = new Lazy<HttpClient>(ValueFactory);

public static HttpClient HttpClient
{
get { return client.Value; }
}
}

然后我创建了自己的 API 客户端,这样我就可以在一个地方调用 API 函数,如下所示:

public class MyApiClient
{

public async Task GetSomeData()
{
var client = HttpClientAccessor.HttpClient;
try
{
var result = await client.GetStringAsync("somedata/search?text=test");
var output = JObject.Parse(result);
}
catch(Exception e)
{
var error = e.Message;
}
}
}

然后在我的 ASP.NET Controller 操作中,我这样做:

public class MyController : Controller
{
private static readonly MyApiClient _apiClient = new MyApiClient ();

public ActionResult ApiTest()
{
var data = _apiClient.GetSomeData().Wait();
}
}

知道我的错误在哪里吗?

更新:这种简单的方法效果很好:

public class MyController : Controller
{
private static readonly HttpClient _client = new HttpClient();

public ActionResult ApiTest()
{
_client.BaseAddress = new Uri("https://apiUrl.com");
_client.DefaultRequestHeaders.Accept.Clear();
_client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
_client.DefaultRequestHeaders.TryAddWithoutValidation("APIAccessToken", "token1");
_client.DefaultRequestHeaders.TryAddWithoutValidation("UserToken", "token2");

var response = _client.GetStringAsync("somedata/search?text=test").Result;
}
}

最佳答案

如前所述,没有使用依赖注入(inject),因此从技术上讲,不需要在这些东西已经初始化的地方使用组合根。

如果不需要在启动时实际初始化客户端,您可以考虑使用惰性单例方法。

一个例子

public static class HttpClientAccessor {
public static Func<HttpClient> ValueFactory = () => {
var client = new HttpClient();

client.BaseAddress = new Uri("https://apiUrl.com");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.TryAddWithoutValidation("APIAccessToken", "token1");
client.DefaultRequestHeaders.TryAddWithoutValidation("UserToken", "token2");

return client;
};

private static Lazy<HttpClient> client = new Lazy<HttpClient>(ValueFactory);

public static HttpClient HttpClient {
get { return client.Value; }
}
}

Lazy<HttpClient>的工厂代表如果客户端需要额外的设置,可以变得更复杂。

在需要客户的地方调用服务

var client = HttpClientAccessor.HttpClient;

var response = await client.GetStringAsync("{url}");

客户端将在第一次使用时初始化,您将在后续调用该实例时获得相同的实例。

如在您的 Controller 中使用的那样,您将异步调用与阻塞调用行混合在一起 .Wait().Result .这可能会导致死锁,应该避免。

public class MyController : Controller {
private static readonly MyApiClient _apiClient = new MyApiClient ();

public async Task<ActionResult> ApiTest() {
var data = await _apiClient.GetSomeData();

//...
}
}

代码应该始终是异步的。

引用 Async/Await - Best Practices in Asynchronous Programming

关于c# - 在没有启动的情况下在旧的 ASP.NET MVC 应用程序中创建 HttpClient,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49621741/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com