Asp.net web api 为什么HttpClient即使在启动时设置了基址,也不保留基址

Asp.net web api 为什么HttpClient即使在启动时设置了基址,也不保留基址,asp.net-web-api,http-headers,asp.net-core-webapi,dotnet-httpclient,httpclientfactory,Asp.net Web Api,Http Headers,Asp.net Core Webapi,Dotnet Httpclient,Httpclientfactory,在我的.net核心web api项目中,我希望使用一个外部api,以便获得预期的响应 我注册和使用HttpClient的方式如下。在启动中,我将添加以下代码,称为命名类型化httpclient way services.AddHttpClient(c=>{ c、 BaseAddress=新Uri(“https://sooome-api-endpoint.com"); c、 DefaultRequestHeaders.Add(“x-raay-key”,“1235678907545645ggg”);

在我的.net核心web api项目中,我希望使用一个外部api,以便获得预期的响应

我注册和使用HttpClient的方式如下。在启动中,我将添加以下代码,称为命名类型化httpclient way

services.AddHttpClient(c=>{
c、 BaseAddress=新Uri(“https://sooome-api-endpoint.com");
c、 DefaultRequestHeaders.Add(“x-raay-key”,“1235678907545645ggg”);
c、 DefaultRequestHeaders.Add(“x-raay-host”、“sooomeapi endpoint.com”);
});
除此之外,我还有一个服务,我在其中注入了HttpClient


公共类配方服务:IRecipeService
{
私有只读HttpClientu HttpClient;
公共配方服务(HttpClient HttpClient)
{
_httpClient=httpClient;
}
公共异步任务GetReBasedOnIngAsync(字符串端点)
{
使用(var response=await_httpClient.GetAsync(recipeEndpoint))
{
// ...
}
}
}
创建httpClient时,如果我将鼠标悬停在对象本身上,基本URI/头就会丢失,我不明白为什么会发生这种情况。如果有人能给我点灯,我将不胜感激:)

第一次更新

该服务正在下面显示的一个控制器中使用。服务由DI注入,然后解析到服务的相对路径(我假设我已经在客户机中存储了基本URL),也许我做错了


名称空间ABC.Controllers
{
[ApiController]
[路线(“[控制器]”)]
公共类FridgeingCreditEntController:ControllerBase
{
私有只读IRecipeService(配方服务);
专用只读IMapper\u映射器;
公共冰箱用户控制器(IRecipeService recipeService、IMapper映射器)
{
_配方服务=配方服务;
_映射器=映射器;
}
[HttpPost(“MyComponents”)]
公共异步任务过帐要素(IngCreditsTo IngCreditsTo)
{
var readyUrIngredientStr=string.Join(“%2”,ingredientsDto.components);
var urlenpoint=$“recipes/FindByingCreditions?Components={ReadyUrringCreditEntStr}”;
var recipesResponse=wait _recipeService.GetRecipeBasedOnIngredientsAsync(urlEndpoint);
InMyFridgereCippesdto Recipes FoundList=新建InMyFridgereCippesdto
{
FoundRecipes=配方响应
};
返回Ok(配方列表);
}
}
}

有什么建议吗?

您将客户端配置为类型化客户端,而不是命名客户端。不需要工厂

您应该在构造函数中显式地注入http客户机,而不是http客户机工厂

将代码更改为:

private readonly HttpClient _httpClient;

public ReService(HttpClient httpClient;) {
    _httpClient = httpClient;
}

public async Task<List<Core.Dtos.Re>> GetReBasedOnIngAsync(string endpoint)
{

    ///Remove this from your code
    var client = _httpClientFactory.CreateClient(); <--- HERE the base URL/Headers are missing
    
    var request = new HttpRequestMessage
    {
        Method = HttpMethod.Get,
        RequestUri = new Uri(endpoint)
    };
    //////

    using (var response = await _httpClient.GetAsync(endpoint))
    {
        // ...
    }
}
private readonly HttpClient\u HttpClient;
公共储备(HttpClient;HttpClient;){
_httpClient=httpClient;
}
公共异步任务GetReBasedOnIngAsync(字符串端点)
{
///从代码中删除此项
var client=_httpClientFactory.CreateClient(){
c、 BaseAddress=新Uri(“https://sooome-api-endpoint.com/");
});

如果问题仍然存在,我建议您尝试命名http客户机。

好的,我将回答我的帖子,因为使用建议的键入方式会导致httpClient内未设置值的问题,例如BaseAddress始终为空

在初创阶段,我尝试使用类型化的httpclient,例如

services.AddHttpClient(c=>。。。
但是我没有这样做,而是选择了与命名客户机一起使用的

services.AddHttpClient(“recipeService”,c=>{
....
然后在服务本身中,我使用了HttpClientFactory,如下所示

专用只读IHttpClientFactory\u httpClientFactory;
公共配方服务(IHttpClientFactory httpClientFactory)
{
_httpClientFactory=httpClientFactory;
}
公共异步任务GetRecipeBasedOnIngredientsAsync(字符串recipeEndpoint)
{
var client=_httpClientFactory.CreateClient(“recipeService”);
使用(var response=await client.GetAsync(client.BaseAddress+recipeEndpoint))
{
response.EnsureSuccessStatusCode();
var responseRecipies=await response.Content.ReadAsStringAsync();
var recipeObj=ConvertResponseToObjectList(响应原则);
返回recipeObj??空;
}
}

发生这种情况的一个简单而令人沮丧的原因是您的服务收集分配顺序

在HTTPClient之后分配从属服务将不起作用,必须在以下时间之前分配:

// NOT WORKING - BaseAddress is null
services.AddTransient<Controller1>();
services.AddTransient<Controller2>();

services.AddHttpClient<HttpService>(client =>
{
    client.BaseAddress = new Uri(baseAdress);
});

services.AddTransient<HttpService>();


// WORKING - BaseAddress is not null
services.AddTransient<Controller1>();
services.AddTransient<Controller2>();
services.AddTransient<HttpService>();

services.AddHttpClient<HttpService>(client =>
{
    client.BaseAddress = new Uri(baseAdress);
});
//不工作-基地址为空
services.AddTransient();
services.AddTransient();
services.AddHttpClient(客户端=>
{
client.BaseAddress=新Uri(BaseAddress);
});
services.AddTransient();
//工作-基址不为空
services.AddTransient();
services.AddTransient();
services.AddTransient();
services.AddHttpClient(客户端=>
{
client.BaseAddress=新Uri(BaseAddress);
});

我完全按照你说的做了,但它仍然不起作用。但是,我有一个问题,我最好还是使用httpclient的工厂?@CsibiNorbert你说它不起作用是什么意思?错误是什么?对不起,我的意思是,即使我调试,httpclient或标头中也没有基址。错误如下
 无效的URI:无法确定URI的格式。
因为in-baseAddress=null。这有意义吗?Microsoft在类型化客户端方面存在问题,并且不断更改所有内容。请查看最后一章
services.AddHttpClient<IReService, ReService>(c => {
                c.BaseAddress = new Uri("https://sooome-api-endpoint.com/");
                 });
// NOT WORKING - BaseAddress is null
services.AddTransient<Controller1>();
services.AddTransient<Controller2>();

services.AddHttpClient<HttpService>(client =>
{
    client.BaseAddress = new Uri(baseAdress);
});

services.AddTransient<HttpService>();


// WORKING - BaseAddress is not null
services.AddTransient<Controller1>();
services.AddTransient<Controller2>();
services.AddTransient<HttpService>();

services.AddHttpClient<HttpService>(client =>
{
    client.BaseAddress = new Uri(baseAdress);
});