【问题标题】:Need some advice about the correct way to write own httpclient interface需要一些关于编写自己的 httpclient 接口的正确方法的建议
【发布时间】:2013-05-04 20:52:45
【问题描述】:

我想创建一个 WPF 应用程序来连接到我的 Web api 服务器。但我是 WPF 的新手。更糟糕的是,即使在 .net 中也是如此。

其实我已经搞定了,关注这个http://www.asp.net/web-api/overview/web-api-clients/calling-a-web-api-from-a-wpf-application

经过更多搜索,我发现我完全以错误的方式工作(winform方式)。似乎我应该像大多数社区所说的那样使用MVVM风格。所以我决定重写我所有的代码。

我使用 prism 创建一个模块,并将名称和密码绑定到 ViewModel 类。现在我可以从 Textbox 中获取名称和密码了。

首先,我未能为每个要使用的 ViewModel 创建一个 httpclient 实例。以下是问题链接

Hot to register already constructed instance in unity?

所以我决定这样写。首先创建接口。

public interface IData
{
    IEnumerable<device> getDevicesByUser(user user);
    IEnumerable<user> getUsers();
    currentUser getCurrentUserInfo();
}

还有一个实现接口

public class HttpService : IData
{
    HttpClient client = new HttpClient();
    public HttpService()
    {
        client.BaseAddress = new Uri("https://localhost:3721");
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    }

    public IEnumerable<device> getDevicesByUser(user user)
    {
        throw new NotImplementedException();
    }

    public IEnumerable<user> getUsers()
    {
        throw new NotImplementedException();
    }

    public currentUser getCurrentUserInfo()
    {
        throw new NotImplementedException();
    }
}

之后,我可以在unity中注册实例,并且可以在每个ViewModel中使用它。但是情况是我不能再进一步了。我用了两种方法,但都不起作用。我需要有关正确方法的建议。

第一种方式。我为每个接口方法编写异步方法。

public currentUser getCurrentUserInfo()
    {
      return getCurrentUserInfoFromServer();
    }

private async void getCurrentUserInfoFromServer()
    {
        try
        {
            var response = await client.GetAsync("api/user");
            response.EnsureSuccessStatusCode(); 
            var currentuser = await response.Content.ReadAsAsync<currentUser>();
        }
        catch (Newtonsoft.Json.JsonException jEx)
        {
            MessageBox.Show(jEx.Message);
        }
        catch (HttpRequestException ex)
        {
            MessageBox.Show(ex.Message);
        }
        finally
        {

        }
    }

但似乎 async 不能返回 void 和 task 以外的类型。而且看起来很奇怪。 所以我尝试将所有请求写入一个方法。

private async void getData(string requestUri)
    {
        try
        {
            var response = await client.GetAsync("api/user"+requestUri);
            response.EnsureSuccessStatusCode();
            var ? = await response.Content.ReadAsAsync<?>();
        }
        catch (Newtonsoft.Json.JsonException jEx)
        {
            MessageBox.Show(jEx.Message);
        }
        catch (HttpRequestException ex)
        {
            MessageBox.Show(ex.Message);
        }
        finally
        {

        }
    }

此代码仍然存在与第一个代码相同的问题。不能返回除了void和task以外的类型,另外一个问题是如何动态获取数据?

【问题讨论】:

    标签: .net wpf async-await


    【解决方案1】:

    异步方法应该几乎总是返回TaskTask&lt;T&gt;,因为这就是异步的含义:该方法几乎立即返回,但实际上还没有完成。所以,要得到它的结果,你 await 返回的 Task。所以,你的方法看起来像这样:

    private async Task<CurrentUser> GetCurrentUserInfoFromServerAsync()
    {
        try
        {
            var response = await client.GetAsync("api/user");
            response.EnsureSuccessStatusCode(); 
            var currentuser = await response.Content.ReadAsAsync<currentUser>();
            return currentUser; // sets the result of the returned Task
        }
        catch (Newtonsoft.Json.JsonException jEx)
        {
            MessageBox.Show(jEx.Message);
        }
        catch (HttpRequestException ex)
        {
            MessageBox.Show(ex.Message);
        }
    }
    

    也就是说调用GetCurrentUserInfoFromServerAsync()的方法也必须是async,那个方法等等,一直到最上面。

    此外,将您的关注点分开是一个好习惯:您的HttpService 不应显示MessabeBoxes,而只是让异常传播到方法之外。您应该将 UI 处理留给更高层。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-05-21
      • 2014-12-16
      • 2011-07-04
      • 2014-01-19
      • 1970-01-01
      • 2013-07-02
      • 1970-01-01
      相关资源
      最近更新 更多