Как я могу преобразовать мой пост в aysnc для синхронизации? - PullRequest
0 голосов
/ 06 декабря 2018

Я написал 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);
                }
            }
        }
    }
}

Этот код отлично работает при запуске в новом проекте .Net, который соответствует версии .Net моей CMS.Но опять же, они сказали мне, что он не поддерживает асинхронные операции (что кажется странным, но я не очень хороший разработчик для 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"));

        }
    }
}

Как видите, это должен быть тот же код.Проблема, с которой я работаю, как в методе Submit в классе submitForm.Когда я запускаю свою программу и открываю fiddler, я вижу запрос на получение токена.И токен получен.Это класс submitForm, который вызывает у меня проблемы.Я даже не вижу POST-запрос в Fiddler.Может кто-нибудь мне помочь?

Вот класс, который доставляет мне проблемы.

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"));

        }
    }
}

Ответы [ 2 ]

0 голосов
/ 06 декабря 2018

Это, вероятно, не то, что вы хотите услышать, но вы не должны преобразовывать асинхронный в синхронный метод.Возможно, вам повезет, что они работают, когда вы используете GetAwaiter().GetResult(), но есть риск тупика, или они просто не работают должным образом.Вы можете запустить их с Task.Run, а затем GetAwaiter().GetResult(), но это будет вращать другой поток, так что это не очень эффективно, и ваш код все еще блокируется.Делая это медленнее, чем синхронный код, потому что он должен вращать другой поток.Кроме того, он, безусловно, выделяет больше памяти, которую должен обрабатывать gc.

Вы также должны называть свои асинхронные методы суффиксом Async.

0 голосов
/ 06 декабря 2018
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 описана здесь (в основном из-за того, как генерируются исключения).

Или,

Сделайте тот же запрос с HttpWebRequest вместо HttpClient, как вы это делали в другой части вашего кода, чтобы вам не приходилось иметь дело с асинхронными методами.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...