C#ASP.NET MVC返回上一页
本文关键字:返回上一页 MVC NET C#ASP | 更新日期: 2023-09-27 18:28:20
我的控制器中有一个基本的Edit方法,当编辑成功时,该方法会重定向回顶级列表("Index")。MVC脚手架之后的标准行为。
我正在尝试更改此编辑方法以重定向回上一页(而不是索引)。由于我的Edit方法没有使用默认的映射输入参数"id",所以我首先尝试使用它来传递以前的URL。
在我的Edit"get"方法中,我用这一行来获取以前的URL,效果很好:
ViewBag.ReturnUrl = Request.UrlReferrer;
然后,我使用我的表单标签将这个返回URL发送到编辑"post"方法,如下所示:
@using (Html.BeginForm(new { id = ViewBag.ReturnUrl }))
这就是轮子掉下来的地方。我无法正确地从id参数中解析URL。
**更新:已解决***
以Garry的例子为例,我将参数从"id"更改为"returnUrl",并使用隐藏字段来传递参数(而不是表单标记)。经验教训:只使用"id"参数,并保持简单。它现在起作用了。这是我的更新代码和注意事项:
首先,我像第一次那样使用Request.UrlReferrer获取以前的URL。
//
// GET: /Question/Edit/5
public ActionResult Edit(int id)
{
Question question = db.Questions.Find(id);
ViewBag.DomainId = new SelectList(db.Domains, "DomainId", "Name", question.DomainId);
ViewBag.Answers = db.Questions
.AsEnumerable()
.Select(d => new SelectListItem
{
Text = d.Text,
Value = d.QuestionId.ToString(),
Selected = question.QuestionId == d.QuestionId
});
// Grab the previous URL and add it to the Model using ViewData or ViewBag
ViewBag.returnUrl = Request.UrlReferrer;
ViewBag.ExamId = db.Domains.Find(question.DomainId).ExamId;
ViewBag.IndexByQuestion = string.Format("IndexByQuestion/{0}", question.QuestionId);
return View(question);
}
现在,我使用以下形式的隐藏字段将returnUrl参数从Model传递到[HttpPost]方法:
@using (Html.BeginForm())
{
<input type="hidden" name="returnUrl" value="@ViewBag.returnUrl" />
...
在[HttpPost]方法中,我们从隐藏字段中提取参数并重定向到它…
//
// POST: /Question/Edit/5
[HttpPost]
public ActionResult Edit(Question question, string returnUrl) // Add parameter
{
int ExamId = db.Domains.Find(question.DomainId).ExamId;
if (ModelState.IsValid)
{
db.Entry(question).State = EntityState.Modified;
db.SaveChanges();
//return RedirectToAction("Index");
return Redirect(returnUrl);
}
ViewBag.DomainId = new SelectList(db.Domains, "DomainId", "Name", question.DomainId);
return View(question);
}
我假设(如果我错了,请纠正我),如果编辑失败,你想重新显示编辑页面,为此你使用了重定向。
您可能会更幸运,只需再次返回视图,而不是尝试重定向用户,这样您也可以使用ModelState来输出任何错误。
编辑:
根据反馈更新。您可以将上一个URL放置在viewModel中,将其添加到隐藏字段中,然后在保存编辑的操作中再次使用它。
例如:
public ActionResult Index()
{
return View();
}
[HttpGet] // This isn't required
public ActionResult Edit(int id)
{
// load object and return in view
ViewModel viewModel = Load(id);
// get the previous url and store it with view model
viewModel.PreviousUrl = System.Web.HttpContext.Current.Request.UrlReferrer;
return View(viewModel);
}
[HttpPost]
public ActionResult Edit(ViewModel viewModel)
{
// Attempt to save the posted object if it works, return index if not return the Edit view again
bool success = Save(viewModel);
if (success)
{
return Redirect(viewModel.PreviousUrl);
}
else
{
ModelState.AddModelError("There was an error");
return View(viewModel);
}
}
您的视图的BeginForm方法也不需要使用此返回URL,您应该可以使用:
@model ViewModel
@using (Html.BeginForm())
{
...
<input type="hidden" name="PreviousUrl" value="@Model.PreviousUrl" />
}
返回到表单操作发布到错误的URL,这是因为您将URL作为"id"参数传递,因此路由会自动使用返回路径格式化您的URL。
这将不起作用,因为您的表单将发布到一个控制器操作,该控制器操作不知道如何保存编辑。您需要先发布到您的保存操作,然后在其中处理重定向。
我知道这已经很晚了,但也许这会帮助其他人。
我使用"取消"按钮返回到引用的url。在视图中,尝试添加以下内容:
@{
ViewBag.Title = "Page title";
Layout = "~/Views/Shared/_Layout.cshtml";
if (Request.UrlReferrer != null)
{
string returnURL = Request.UrlReferrer.ToString();
ViewBag.ReturnURL = returnURL;
}
}
然后你可以像这样设置你的按钮href:
<a href="@ViewBag.ReturnURL" class="btn btn-danger">Cancel</a>
除此之外,Jason Enochs的更新效果非常好!
对于ASP.NET核心您可以使用asp路由-*属性:
<form asp-action="Login" asp-route-previous="@Model.ReturnUrl">
示例:想象一下,你有一个动作的车辆控制器
索引
详细信息
编辑
并且您可以从"索引"或"详细信息"编辑任何车辆,因此如果您单击"从索引编辑",则必须在编辑后返回到索引如果您单击了从详细信息编辑,则必须在编辑后返回到详细信息。
//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);
}
这里只是您可以应用于ASP.NET MVC的另一个选项。
通常情况下,每个Controller
类都应该使用BaseController
类。
所以在它的构造函数方法内部执行以下操作。
public class BaseController : Controller
{
public BaseController()
{
// get the previous url and store it with view model
ViewBag.PreviousUrl = System.Web.HttpContext.Current.Request.UrlReferrer;
}
}
现在在ANY视图中,您可以像一样操作
<button class="btn btn-success mr-auto" onclick=" window.location.href = '@ViewBag.PreviousUrl'; " style="width:2.5em;"><i class="fa fa-angle-left"></i></button>
享受吧!