【问题标题】:C# Web API Sending Body Data in HTTP Post REST ClientC# Web API 在 HTTP Post REST 客户端中发送正文数据
【发布时间】:2018-10-31 16:19:54
【问题描述】:

我需要发送这个 HTTP Post 请求:

 POST https://webapi.com/baseurl/login
 Content-Type: application/json

 {"Password":"password",
 "AppVersion":"1",
 "AppComments":"",
 "UserName":"username",
 "AppKey":"dakey" 
  }

就像上面一样,它在 RestClient 和 PostMan 中效果很好。

我需要以编程方式使用它,但不确定是否使用

WebClient、HTTPRequest 或 WebRequest 来完成此操作。

问题是如何格式化正文内容并将其与请求一起发送到上面。

这是我使用 WebClient 的示例代码的地方...

  private static void Main(string[] args)
    {
        RunPostAsync();
    } 

    static HttpClient client = new HttpClient();

    private static void RunPostAsync(){

            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(
                new MediaTypeWithQualityHeaderValue("application/json"));

            Inputs inputs = new Inputs();

            inputs.Password = "pw";
            inputs.AppVersion = "apv";
            inputs.AppComments = "apc";
            inputs.UserName = "user";
            inputs.AppKey = "apk";


            var res = client.PostAsync("https://baseuriplus", new StringContent(JsonConvert.SerializeObject(inputs)));

            try
            {
                res.Result.EnsureSuccessStatusCode();

                Console.WriteLine("Response " + res.Result.Content.ReadAsStringAsync().Result + Environment.NewLine);

            }
            catch (Exception ex)
            {
                Console.WriteLine("Error " + res + " Error " + 
                ex.ToString());
            }

        Console.WriteLine("Response: {0}", result);
    }       

    public class Inputs
    {
        public string Password;
        public string AppVersion;
        public string AppComments;
        public string UserName;
        public string AppKey;
    }

现在可以正常工作并使用 (200) OK 服务器和响应进行响应

【问题讨论】:

  • 属性键和它们的值都没有必需的双引号才能成为 JSON。

标签: c# asp.net-web-api asp.net-core advanced-rest-client


【解决方案1】:

为什么要生成自己的 json?

使用来自 JsonNewtonsoft 的 JSONConvert

您的 json 对象字符串值需要 " " 引号和 ,

我会使用 http 客户端进行发布,而不是 web 客户端。

using (var client = new HttpClient())
{
   var res = client.PostAsync("YOUR URL", 
     new StringContent(JsonConvert.SerializeObject(
       new { OBJECT DEF HERE },
       Encoding.UTF8, "application/json")
   );

   try
   {
      res.Result.EnsureSuccessStatusCode();
   } 
   catch (Exception e)
   {
     Console.WriteLine(e.ToString());
   }
}   

【讨论】:

  • 发布了上面这段代码的工作版本供我使用。不需要 StringContent 参数。谢谢@Ya
【解决方案2】:

在发送之前,您没有正确地将值序列化为 JSON。与其尝试自己构建字符串,不如使用 JSON.Net 之类的库。

你可以像这样得到正确的字符串:

var message = JsonConvert.SerializeObject(new {Password = pw, AppVersion = apv, AppComments = acm, UserName = user, AppKey = apk});
Console.WriteLine(message); //Output: {"Password":"password","AppVersion":"10","AppComments":"","UserName":"username","AppKey":"dakey"}

【讨论】:

    【解决方案3】:
                var client = new RestClient("Your URL");
                var request = new RestRequest(Method.POST);
                request.AddHeader("Content-Type", "application/json");
                request.AddHeader("apk-key", apk);
    
                //Serialize to JSON body.
                JObject jObjectbody = new JObject();
                jObjectbody.Add("employeeName", data.name);
                jObjectbody.Add("designation", data.designation);
    
                request.AddParameter("application/json", jObjectbody, ParameterType.RequestBody);
    
                try
                {
                    var clientValue= client.Execute<Response>(request);
                    return RequestResponse<Response>.Create(ResponseCode.OK, "", clientValue.Data);
                }
                catch (Exception exception)
                {
                    throw exception;
                }
    

    【讨论】:

    • 请解释您的代码在做什么,以及为什么它可以解决问题
    【解决方案4】:

    我制作了一个工具来快速轻松地完成它:

    Install-Package AdvancedRestHandler
    

    dotnet add package AdvancedRestHandler
    
    AdvancedRestHandler arh = new AdvancedRestHandler("https://webapi.com/baseurl");
    var result = await arh.PostDataAsync<MyLoginResponse, MyLoginRequest>("/login", new MyLoginRequest{
      Password = "password",
      AppVersion = "1",
      AppComments = "",
      UserName = "username",
      AppKey = "dakey"
    });
    
    
    public class MyLoginRequest{
      public string Password{get;set;}
      public string AppVersion{get;set;}
      public string AppComments{get;set;}
      public string UserName{get;set;}
      public string AppKey{get;set;}
    }
    
    public class MyLoginResponse {
      public string Token{get;set;}
    }
    

    额外:

    您可以做的另一件事是使用ArhResponse

    • 无论哪种方式,在类定义中:
    public class MyLoginResponse: ArhResponse 
    {
    ...
    }
    
    • 或者这样,在 API 调用中:
    var result = await arh.PostDataAsync<ArhResponse<MyLoginResponse>, MyLoginRequest> (...)
    

    使用简单的if 语句检查您的 API 调用状态,而不是尝试或缓存:

    // check service response status:
    if(result.ResponseStatusCode == HttpStatusCode.OK) { /* api receive success response data */ }
    
    // check Exceptions that may occur due to implementation change, or model errors
    if(result.Exception!=null) { /* mostly serializer failed due to model mismatch */ }
    
    // have a copy of request and response, in case the service provider need your request response and they think you are hand writing the service and believe you are wrong
    _logger.Warning(result.ResponseText);
    _logger.Warning(result.RequestText);
    
    // Get deserialized verion of, one of the fallback models, in case the provider uses more than one type of data in same property of the model
    var fallbackData = (MyFallbackResponse)result.FallbackModel;
    

    标题可能的问题

    由于HttpClient生成的header,有些情况下Server不接受C#请求。

    这是因为HttpClient默认使用application/json; charset=utf-8的值对Content-Type...

    对于仅将application/json 部分发送为Content-Type 而忽略; charset=utf-8 部分,您可以执行以下操作:

    对于HttpClient,您可以通过查看此线程来修复它:How do you set the Content-Type header for an HttpClient request?

    至于 (AdvancedRestHandler) ARH,由于与某些公司的集成,我已修复它,但我不记得完全...我是通过 options 之类的请求或通过重置 header 值完成的.

    【讨论】:

      【解决方案5】:

      我们将使用 HttpPost 和 HttpClient PostAsync 来解决这个问题。

      using System.Net.Http;
          static async Task<string> PostURI(Uri u, HttpContent c)
          {
          var response = string.Empty;
          using (var client = new HttpClient())
          {
          HttpResponseMessage result = await client.PostAsync(u, c);
          if (result.IsSuccessStatusCode)
          {
          response = result.StatusCode.ToString();
          }
          }
          return response;
          }
      

      我们将通过创建一个用于发布的字符串来调用它:

        Uri u = new Uri("http://localhost:31404/Api/Customers");
              var payload = "{\"CustomerId\": 5,\"CustomerName\": \"Pepsi\"}";
      
              HttpContent c = new StringContent(payload, Encoding.UTF8, "application/json");
              var t = Task.Run(() => PostURI(u, c));
              t.Wait();
      
              Console.WriteLine(t.Result);
              Console.ReadLine();
      

      【讨论】:

      • 这段代码有很多问题。为什么是 Task.Run()?为什么要处理你的 HttpClient?为什么在失败时返回一个空字符串,或者将状态码作为字符串返回?这种方法有什么方便,在哪些场景下?这段代码如何回答这个问题?
      • 这完全没有错...我尝试了上面提供的许多解决方案。空响应,如果我们有错误的 api 或错误的参数..在这种情况下它将返回空响应..任务.Run() 将根据任务的分配执行 Api 并返回值。
      • 某些代码适用于您的某些场景,并不意味着它是好的代码。参见例如stackoverflow.com/questions/15705092/…stackoverflow.com/questions/18013523/…
      猜你喜欢
      • 2016-10-14
      • 2017-06-13
      • 1970-01-01
      • 1970-01-01
      • 2013-12-07
      • 1970-01-01
      • 2017-03-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多