繁体   English   中英

在Xamarin和Android中使用C#在网页的登录表单中发布帖子

[英]Make a post to a login form of a webpage using C# in Xamarin and Android

我刚刚开始学习C#,并且从未在开发移动环境方面经历过。 我有Java方面的经验,可以从那里学到一些知识。

我拥有VisualStudio 2017RC,并启动了Xamarin.Android项目。 此外,还有一个用于注册和登录以及令牌生成(SQLite用户存储)的ASP.NET网站。 我的目标是在xamarin中进行查看,用户可以在其中键入他/她的名称和密码,然后可以登录到他/她获得访问令牌的网站。

我已经制作了一个LoginView,这真是小菜一碟……现在,我必须将填充的数据发布到网站上,并使用Xamarin.Android中的c#登录到页面。 让我们看看我走了多远。

protected override void OnCreate(Bundle bundle)
{
    base.OnCreate(bundle);

    SetContentView(Resource.Layout.LoginWebview);

    //code for getting the login details(emial, password) from the user
    //code for getting the access token
    //apiBaseUri is fixed value

    MainAsync(email, password, apiBaseUri, loginToken).Wait();
}


public static async Task MainAsync(string email, string password, string apiBaseUri, string loginToken)
{
    var token = await GetApiTokenAsync(email, password, apiBaseUri, loginToken);
}

public static async Task<string> GetApiTokenAsync(string email, string password, string apiBaseUri, string tokenValue)
{
    var token = string.Empty;

    var handler = new HttpClientHandler()
    {
        AllowAutoRedirect = false
    };


    using (var client = new HttpClient(handler))
    {
        client.BaseAddress = new Uri(apiBaseUri);
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        client.Timeout = TimeSpan.FromSeconds(60);

        //set cookie
        client.DefaultRequestHeaders.Add("Set-Cookie", CookieManager.Instance.GetCookie(apiBaseUri));

        //setup login data
        var formContent = new FormUrlEncodedContent(new[]
        {
 //new KeyValuePair<string, string>("grant_type", "password"),
 new KeyValuePair<string, string>("Email", username),
 new KeyValuePair<string, string>("Password", password),
 new KeyValuePair<string,string>("__RequestVerificationToken",tokenValue),
 new KeyValuePair<string,string>("RememberMe","false")
          });

        //send request               
        HttpResponseMessage responseMessage = await client.PostAsync("/Login?returnurl=%2FGame%2Fkz%2FToken", formContent);
        var responseJson = await responseMessage.Content.ReadAsStringAsync();
        var jObject = JObject.Parse(responseJson);
        token = jObject.GetValue("access_token").ToString();

        return token;
    }

}
}

好吧

HttpResponseMessage responseMessage = await client.PostAsync("/Login?returnurl=%2FGame%2Fkz%2FToken", formContent);

该程序挂起,我没有访问令牌。

让我们从网站的角度看问题:在网络浏览器中,可以使用以下链接打开登录表单:(我将在URL中使用一些虚拟值(“游戏”)以保持其私密性) http:/ /www.game.nl/PlayGame/kz/Account/Login?ReturnUrl=%2FGame%2Fkz%2Ftoken

打开这个网站,我可以输入电子邮件和密码。 然后,如果我单击登录按钮,我将获得一个访问令牌(将用于以后的目的)。 我想说到这一点,但是当然可以在带有Android手机的C#中使用

我将列出有关该网站的其他信息,因为我认为它们也与解决方案有关。 如果我通过网站登录,详细信息如下。 (我在网络标签上使用Google Chrome开发者工具检查了详细信息)

一般:

  • 请求网址: http ://www.game.nl/PlayGame/kz/Account/Login?returnurl =% 2FGame%2Fkz% 2Ftoken
  • 请求方法:POST
  • 状态码:302已找到
  • 远程地址:(私人)

FORMDATA:

  • 电子邮件:example@company.nl
  • 密码:chocolate09#
  • __RequestVerificationToken:CfDJ8L1aKkmfKmBLlQIwHTacxWKOtRekEcOfxKQGBrXUEkE2XpWyxYmMKOTlgZ7gCZq3FEx8ILF_VgQcsjBztZhCwUUYSV966s1BgjFs5I8IefGSoei5hfzK-WQQr8Ztjpn3oGq40neXx4_iBUUMRjFpKz_DdBqzQ
  • 与rememberMe:假

表单数据的来源:

电子邮件=示例%40company.nl&密码= chocolate09%23&__ RequestVerificationToken = CfDJ8L1aKkmfKmBLlQIwHTacxWKOtRekEcOfxKQGBrXUEkE2XpWyxYmMKOTlgZ7gCZq3FEx8ILF_VgQcsjBztZhCwUUYSV966s1BgjFs5I8IefGSoei5hfzK-WQQr8Ztjpn3oGq40neXx4_iBUUMRjFpKz_DdBqzQ&了rememberMe =假

所以我被困在这一点上,我不知道为什么它挂在

await client.PostAsync("/Login?returnurl=%2FGame%2Fkz%2FToken", formContent);

VS控制台输出的最后几行:

02-11 00:07:01.404 D/Mono    ( 2853): [0x982bf930] hill climbing, change max number of threads 2
02-11 00:07:07.829 D/Mono    ( 2853): [0x9847f930] worker finishing
Thread finished: <Thread Pool> #4
The thread 'Unknown' (0x4) has exited with code 0 (0x0).

我相信您的问题是OnCreate这一行:

MainAsync(email, password, apiBaseUri, loginToken).Wait();

特别是.Wait()语句。 总是在UI线程上调用OnCreate 每当您使用async / await并使用.Wait().Result .Wait()结果时,就会发生不好的事情,并且由于继续操作无法跳回到UI线程,您的应用程序将挂起-您将在对PostAsync的调用中PostAsync此内容是第一个实际上将使用其他线程运行的调用。

我猜你之所以调用.Wait()的原因是因为OnCreate不是异步方法-好消息是它可以。 我会将其标记为asyncawait登录(您可以将无效方法标记为异步,这样做有很多陷阱,因此请确保在方法内部捕获所有异常!)

// Mark the method as async
protected override async void OnCreate(Bundle bundle)
{
    base.OnCreate(bundle);

    SetContentView(Resource.Layout.LoginWebview);

    // remove the .Wait() and await the method call
    await MainAsync(email, password, apiBaseUri, loginToken);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM