繁体   English   中英

可移植类库HttpClient

[英]Portable Class Library HttpClient

对于我的一个项目,我想开发一个可在不同平台(桌面,移动,Surface等)中使用的库。 因此选择了Porable Class Library。

我正在开发一个使用HttpClient调用不同API调用的类。 我对如何调用方法,响应和解决方法感到困惑。 这是我的代码:-

    public static async Task<JObject> ExecuteGet(string uri)
    {
        using (HttpClient client = new HttpClient())
        {
            // TODO - Send HTTP requests
            HttpRequestMessage reqMsg = new HttpRequestMessage(HttpMethod.Get, uri);
            reqMsg.Headers.Add(apiIdTag, apiIdKey);
            reqMsg.Headers.Add(apiSecretTag, ApiSecret);
            reqMsg.Headers.Add("Content-Type", "text/json");
            reqMsg.Headers.Add("Accept", "application/json");

            //response = await client.SendAsync(reqMsg);
            //return response;

            //if (response.IsSuccessStatusCode)
            //{
                string content = await response.Content.ReadAsStringAsync();
                return (JObject.Parse(content));
            //}
        }
    }

    // Perform AGENT LOGIN Process
    public static bool agentStatus() {
        bool loginSuccess = false;

        try
        {
            API_Utility.ExecuteGet("http://api.mintchat.com/agent/autoonline").Wait();
            // ACCESS Response, JObject ???
        }
        catch
        {
        }
        finally
        {
        }

像ExecuteGet一样,我还将为ExecutePost创建。 我的查询来自ExecuteGet,如果(1)仅当IsSuccessStatusCode时,我在解析时通过JObject,那么我如何知道任何其他错误或消息来通知用户。 (2)如果我通过了响应,那么我如何在这里分配它

response = API_Utility.ExecuteGet("http://api.mintchat.com/agent/autoonline").Wait();  

这是错误的。

处理这种情况的最佳方法是什么? 我必须调用多个API,因此不同的API将具有不同的结果集。

另外,您是否可以确认以这种方式设计并添加PCL参考,我将能够在多个项目中进行访问。

更新:-如以下两个答案中所述,我已经更新了我的代码。 如提供的链接中所述,我正在从另一个项目中调用。 这是我的代码:-

便携式类库:-

    private static HttpRequestMessage getGetRequest(string url)
    {
        HttpRequestMessage reqMsg = new HttpRequestMessage(HttpMethod.Get, url);
        reqMsg.Headers.Add(apiIdTag, apiIdKey);
        reqMsg.Headers.Add(apiSecretTag, ApiSecret);
        reqMsg.Headers.Add("Content-Type", "text/json");
        reqMsg.Headers.Add("Accept", "application/json");

        return reqMsg;
    }

    // Perform AGENT LOGIN Process
    public static async Task<bool> agentStatus() {
        bool loginSuccess = false;
        HttpClient client = null;
        HttpRequestMessage request = null;

        try
        {
            client = new HttpClient();
            request = getGetRequest("http://api.mintchat.com/agent/autoonline");
            response = await client.SendAsync(request).ConfigureAwait(false);

            if (response.IsSuccessStatusCode)
            {
                string content = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
                JObject o = JObject.Parse(content);
                bool stat = bool.Parse(o["status"].ToString());

                ///[MainAppDataObject sharedAppDataObject].authLogin.chatStatus = str;
                o = null;
            }
            loginSuccess = true;

        }
        catch
        {
        }
        finally
        {
            request = null;
            client = null;
            response = null;
        }

        return loginSuccess;
    }

在另一个WPF项目中,在btn click事件中,我将其称为:-

    private async void btnSignin_Click(object sender, RoutedEventArgs e)
   {
         /// Other code goes here
         // ..........

            agent = doLogin(emailid, encPswd);
            if (agent != null)
            {
                //agent.OnlineStatus = getAgentStatus();

                // Compile Error at this line
                bool stat = await MintWinLib.Helpers.API_Utility.agentStatus();

                ... 

我得到这四个错误:

Error   1   Predefined type 'System.Runtime.CompilerServices.IAsyncStateMachine' is not defined or imported D:\...\MiveChat\CSC 
Error   2   The type 'System.Threading.Tasks.Task`1<T0>' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Threading.Tasks, Version=1.5.11.0, Culture=neutral, PublicKeyToken=b03f5f7f89d50a3a'.   D:\...\Login Form.xaml.cs   97  21  
Error   3   Cannot find all types required by the 'async' modifier. Are you targeting the wrong framework version, or missing a reference to an assembly?   D:\...\Login Form.xaml.cs   97  33  
Error   4   Cannot find all types required by the 'async' modifier. Are you targeting the wrong framework version, or missing a reference to an assembly?   D:\...\Login Form.xaml.cs   47  28  

我尝试仅从PCL库添加System.Threading.Tasks,这给了7个不同的错误。 我要去哪里错了? 要使此工作正常怎么办?

请指导我。 花了很多时间来找出最好的方法来开发可通过桌面应用程序和Win Phone应用程序访问的库。 任何帮助都是高度赞赏的。 谢谢。

如果在进行http调用时调用了async api,则还应该向用户公开该异步端点,而不要使用Task.Wait阻止请求。

另外,在创建第三方库时,建议在调用代码尝试访问Result属性或Wait方法时,使用ConfigureAwait(false)避免死锁。 您还应该遵循准则,并使用Async标记任何异步方法,因此该方法应称为ExecuteStatusAsync

public static Task<bool> AgentStatusAsync() 
{
    bool loginSuccess = false;

    try
    {
        // awaiting the task will unwrap it and return the JObject
        var jObject = await API_Utility.ExecuteGet("http://api.mintchat.com/agent/autoonline").ConfigureAwait(false);

    }
    catch
    {
    }
}

ExecuteGet内部:

response = await client.SendAsync(reqMsg).ConfigureAwait(false);
string content = await response.Content.ReadAsStringAsync().ConfigureAwait(false);

如果IsSuccessStatusCode为false,则可以向调用代码抛出异常以表明出了点问题。 为此,您可以使用HttpResponseMessage.EnsureSuccessStatusCode ,如果状态代码!= 200 OK,它将引发异常。

就个人而言,如果ExecuteGet是公共API方法,则我绝对不会将其公开为JObject而是强类型。

如果需要任务的结果,则需要使用Result属性:

var obj = API_Utility.ExecuteGet("http://api.mintchat.com/agent/autoonline").Result;

但是,同步等待异步方法完成通常不是一个好主意,因为它可能导致死锁。 更好的方法是await该方法:

var obj = await API_Utility.ExecuteGet("http://api.mintchat.com/agent/autoonline");

请注意,您还需要使调用方法async

public static async Task<bool> agentStatus()

同步和异步代码不能很好地配合使用,因此异步往往会在整个代码库中传播。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM