【问题标题】:What is the correct way to call ASP.NET web APIs from Xamarin mobile app using C# especially for post method使用 C# 从 Xamarin 移动应用程序调用 ASP.NET Web API 的正确方法是什么,尤其是对于 post 方法
【发布时间】:2020-08-23 11:36:02
【问题描述】:

我创建了一个 ASP.NET Web API 项目,其中创建了两个 api 控制器,一个是获取所有注册用户,第二个是通过用户名和密码登录到应用程序。虽然我用邮递员测试了这两种方法,但工作正常。我正在使用 BaseAddress 属性来放置 URI,并将“api/controllername/action”放在 PostAsJsonAsync() 方法中。当我调试我的 xamarin 应用程序代码时,它在 PostAsJasonAsync() 方法中显示-

{StatusCode: 400, ReasonPhrase: 'Bad Request', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
  Connection: close
  Date: Sun, 23 Aug 2020 11:13:44 GMT
  Forwarded: host=192.168.20.176:45459; proto=http
  Server: Microsoft-HTTPAPI/2.0
  X-Android-Received-Millis: 1598181223781
  X-Android-Response-Source: NETWORK 400
  X-Android-Selected-Protocol: http/1.1
  X-Android-Sent-Millis: 1598181223764
  Content-Length: 374
  Content-Type: text/html; charset=us-ascii}.

Web API 控制器代码是:

    public class LoginController : ApiController
    {
        SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["SPCon"].ToString());
        SqlCommand cmd = new SqlCommand();

        [HttpPost]
        public int Login([FromBody] Login user)
        {
            int ret = 0;
            try
            {
                cmd.CommandType = CommandType.Text;
                cmd.CommandText = "SELECT count(*) FROM Login WHERE UserNames = '" + user.UserName.Trim() + "' and PassWord=" + user.PassWord.Trim();
                cmd.Connection = con;
                if (con.State == ConnectionState.Open)
                {
                    con.Close();
                }
                con.Open();
                ret = Convert.ToInt32(cmd.ExecuteScalar());
                con.Close();
            }
            catch
            {

            }
            return ret;
        }

    }

移动应用代码如下:

public void LoginBtnClicked()
        {
            if (Username.Trim() != "" && Password.Trim() != "")
            {
                using(var client=new HttpClient())
                {
                    client.BaseAddress = new Uri("http://ipaddress:45459/"); //I'm using conveyor to get this address and I'm running mobile app in android emulator
                    client.DefaultRequestHeaders.Accept.Clear();
                    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                    UserLogin user = new UserLogin
                    {
                        UserName = Username,
                        PassWord = Password
                    };
                    var response = client.PostAsJsonAsync("api/Login/Login", user).Result;
                    if (response.IsSuccessStatusCode)
                    {
                        var a = response.Content.ReadAsStringAsync();
                        if (a.Result.ToString().Trim() == "0")
                        {
                            Application.Current.MainPage.DisplayAlert("Error", "Invalid Login Credentials", "Cancel");
                        }
                        else
                        {
                            Application.Current.MainPage.Navigation.PushAsync(new Home());
                        }
                    }
                    else
                    {
                        Application.Current.MainPage.DisplayAlert("Error", "Internal Server Error", "Ok");
                    }
                    
                }
            }
        }

【问题讨论】:

  • 服务端的Login类和客户端的UserLogin类定义一样吗?
  • 是的,定义相同
  • 解决问题的最佳方法是使用像 wireshark 或 fiddler 这样的嗅探器。使用 Postman 将第一个请求中的标头与 c# 标头进行比较。使 c# 代码看起来与 Postman 完全一样。 c# 中的默认标头与 Postman 不同,要么标头错误,要么标头缺失。
  • 就像@jdweng 说的,你应该检查你添加的标题。邮递员通常会添加一些通用标题,尤其是未包含的 language 在过去给我带来了问题。但就目前而言,没有办法确切知道问题是什么
  • 您可能需要指定 TLS 版本 1.2 : HttpClient httpClient = new HttpClient(); //指定使用 TLS 1.2 作为默认连接 System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

标签: c# android asp.net-web-api xamarin.forms httpclient


【解决方案1】:

感谢您为我的问题付出的努力。我通过更改在客户端调用 Web API 的过程找到了解决方案。我使用 HttpContent 和 PostAsync() 方法而不是 BaseAddress 和 PostAsJsonAsync() 方法。代码如下:

using(HttpClient client=new HttpClient())
                {
                    UserLogin user = new UserLogin
                    {
                        UserName = Username,
                        PassWord = Password
                    };
                    var json = JsonConvert.SerializeObject(user);
                    HttpContent content = new StringContent(json);
                    content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                    var uri = new Uri("http://ipaddress/api/UserLogin");
                    var response = await client.PostAsync(uri, content);

                    //more conditions and code....
                }

【讨论】:

    猜你喜欢
    • 2014-09-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-08
    • 2022-07-23
    • 2013-06-18
    • 2021-04-18
    • 2011-07-29
    • 1970-01-01
    相关资源
    最近更新 更多