好的,前面这里:这在其他所有浏览器中100%有效。但Chrome(特别是其变体,如Vivaldi和Blisk)在重定向被触及后被NullReferenceException
抛出时失败了。威士忌探戈狐步。
当前项目:
我通过控制器填写几个列表:
public static class SelectLists {
public static IEnumerable<SelectListItem> ProvinceList() {
return new List<SelectListItem> {
new SelectListItem() {Text = @"British Columbia", Value = "2"},
new SelectListItem() {Text = @"Alberta", Value = "1"},
new SelectListItem() {Text = @"Saskatchewan", Value = "5"},
new SelectListItem() {Text = @"Manitoba", Value = "3"},
new SelectListItem() {Text = @"Ontario", Value = "4"}
};
}
public static IEnumerable<SelectListItem> ClientList() {
return new List<SelectListItem> {
new SelectListItem() {Text = @"ClientType1", Value = "1"},
new SelectListItem() {Text = @"ClientType2", Value = "2"},
};
}
}
然后我通过模型将它们拉进去:
[Validator(typeof(IndexValidator))]
public class IndexViewModel {
public int Province { get; set; }
public int Client { get; set; }
public IEnumerable<SelectListItem> ProvinceList => SelectLists.ProvinceList();
public IEnumerable<SelectListItem> ClientList => SelectLists.ClientList();
}
然后将模型转储到View:
@using(Html.BeginForm("Process", "Home", FormMethod.Post, new { @class = "form-inline body-form", role = "form" })) {
@Html.AntiForgeryToken()
@Html.DropDownListFor(x => x.Province, Model.ProvinceList, "« ‹ Select › »", new { @class = "form-control required" })<br />
@Html.ValidationMessageFor(x => x.Province)<br />
foreach(var item in Model.ClientList) {
@Html.RadioButton("Client", item.Value, new {id = item.Text}) <label for="@item.Text">@item.Text</label><br />
}
@Html.ValidationMessageFor(x => x.Client)<br />
<button type="submit" class="btn btn-primary btn-lg">Submit</button>
}
提交后,表单已经过验证:
public class IndexValidator : AbstractValidator<IndexViewModel> {
public IndexValidator() {
RuleFor(x => x.Province).NotEmpty().WithMessage("You must choose your province.");
RuleFor(x => x.Client).NotEmpty().WithMessage("Are you [client type 1] or [client type 2]?");
}
}
然后我处理它们:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Process(IndexViewModel model) {
if (ModelState.IsValid) {
switch(model.Client) {
case 1:
return Redirect("https://example1.com");
default:
return Redirect("https://example2.com");
}
}
return View("Index", model);
}
所以真正奇怪的是,当我逐步使用调试器时,一切都与每个浏览器相同,甚至调试器都会点击Process()
方法的结束标记。同样,调试器会清楚地显示正确的重定向,表明switch
有内容可以对其进行操作。
但是一旦该方法完全处理完毕,Chrome(特别是其变体,如Vivaldi和Blisk)会在代码中导致NullReferenceException
,从而阻止重定向重定向。完全清楚:一旦调试器到达方法的结束括号,下一步(F11)就是NullReferenceException
。 没有其他浏览器 。
使用其他类型的重定向,例如
return new RedirectResult("https://example.com/", false);
引发同样的问题。
我完全不知道Chrome是如何能够自行触发这样的错误的。
更新
用以下三元替换switch
:
return Redirect(model.Client == 1 ? "https://example1.com/" : "https://example2.com/");
没有区别 - Chrome在退出方法时仍会抛出NullReferenceException。所有其他浏览器都可以正常处理重定向。
更新2:
嗯...完整的披露包括我现在提到我正在使用ASP.NET MVC HTML5 Boilerplate。此模板还附带了一个名为内容安全策略的小宝石。虽然它应该增加安全性,但它也增加了通过监视器的挫败感。在这种情况下,在Chrome(以及为什么只有Chrome?)下,CSP会阻止外向重定向工作。如同,它会抛出NullReferenceException
。
为什么要传出重定向?为什么只在Chrome上?谁知道f ** k。特别是因为它是特定于Chrome的,并且不会影响任何其他浏览器。现在我完全关闭了CSP,Chrome现在可以使用重定向。