如何正确使用 HttpClient PostAsync 参数?

Posted

技术标签:

【中文标题】如何正确使用 HttpClient PostAsync 参数?【英文标题】:How do I use HttpClient PostAsync parameters properly? 【发布时间】:2017-12-22 16:13:30 【问题描述】:

所以我正在使用 HttpClient 为我的项目编写一个扩展类,因为我要从 HttpWebRequest 迁移过来。

在进行 POST 请求时,如何发送一个普通字符串作为参数?没有 json 或任何东西,只是一个简单的字符串。

这就是目前的样子。

static class HttpClientExtension
    
        static HttpClient client = new HttpClient();
        public static string GetHttpResponse(string URL)
        
            string fail = "Fail";
            client.BaseAddress = new Uri(URL);
            HttpResponseMessage Response = client.GetAsync(URL).GetAwaiter().GetResult();
            if (Response.IsSuccessStatusCode)
                return Response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
            else
                return fail;
        

        public static string PostRequest(string URI, string PostParams)
        
            client.PostAsync(URI, new StringContent(PostParams));
            HttpResponseMessage response = client.GetAsync(URI).GetAwaiter().GetResult();
            string content = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
            return content;
        
    

如果你这样看

client.PostAsync(URI, new StringContent(PostParams));

您可以看到我刚刚尝试创建新的 StringContent 并将字符串传递给它,响应返回 404 page not found。 如何正确使用 Post.Async();发送字符串或字节数组?因为使用 HttpWebRequest 你会这样做

public static void SetPost(this HttpWebRequest request, string postdata)
        
            request.Method = "POST";
            byte[] bytes = Encoding.UTF8.GetBytes(postdata);

            using (Stream requestStream = request.GetRequestStream())
                requestStream.Write(bytes, 0, bytes.Length);
        

【问题讨论】:

【参考方案1】:

PostRequest 中完成了以下操作..

client.PostAsync(URI, new StringContent(PostParams));
HttpResponseMessage response = client.GetAsync(URI).GetAwaiter().GetResult();

不捕获 POST 的响应。

重构为

public static string PostRequest(string URI, string PostParams)             
    var response = client.PostAsync(URI, new StringContent(PostParams)).GetAwaiter().GetResult();
    var content = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
    return content;

HttpClient 主要用于异步,因此请考虑重构为

public static async Task<string> PostRequestAsync(string URI, string PostParams)             
    var response = await client.PostAsync(URI, new StringContent(PostParams));
    var content = await response.Content.ReadAsStringAsync();
    return content;

【讨论】:

使用异步版本如何获取返回字符串? @AleksSlade 取决于发出请求的上下文。应用有关如何进行异步调用的规则。 var result = await HttpClientExtension.PostRequestAsync("URL here", "Params Here")【参考方案2】:

您需要准备对象,然后您将使用Newtonsoft.Json 序列化对象。之后,您将从缓冲区准备字节内容。我们正在使用 api url api/auth/login 并且它不是完整的 api url,因为我们使用了依赖注入并在启动时配置了基地址,请参见第二个代码。

public async void Login(string username, string password)
    
        LoginDTO login = new LoginDTO();
        login.Email = username;
        login.Password = password;
        var myContent = JsonConvert.SerializeObject(login);
        var buffer = System.Text.Encoding.UTF8.GetBytes(myContent);
        var byteContent = new ByteArrayContent(buffer);
        byteContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");

        var response = await httpClient.PostAsync("api/auth/login", byteContent);
        var contents = await response.Content.ReadAsStringAsync();
    
services.AddHttpClient<IAuthService, AuthService>(client =>
        
            client.BaseAddress = new Uri("https://localhost:44354/");
        );

.NET 5 解决方案

在 .NET 5 中,有一个新类 JsonContent,您可以轻松实现它

LoginDTO login = new LoginDTO();
login.Email = username;
login.Password = password;

JsonContent content = JsonContent.Create(login);
var url = "http://...";
HttpResponseMessage response = await httpClient.PostAsync(url, content);

【讨论】:

【参考方案3】:

我已经完成了以下工作(使用包 Ngonzalez.ImageProcessorCore)。

查询(ASP.NET Core 2 控制器):

async Task<byte[]> CreateImage(IFormFile file)

  using (var memoryStream = new MemoryStream())
  
    await file.CopyToAsync(memoryStream);
    var image = new Image(memoryStream);
    var height = image.Height < 150 ? image.Height : 150;
    image.Resize((int)(image.Width * height / image.Height), height).Save(memoryStream);
    return memoryStream.ToArray();
  


[HttpPost, ValidateAntiForgeryToken]
public async Task<IActionResult> ImageAdd(ImageAddVm vm)

  byte[] image = null;
  if (vm.File != null && vm.File.Length > 0)
     image = await CreateImage(vm.File);
  if (image != null)
  
    var json = JsonConvert.SerializeObject(new  vm.ObjectId, image );
    var content = new StringContent(json, Encoding.UTF8, "application/json");
    var client= new HttpClient();
    await client.PostAsync($"ApiUrl/SaveImage", content);
  
  return RedirectToAction("ReturnAction");

API(ASP.NET Core 2 控制器):

public class ObjectImage

  public int ObjectId  get; set; 
  public byte[] Image  get; set; 


[HttpPost("SaveImage")]
public void SaveImage([FromBody]object content)

  var obj = JsonConvert.DeserializeObject<ObjectImage>(content.ToString());
  _db.Images.Find(obj.ObjectId).Image = obj.Image;
  _db.SaveChanges();

【讨论】:

以上是关于如何正确使用 HttpClient PostAsync 参数?的主要内容,如果未能解决你的问题,请参考以下文章

Angular - 如何正确使用服务、HttpClient 和 Observables 在我的应用程序周围传递对象数组

如何使用 System.Net.Http.HttpClient 为 Azure 表存储正确设置 content.Headers.ContentMD5 属性

使用 HttpClient 类时如何对代理进行身份验证?

Ktor 的 HttpClient 使用的正确模式

在.NET Core使用 HttpClient 的正确方式

如何使用 HttpClient 在 Web api 中传递标头值