【问题标题】:How to Seriailize an c# object into Json, while using httpClient?如何在使用 httpClient 时将 c# 对象序列化为 Json?
【发布时间】:2018-12-03 10:57:32
【问题描述】:

我有一个应该与“Slack”通信的小程序。在旧版本中,我使用了“Dictionary<string, string>”,然后将它们放入UrlEncodedContent - 效果很好。 现在我正在尝试创建一个 Json 对象,使用 Newtonsoft 的 Nuget 包并(在我看来)按照他们在网站上所说的方式格式化我的对象。 问题是,当我尝试发出一个简单的请求时,我的程序只运行到代码中的一个特定行(var response = await _httpClient.SendAsync(request);)然后就结束了。它不会抛出异常或显示任何类型的消息,它只是在这一行结束。我在调试时一步一步地浏览了我的代码,这就是我知道它正好在这一行结束的方式。我只是不知道为什么!

现在我的代码: 首先,我的对象...

namespace BPS.Slack
{
    public class JsonObject
    {
        //generally needed parameters
        [JsonProperty("ok")]
        public bool ok { get; set; }    
        [JsonProperty("error")]
        public string error { get; set; }   
        [JsonProperty("channel")]
        public string channel { get; set; }
        [JsonProperty("token")]
        private string token = "xoxp-MyToken";
        [JsonProperty("as_user")]
        public bool as_user = false;       
        [JsonProperty("username")]
        public string username { get;set; } 
        //--------------------------------
        //only needed for textmessages
        [JsonProperty("text")]
        public string text { get; set; }
        //--------------------------------
        //for posting messages with data attached
        [JsonProperty("initial_comment")]
        public string initial_comment { get; set; }
        [JsonProperty("file")]
        public string file { get; set; }
        [JsonProperty("channels")]
        public string channels { get; set; }
        //--------------------------------
        //for getting the latest message from a channel
        [JsonProperty("count")]
        public string count = "1";
        [JsonProperty("unreads")]
        public bool unreads = true;
    }
}

现在是客户:

   namespace BPS.Slack
    {
        public class BpsHttpClient
        {
            private readonly HttpClient _httpClient = new HttpClient { };
            public Uri UriMethod { get; set; }

            public BpsHttpClient(string webhookUrl)
            {
                UriMethod = new Uri(webhookUrl);
            }


            public async Task<HttpResponseMessage> UploadFileAsync(MultipartFormDataContent requestContent)
            {
                HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, UriMethod);
                request.Content = requestContent;
                var response = await _httpClient.SendAsync(request);

                return response;
            }
        }

    }

和主要的

namespace TestArea
{
    class MainArea
    {
        public static void Main( string[] args)
        {
            try
            {
                Task.WhenAll(SendMessage());
            }
            catch(Exception ass)
            {
                Console.WriteLine(ass);
                Console.ReadKey();
            }
        }
        private static async Task SendMessage()
        {
            var client = new BpsHttpClient("https://slack.com/api/im.history");
            JsonObject JO = new JsonObject();
            JO.channel = "DCW21NBHD";            
            var Json = JsonConvert.SerializeObject(JO);

            var StringJson = new StringContent(Json, Encoding.UTF8);
            MultipartFormDataContent content = new MultipartFormDataContent();
            content.Add(StringJson);

            var Response = await client.UploadFileAsync(content);


            string AnswerContent = await Response.Content.ReadAsStringAsync();

            Console.WriteLine(AnswerContent);
            Console.ReadKey();
        }
    }

}

我在旧版本中遇到了同样的问题,但只是因为我想反序列化从 Slack 获得的答案。这与我尝试将答案反序列化的对象有关。但这一次我无法弄清楚出了什么问题。但是,正如我所说,我没有任何使用序列化对象作为 Json 属性来发送请求的经验......有人知道我的代码有什么问题吗?

编辑:这个问题已经解决了。但是有一个后续问题。

好的,我发现abprubt终止的原因是

Task.WhenAll(SendMessage());

应该是

Task.WaitAll(SendMessage());为什么???有人说我应该使用WhenAll,但显然在这种情况下它不能正常工作......

现在我收到了 Slack 的回复,但现在出现了另一个问题。当我使用这种方法时:

    public async Task<HttpResponseMessage> UploadFileAsync(MultipartFormDataContent requestContent)
    {
        HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, UriMethod);
        request.Content = requestContent;
        var response = await _httpClient.SendAsync(request);

        return response;
    }

我总能得到答案:

{"ok":false,"error":"invalid_form_data"}

所以我试图明确地告诉它“mediaType”,我尝试了“application/json”和其他的,但是我得到了同样的错误。下面是调用上层方法的完整方法:

 private static async Task SendMessage()
    {
        var client = new BpsHttpClient("https://slack.com/api/chat.postMessage");
        JsonObject JO = new JsonObject();
        JO.channel = "DCW21NBHD";
        JO.text = "This is so much fun :D !";
        var Json = JsonConvert.SerializeObject(JO, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });

        var StringJson = new StringContent(Json, Encoding.UTF8, "application/json");

        var requestContent = new MultipartFormDataContent();
        requestContent.Add(StringJson);

        var Response = await client.UploadFileAsync(requestContent);

        string AnswerContent = await Response.Content.ReadAsStringAsync();

    }

当我使用这个方法时:

    public async Task<HttpResponseMessage> SendMessageAsync(FormUrlEncodedContent content)
    {
        var response = await _httpClient.PostAsync(UriMethod, content);

        return response;
    }

所以基本上我在此传递“FormUrlEncodedContent”而不是“MultipartFormDataContent”,然后我得到我想要的响应并且可以使用它。但是这对我来说没什么用,因为我必须使用“MultipartFormDataContent”才能发送带有我的请求的文件。

有人知道这里出了什么问题吗?为什么它不喜欢一种内容类型而是另一种?非常感谢您的提示和想法!

【问题讨论】:

    标签: c# json slack-api


    【解决方案1】:

    您将对象序列化为 Json,然后将其添加到 Multipart 主体,这很奇怪。除非您要上传二进制数据(例如文件),否则无需使用 MultipartFormDataContent。

    您可以直接将您的JsonObject 序列化为 JSON:

            public async Task<HttpResponseMessage> PostJsonAsync(StringContent content)
            {                
                var response = await client.PostAsync(url, content);
    
                return response;
            }
    
           var client = new BpsHttpClient("https://slack.com/api/im.history");                  
           JsonObject JO = new JsonObject();
           JO.channel = "DCW21NBHD";            
           var Json = JsonConvert.SerializeObject(JO);
           var StringJson = new StringContent(Json, Encoding.UTF8);
           var Response = await client.PostJsonAsync(content);
    

    这也应该是UploadFileAsync函数上的POST。

    HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, UriMethod);
    

    【讨论】:

    • 嘿,这并不能解决问题。我的意思是,您可能是对的,我不需要使用 MultipartFormDataContent。但这根本不会改变结果。它仍然在完全相同的点终止......不,这是一个 GET 请求,所以方法应该是 GET。但在我的旧版本中,我的 GET 请求也适用于 POST 方法。但是,是的,它在这个版本中仍然不起作用。
    • 带有 GET 的多部分正文?那我想我帮不了了。
    【解决方案2】:

    所以我发现在 Main() 中问题是这样的:

    Task.WhenAll(SendMessage());
    

    我应该改用:

     Task.WaitAll(SendMessage());
    

    谁有这方面的知识,请详细说明原因!

    【讨论】:

    • 原因是WhenAll 没有等待你的异步任务完成,但WaitAll 会。你也可以写SendMessage().Wait(); 来等待这个异步方法完成。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-19
    • 2017-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-05
    相关资源
    最近更新 更多