如何在Http Post之后保留url(带有querystring),但同时向Model State添加错误?



基本上我想要做的是通过让他们输入他们的帐户和社会保险号来验证用户。如果他们输入了不正确的组合,我对Authenticate post操作执行以下操作:

ModelState.AddModelError("Authenticated", authenticationError);
return View();

这将显示错误,但随后我将丢失查询字符串中的内容。保留查询字符串的另一种方法是:

ModelState.AddModelError("Authenticated", authenticationError);
return Redirect(Request.Url + "?returnUrl=" + returnUrl);

这将保留查询字符串,但不会显示错误。我想这是因为ModelState发生了变化。

我需要returnUrl,因为每当用户点击查看特定事件时,他们都会被迫进入Authenticate页面。我想设置它,这样他们在验证了自己之后仍然会去这个事件。

是否有一种方法可以实现查询字符串的保存和显示模型错误?

Ivan Korytin的答案是最好的(也是我能找到的唯一的答案,似乎没有使用隐藏字段hack就能正常工作),我已经用Request.QueryString改进了一点。

你必须把参数作为表单动作的一部分:

<form action="@Url.Action("CreateEntity", "Employee")?@(Request.QueryString)"
  enctype="multipart/form-data" method="POST">

当您执行以下操作时,查询字符串(和GET参数)现在被保留:

[HttpPost]
public ActionResult MyAction(MyAction model)
{
    if (!ModelState.IsValid)
    {
        return View(model);
    }

第二个场景没有模型状态,因为当您进行重定向时,浏览器会向该位置发出单独的请求,单独的请求=新的模型状态。

我建议使用您的第一个场景,并在您的模型中放置一个"ReturnUrl",并将其作为隐藏字段呈现给客户端。

//In your model add the ReturnUrl Property
public class AuthenticatModel
{
     public string Account {get; set;}
     public string SocialSecurityNumber {get;set;}
     public string ReturnUrl {get;set;}
}

ModelState.AddModelError("Authenticated", authenticationError);
//Set the return URL property before returning the view
model.ReturnUrl = returnUrl;
return View(model);

@* add the return URL as a hidden field to your view so it can be posted back *@
@Html.HiddenFor(model => model.ReturnUrl)

对于ASP。网络核心你可以使用asp-route-* attribute:

<form asp-action="Login" asp-route-returnUrl="@Model.ReturnUrl">

其他详细示例:假设你有一个带有动作的Vehicle Controller

指数

详细信息

编辑

,您可以从索引或详细信息编辑任何车辆,因此,如果您单击从索引编辑,则必须在编辑后返回索引如果您单击了从详细信息编辑,则必须在编辑后返回详细信息。

//In your viewmodel add the ReturnUrl Property
public class VehicleViewModel
{
     ..............
     ..............
     public string ReturnUrl {get;set;}
}

Details.cshtml
<a asp-action="Edit" asp-route-previous="Details" asp-route-id="@Model.CarId">Edit</a>
Index.cshtml
<a asp-action="Edit" asp-route-previous="Index" asp-route-id="@item.CarId">Edit</a>
Edit.cshtml
<form asp-action="Edit" asp-route-previous="@Model.ReturnUrl" class="form-horizontal">
        <div class="box-footer">
            <a asp-action="@Model.ReturnUrl" class="btn btn-default">Back to List</a>
            <button type="submit" value="Save" class="btn btn-warning pull-right">Save</button>
        </div>
    </form>

在你的控制器中:

// GET: Vehicle/Edit/5
    public ActionResult Edit(int id,string previous)
    {
            var model = this.UnitOfWork.CarsRepository.GetAllByCarId(id).FirstOrDefault();
            var viewModel = this.Mapper.Map<VehicleViewModel>(model);//if you using automapper
    //or by this code if you are not use automapper
    var viewModel = new VehicleViewModel();
    if (!string.IsNullOrWhiteSpace(previous)
                viewModel.ReturnUrl = previous;
            else
                viewModel.ReturnUrl = "Index";
            return View(viewModel);
        }

[HttpPost]
    public IActionResult Edit(VehicleViewModel model, string previous)
    {
            if (!string.IsNullOrWhiteSpace(previous))
                model.ReturnUrl = previous;
            else
                model.ReturnUrl = "Index";
            ............. 
            .............
            return RedirectToAction(model.ReturnUrl);
    }

最新更新