wake-up-neo.com

Konvertieren einer normalen HTTP-Post-Webanforderung mit Async und Await

Wie kann ich meinen traditionellen HttpWebRequest "POST" -Aufruf mit Async/Await-Muster konvertieren? Hier füge ich meinen aktuellen Code hinzu. Bitte helfen Sie mir, diesen Code mit Async/Await-Muster für Windows Phone 8 zu konvertieren.

public void GetEnvironmentVariables(Action<Credentials> getResultCallback, Action<Exception> getErrorCallback)
{
    CredentialsCallback = getResultCallback;
    ErrorCallback = getErrorCallback;
    var uri = new Uri(BaseUri);
    var request = (HttpWebRequest)WebRequest.Create(uri);
    request.Method = "POST";
    request.ContentType = "application/json";
    var jsonObject = new JObject
    {
        new JProperty("apiKey",_api),
        new JProperty("affiliateId",_affid),
    };
    var serializedResult = JsonConvert.SerializeObject(jsonObject);
    byte[] requestBody = Encoding.UTF8.GetBytes(serializedResult);

    request.BeginGetRequestStream(GetRequestStreamCallback, new object[] { request, requestBody });

}

private void GetRequestStreamCallback(IAsyncResult asynchronousResult)
{
    var request = (HttpWebRequest)((object[])asynchronousResult.AsyncState)[0];
    using (var postStream = request.EndGetRequestStream(asynchronousResult))
    {
        var byteArray = (byte[])((object[])asynchronousResult.AsyncState)[1];

        // Write to the request stream.
        postStream.Write(byteArray, 0, byteArray.Length);

    }
    request.BeginGetResponse(GetResponseCallback, request);
}

private void GetResponseCallback(IAsyncResult asynchronousResult)
{
    var request = (HttpWebRequest)asynchronousResult.AsyncState;
    try
    {
        var response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
        if (response != null)
        {
            var reader = new StreamReader(response.GetResponseStream());
            string responseString = reader.ReadToEnd();
            Credentails = JsonConvert.DeserializeObject<Credentials>(responseString);
            if (Credentails != null && string.IsNullOrEmpty(Credentails.Err))
                CredentialsCallback(Credentails);
            else
            {
                if (Credentails != null)
                    ErrorCallback(new Exception(string.Format("Error Code : {0}", StorageCredentails.Err)));
            }
        }
    }
    catch (WebException we)
    {
            var reader = new StreamReader(we.Response.GetResponseStream());
            string responseString = reader.ReadToEnd();
            Debug.WriteLine(responseString);
            ErrorCallback(we);

    }
} 
23
Nitha Paul

Da Windows Phone 8 anscheinend nicht die erforderlichen TAP-Methoden wie GetRequestStreamAsync bietet, müssen Sie zunächst einen kleinen Wrapper schreiben, um diese für sich selbst bereitzustellen:

public static class WebRequestAsyncExtensions
{
    public static Task<Stream> GetRequestStreamAsync(this WebRequest request)
    {
        return Task.Factory.FromAsync<Stream>(
            request.BeginGetRequestStream, request.EndGetRequestStream, null);
    }

    public static Task<WebResponse> GetResponseAsync(this WebRequest request)
    {
        return Task.Factory.FromAsync<WebResponse>(
            request.BeginGetResponse, request.EndGetResponse, null);
    }
}

Beachten Sie die Verwendung von Task.Factory.FromAsync - dies ist die bevorzugte Methode, um einen await-freundlichen Wrapper für eine APM-basierte asynchrone API zu erhalten, wie die von WebRequest angebotenen. Dies ist weitaus effizienter als die Verwendung von Task.Factory.StartNew, wie von jemand anderem vorgeschlagen, da dies einen neuen Thread auslösen würde, während dies nicht erforderlich ist.

Mit dieser Funktion können Sie Ihren Code jetzt auf die gleiche Weise wie auf Plattformen schreiben, auf denen diese Methoden im TAP-Stil verfügbar sind (z. B. Windows 8-Store-Apps, Desktop-Apps usw.):

public async Task GetEnvironmentVariablesAsync(Action<Credentials> getResultCallback, Action<Exception> getErrorCallback)
{
    CredentialsCallback = getResultCallback;
    ErrorCallback = getErrorCallback;
    var uri = new Uri(BaseUri);
    var request = (HttpWebRequest) WebRequest.Create(uri);
    request.Method = "POST";
    request.ContentType = "application/json";
    var jsonObject = new JObject
    {
        new JProperty("apiKey",_api),
        new JProperty("affiliateId",_affid),
    };
    var serializedResult = JsonConvert.SerializeObject(jsonObject);
    byte[] requestBody = Encoding.UTF8.GetBytes(serializedResult);

    // ASYNC: using awaitable wrapper to get request stream
    using (var postStream = await request.GetRequestStreamAsync())
    {
        // Write to the request stream.
        // ASYNC: writing to the POST stream can be slow
        await postStream.WriteAsync(requestBody, 0, requestBody.Length);
    }

    try
    {
        // ASYNC: using awaitable wrapper to get response
        var response = (HttpWebResponse) await request.GetResponseAsync();
        if (response != null)
        {
            var reader = new StreamReader(response.GetResponseStream());
            // ASYNC: using StreamReader's async method to read to end, in case
            // the stream i slarge.
            string responseString = await reader.ReadToEndAsync();
            Credentails = JsonConvert.DeserializeObject<Credentials>(responseString);
            if (Credentails != null && string.IsNullOrEmpty(Credentails.Err))
                CredentialsCallback(Credentails);
            else
            {
                if (Credentails != null)
                    ErrorCallback(new Exception(string.Format("Error Code : {0}", StorageCredentails.Err)));
            }
        }
    }
    catch (WebException we)
    {
        var reader = new StreamReader(we.Response.GetResponseStream());
        string responseString = reader.ReadToEnd();
        Debug.WriteLine(responseString);
        ErrorCallback(we);

    }
}

Beachten Sie die vier Zeilen mit // ASYNC: Kommentaren - diese zeigen, wo ich Änderungen vorgenommen habe. Ich habe Ihre Methode auf eine reduziert, da dies a) möglich ist, sobald Sie async und await verwenden, und b) viel einfacher ist, als Dinge mit Statusargumenten von einer Methode zur nächsten zu übergeben.

Beachten Sie, dass beim zweiten und vierten Vorgang einige Dinge, die Sie zuvor synchron ausgeführt haben, tatsächlich asynchronisiert werden: Schreiben von Daten in den Anforderungsdatenstrom und Lesen von Daten aus dem Antwortdatenstrom. Für eine kleine Anfrage spielt dies wahrscheinlich keine Rolle, aber wenn große Datenmengen übertragen werden, kann ein synchroner Aufruf von Write oder ReadToEnd blockiert werden. Obwohl Windows Phone 8 die TAP-Methoden für WebRequest zu fehlen scheint, bietet es sie zum Glück für Stream und StreamReader an, sodass keine Erweiterungsmethoden geschrieben werden müssen.

20
Ian Griffiths

Ich bin neu in der Community und hier ist mein erster Beitrag. In diesem Fall können Sie jeden Typ mit einer generischen Task zurückgeben. Das hat in der Vergangenheit für mich gut funktioniert.

Serverseite

public class MyController : ApiController
{
    public Task<string> PostAsync()
    {
        return Task.Factory.StartNew(() =>
        {
            return "populate me with any type and data, but change the type in the response signature.";
        });
    }
}

Client-Seite

public class HomeController : Controller
{
    public Task<ViewResult> Index()
    {
        return Task.Factory.StartNew(() =>
        {
            var model = "use a provider, get some data, or something";
            return View(model);
        });
    }
}
2
user586588

Dies sollte den Job machen:

    public async void GetEnvironmentVariables(Action<Credentials> getResultCallback, Action<Exception> getErrorCallback) {
        CredentialsCallback = getResultCallback;
        ErrorCallback = getErrorCallback;
        var uri = new Uri(BaseUri);
        var request = (HttpWebRequest)WebRequest.Create(uri);
        request.Method = "POST";
        request.ContentType = "application/json";

        var jsonObject = new JObject {
            new JProperty("apiKey", _api),
            new JProperty("affiliateId", _affid),
        };

        var serializedResult = JsonConvert.SerializeObject(jsonObject);
        var requestBody = Encoding.UTF8.GetBytes(serializedResult);

        var requestStream = request.GetRequestStream();
        requestStream.Write(requestBody, 0, requestBody.Length);

        await GetResponse(request);
    }

    private async Task GetResponse(WebRequest request) {
        Stream resStream = null;

        try {
            var response = await request.GetResponseAsync();

            if (response == null) {
                return;
            }

            resStream = response.GetResponseStream();
            if (resStream == null) {
                return;
            }

            var reader = new StreamReader(resStream);
            var responseString = await reader.ReadToEndAsync();
            Credentails = JsonConvert.DeserializeObject<Credentials>(responseString);
            if (Credentails != null && string.IsNullOrEmpty(Credentails.Err)) {
                CredentialsCallback(Credentails);
            }
            else {
                if (Credentails != null) {
                    ErrorCallback(new Exception(string.Format("Error Code : {0}", StorageCredentails.Err)));
                }
            }
        }
        catch (WebException we) {
            if (resStream != null) {
                var reader = new StreamReader(resStream);
                var responseString = reader.ReadToEnd();
                Debug.WriteLine(responseString);
            }
            ErrorCallback(we);
        }
    }
0
lboshuizen