ASP.NET Core 6 MVC中如何从视图传递ReturnUrl至控制器并实现原页面重定向
针对你提到的两个需求——获取当前视图URL传给控制器、完成逻辑后重定向回来源页,以及具体给SetLanguage控制器传递ReturnUrl的问题,我整理了两种实用的视图实现方式,还顺便帮你修正了控制器里的小bug:
一、核心思路
要传递当前页面的URL作为returnUrl,我们可以在视图中通过Context.Request.Path + Context.Request.QueryString获取完整的本地路径(包含查询参数),然后把它作为参数传递给控制器的SetLanguage方法。
二、视图实现方式
方式1:用锚点链接(A标签)直接传递
如果你是做语言切换的按钮/文字链接,这种方式最直接:
<!-- 示例:遍历展示语言选项 --> @foreach (var cultureOption in new[] { "en-US", "zh-CN", "fr-FR" }) { <a asp-action="SetLanguage" asp-route-culture="@cultureOption" asp-route-returnUrl="@Context.Request.Path + Context.Request.QueryString"> @cultureOption </a> <span>|</span> }
这里的asp-route-returnUrl会自动把当前页面的URL(路径+查询参数)拼接成请求参数,控制器就能直接拿到returnUrl的值。
方式2:用表单提交(适合下拉选择等场景)
如果是用下拉框切换语言,用表单提交更友好:
@using (Html.BeginForm("SetLanguage", "Home", FormMethod.Get)) { <!-- 隐藏域传递当前页面URL作为returnUrl --> <input type="hidden" name="returnUrl" value="@Context.Request.Path + Context.Request.QueryString" /> <select name="culture" onchange="this.form.submit()"> <option value="en-US">English</option> <option value="zh-CN">中文</option> <option value="fr-FR">Français</option> </select> }
注意这里用了FormMethod.Get,和你的控制器默认的请求方式匹配;如果想改成POST,只要把FormMethod.Post加上,同时给控制器的SetLanguage方法标注[HttpPost]特性即可。
三、控制器代码修正
你的控制器里有个小问题:return Redirect(returnUrl);之后的return LocalRedirect(_returnUrl);永远不会执行,而且*LocalRedirect*比*Redirect*更安全(会自动验证是否为本地URL,防止开放重定向攻击),修正后的代码如下:
public IActionResult SetLanguage(string culture, string returnUrl) { var _returnUrl = returnUrl; Response.Cookies.Append( CookieRequestCultureProvider.DefaultCookieName, CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)), new CookieOptions { Expires = DateTimeOffset.UtcNow.AddYears(1) } ); if (Url.IsLocalUrl(_returnUrl)) { // 验证通过后重定向回来源页 return LocalRedirect(_returnUrl); } else { // 非本地URL则跳转到首页 return RedirectToAction("Index", "Home"); } }
这样就能完美实现:用户在任意页面切换语言后,自动回到原来的页面;如果传递的returnUrl是不安全的外部URL,就默认跳转到首页。
内容的提问来源于stack exchange,提问作者Eskander One

