【问题标题】:C# ASP.NET MVC Return to Previous PageC# ASP.NET MVC 返回上一页
【发布时间】:2012-04-04 02:27:18
【问题描述】:

我的控制器中有一个基本的 Edit 方法,当编辑成功时,它会重定向回顶级列表(“索引”)。 MVC 脚手架后的标准行为。

我正在尝试更改此编辑方法以重定向回上一页(不是索引)。由于我的 Edit 方法没有使用默认的映射输入参数“id”,因此我首先尝试使用它来传递上一个 URL。

在我的 Edit “get” 方法中,我使用这一行来获取上一个 URL,它运行良好:

ViewBag.ReturnUrl = Request.UrlReferrer;

然后,我使用我的表单标签将这个返回 URL 发送到 Edit “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 参数传递给 [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);
    }

【问题讨论】:

  • 即使您不使用id,我也不会使用它来传递 URL。这似乎是一个 hack,我相信有更好的方法来做到这一点。
  • 是的,Eirc 你是对的。我正在使用一个丑陋的黑客。这是我的第一个 MVC 应用程序。我尝试了很多事情并阅读了很多帖子,黑客是我最好的尝试。我根据 Gary 的示例修复了它。谢谢,

标签: c# asp.net-mvc asp.net-mvc-4


【解决方案1】:

我知道这已经很晚了,但也许这会对其他人有所帮助。

我使用取消按钮返回到引用的 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 的更新效果很好!

【讨论】:

    【解决方案2】:

    对于 ASP.NET Core 你可以使用 asp-route-* 属性:

    <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);
        }
    

    【讨论】:

      【解决方案3】:

      这只是您可以申请 ASP NET MVC 的另一种选择。

      通常你应该为每个Controller 类使用BaseController 类。

      所以在它的 constructor 方法里面做以下操作。

      public class BaseController : Controller
      {
              public BaseController()
              {
                  // get the previous url and store it with view model
                  ViewBag.PreviousUrl = System.Web.HttpContext.Current.Request.UrlReferrer;
              }
      }
      

      现在在任何视图中您都可以这样做

      <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>
      

      享受吧!

      【讨论】:

      • 我还没有尝试过,但我确实喜欢它的外观。如果这可行,那么我认为它比我几年前发布的示例要好。我现在会尝试这个,但我在 Linux 机器上对 Python 非常熟悉。谢谢你分享这个。
      • 如果用户直接访问网页会发生什么?
      【解决方案4】:

      我假设(如果我错了,请纠正我)如果编辑失败,您想重新显示编辑页面,并且您正在使用重定向。

      通过再次返回视图而不是尝试重定向用户可能会更幸运,这样您也可以使用 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。

      这不起作用,因为您的表单将发布到不知道如何保存编辑的控制器操作。您需要先发布到您的保存操作,然后在其中处理重定向。

      【讨论】:

      • 是的,但如果编辑成功,我需要它重定向回上一页。我认为它不起作用,因为我使用的是“id”。我将参数更改为“url”,如下所示,它似乎在我的第一次尝试中有效,但我需要对其进行更多测试......等等,我会发布我所拥有的。我刚开始在这个网站上发帖,并且习惯了它。
      • 在这种情况下,您可以在最初加载编辑页面时将之前的 URL 放置在 ViewBag 中,然后将其放置在隐藏字段中。然后,您可以在 post 操作中将其作为 ViewModel 的一部分访问并重定向到它。我更喜欢这样的东西而不是通过查询字符串发送它。如果你想要一个例子,请告诉我。
      • 见,Garry 的 if(success) 子句。在这里,您可以重定向到您想要的任何页面。又回到上一页。 redirectToAction也可以带参数,controller-action-variables。
      • 好的,加里。坚持几分钟。我正在尝试你的技术。我的最后一次尝试似乎奏效了,但你的看起来更像是正确的方法......我一次做三件事,所以这需要我几分钟。
      • 我认为这里的代码有一个小错误。而不是使用:“return RedirectToAction(viewModel.PreviousUrl);”你应该使用:“return Redirect(viewModel.PreviousUrl);”
      猜你喜欢
      • 2017-07-02
      • 2020-09-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-28
      • 1970-01-01
      • 1970-01-01
      • 2018-01-07
      相关资源
      最近更新 更多