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

MVC调用API无数据返回问题排查(Postman可正常获取数据)

问题排查与解决方案

API通过Postman请求正常返回数据,但MVC调用后前端无数据显示且无错误,可从以下几点逐一排查:

1. 空搜索参数的路由匹配问题

当搜索框为空时,MVC控制器的search参数为null,拼接后的API URL会变成https://localhost:7198/api/Expense/ListExpenseByAccountingSearch/,而API路由{search}要求必须传入参数,导致API返回404,但MVC控制器会返回空列表,前端因此拿到空数据。

解决方法:

  • 方案一:修改API路由允许可选参数:
    [HttpGet("ListExpenseByAccountingSearch/{search?}")]
    public async Task<IActionResult> ListExpenseByAccountingSearch(string search = "")
    {
        var values = await _expenseService.itemListExpenseByAccountingSearch(search ?? "");
        return Ok(values);
    }
    
  • 方案二:在MVC控制器中处理空参数:
    var searchParam = string.IsNullOrEmpty(search) ? "" : search;
    var responseMessage = await client.GetAsync($"https://localhost:7198/api/Expense/ListExpenseByAccountingSearch/{searchParam}");
    

2. 特殊字符的URL编码问题

搜索文本包含空格、&、=等特殊字符时,直接拼接URL会导致参数传递失真,API接收到的参数与预期不符,返回空结果。

解决方法:

  • 前端Ajax编码搜索参数:
    url: "/Management/Accounting/ListExpenseByAccountingSearch/" + encodeURIComponent(searchText),
    
  • 或在MVC控制器中编码参数:
    var encodedSearch = Uri.EscapeDataString(search ?? "");
    var responseMessage = await client.GetAsync($"https://localhost:7198/api/Expense/ListExpenseByAccountingSearch/{encodedSearch}");
    

3. JSON反序列化不匹配问题

MVC控制器中反序列化DTO时,若ResultExpenseByAccountingDto的属性名与API返回的JSON字段名不匹配(如大小写、驼峰/下划线命名差异),会导致反序列化失败,得到空列表。

解决方法:

  • 检查DTO属性与API返回的JSON字段是否一致,可添加JsonProperty特性映射:
    public class ResultExpenseByAccountingDto
    {
        [JsonProperty("periodId")] // 对应API返回的字段名
        public int periodID { get; set; }
        [JsonProperty("createUser")]
        public string createUser { get; set; }
        // 其他属性同理
    }
    
  • 临时在MVC控制器中打印API返回的原始JSON,确认结构:
    var jsonData = await responseMessage.Content.ReadAsStringAsync();
    Console.WriteLine(jsonData); // 查看控制台输出的JSON结构
    var values = JsonConvert.DeserializeObject<List<ResultExpenseByAccountingDto>>(jsonData);
    

4. 表格渲染的DOM选择器错误

Ajax代码中清空了#tableExpense tbody,但渲染时却把行添加到#tableExpense根节点,导致DOM结构错误,浏览器无法正常渲染行。

解决方法:
修改表格行追加的目标选择器:

$("#tableExpense tbody").append(tablerow);

5. HTTPS证书信任问题(开发环境)

若MVC项目是HTTP协议,调用HTTPS的API可能因证书未信任导致请求失败,但MVC控制器会返回空列表,前端无错误提示。

解决方法:
在MVC中配置HttpClient忽略证书验证(仅开发环境使用):

var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => true;
var client = new HttpClient(handler);

相关代码参考

API控制器

[HttpGet("ListExpenseByAccountingSearch/{search}")]
public async Task<IActionResult> ListExpenseByAccountingSearch(string search)
{
    var values = await _expenseService.itemListExpenseByAccountingSearch(search);
    return Ok(values);
}

MVC控制器

[HttpGet]
public async Task<IActionResult> ListExpenseByAccountingSearch(string search)
{
    var client = _httpClientFactory.CreateClient();
    var searchParam = string.IsNullOrEmpty(search) ? "" : search;
    var encodedSearch = Uri.EscapeDataString(searchParam);
    var responseMessage = await client.GetAsync($"https://localhost:7198/api/Expense/ListExpenseByAccountingSearch/{encodedSearch}");
    if (responseMessage.IsSuccessStatusCode)
    {
        var jsonData = await responseMessage.Content.ReadAsStringAsync();
        var values = JsonConvert.DeserializeObject<List<ResultExpenseByAccountingDto>>(jsonData);
        return Json(values);
    }
    return Json(new List<ResultExpenseByAccountingDto>());
}

搜索输入框

<input class="form-control form-control-sm" id="txtSearch" type="text" oninput="listExpenseBySearch()" placeholder="Search...">

Ajax代码

function listExpenseBySearch() {
     var searchText = $("#txtSearch").val();
     $.ajax({
         type: "GET",
         url: "/Management/Accounting/ListExpenseByAccountingSearch/" + encodeURIComponent(searchText),
         success: function (value) {
             console.log(value);
             $("#tableExpense tbody").empty();
             var tablerow;
             $.each(value, (index, item) => {
                 tablerrow = $("<tr/>");
                 tablerow.append(`<td><a class="fw-semibold text-primary">#${item.periodID}</a></td>`)
                 tablerow.append(`<td>${item.createUser}</td>`)
                 tablerow.append(`<td>${item.periodMonth}</td>`)
                 tablerow.append(`<td>${item.periodYear}</td>`)
                 switch (item.paymentStatus) {
                     case 9999:
                         tablerow.append(`<td><span class="badge bg-warning-transparent">Bekleniyor</span></td>`)
                         break;
                     case 9998:
                         tablerow.append(`<td><span class="badge bg-warning-transparent">Onay Sürecinde - Yönetici</span></td>`)
                         break;
                     case 9997:
                         tablerow.append(`<td><span class="badge bg-warning-transparent">Onay Sürecinde - Muhasebe</span></td>`)
                         break;
                     case 1:
                         tablerow.append(`<td><span class="badge bg-warning-transparent">Ödeme Bekleniyor</span></td>`)
                         break;
                     case 2:
                         tablerow.append(`<td><span class="badge bg-success-transparent">Ödeme Yapıldı</span></td>`)
                         break;
                     case 3:
                         tablerow.append(`<td><span class="badge bg-dark-transparent">Gecikmiş Ödeme</span></td>`)
                         break;
                     case 4:
                         tablerow.append(`<td><span class="badge bg-danger-transparent">İptal Edilen Ödeme</span></td>`)
                         break;
                 }
                 let formattedAmount = parseFloat(item.totalAmount).toLocaleString('tr-TR', { minimumFractionDigits: 2 });
                 tablerow.append(`<td>₺${formattedAmount}</td>`)
                 tablerow.append(`<td><a href="#" class="btn btn-primary-light btn-icon btn-sm"><i class="ri-eye-line"></i></a> <a href="/Management/Accounting/ExpenseSummary/${item.expenseID}" class="btn btn-primary-light btn-icon btn-sm"><i class="ri-send-plane-2-line"></i></a></td>`)
                 $("#tableExpense tbody").append(tablerow);
             })
         },
         error: function (xhr, status, error) {
             console.log(xhr, status, error);
         }
     });
 }

内容的提问来源于stack exchange,提问作者Gökmen Ada

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 17:07:06