标签: dotnet-httpclient

.net HttpClient与自定义JsonConverter

我正在使用.NET的HttpClient向WebAPI发出请求,该WebAPI返回一些需要在客户端进行一些自定义反序列化的JSON数据.为此,我已经制作了自己的JsonConverter,但我无法弄清楚如何让ReadAsAsync<T>方法获得转换器的存在.

我现在通过使用ReadAsStringAsync读取响应,然后将该字符串传递给我来解决我的问题JsonConvert.DeserializeObject,但似乎应该有一个更优雅的解决方案.

这是我的代码:

public PrefsResponse GetAllPrefs(string sid) {
    HttpClient client = CreateHttpClient(null, sid);
    var response = client.GetAsync("api/sites/" + sid).Result;

    // TODO : find a way to hook custom converters to this...
    // return response.Content.ReadAsAsync<PrefsResponse>().Result;

    var stringResult = response.Content.ReadAsStringAsync().Result;

    return JsonConvert.DeserializeObject<PrefsResponse>(stringResult, new PrefClassJsonConverter());
}
Run Code Online (Sandbox Code Playgroud)

这是我能做的最好的,还是有更优雅的方式?

这里也是我创建HttpClient的地方,如果那是我需要连接它的地方:

        private HttpClient CreateHttpClient(CommandContext ctx, string sid) {
        var cookies = new CookieContainer();

        var handler = new HttpClientHandler {
            CookieContainer = cookies,
            UseCookies = true,
            UseDefaultCredentials = false …
Run Code Online (Sandbox Code Playgroud)

.net json asp.net-web-api dotnet-httpclient

15
推荐指数
1
解决办法
9983
查看次数

HttpClient和ReadAsAsync <T>()扩展方法

所以我正在启动一个新的.Net 4.0项目,并将使用公共API进行一些工作.我打算使用Microsoft HttpClient类,所以我安装了最新的稳定版Microsoft.Net.Http NuGet包(版本2.2.13).我正在看一些同事放在一起的POC代码,也使用HttpClient的NuGet包,并注意到这样的代码:

HttpClient client = new HttpClient();
HttpResponseMessage response = client.GetAync("/uri").Result;

DomainType result = response.Content.ReadAsAsync<DomainType>().Result;
Run Code Online (Sandbox Code Playgroud)

在我的项目中,在添加对Microsoft.Net.Http包的引用之后,当我尝试编写类似的代码时,我注意到HttpResponseMessage没有ReadAsAsync<T>()方法.在对我的同事的POC解决方案进行一些挖掘后,看起来ReadAsAsync<T>()它实际上是System.Net.Http.Formatting装配中的扩展方法.在这个POC解决方案中,有一个对System.Net.Http.Formatting的引用,但它从路径中提取此文件C:\Program Files (x86)\Microsoft ASP.NET\ASP.NET MVC 4\Assemblies\System.Net.Http.Formatting.dll.

我的问题是,是否有更好的解决方案来访问此扩展方法,而不是从我的本地ASP.Net安装引用此程序集?我担心这会导致我们的CI服务器出现问题,因为它不太可能安装ASP.Net.我想我可以将System.Net.Http.Formatting复制到我的解决方案中的Lib目录,但是我希望有一个更好的选择,比如我错过的另一个NuGet包会给我这个程序集.

谢谢!

.net c# dotnet-httpclient

15
推荐指数
1
解决办法
2万
查看次数

StringContent vs ObjectContent

我正在使用System.Net.Http的HttpClient使用以下代码使用"POST"调用REST API:

using (HttpRequestMessage requestMessage = new HttpRequestMessage(
                                           HttpMethod.Post, new Uri(request)) { })
{
     response = await httpClient.PostAsync(request, objectContent);
}
Run Code Online (Sandbox Code Playgroud)

"objectContent"目前是这个 -

objectContent = new ObjectContent(jsonContent.GetType(),
                                  jsonContent,
                                  new JsonMediaTypeFormatter());
Run Code Online (Sandbox Code Playgroud)

我想知道如果这是一个StringContent而不是像这样的ObjectContent会有什么不同?

objectContent = new StringContent(content);
objectContent.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
Run Code Online (Sandbox Code Playgroud)

两者都很好.因为它是JSON,我倾向于认为StringContent是有意义的.但是什么时候使用ObjectContent,因为几乎所有发送的内容都是"字符串".

c# serialization json httpclient dotnet-httpclient

15
推荐指数
1
解决办法
2万
查看次数

单元测试/集成在Visual Studio 2013中使用HttpClient测试Web API

我很难用Visual Studio 2013测试我的API控制器.我的一个解决方案有一个Web API项目和一个测试项目.在我的测试项目中,我有一个单元测试:

[TestMethod]
public void GetProduct()
{
    HttpConfiguration config = new HttpConfiguration();
    HttpServer _server = new HttpServer(config);

    var client = new HttpClient(_server);

    var request = new HttpRequestMessage
    {
        RequestUri = new Uri("http://localhost:50892/api/product/hello"),
        Method = HttpMethod.Get
    };

    request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

    using (var response = client.SendAsync(request).Result)
    {
        Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);

        var test = response.Content.ReadAsAsync<CollectionListDTO>().Result;
    }
}
Run Code Online (Sandbox Code Playgroud)

我一直得到404.我尝试使用一个Visual Studio实例(IIS Express)运行我的API,并尝试在另一个实例中调试此单元测试.但没有运气.我已经验证我可以将此URL放在浏览器中(当一个Visual Studio正在调试时),我看到了我的JSON响应.但我无法弄清楚如何让它与我的单元测试一起工作HttpClient.我试图在网上找到例子,但似乎找不到一个.有人可以帮忙吗?

更新1: 我尝试添加路线但没有发生任何事情.

HttpConfiguration config = new HttpConfiguration();

// Added this line
config.Routes.MapHttpRoute(name: "Default", routeTemplate: "api/product/hello/");

HttpServer _server = new …
Run Code Online (Sandbox Code Playgroud)

c# unit-testing asp.net-web-api dotnet-httpclient visual-studio-2013

15
推荐指数
1
解决办法
3万
查看次数

您如何将基本身份验证与 System.Net.Http.HttpClient 一起使用?

我正在尝试在 c# .net core 中实现一个 rest 客户端,它需要首先进行基本身份验证,然后在后续请求中利用一个 Bearer 令牌。

当我尝试将基本身份验证与带有 FormUrlEncodedContent 对象的 client.PostAsync 结合使用时,出现异常:

System.InvalidOperationException occurred in System.Net.Http.dll: 'Misused header name. Make sure request headers are used with HttpRequestMessage, response headers with HttpResponseMessage, and content headers with HttpContent objects.'
Run Code Online (Sandbox Code Playgroud)
//setup reusable http client
HttpClient client = new HttpClient();
Uri baseUri = new Uri(url);
client.BaseAddress = baseUri;
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.ConnectionClose = true;

//Post body content
var values = new List<KeyValuePair<string,string>>();
values.Add(new KeyValuePair<string, string>("grant_type", "client_credentials"));

var content = new FormUrlEncodedContent(values);

//Basic Authentication
var …
Run Code Online (Sandbox Code Playgroud)

c# basic-authentication dotnet-httpclient

15
推荐指数
5
解决办法
3万
查看次数

使用MultipartFormDataContent生成错误的Content-Type标头

我有以下代码:

private static string boundary = "----CustomBoundary" + DateTime.Now.Ticks.ToString("x");

private static async Task<string> PostTest()
{
    string servResp = "";

    using (var content = new MultipartFormDataContent(boundary))
    {
        content.Add(new StringContent("105212"), "case-id");
        content.Add(new StringContent("1/14/2014"), "dateFrom");
        content.Add(new StringContent("1/15/2014"), "dateTo");

        HttpClientHandler handler = new HttpClientHandler();
        cookieContainer = new CookieContainer();
        handler.CookieContainer = cookieContainer;

        HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "http://somewebsite.com/form");
        request.Headers.ExpectContinue = false;
        request.Content = content;

        httpClient = new HttpClient(handler);

        HttpResponseMessage response = await httpClient.SendAsync(request);
        response.EnsureSuccessStatusCode();

        servResp = await response.Content.ReadAsStringAsync();
    }

    return servResp;
}
Run Code Online (Sandbox Code Playgroud)

当我运行它时,我在Fiddler中看到了Content-Type标头:

Content-Type: multipart/form-data; …
Run Code Online (Sandbox Code Playgroud)

c# content-type multipartform-data .net-4.5 dotnet-httpclient

14
推荐指数
1
解决办法
1万
查看次数

在HttpClient中为Get操作显式设置Content-Type标头

有没有一种方法可以Content-Type在执行GETwith 时显式设置标头值HttpClient

我意识到这打破了1.1协议,但我正在使用一个不符合它的API,并且要求我设置一个Content-TypeHeader.

我试过这个无济于事......

using (var httpClient = new HttpClient())
{
   var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, "http://example.com");

   httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/x-www-form-urlencoded+v1.3");

   await httpClient.SendAsync(httpRequestMessage)
}
Run Code Online (Sandbox Code Playgroud)

我检查了DefaultRequestHeadersTryAddWithoutValidation添加,它似乎并没有被设置的Content-Type值.

如果我尝试设置httpRequestMessage的Content-Type(通过设置httpRequestMessage.Content = ...,我收到以下错误:

Cannot send a content-body with this verb-type.
Run Code Online (Sandbox Code Playgroud)

有没有办法,我可以明确地设置的方式Content-TypeGET使用HttpClient的操作?

.net c# dotnet-httpclient

14
推荐指数
2
解决办法
8311
查看次数

每个服务端点的HttpClient实例化

在实例化HttpClient时,一个常见的建议是:

但是,根据这个链接我看到评论,我认为这意味着另一个规则:

HttpClient类实例充当发送HTTP请求的会话.HttpClient实例是应用于该实例执行的所有请求的设置集合.此外,每个HttpClient实例都使用自己的连接池,将其请求与其他HttpClient实例执行的请求隔离开来.

这让我想知道我是否应该为每个与之交互的服务端点创建一个HttpClient实例.通过"服务端点",我的意思是一个不同的基地址.以下各项将是一个独特的"服务端点":

当然,如果我打算使用HttpClient的"BaseAddress"属性,并且如果我正在处理并发调用,那么我将需要每个"service-endpoint"有一个HttpClient实例.

但是,HttpClient允许我明确指定一个绝对地址:

HttpClient client = new HttpClient(...);

client.PostAsJsonAsync("http://foo.net/api/Message/", ...);
client.PostAsJsonAsync("http://bar.com/api/Message/", ...);
client.PostAsJsonAsync("http://wow.gov/api/Message/", ...);
client.PostAsJsonAsync("http://now.com/api/Message/", ...);
client.PostAsJsonAsync("http://mom.org/api/Message/", ...);
client.PostAsJsonAsync("http://dog.com/api/Message/", ...);
Run Code Online (Sandbox Code Playgroud)

上面的代码工作,它正是我想要的当前应用程序我正在构建.但是唠叨的问题仍然存在......如果我将一个HttpClient用于我的应用程序与之通信的所有服务端点,那么我做错了什么?

有没有理由我真的需要上面引文中提到的"连接池隔离"?

.net c# asp.net-web-api dotnet-httpclient

14
推荐指数
1
解决办法
2304
查看次数

向通过 IHttpClientFactory 创建的所有客户端添加处理程序?

有没有办法向 IHttpClientFactory 创建的所有客户端添加处理程序?我知道您可以对指定客户执行以下操作:

services.AddHttpClient("named", c =>
{
    c.BaseAddress = new Uri("TODO");
    c.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    c.DefaultRequestHeaders.CacheControl = new CacheControlHeaderValue
    {
        NoCache = true,
        NoStore = true,
        MaxAge = new TimeSpan(0),
        MustRevalidate = true
    };
}).ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler
{
    AllowAutoRedirect = false,
    AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip
});
Run Code Online (Sandbox Code Playgroud)

但我不想使用命名客户端,我只想向通过以下方式返回给我的所有客户端添加一个处理程序:

clientFactory.CreateClient();
Run Code Online (Sandbox Code Playgroud)

c# dotnet-httpclient asp.net-core httpclientfactory

14
推荐指数
1
解决办法
2285
查看次数

为什么 HttpClient 即使在 Startup 中设置了基地址也不保留基地址

在我的 .net core Web api 项目中,我想使用外部 API,以便获得预期的响应。

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

 services.AddHttpClient<IRecipeService, RecipeService>(c => {
                c.BaseAddress = new Uri("https://sooome-api-endpoint.com");
                c.DefaultRequestHeaders.Add("x-raay-key", "123567890754545645gggg");
                c.DefaultRequestHeaders.Add("x-raay-host", "sooome-api-endpoint.com");
            });
Run Code Online (Sandbox Code Playgroud)

除此之外,我还有 1 个服务,我在其中注入了 HttpClient。


    public class RecipeService : IRecipeService
    {
        private readonly HttpClient _httpClient;

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

        public async Task<List<Core.Dtos.Recipes>> GetReBasedOnIngAsync(string endpoint)
        {
            
            using (var response = await _httpClient.GetAsync(recipeEndpoint))
            {
                // ...
            }
        }
    }

Run Code Online (Sandbox Code Playgroud)

创建 httpClient 时,如果我将鼠标悬停在对象本身上,则基本 URI/标头会丢失,并且我不明白为什么会发生这种情况。如果有人能透露一些信息,我将不胜感激:)

第一次更新

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


namespace ABC.Controllers
{
    [ApiController]
    [Route("[controller]")] …
Run Code Online (Sandbox Code Playgroud)

c# asp.net-web-api dotnet-httpclient asp.net-core-webapi httpclientfactory

14
推荐指数
3
解决办法
2万
查看次数