我该如何在Windows Phone 7上使用RestSharp实现ExecuteAsync?

35
我将尝试使用RestSharp GitHub wiki上的文档来实现对我的REST API服务的调用,但是我在特别是ExecuteAsync方法方面遇到了问题。
目前我的API类代码如下:
public class HarooApi
{
    const string BaseUrl = "https://domain.here";

    readonly string _accountSid;
    readonly string _secretKey;

    public HarooApi(string accountSid, string secretKey)
    {
        _accountSid = accountSid;
        _secretKey = secretKey;
    }

    public T Execute<T>(RestRequest request) where T : new()
    {
        var client = new RestClient();
        client.BaseUrl = BaseUrl;
        client.Authenticator = new HttpBasicAuthenticator(_accountSid, _secretKey);
        request.AddParameter("AccountSid", _accountSid, ParameterType.UrlSegment);
        client.ExecuteAsync<T>(request, (response) =>
        {
            return response.Data;
        });
    }
}

我知道这与GitHub页面上的内容略有不同,但我正在使用WP7,并且认为示例是针对C#的,因此使用ExecuteAsync方法。
我的问题是ExecuteAsync命令应该包含什么。我不能使用return response.Data,因为我收到了警告:
'System.Action<RestSharp.RestResponse<T>,RestSharp.RestRequestAsyncHandle>' returns void, a return keyword must not be followed by an object expression

有人对如何修复这个问题有任何见解或者有可能帮助的教程吗?

6个回答

50

虽然这个问题比较老,但如果你正在使用C# 5,你可以创建一个返回T类型任务的TaskCompleteSource,从而拥有一个通用的执行类。你的代码可以像这样:

public Task<T> ExecuteAsync<T>(RestRequest request) where T : new()
    {
        var client = new RestClient();
        var taskCompletionSource = new TaskCompletionSource<T>();
        client.BaseUrl = BaseUrl;
        client.Authenticator = new HttpBasicAuthenticator(_accountSid, _secretKey);
        request.AddParameter("AccountSid", _accountSid, ParameterType.UrlSegment);
        client.ExecuteAsync<T>(request, (response) => taskCompletionSource.SetResult(response.Data));
        return taskCompletionSource.Task;
    }

然后像这样使用:

private async Task DoWork()
    {
        var api = new HarooApi("MyAcoountId", "MySecret");
        var request = new RestRequest();
        var myClass = await api.ExecuteAsync<MyClass>(request);

        // Do something with myClass
    }

我需要一个字符串响应来解决我的问题。但是这一行代码真的帮了我很多: client.ExecuteAsync<T>(request, (response) => taskCompletionSource.SetResult(response.Data)); 我之前不确定如何直接返回响应而不是使用回调,现在找到了解决方法。如果有人想使用这个,请将response.Data替换为response.Content,并从所有地方删除T。 - Alek Arsovski
我必须询问 - 您如何通过NotYetExecuted状态?我今天一直在尝试这个示例,但是无法获得任何结果。非常感谢任何帮助。 - Richard Griffiths

33
作为Gusten提供的fine answer的替代方案(或补充),您可以使用ExecuteAsync。这样,您就不必手动处理TaskCompletionSource。请注意签名中的async关键字。 更新:106.4.0起,ExecuteTaskAsync已过时。自104.2起,应改用ExecuteAsync
public async Task<T> ExecuteAsync<T>(RestRequest request) where T : new()
{
    var client = new RestClient();
    client.BaseUrl = BaseUrl;
    client.Authenticator = new HttpBasicAuthenticator(_accountSid, _secretKey);
    request.AddParameter("AccountSid", _accountSid, ParameterType.UrlSegment);
    IRestResponse<T> response = await client.ExecuteAsync<T>(request);
    return response.Data;
}

旧答案:

public async Task<T> ExecuteAsync<T>(RestRequest request) where T : new()
{
    var client = new RestClient();
    client.BaseUrl = BaseUrl;
    client.Authenticator = new HttpBasicAuthenticator(_accountSid, _secretKey);
    request.AddParameter("AccountSid", _accountSid, ParameterType.UrlSegment);
    IRestResponse<T> response = await client.ExecuteTaskAsync<T>(request); // Now obsolete
    return response.Data;
}

1
这就是我一直在寻找的答案...谢谢!比其他解决方案简单得多(虽然不一定是OP想要的)。 - reidLinden
如何从此方法的输出中访问 StatusCode - Mehdi Dehghani
我不确定我是否理解。上面的示例根本没有使用StatusCode。你可以返回response而不是返回response.Data。然后你需要将返回类型更改为Task<IRestResponse<T>> - smoksnes

32

您的代码应该类似于这样:

public class HarooApi
{
    const string BaseUrl = "https://domain.here";

    readonly string _accountSid;
    readonly string _secretKey;

    public HarooApi(string accountSid, string secretKey)
    {
        _accountSid = accountSid;
        _secretKey = secretKey;
    }

    public void ExecuteAndGetContent(RestRequest request, Action<string> callback)
    {
        var client = new RestClient();
        client.BaseUrl = BaseUrl;
        client.Authenticator = new HttpBasicAuthenticator(_accountSid, _secretKey);
        request.AddParameter("AccountSid", _accountSid, ParameterType.UrlSegment);
        client.ExecuteAsync(request, response =>
        {
            callback(response.Content);
        });
    }

    public void ExecuteAndGetMyClass(RestRequest request, Action<MyClass> callback)
    {
        var client = new RestClient();
        client.BaseUrl = BaseUrl;
        client.Authenticator = new HttpBasicAuthenticator(_accountSid, _secretKey);
        request.AddParameter("AccountSid", _accountSid, ParameterType.UrlSegment);
        client.ExecuteAsync<MyClass>(request, (response) =>
        {
            callback(response.Data);
        });
    }
}
我添加了两个方法,这样你就可以检查你想要的东西(响应正文中的字符串内容,或由MyClass表示的反序列化类)。

你的示例也有相同的语法错误,无法编译。ExecuteAsync 的第二个参数是 Action<RestResponse>,因此不能在其中使用 return - nemesv
抱歉,我已经修复了示例,请现在尝试它(请注意:这些方法是异步的,因此除非使用.NET Async Task,否则无法直接返回结果)。 - Pedro Lamas
9
有人可以告诉我如何使用ExecuteAndGetMyClass吗? - Nil Pun
1
回调在当前上下文中不存在。 - Parth Savadiya
尝试使用此解决方案时,我收到以下错误: 错误 CS1593 委托“Action<IRestResponse, RestRequestAsyncHandle>”不接受1个参数。 - Kevin Burton

7
更精确地说,就像这样:
    public async Task<IRestResponse<T>> ExecuteAsync<T>(IRestRequest request) where T : class, new()
    {
        var client = new RestClient(_settingsViewModel.BaseUrl);

        var taskCompletionSource = new TaskCompletionSource<IRestResponse<T>>();
        client.ExecuteAsync<T>(request, restResponse =>
        {
            if (restResponse.ErrorException != null)
            {
                const string message = "Error retrieving response.";
                throw new ApplicationException(message, restResponse.ErrorException);
            }
            taskCompletionSource.SetResult(restResponse);
        });

        return await taskCompletionSource.Task;
    }

1
以下完成了工作。
public async Task<IRestResponse<T>> ExecuteAsync<T>(IRestRequest request) where T : class, new()
{
    var client = new RestClient
    {
        BaseUrl = _baseUrl,
        Authenticator = new HttpBasicAuthenticator(_useraname, _password),
        Timeout = 3000,
    };

    var tcs = new TaskCompletionSource<T>();
    client.ExecuteAsync<T>(request, restResponse =>
    {
        if (restResponse.ErrorException != null)
        {
            const string message = "Error retrieving response.";
            throw new ApplicationException(message, restResponse.ErrorException);
        }
        tcs.SetResult(restResponse.Data);
    });

    return await tcs.Task as IRestResponse<T>;

}

这个函数调用是如何实现的?是这样的吗:var myclass = await apiService.ExecuteAsync<MyClass>(request); - DogEatDog

1

由于public static RestRequestAsyncHandle ExecuteAsync(this IRestClient client, IRestRequest request, Action<IRestResponse> callback)已被弃用,您应该使用public Task<IRestResponse> ExecuteAsync(IRestRequest request, CancellationToken token = default)

以下是代码:

client.ExecuteAsync(request, response => { callback(response.Content); });

应该改为:

应该改为

await client.ExecuteAsync(request).ContinueWith(task => callback(task.Result.Content));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接