Nhận lại dữ liệu JSON từ yêu cầu HTTP


93

Tôi có một yêu cầu web đang hoạt động bình thường, nhưng nó chỉ trả lại trạng thái OK, nhưng tôi cần đối tượng mà tôi đang yêu cầu nó trả lại. Tôi không chắc làm thế nào để nhận được giá trị json mà tôi đang yêu cầu. Tôi mới sử dụng đối tượng HttpClient, có thuộc tính nào mà tôi đang bỏ lỡ không? Tôi thực sự cần đối tượng trả lại. Cảm ơn vì bất kì sự giúp đỡ

Thực hiện cuộc gọi - chạy tốt trả về trạng thái OK.

HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Accept
  .Add(new MediaTypeWithQualityHeaderValue("application/json"));
var responseMsg = client.GetAsync(string.Format("http://localhost:5057/api/Photo")).Result;

Phương thức lấy api

//Cut out alot of code but you get the idea
public string Get()
{
    return JsonConvert.SerializeObject(returnedPhoto);
}

Bạn đang hỏi cách lấy nội dung phản hồi khi sử dụng lớp .NET 4.5 HttpClient?
Panagiotis Kanavos

Câu trả lời:


163

Nếu bạn đang đề cập đến System.Net.HttpClient trong .NET 4.5, bạn có thể lấy nội dung được trả về bởi GetAsync bằng cách sử dụng thuộc tính HttpResponseMessage.Content dưới dạng đối tượng HttpContent -derived. Sau đó, bạn có thể đọc nội dung thành một chuỗi bằng phương thức HttpContent.ReadAsStringAsync hoặc dưới dạng một luồng bằng phương thức ReadAsStreamAsync .

Các HttpClient tài liệu hướng dẫn lớp học bao gồm ví dụ này:

  HttpClient client = new HttpClient();
  HttpResponseMessage response = await client.GetAsync("http://www.contoso.com/");
  response.EnsureSuccessStatusCode();
  string responseBody = await response.Content.ReadAsStringAsync();

3
Chưa thử nghiệm điều này nhưng tài liệu của EnsureSuccessStatusCode cho biết "Nếu Nội dung không rỗng, phương pháp này cũng sẽ gọi Dispose để giải phóng tài nguyên được quản lý và không được quản lý." vì vậy bạn có thể muốn đọc nội dung trước. msdn.microsoft.com/en-us/library/…
Ryan Williams

4
Không có lý do cho điều này. Như được chứng minh bởi Reflector, EnsureSuccessStatusCode sẽ CHỈ loại bỏ nếu mã trạng thái không thành công, ngay trước khi đưa ra một ngoại lệ. Tuy nhiên, một trường hợp khác mà văn bản tài liệu hơi khó hiểu.
Panagiotis Kanavos

1
Tại sao không chỉ client.GetStringAsync(...)? Có phải điều đó đã không xảy ra vào năm 2012. Cả hai sẽ đưa ra một ngoại lệ nếu phản hồi không 200đúng?
Simon_Weaver

1
@Simon_Weaver vì đó không phải là câu hỏi - OP hỏi cách đọc chuỗi từ phản hồi. Có được sự khác biệt. Bạn không thể kiểm tra phản hồi có GetStringAsyncnghĩa là bạn không biết thông báo phản hồi là gì. Bạn có thể không muốn ném nếu phản hồi 3xx được trả lại. Bạn có thể muốn thử lại mà không ném nếu lỗi điều chỉnh được trả về.
Panagiotis Kanavos

1
@Simon_Weaver có rất nhiều cách để thực hiện cuộc gọi đó - tại sao không GetAsync<T>? Hoặc GetStreamAsync và chuyển luồng sang Json.NET, tránh chuỗi tạm thời? Một lần nữa, nó có thể thích hợp hơn để sử dụng GetAsyncđầu tiên sau đó truy cập vào đối tượng nội dung
Panagiotis Kanavos

40

Dựa trên câu trả lời của @Panagiotis Kanavos , đây là một phương pháp làm việc làm ví dụ cũng sẽ trả về phản hồi dưới dạng một đối tượng thay vì một chuỗi:

using System.Text;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json; // Nuget Package

public static async Task<object> PostCallAPI(string url, object jsonObject)
{
    try
    {
        using (HttpClient client = new HttpClient())
        {
            var content = new StringContent(jsonObject.ToString(), Encoding.UTF8, "application/json");
            var response = await client.PostAsync(url, content);
            if (response != null)
            {
                var jsonString = await response.Content.ReadAsStringAsync();
                return JsonConvert.DeserializeObject<object>(jsonString);
            }
        }
    }
    catch (Exception ex)
    {
        myCustomLogger.LogException(ex);
    }
    return null;
}

Hãy nhớ rằng đây chỉ là một ví dụ và bạn có thể muốn sử dụng HttpClientnhư một trường hợp dùng chung thay vì sử dụng nó trong mệnh đề using.


Hãy cẩn thận httpclient không vứt bỏ như vậy với trạng thái đang sử dụng
rogue39 trong

Vì await trả về ngay lập tức, có thể nó if (response != null)được thực hiện trước khi cuộc gọi đăng hoàn thành?
Nishant


8

Tôi nghĩ con đường ngắn nhất là:

var client = new HttpClient();
string reqUrl = $"http://myhost.mydomain.com/api/products/{ProdId}";
var prodResp = await client.GetAsync(reqUrl);
if (!prodResp.IsSuccessStatusCode){
    FailRequirement();
}
var prods = await prodResp.Content.ReadAsAsync<Products>();

8
Chỉ nghĩ rằng id thêm rằng ReadAsAsync là một phương thức mở rộng. bạn sẽ cần sử dụng System.Net.Http.Formatting cho .net 4+ và Microsoft.AspNet.WebApi.Client cho lõi .net. để làm cho điều này hoạt động.
Chắc chắn

0

Những gì tôi thường làm, tương tự như câu trả lời:

var response = await httpClient.GetAsync(completeURL); // http://192.168.0.1:915/api/Controller/Object

if (response.IsSuccessStatusCode == true)
    {
        string res = await response.Content.ReadAsStringAsync();
        var content = Json.Deserialize<Model>(res);

// do whatever you need with the JSON which is in 'content'
// ex: int id = content.Id;

        Navigate();
        return true;
    }
    else
    {
        await JSRuntime.Current.InvokeAsync<string>("alert", "Warning, the credentials you have entered are incorrect.");
        return false;
    }

Trong đó 'model' là lớp mô hình C # của bạn.


0

Nó hoạt động tốt đối với tôi theo cách sau -

public async Task<object> TestMethod(TestModel model)
    {
        try
        {
            var apicallObject = new
            {
                Id= model.Id,
                name= model.Name
            };

            if (apicallObject != null)
            {
                var bodyContent = JsonConvert.SerializeObject(apicallObject);
                using (HttpClient client = new HttpClient())
                {
                    var content = new StringContent(bodyContent.ToString(), Encoding.UTF8, "application/json");
                    content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                    client.DefaultRequestHeaders.Add("access-token", _token); // _token = access token
                    var response = await client.PostAsync(_url, content); // _url =api endpoint url
                    if (response != null)
                    {
                        var jsonString = await response.Content.ReadAsStringAsync();

                        try
                        {
                            var result = JsonConvert.DeserializeObject<TestModel2>(jsonString); // TestModel2 = deserialize object
                        }
                        catch (Exception e){
                            //msg
                            throw e;
                        }
                    }
                }
            }
        }
        catch (Exception ex)
        {
            throw ex;
        }
        return null;
    }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.