【问题标题】:Poper way to make a HTTPClient PostAsync and GetAsync?制作 HTTPClient PostAsync 和 GetAsync 的正确方法?
【发布时间】:2019-06-12 16:20:25
【问题描述】:

我想发出一个正确的 HTTPClient 请求。我有一个代码,但我总是收到这样的异常:

  1. Java.IO.IOException:套接字关闭
  2. System.OperationCanceledException:操作已取消。
  3. Java.Net.SocketException:连接重置
  4. Java.Net.SocketException:软件导致连接中止
  5. Java.Net.UnknownHostException:android_getaddrinfo 失败:EAI_NODATA(没有与主机名关联的地址)
  6. Java.Net.UnknownHostException:无法解析主机“tbs.scratchit.ph”:没有与主机名关联的地址
  7. Java.IO.IOException:isConnected 失败:ETIMEDOUT(连接超时)
  8. Java.Net.SocketException:recvfrom 失败:ECONNRESET(对等方重置连接)

我总是遇到这些异常、错误。

我开始想知道如何正确创建 Post Async 和 GetAsync 以避免将来出现这些错误?

以下是我创建 HTTP 客户端的方法:
1. 我有一个类调用 Constants,我将在其中声明一个新的 HTTP 客户端,这样我的项目中只有 1 个 HTTPClient

public class Constants
{
    public static HttpClient client = new HttpClient();
}

2。我有一个函数,它通过 JSON 发送参数,通过 PHP API 从我的服务器获取数据。

public async void FirstTimeSyncUser(string host, string database, string contact, string ipaddress)
    {
        try
        {
            syncStatus.Text = "Checking internet connection";

            string apifile = "first-time-sync-user-api.php";

            if (CrossConnectivity.Current.IsConnected)
            {
                syncStatus.Text = "Initializing first-time user sync";

                var db = DependencyService.Get<ISQLiteDB>();
                var conn = db.GetConnection();

                var getData = conn.QueryAsync<UserTable>("SELECT * FROM tblUser WHERE ContactID = ? AND Deleted != '1'", contact);
                var resultCount = getData.Result.Count;

                var current_datetime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                int count = 1;

                var settings = new JsonSerializerSettings
                {
                    NullValueHandling = NullValueHandling.Ignore,
                    MissingMemberHandling = MissingMemberHandling.Ignore
                };

                if (resultCount == 0)
                {
                    syncStatus.Text = "Getting user data from the server";

                    var link = "http://" + ipaddress + "/" + Constants.apifolder + "/api/" + apifile;
                    string contentType = "application/json";
                    JObject json = new JObject
                    {
                        { "Host", host },
                        { "Database", database },
                        { "ContactID", contact }
                    };

                     Constants.client.DefaultRequestHeaders.ConnectionClose = true;

                    var response = await Constants.client.PostAsync(link, new StringContent(json.ToString(), Encoding.UTF8, contentType));

                    if (response.IsSuccessStatusCode)
                    {
                        var content = await response.Content.ReadAsStringAsync();

                        if (!string.IsNullOrEmpty(content))
                        {
                            try
                            {
                                var dataresult = JsonConvert.DeserializeObject<List<UserData>>(content, settings);
                                var datacount = dataresult.Count;

                                for (int i = 0; i < datacount; i++)
                                {
                                    syncStatus.Text = "Syncing user " + count + " out of " + datacount;

                                    var item = dataresult[i];
                                    var userid = item.UserID;
                                    var usrpassword = item.UsrPassword;
                                    var usertypeid = item.UserTypeID;
                                    var userstatus = item.UserStatus;
                                    var lastsync = DateTime.Parse(current_datetime);
                                    var lastupdated = item.LastUpdated;
                                    var deleted = item.Deleted;

                                    var insertdata = new UserTable
                                    {
                                        UserID = userid,
                                        UsrPassword = usrpassword,
                                        ContactID = contact,
                                        UserTypeID = usertypeid,
                                        UserStatus = userstatus,
                                        LastSync = lastsync,
                                        LastUpdated = lastupdated,
                                        Deleted = deleted
                                    };

                                    await conn.InsertOrReplaceAsync(insertdata);

                                    count++;
                                }

                                synccount += "Total synced user: " + count + "\n";

                                var logType = "App Log";
                                var log = "Initialized first-time sync (<b>User</b>)  <br/>" + "App Version: <b>" + Constants.appversion + "</b><br/> Device ID: <b>" + Constants.deviceID + "</b>";
                                int logdeleted = 0;

                                Save_Logs(contact, logType, log, database, logdeleted);

                                Preferences.Set("userchangeslastcheck", current_datetime, "private_prefs");

                                FirstTimeSyncSystemSerial(host, database, contact, ipaddress);
                            }
                            catch
                            {
                                var retry = await DisplayAlert("Application Error", "Syncing failed. Failed to send the data.\n\n Error:\n\n" + content + "\n\n Do you want to retry?", "Yes", "No");

                                if (retry.Equals(true))
                                {
                                    FirstTimeSyncUser(host, database, contact, ipaddress);
                                }
                                else
                                {
                                    First_Time_OnSyncFailed();
                                }
                            }
                        }
                        else
                        {
                            Preferences.Set("userchangeslastcheck", current_datetime, "private_prefs");

                            FirstTimeSyncSystemSerial(host, database, contact, ipaddress);
                        }
                    }
                    else
                    {
                        var retry = await DisplayAlert("Application Error", "Syncing failed. Server is unreachable.\n\n Error:\n\n"+ response.StatusCode +" Do you want to retry?", "Yes", "No");

                        if (retry.Equals(true))
                        {
                            FirstTimeSyncUser(host, database, contact, ipaddress);
                        }
                        else
                        {
                            First_Time_OnSyncFailed();
                        }
                    }
                }
                else
                {
                    SyncUserClientUpdate(host, database, contact, ipaddress);
                }
            }
            else
            {
                var retry = await DisplayAlert("Application Error", "Syncing failed. Please connect to the internet to sync your data. Do you want to retry?", "Yes", "No");

                if (retry.Equals(true))
                {
                    FirstTimeSyncUser(host, database, contact, ipaddress);
                }
                else
                {
                    First_Time_OnSyncFailed();
                }
            }
        }
        catch (Exception ex)
        {
            Crashes.TrackError(ex);
            var retry = await DisplayAlert("Application Error", "Syncing failed. Failed to send the data.\n\n Error:\n\n" + ex.Message.ToString() + "\n\n Do you want to retry?", "Yes", "No");

            if (retry.Equals(true))
            {
                FirstTimeSyncUser(host, database, contact, ipaddress);
            }
            else
            {
                First_Time_OnSyncFailed();
            }
        }
    }

3。在获得我需要的数据后,它将通过另一个 POSTASYNC 调用执行另一个函数。在上面的代码中,当我从服务器获取用户数据时,它将执行下一个函数,即 FirstTimeSyncSystemSerial(host, database, contact, ipaddress);

我做错了什么?以及如何改进这一点,以避免这些异常?

【问题讨论】:

  • 所有这些异常似乎都表明互联网连接不好......
  • 所有这些异常似乎要么是坏连接,要么是对我的坏反应!并且与你在Mono 侧的HttpClient 无关...
  • @SushiHangover 有没有办法改进我的代码以至少避免这些异常?
  • @G.hakim 有没有办法改进我的代码以至少避免这些异常?
  • @G.hakim 你能远程我吗?使用 anydesk 来查看我需要做哪些改进?我的 anydesk 是 782 114 930

标签: xamarin xamarin.forms xamarin.android


【解决方案1】:

调试您的代码以找出引发异常的位置。 在该代码块周围放置一个 try catch 阻塞。然后捕获所有预期的异常并再次尝试回送一段时间。

【讨论】:

  • 如果您知道自己遇到了可能会被修复的错误,那么使用 try catch 而不是修复问题不是一个合适的答案。这只是“掩盖”问题。
【解决方案2】:

您可以进行通用自定义服务调用,在需要时可以在任何地方调用

 public class RestClient : IRestClient
{
    private const string TokenHeaderKey = "Any Token Header";
    private HttpClient _httpclient = new HttpClient();

    public async Task<T> GetAsync<T>(string url, string token) where T : new()
    {
        var responseContent = await ExecuteRequest(
            async () =>
            {
                try
                {
                    AddTokenToDefaultRequestsHeader(token);
                    return await _httpclient.GetAsync(url);
                }
                finally
                {
                    ClearAuthenticationHeader();
                }
            });

        return await Deserialize<T>(responseContent);
    }

    private void AddTokenToDefaultRequestsHeader(string token)
    {
        _httpclient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(TokenHeaderKey, token);
    }

    private void ClearAuthenticationHeader()
    {
        _httpclient.DefaultRequestHeaders.Authorization = null;
    }

    private static async Task<HttpContent> ExecuteRequest(Func<Task<HttpResponseMessage>> requestFunc)
    {
        HttpResponseMessage response = null;
        try
        {
            response = await requestFunc();
            if (!response.IsSuccessStatusCode)
            {
                var message = $"Executed HTTP request returned status code {response.StatusCode} and reason phrase {response.ReasonPhrase}";

                if (response.StatusCode == HttpStatusCode.Unauthorized)
                {
                    throw new Exception(message);
                }

                throw new Exception(message);
            }

            return response.Content;
        }
        catch (Exception exception)
        {
            if (exception is HttpRequestException || exception is WebException || exception is TaskCanceledException)
            {
                throw new Exception(
                    "Could not connect to service.");
            }

            throw;
        }
    }

    private static async Task<T> Deserialize<T>(HttpContent responseContent) where T : new()
    {
        try
        {
            var responseContentString = await responseContent.ReadAsStringAsync();
            return JsonConvert.DeserializeObject<T>(responseContentString);
        }

        catch (Exception exception)
        {
            if (exception is TaskCanceledException || exception is JsonException)
            {
                throw new Exception("Could not deserialize response content.", exception);
            }
            throw;
        }
    }

并添加一个应用设置类

 public class AppSettings : IAppSettings
{
    public string Server => "server url";
    public string ServerEndPoint => "End point";

    public string Token => "Token If you Have any";
}

然后这样调用

 public class Servicecall 
{
    private readonly IRestClient _restClient;
    private readonly IAppSettings _appSettings;

    public PatientService(IRestClient restClient, IAppSettings appSettings)
    {
        _restClient = restClient;
        _appSettings = appSettings;
    }

    public async Task<IList<PatientViewModel>> GetPatients()
    {
        var url = _appSettings.Server + _appSettings.EndPoint ;
        var token = _appSettings.Token;
        return GetPatientList(await _restClient.GetAsync<List<ListModelClass>>(url, token));
    }

    public IList<Model> GetPatientList(IList<ListModelClass> List)
    {
        return List.Select(p => new Model(p)).ToList();
    }
}

这样你就可以调用不同的服务而不需要输入大量的代码 这样您就可以真正轻松地调用服务

【讨论】:

  • 你能把它设计成我的代码吗?这样我就可以了解它的要点
  • 这对你有帮助吗
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-15
  • 1970-01-01
相关资源
最近更新 更多