.NET Core 3.1调用过长URL出现Bad Request的问题求助
解决URL过长导致的Bad Request错误(.NET Core 3.1)
问题描述
调用包含长JSON参数的GET请求URL时出现Bad Request错误,示例URL如下:
https://localhost:44320/RespostaEmail/96635/750396/[%7B%22IdItem%22:8,%22IdTipoReposta%22:80%7D,%7B%22IdItem%22:1,%22IdTipoReposta%22:80%7D,%7B%22IdItem%22:3,%22IdTipoReposta%22:80%7D,%7B%22IdItem%22:2,%22IdTipoReposta%22:80%7D,%7B%22IdItem%22:5,%22IdTipoReposta%22:80%7D,%7B%22IdItem%22:7,%22IdTipoReposta%22:80%7D,%7B%22IdItem%22:10,%22IdTipoReposta%22:80%7D,%7B%22IdItem%22:4,%22IdTipoReposta%22:80%7D,%7B%22IdItem%22:6,%22IdTipoReposta%22:80%7D,%7B%22IdItem%22:9,%22IdTipoReposta%22:80%7D]
生成该URL的前端JavaScript代码:
function responder(idDivergencia, numGF, dia, mes, ano) { let observacao = $('#observacao').val(); if (observacao.trim() == '') { abrirDialogAlertaMensagem('Informe uma observação para visualizar a tela de resposta.'); return; } while (observacao.indexOf('/') != -1) { observacao = observacao.replace('/', '-') } var lista = ObterListaDeItens(idDivergencia, numGF); var itens; if (lista != null) { $('.btnSalvarDiv').click(); itens = JSON.stringify(lista); window.location.href = RELATIVE_PATH + 'RespostaEmail/' + idDivergencia + '/' + numGF + '/' + itens } else { abrirDialogAlertaMensagem('Informe o(s) tipo(s) de resposta para visualizar a tela de resposta.'); return; } }
后端.NET Core 3.1控制器代码:
[HttpGet] [Route("RespostaEmail/{idDivergencia}/{numeroGf}/{itensDivergencia}")] public IActionResult RespostaEmail(int idDivergencia, int numeroGf, string itensDivergencia) { if (itensDivergencia == "favicon.ico") return View(); var listaItems = JsonConvert.DeserializeObject<List<ItemResposta>>(itensDivergencia); var breadcrumb = BreadcrumbControl.GetInstance(); breadcrumb.AddNewPage("Resposta Email", "Resposta", "RespostaEmail"); var dados = new Resposta(); var itens = _divergenciaAppService.ListarItensDivergencia(idDivergencia); foreach (var item in itens) { dados.ItemSolicitado.Add(new ItemSolicitado { CodigoDivergencia = item.CodDivergencia, IdGrupo = item.IdGrupo, IdItem = item.IdItem, Peca = item.PecaSolicitada, Quantidade = item.QtdDivergente ?? 0, TipoResposta = listaItems.FirstOrDefault(x => x.IdItem == item.IdItem).IdTipoReposta }); } dados.IdDivergencia = idDivergencia; dados.NumeroGF = numeroGf; var email = _respostaAppService.MontarEmailResposta(dados); ViewBag.TextoPadrao = email; ViewBag.IdDivergencia = idDivergencia; ViewBag.Conta = ContaUsuario; ViewBag.IdGrupo = dados.ItemSolicitado.Select(x => x.IdGrupo).LastOrDefault(); return View(); }
解决方案
方案1:调整服务器URL长度限制(不推荐)
GET请求的URL长度受浏览器和服务器双重限制,即使修改服务器配置,仍可能被浏览器限制,仅作为临时应急方案。
在Startup.cs的ConfigureServices方法中添加以下配置:
public void ConfigureServices(IServiceCollection services) { // 配置HTTP请求行最大长度 services.Configure<HttpOptions>(options => { options.MaxRequestLineSize = 8192; // 可根据需求调整,单位为字节 }); // 配置Kestrel服务器的请求行限制 services.Configure<KestrelServerOptions>(options => { options.Limits.MaxRequestLine = 8192; }); // 其他原有配置... }
方案2:改用POST请求传递数据(推荐)
POST请求将数据放在请求体中,不受URL长度限制,更符合REST规范。
前端代码修改
将原有的URL跳转改为动态创建POST表单提交:
function responder(idDivergencia, numGF, dia, mes, ano) { let observacao = $('#observacao').val(); if (observacao.trim() == '') { abrirDialogAlertaMensagem('Informe uma observação para visualizar a tela de resposta.'); return; } while (observacao.indexOf('/') != -1) { observacao = observacao.replace('/', '-') } var lista = ObterListaDeItens(idDivergencia, numGF); var itens; if (lista != null) { $('.btnSalvarDiv').click(); itens = JSON.stringify(lista); // 动态创建POST表单 const form = document.createElement('form'); form.method = 'POST'; form.action = RELATIVE_PATH + 'RespostaEmail'; // 添加隐藏参数 const idInput = document.createElement('input'); idInput.type = 'hidden'; idInput.name = 'idDivergencia'; idInput.value = idDivergencia; form.appendChild(idInput); const gfInput = document.createElement('input'); gfInput.type = 'hidden'; gfInput.name = 'numeroGf'; gfInput.value = numGF; form.appendChild(gfInput); const itensInput = document.createElement('input'); itensInput.type = 'hidden'; itensInput.name = 'itensDivergencia'; itensInput.value = itens; form.appendChild(itensInput); // 提交表单并清理 document.body.appendChild(form); form.submit(); document.body.removeChild(form); } else { abrirDialogAlertaMensagem('Informe o(s) tipo(s) de resposta para visualizar a tela de resposta.'); return; } }
后端控制器修改
将HttpGet改为HttpPost,并调整路由(无需在URL中携带参数):
[HttpPost] [Route("RespostaEmail")] public IActionResult RespostaEmail(int idDivergencia, int numeroGf, string itensDivergencia) { if (string.IsNullOrEmpty(itensDivergencia)) return BadRequest("Dados de itens inválidos"); var listaItems = JsonConvert.DeserializeObject<List<ItemResposta>>(itensDivergencia); var breadcrumb = BreadcrumbControl.GetInstance(); breadcrumb.AddNewPage("Resposta Email", "Resposta", "RespostaEmail"); var dados = new Resposta(); var itens = _divergenciaAppService.ListarItensDivergencia(idDivergencia); foreach (var item in itens) { dados.ItemSolicitado.Add(new ItemSolicitado { CodigoDivergencia = item.CodDivergencia, IdGrupo = item.IdGrupo, IdItem = item.IdItem, Peca = item.PecaSolicitada, Quantidade = item.QtdDivergente ?? 0, TipoResposta = listaItems.FirstOrDefault(x => x.IdItem == item.IdItem).IdTipoReposta }); } dados.IdDivergencia = idDivergencia; dados.NumeroGF = numeroGf; var email = _respostaAppService.MontarEmailResposta(dados); ViewBag.TextoPadrao = email; ViewBag.IdDivergencia = idDivergencia; ViewBag.Conta = ContaUsuario; ViewBag.IdGrupo = dados.ItemSolicitado.Select(x => x.IdGrupo).LastOrDefault(); return View(); }
优化建议:可以创建DTO类统一接收参数,代码更规范:
public class RespostaEmailRequest { public int IdDivergencia { get; set; } public int NumeroGf { get; set; } public string ItensDivergencia { get; set; } } // 控制器修改为 [HttpPost] [Route("RespostaEmail")] public IActionResult RespostaEmail(RespostaEmailRequest request) { if (string.IsNullOrEmpty(request.ItensDivergencia)) return BadRequest("Dados de itens inválidos"); var listaItems = JsonConvert.DeserializeObject<List<ItemResposta>>(request.ItensDivergencia); // 后续逻辑与之前一致 }
内容的提问来源于stack exchange,提问作者Willian
相关产品推荐
相关产品推荐

