You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在ASP.NET WebForm中通过HttpClient调用ASP.NET Core Web API?

ASP.NET WebForms调用ASP.NET Core API无响应问题排查与解决

问题描述

我有两个项目:一个是基于ASP.NET Core 3.1(MVC)的Web API,另一个是ASP.NET WebForms网站(.NET Framework 4.8)。从WebForms网站调用Core API时没有响应,但在另一个.NET Core项目中,使用Page_Load里的相同HttpClient代码却能正常调用。

ASP.NET Core 3.1 API控制器代码

namespace User
{
    [Authorize]
    [Route("api/[controller]")]
    [ApiController]
    public class UserController : ControllerBase
    {   
        [HttpGet("GetUserDetailsByUserName/{userName}")]
        public IActionResult GetUserDetailsByUserName(string userName)
        {
            //根据userName从数据库获取数据
        }
        
        [HttpPost("AddNewUser")]        
        public ActionResult AddNewUser([FromBody] UserModel userModel)
        {
            //将新用户数据保存到数据库
        }       
    }
}

ASP.NET WebForms(.NET Framework 4.8)代码

using System;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

namespace WebApplication
{
    public partial class User : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            //调用GetUserDetailsByUserName();
            
            HttpClient httpClient = Client.GetClient();
            httpClient.BaseAddress = new Uri("https://*******/");   //DOT_NET_CORE_WEBSITE_URL
            httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", "TOKEN");  
            
            HttpResponseMessage httpResponseMessage;
            httpResponseMessage = await httpClient.GetAsync($"https://*******/GetUserDetailsByUserName/{userName}");    //此处无响应
            httpResponseMessage.EnsureSuccessStatusCode();
            string result = await httpResponseMessage.Content.ReadAsStringAsync();
        }       
    }
    
    public class Client
    {
        public static HttpClient GetClient()
        {
            var httpClientHandler = new HttpClientHandler();
            httpClientHandler.ServerCertificateCustomValidationCallback =
            (message, cert, chain, errors) => { return true; };
            httpClientHandler.UseDefaultCredentials = true;
            HttpClient httpClient = new HttpClient(httpClientHandler);
            httpClient.Timeout = TimeSpan.FromMinutes(10);
            httpClient.DefaultRequestHeaders.Accept.Clear();
            return httpClient;
        }
    }
    
    public class UserModel
    {
        public string UserName{get;set;}
        public string Password{get;set;}
    }
}

排查与解决办法

1. 修复异步方法使用问题

WebForms的Page_Load是同步方法,直接使用await会触发上下文死锁——ASP.NET Framework的同步上下文会等待异步操作完成,但await会捕获该上下文,导致线程阻塞。
解决: 将Page_Load标记为异步方法:

protected async void Page_Load(object sender, EventArgs e)
{
    // 原有业务逻辑保留,await正常使用
}

注:async void仅在页面事件处理程序中允许,其他场景尽量避免使用。

2. 修正请求URL路径错误

API的路由规则是api/[controller]/GetUserDetailsByUserName/{userName},完整路径应为https://xxx/api/User/GetUserDetailsByUserName/{userName},但现有代码的请求URL缺少api/User前缀。
解决: 调整请求URL,可结合BaseAddress使用相对路径:

httpClient.BaseAddress = new Uri("https://*******/");
// 使用相对路径调用
httpResponseMessage = await httpClient.GetAsync($"api/User/GetUserDetailsByUserName/{userName}");

3. 优化HttpClient实例管理

WebForms中每次创建新的HttpClient实例可能导致连接池耗尽,虽不是当前无响应的直接原因,但会引发长期稳定性问题。
优化方案: 将HttpClient改为静态单例:

public class Client
{
    private static readonly HttpClient _httpClient;

    static Client()
    {
        var httpClientHandler = new HttpClientHandler();
        httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true;
        httpClientHandler.UseDefaultCredentials = true;
        _httpClient = new HttpClient(httpClientHandler);
        _httpClient.Timeout = TimeSpan.FromMinutes(10);
        _httpClient.DefaultRequestHeaders.Accept.Clear();
    }

    public static HttpClient GetClient()
    {
        return _httpClient;
    }
}

4. 排查证书与权限冲突

  • 若API使用自签名证书,虽已关闭验证,但仍需确保WebForms服务器能正常访问API端点(可先用浏览器/Postman在WebForms服务器上测试API连通性)。
  • UseDefaultCredentials = true会发送当前Windows凭据,若API仅需Bearer Token授权,可能导致权限冲突,可尝试设置为false:
httpClientHandler.UseDefaultCredentials = false;

5. 避免同步上下文捕获

若仍存在死锁问题,可在await时使用ConfigureAwait(false)跳过同步上下文捕获:

httpResponseMessage = await httpClient.GetAsync($"api/User/GetUserDetailsByUserName/{userName}").ConfigureAwait(false);
string result = await httpResponseMessage.Content.ReadAsStringAsync().ConfigureAwait(false);

内容的提问来源于stack exchange,提问作者Prashant Girase

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 11:38:19