ASP.NET MVC通过JS向Action传JSON参数时字符串被截断如何解决?
问题根本原因
- URL中
#是片段标识符,浏览器默认不会将#及之后的内容发送到服务端,这是参数只到youtube就截断的直接原因 - 原有替换逻辑存在缺陷:
replace('#', '$')默认只会替换第一个匹配到的#,JSON中存在多个#时剩余部分依然会导致截断 - JSON中还包含大量其他URL敏感字符,比如空格、
&、%、=等,都会导致参数解析异常,仅处理#无法解决所有问题 - GET请求本身存在长度限制,若JSON数据量较大也会出现截断风险
解决方案
方案1:前端URL编码(改动最小,优先推荐)
使用JS内置的encodeURIComponent方法对JSON字符串做全局URL编码,该方法会自动转义所有URL敏感字符,ASP.NET MVC会自动完成参数解码,无需手动做字符替换。
修改后JS代码:
async function GravarPlayList() { var listaDeVideos = []; for (var i = 0; i < listaDeIds.length; i++) { var videos = await executeSearch(listaDeIds[i], maxResult); for (var j = 0; j < videos.length; j++) { listaDeVideos.push(videos[j]); } } var jsonVideos = JSON.stringify(listaDeVideos); // 对JSON参数做全局URL编码 var encodedJson = encodeURIComponent(jsonVideos); var url = "/Playlist/CreatePlaylist?pListaIds=" + encodedJson; window.location.href = url; }
修改后后端代码:
[HttpGet] public ActionResult CreatePlaylist(string pListaIds) { // 框架已自动完成URL解码,无需手动替换字符 AppCache.Instance.VideoPesquisa = JsonConvert.DeserializeObject<IEnumerable<VideoItem>>(pListaIds); PlaylistModel playlistModel = new PlaylistModel() { VideosPesquisa = AppCache.Instance.VideoPesquisa }; return View(playlistModel); }
方案2:动态表单POST提交(适合数据量较大场景)
如果JSON数据量超过浏览器GET请求长度限制(不同浏览器一般为2KB~8KB),可以改用POST表单提交的方式实现跳转,完全规避URL长度和特殊字符问题。
修改后JS代码:
async function GravarPlayList() { var listaDeVideos = []; for (var i = 0; i < listaDeIds.length; i++) { var videos = await executeSearch(listaDeIds[i], maxResult); for (var j = 0; j < videos.length; j++) { listaDeVideos.push(videos[j]); } } var jsonVideos = JSON.stringify(listaDeVideos); // 动态创建表单提交 const form = document.createElement('form'); form.method = 'post'; form.action = '/Playlist/CreatePlaylist'; const input = document.createElement('input'); input.type = 'hidden'; input.name = 'pListaIds'; input.value = jsonVideos; form.appendChild(input); document.body.appendChild(form); form.submit(); }
修改后后端代码:
[HttpPost] public ActionResult CreatePlaylist(string pListaIds) { AppCache.Instance.VideoPesquisa = JsonConvert.DeserializeObject<IEnumerable<VideoItem>>(pListaIds); PlaylistModel playlistModel = new PlaylistModel() { VideosPesquisa = AppCache.Instance.VideoPesquisa }; return View(playlistModel); }
内容的提问来源于stack exchange,提问作者Leonardo Silva
相关产品推荐
相关产品推荐

