【问题标题】:System.Net.Http.HttpClient 4 ErrorsSystem.Net.Http.HttpClient 4 错误
【发布时间】:2021-09-08 16:14:59
【问题描述】:

我无法使用 HttpClient 对象从 WPF 应用程序执行发布或删除操作。 但我可以使用 HttpClient 进行 Get 和 GetById(string id) 操作。

HttpClient 的命名空间是 System.Net.Http。 [我尝试使用 Windows.Web.Http.HttpClient,但我无法将此 dll 添加为 WPF 项目中的引用。此 httpclient dll 必须从 Internet 下载。]

这是删除操作的代码。以下代码在 WPF 按钮的点击事件处理程序中。

   public void DeleteByID(string id)
    {
      HttpClient client = new HttpClient();  //system.net.http          
      client.BaseAddress = new Uri("http://localhost:44390/");             
      var url = "api/Player/" + id;
    
      HttpResponseMessage response = client.DeleteAsync(url).Result; **// ERROR here**

      response.EnsureSuccessStatusCode();
      if (response.IsSuccessStatusCode)
      {
        MessageBox.Show("User Deleted");                
      }
      else
      {
        MessageBox.Show("Error Code");
      }
   }

其对应的Web Api HttpDelete方法如下图:

   public class PlayerController : ApiController
      {
        SqlConnection con = new 
             SqlConnection(ConfigurationManager.ConnectionStrings["dbconnection"].ToString());
        SqlCommand cmd = new SqlCommand();
        SqlDataAdapter adp = null;

       [HttpDelete]
       public bool DeleteByID(string id)
       {
          bool isdeleted = false;
        
        try
        {
            cmd.CommandType = CommandType.Text;
            cmd.CommandText = "delete from tbl_Player where ID = '" + id + "'";
            cmd.Connection = con;
            if (con.State == ConnectionState.Open)
            {
                con.Close();
            }

            int res = cmd.ExecuteNonQuery();
            if (res > 0)
            {
                isdeleted = true;
            }
            else
            {
                isdeleted = false;                   
            }
            con.Close();
            return isdeleted;
        }
        catch
        {
            return isdeleted;
        }            
     }

     [HttpGet]
    public DataTable Get()
    {
        DataTable dt = new DataTable();
        try
        {
            cmd.CommandType = CommandType.Text;
            cmd.CommandText = "select * from tbl_Player";
            cmd.Connection = con;
            if (con.State == ConnectionState.Open)
            {
                con.Close();
            }
            adp = new SqlDataAdapter(cmd);
            dt.TableName = "tbl_Player";
            adp.Fill(dt);
            con.Close();
        }
        catch
        {

        }
        return dt;
    }
 }

我的 Player 类如下所示:

  public class Player
  {
    public int ID { get; set; }
    public string Name { get; set; }

    public int Age { get; set; }
    public string Place { get; set; }
    public string Country { get; set; }
    public bool IsActive { get; set; }
  }

在SQLServer中,表定义如下图。

 CREATE TABLE [dbo].[tbl_Player](
  [ID] [int] IDENTITY(1,1) NOT NULL,
  [Name] [varchar](50) NULL,
  [Age] [int] NULL,
  [Place] [varchar](50) NULL,
  [Country] [varchar](50) NULL,
  [IsActive] [bit] NULL,
  CONSTRAINT [PK_tbl_Player] PRIMARY KEY CLUSTERED 

下面是 Get 操作的工作代码,上面的控制器类中提到了它的 web api 方法。

   public void GetData()
     {
        HttpClient client = new HttpClient();
        client.BaseAddress = new Uri("https://localhost:44390/");
        
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

        HttpResponseMessage response = client.GetAsync("api/Player").Result;
        response.EnsureSuccessStatusCode();
        if (response.IsSuccessStatusCode)
        {
            var players = response.Content.ReadAsAsync<IEnumerable<Player>>().Result;
            dgPlayers.ItemsSource = players; // dgPlayers is the datagrid in WPF Window.
        }
        else
        {
            MessageBox.Show("Error Code");
        }
    }  

实际上,我遇到了 4 种错误。错误的详细信息如下:

System.AggregateException: '发生一个或多个错误。'

错误1:HttpRequestException:发送请求时发生错误。

错误号 2:WebException:底层连接已关闭:接收时发生意外错误。

Error No.3 : IOException: Unable to read data from the transport connection: 一个现有的连接被远程主机强行关闭。

错误号 4 : SocketException: 现有连接被远程主机强行关闭

我尝试了所有方法来解决它。我也使用了异步和等待。当我使用 async 和 await 时,没有抛出错误,它被卡在那里 - UI 变得没有响应。 DeleteById 方法中抛出错误。调用没有来到 web api 删除 web 方法。

请帮我解决这个问题。

谢谢

【问题讨论】:

  • 你能显示控制器动作吗?
  • @Serge 更新了问题。谢谢。
  • 不要阻止异步调用。使 DeleteByID 异步并使用 await client.DeleteAsync(url); 。发布实际的、完整的异常文本,而不仅仅是其中的一部分。您发布的部分表明 服务器 崩溃了。
  • 服务器操作很容易受到 SQL 注入攻击。如果ID 包含例如1'; drop table tbl;-,您的代码将删除该表。 catch 将隐藏之后发生的任何错误。服务器崩溃的事实表明在该操作之前引发了异常,可能在控制器的构造函数中。您应该添加适当的异常处理和日志记录而不是隐藏错误,否则几乎不可能发现问题
  • @Serge 我已经详细阐述了这个问题。请看一下。

标签: c# asp.net-web-api


【解决方案1】:

修复你的代码,移除连接关闭

        SqlCommand cmd1 = new SqlCommand();
        try
        {
            cmd1.CommandType = CommandType.Text;
            cmd1.CommandText = $"delete from tbl where ID = '{id}'";
            cmd1.Connection = con;
            if (con.State != ConnectionState.Open) con.Open();
            int res = cmd1.ExecuteNonQuery();                
            con.Close();                
        }
        catch
        {
            
        }            
    }

记住 sql 脚本注入。使用参数而不是字符串值。

【讨论】:

  • 我按照您的建议再次检查。实际上在到达 HttpDelete 方法之前,错误抛出 HttpResponseMessage response = client.DeleteAsync(url).Result; // 这里出错
  • @Johnny 你知道如何使用邮递员吗?尝试使用localhost:44390/api/Player + id 和删除方法进行测试。
【解决方案2】:

我解决了这个问题,我的代码运行良好,没有任何错误。 问题很简单。

    HttpClient client = new HttpClient();
    client.BaseAddress = new Uri("https://localhost:44390/");

我在 Uri 中使用“http”而不是“https”。这就是问题所在。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-17
    • 1970-01-01
    • 2018-04-25
    • 2012-06-04
    • 2015-08-15
    相关资源
    最近更新 更多