簡體   English   中英

如何轉換aysnc帖子以進行同步?

[英]How can I transform my aysnc post to sync?

我編寫了一個C#程序,該程序以異步方式對供應商進行API調用以生成提交令牌。 然后,將此令牌附加到任何表單發布有效負載上,以驗證其完整性。 它可以作為獨立的.Net 4.6.1應用程序很好地工作。 我遇到的問題是將其集成到CMS中。 與CMS支持人員交談后,他們要求我將其改為同步操作。 我在轉換代碼時遇到問題。 特別是有關檢索令牌后發布表單的部分。

這是我最初編寫的源代碼。 顯然,AppID和機密已被刪除。

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Web.UI;

namespace FormSubmission
{
    public partial class _Default : Page
    {
        protected async void Page_Load(object sender, EventArgs e)
        {
            var start = new Start();
            await start.KickOff();
        }

        public class Start
        {

            public async Task<String> KickOff()
            {
                var auth = new Authentication();
                var token = await auth.Authenticate();

                // return await Task.FromResult(token);
                // //Task.FromResult(token);
                if (!String.IsNullOrEmpty(token))
                {
                    var form = new FormSubmission();
                    var formFields = new Form();
                    formFields.createMethod = "SubmitForm";
                    formFields.email = "email@email.com";
                    formFields.mobile = "555-555-5555";
                    formFields.remark = "Hello, hope this works";
                    formFields.attr.attr3 = "mnc";
                    formFields.attr.attr6 = "1000";
                    formFields.attr.attr10 = "first name";
                    formFields.attr.attr11 = "lastname";
                    formFields.attr.attr14 = "City";
                    formFields.attr.attr15 = "State";
                    formFields.attr.attr18 = "USA";
                    formFields.attr.attr25 = "USA";
                    formFields.attr.attr28 = "Newsletter";

                    var serializer = JsonSerializer.Create();

                    var optionsString = new StringBuilder();
                    var writer = new StringWriter(optionsString);

                    serializer.Serialize(writer, formFields);

                    await form.Submit(token, optionsString.ToString());
                }

                return await Task.FromResult("");

            }
        }

        public class Authentication 
        {
            private const string appId = "XXXXXXXXXXXXX";
            private const string secret = "XXXXXXXXXXXXXXXXXXXXXX";

            public async Task<String> Authenticate()
            {
                string url = "https://api-url-goes-here";
                string token = "";

                try
                {

                    using (var client = new HttpClient())
                    {
                        var responseMessage = await client.GetAsync(url + appId + "&secret=" + secret);
                        var content = await responseMessage.Content.ReadAsStringAsync();
                        var contentObject = JObject.Parse(content);
                        token = contentObject["access_token"].ToString();
                        return token;
                    };
                }
                catch (Exception e)
                {
                    throw new Exception("Access token not found");
                }

            }
        }

        public class FormSubmission
        {

            public async Task Submit(string token, string json)
            {
                using (var client = new HttpClient())
                {
                    var message = await client.PostAsync(
                        "https://api-url-goes-here/access_token=" + token,
                        new StringContent(json, Encoding.UTF8, "application/json"));

                    var content = await message.Content.ReadAsStringAsync();
                    Console.Write(content);
                }
            }
        }
    }
}

在與我的CMS版本的.Net相匹配的新.Net項目中運行時,此代碼非常有用。 但是再次,他們告訴我它不支持異步操作(這看起來很奇怪,但是我顯然不是一個出色的C#開發人員)

所以我重寫了它。

public class Attr
{
    public string attr3;
    public string attr6;
    public string attr10;
    public string attr11;
    public string attr14;
    public string attr15;
    public string attr18;
    public string attr25;
    public string attr28;
}

public class FormSubmission
{
    public string mobile;
    public string email;
    public string remark;
    public string createMethod;
    public Attr attr = new Attr();
}
protected void Page_Load(object sender, EventArgs e)
{

    string token = fetchToken();


    var formFields = new FormSubmission();
    formFields.createMethod = "SubmitForm";
    formFields.email = "email@email.com";
    formFields.mobile = "5555555555";
    formFields.remark = "Non sync";
    formFields.attr.attr3 = "mnc";
    formFields.attr.attr6 = "1000";
    formFields.attr.attr10 = "first name";
    formFields.attr.attr11 = "last name";
    formFields.attr.attr14 = "City";
    formFields.attr.attr15 = "State";
    formFields.attr.attr18 = "USA";
    formFields.attr.attr25 = "USA";
    formFields.attr.attr28 = "Newsletter";

    var serializer = JsonSerializer.Create();

    var optionsString = new StringBuilder();
    var writer = new StringWriter(optionsString);

    serializer.Serialize(writer, formFields);


    var x = new submitForm();
    x.Submit(token, optionsString.ToString());
}

protected string fetchToken()
{

    string appId = "xxxxxxxxxxxxxxx";
    string secret = "xxxxxxxxxxxxxxxxxxxxxxxxxx";
    string url = "https://api-url-goes-here/security/accesstoken?grant_type=client_credentials&appid=";

    string token;

    try
    {
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url + appId + "&secret=" + secret);
        request.Method = "GET";
        request.KeepAlive = false;
        request.ContentType = "appication/json";

        HttpWebResponse response = (HttpWebResponse)request.GetResponse();

        string myResponse = "";

        using (System.IO.StreamReader sr = new System.IO.StreamReader(response.GetResponseStream()))
        {
            myResponse = sr.ReadToEnd();
        }

        JObject jobj = JObject.Parse(myResponse);
        token = jobj["access_token"].ToString();

        return token;


    }
    catch (Exception e)
    {
        return e.ToString();
    }

}

public class submitForm
{
    public void Submit(string token, string json)
    {
        using (var client = new HttpClient())
        {
            var message = client.PostAsync("https://api-url-goes-here/v1/customers?access_token=" + token,
                new StringContent(json, Encoding.UTF8, "application/json"));

        }
    }
}

如您所見,它應該是相同的代碼。 我正在運行的問題,如SubmitForm類上的Submit方法。 當我運行程序並打開提琴手時,我可以看到為獲取令牌而進行的請求。 並且接收到令牌。 是SubmitForm類給了我一些問題。 我什至沒有在提琴手中看到POST請求。 誰能幫我嗎?

這是給我麻煩的課。

public class submitForm
{
    public void Submit(string token, string json)
    {
        using (var client = new HttpClient())
        {
            var message = client.PostAsync("https://api-url-goes-here/v1/customers?access_token=" + token,
                new StringContent(json, Encoding.UTF8, "application/json"));

        }
    }
}
public void Submit(string token, string json)
{
    using (var client = new HttpClient())
    {
        var message = client.PostAsync("https://api-url-goes-here/v1/customers?access_token=" + token,
            new StringContent(json, Encoding.UTF8, "application/json"));

    }
}

這不符合您的預期,因為message現在是Task ,而不是您希望的響應,因為您沒有等到PostAsync完成。

要使此同步,您有兩個選擇:

  1. 對其調用.GetAwaiter().GetResult() 可以在您之前使用await任何地方使用該方法,並且不存在該方法的同步版本。 例如:
public void Submit(string token, string json)
{
    using (var client = new HttpClient())
    {
        var message = client.PostAsync(
            "https://api-url-goes-here/access_token=" + token,
            new StringContent(json, Encoding.UTF8, "application/json")).GetAwaiter().GetResult();

        var content = message.Content.ReadAsStringAsync().GetAwaiter().GetResult();
        Console.Write(content);
    }
}

之所以使用.GetAwaiter().GetResult()而不是只.Result描述這里 (基本上因為異常是如何被拋出)。

要么,

  1. 使用HttpWebRequest而不是HttpClient進行相同的請求,就像在代碼的另一部分中所做的一樣,因此您不必處理僅異步方法。

這可能不是您想聽到的,但您不應將異步轉換為同步方法。 當您使用GetAwaiter().GetResult()時,您可能會幸運地發現它們可以工作,但存在死鎖的風險,或者它們無法正常工作。 您可以先使用Task.Run然后再運行GetAwaiter().GetResult()來運行它們,但這會旋轉另一個線程,因此效率不是很高,並且您的代碼仍在阻塞。 使它比同步代碼慢,因為它必須旋轉另一個線程。 另外,它肯定會分配gc必須處理的更多內存。

您還應該使用Async后綴來命名異步方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM