在 Xamarin Forms C# 中发送 HTTP Post 请求

14

在我开始之前,我想说我已经谷歌搜索过这个问题的解决方案,但要么是我没理解(因为我是新手),要么就不起作用。

我想做的是以以下格式向本地主机上的REST API发送JSON数据:

{
    "username" : "myusername",
    "password" : "mypass"
}

然后,我期望得到一个字符串令牌的回应,例如下面这个:

{
    "token" : "rgh2ghgdsfds"
}

如何发送JSON数据并从响应中解析令牌?我见过一些同步方法,但由于某些原因它们不起作用(或者只是因为我不知道它在哪个命名空间中)。如果您采用异步方式来处理这个问题,能否向我解释一下它的工作原理?

先行致谢。

3个回答

25

我使用HttpClient。一个简单的示例:

var client = new HttpClient();
client.BaseAddress = new Uri("localhost:8080");

string jsonData = @"{""username"" : ""myusername"", ""password"" : ""mypassword""}"

var content = new StringContent (jsonData, Encoding.UTF8, "application/json");
HttpResponseMessage response = await client.PostAsync("/foo/login", content);

// this result string should be something like: "{"token":"rgh2ghgdsfds"}"
var result = await response.Content.ReadAsStringAsync();

需要将"/foo/login"指向您的HTTP资源。例如,如果您有一个AccountController具有Login方法,则应使用类似于"/Account/Login"而不是"/foo/login"

总的来说,为了处理序列化和反序列化,我建议使用Json.Net等工具。

至于如何工作的问题,这里涉及到很多内容。如果您对异步/等待操作的工作原理有疑问,那么建议查看MSDN上的“使用Async和Await进行异步编程”


因为它是一个异步函数,使用了 await,我需要改变我的函数签名吗?目前我有:private void authLogin(string user, string pass)。 - alexcons
1
只需在方法签名中添加async:private async void authLogin(string user, string pass) - Jacob Shanley
2
请不要将其设置为void,如果出现异常,它将无法处理并导致应用程序崩溃。 - Cheesebaron
啊,是的,我至少会返回Task或Task<T>,其中T是在此处对您的程序有意义的任何类型。看起来Cheesebaron更新了他的答案 - Jacob Shanley
@JacobShanley,你应该只在事件处理程序中使用async void。在其他情况下,请将其设置为async Task<T>,其中T是返回类型,或者如果该方法不应返回任何内容,则设置为async Task - Matheus Rocha
是的,我非常清楚这一点。谢谢。 - Jacob Shanley

11

使用HttpClient应该相当容易。

类似这样的代码可能有效。但是,您可能需要以某种方式代理从设备/模拟器传输数据以访问您的服务器。

var client = new HttpClient();
var content = new StringContent(
    JsonConvert.SerializeObject(new { username = "myusername", password = "mypass" }));
var result = await client.PostAsync("localhost:8080", content).ConfigureAwait(false);
if (result.IsSuccessStatusCode)
{
    var tokenJson = await result.Content.ReadAsStringAsync();
}

这段代码可能会被放入以下签名的方法中:

private async Task<string> Login(string username, string password)
{
    // code
}

请注意不要使用void作为返回类型,而应该使用Task。如果在方法内部抛出任何异常,则该异常将不会上升并且将未能处理,这会导致应用程序崩溃。最佳实践是仅在事件或类似情况下使用void。在这些情况下,请确保适当处理所有可能的异常。

此外,上面的示例使用来自System.Net.HttpClientHttpClient。某些PCL配置文件不包括它。在这种情况下,您需要从NuGet添加Microsoft的HttpClient库。我还使用JSON.Net(Newtonsoft.Json)序列化带有用户名和密码的对象。

我还想指出,像这样以明文形式发送用户名和密码并不是真正推荐的做法,应该采用其他方式。

编辑:如果您在大多数版本上使用.NET Standard,则无需再从NuGet安装System.Net.HttpClient,因为它已经随之而来。


HttpClient属于哪个命名空间? - alexcons
System.Net.HttpClient - Cheesebaron

-1

尝试使用这段代码。

HttpClient httpClient = new HttpClient();

            httpClient.BaseAddress = new Uri(APIAddress); // Insert your API URL Address here.
            string serializedObject = JsonConvert.SerializeObject(data);
            HttpContent contentPost = new StringContent(serializedObject, Encoding.UTF8, "application/json");
            try
            {
                HttpResponseMessage response = await httpClient.PostAsync(ControllerWithMethod, contentPost);
                return response;
            }
            catch (TaskCanceledException ex)
            {
                throw;
            }
            catch (Exception ex)
            {
                return new HttpResponseMessage();
            }

仅提供代码的答案对新手没有帮助。 - Matthew Swallow

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接