Что использовать, если я хочу вернуть результат веб-клиента

Возьмите следующий код:

    public async Task<string> AuthenticatedGetData(string url, string token)
    {
        WebClient client = new WebClient();
        client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(WebClient_DownloadStringCompleted);
        client.DownloadStringAsync(new Uri(url + "?oauth_token=" + token));
    }

    private void WebClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
    {
        string response = e.Result;    
    }

WebClient_DownloadStringCompleted вызывается... и response = ответ, который я хочу... Отлично. идеально...

Теперь рассмотрим, как я вызываю этот метод AuthenticatedGetData:

Он вызывается из своего рода репозитория... Хранилищу нужна строка, чтобы он мог сериализоваться и что-то делать с результирующим объектом...

Таким образом, все выполняется асинхронно из репозитория... Вызов выполняется для authenticatedgetdata, затем он делает запрос... но поскольку downloadstringasync не имеет метода.Result(), и поскольку downloadstringcompleted требует вызова метода void... Я не могу вернуть строку результата в вызывающий репозиторий.

Любые идеи о том, что я должен сделать, чтобы получить client.DownloadStringAsync для возврата строки ответа по завершении?

Неужели мне просто нужно тесно связать свои операции доступа к данным с этим конкретным приложением... Кажется, это не может быть повторно использовано:(Я действительно хочу полностью отделить весь свой процесс аутентификации от того, что произойдет. не хочу повторять приведенный выше код для каждого репозитория, потому что в любом случае он будет одинаковым для каждого!

Редактировать:://

Я создал абстрактный метод в своем классе, который обрабатывает вышеупомянутые запросы... а затем я расширяю этот класс с помощью своего репозитория и реализую абстрактный метод. звучит неплохо?

Редактировать: // Код вызова по запросу:

public class OrganisationRepository
{
    PostRequest postRequest;

    public OrganisationRepository()
    {
        this.postRequest = new PostRequest();
    }
    public IEnumerable<Organisation> GetAll()
    {
        string requestUrl = BlaBla.APIURL + "/org/";
        string response = postRequest.AuthenticatedGetData(requestUrl, BlaBla.Contract.AccessToken).Result;
    }
}

public class PostRequest
{

    public Task<string> AuthenticatedGetData(string url, string token)
    {

        TaskCompletionSource<string> tcs = new TaskCompletionSource<string>();

        WebClient client = new WebClient();
        client.DownloadStringCompleted += (sender, e) =>
        {
            if (e.Error != null)
            {
                tcs.TrySetException(e.Error);
            }
            else if (e.Cancelled)
            {
                tcs.TrySetCanceled();
            }
            else
            {
                tcs.TrySetResult(e.Result);
            }
        };
        client.DownloadStringAsync(new Uri(url + "?oauth_token=" + token));
        return tcs.Task;
    }
}

2 ответа

Я не уверен, каковы ограничения Windows-Phone-8 в отношении этого. Но я думаю, что это должно работать.

public Task<string> AuthenticatedGetData(string url, string token)
    {
        TaskCompletionSource<string> tcs = new TaskCompletionSource<string>();

        WebClient client = new WebClient();
        client.DownloadStringCompleted += (sender, e) =>
        {
            if (e.Error != null)
            {
                tcs.TrySetException(e.Error);
            }
            else if (e.Cancelled)
            {
                tcs.TrySetCanceled();
            }
            else
            {
                tcs.TrySetResult(e.Result);
            }            
        };
        client.DownloadStringAsync(new Uri(url + "?oauth_token=" + token));
        return tcs.Task;
    }

Вы также могли бы сойти с рук с этим (не уверен, что он работает на Windows Phone 8)

public Task<string> AuthenticatedGetData(string url, string token)
    {
        WebClient client = new WebClient();
        return client.DownloadStringTaskAsync(new Uri(url + "?oauth_token=" + token));

    }

Решение состоит в том, чтобы вообще не использовать библиотеку WebClient. Вот в чем проблема: вы ожидаете свою асинхронную задачу AuthenticatedGetData, но она ничего не делает, потому что у задачи нет ожидающих вызовов, то есть она завершится мгновенно. Вызов.result для задачи всегда будет нулевым, потому что вы никогда не сможете вернуть значение в этом методе. WebClient полагается на вызов функции после запуска события DownloadCompleted. Однако никто не может точно знать, когда это произойдет, если только он не подпишется на этот обработчик события DownloadCompleted, что глупо. Я рекомендую создать настоящую службу асинхронных веб-запросов с использованием HttpWebRequest http://blogs.msdn.com/b/andy_wigley/archive/2013/02/07/async-and-await-for-http-networking-on-windows-phone.aspx удачи.

Другие вопросы по тегам