简体   繁体   English

C# ASP.NET MVC 返回上一页

[英]C# ASP.NET MVC Return to Previous Page

I have a basic Edit method in my controller that redirects back to a top level listing (“Index”) when the edit succeeds.我的控制器中有一个基本的 Edit 方法,当编辑成功时,它会重定向回顶级列表(“索引”)。 Standard behavior after MVC scaffolding. MVC 脚手架后的标准行为。

I am trying to change this Edit method to redirect back to the previous page (not Index).我正在尝试更改此 Edit 方法以重定向回上一页(而不是 Index)。 Since my Edit method wasn't using the default mapped input parameter “id”, I first tried using that to pass in the previous URL.由于我的 Edit 方法没有使用默认的映射输入参数“id”,我首先尝试使用它来传递前一个 URL。

In my Edit “get” method, I used this line to grab the previous URL and it worked fine:在我的 Edit “get” 方法中,我使用这一行来获取以前的 URL,它工作正常:

ViewBag.ReturnUrl = Request.UrlReferrer;

I then sent this return URL to the Edit “post” method by using my form tag like this:然后我使用我的表单标签将这个返回 URL 发送到 Edit “post” 方法,如下所示:

@using (Html.BeginForm(new { id = ViewBag.ReturnUrl }))

Now this is where the wheels fell off.现在这是轮子掉下来的地方。 I couldn't get the URL parsed from the id parameter properly.我无法从 id 参数正确解析出 URL。

*** *** UPDATE: SOLVED更新:已解决** * ** *

Using Garry's example as a guide, I changed my parameter from "id" to "returnUrl" and used a hidden field to pass my parameter (instead of the form tag).使用 Garry 的示例作为指导,我将参数从“id”更改为“returnUrl”并使用隐藏字段来传递我的参数(而不是表单标签)。 Lesson learned: Only use the "id" parameter how it was intended to be used and keep it simple.经验教训:仅使用“id”参数的预期用途并保持简单。 It works now.它现在有效。 Here is my updated code with notes:这是我带注释的更新代码:

First, I grab the previous URL using Request.UrlReferrer as I did the first time.首先,我像第一次一样使用 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);
    }

and I now pass the returnUrl parameter from the Model to the [HttpPost] method using a hidden field in the form:我现在使用表单中的隐藏字段将模型中的 returnUrl 参数传递给 [HttpPost] 方法:

@using (Html.BeginForm())
{
    <input type="hidden" name="returnUrl" value="@ViewBag.returnUrl" />
    ...

In the [HttpPost] method we pull the parameter from the hidden field and Redirect to it....在 [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);
    }

I am assuming (please correct me if I am wrong) that you want to re-display the edit page if the edit fails and to do this you are using a redirect.我假设(如果我错了,请纠正我)如果编辑失败,您想重新显示编辑页面,为此您正在使用重定向。

You may have more luck by just returning the view again rather than trying to redirect the user, this way you will be able to use the ModelState to output any errors too.通过再次返回视图而不是尝试重定向用户,您可能会更幸运,这样您也可以使用 ModelState 输出任何错误。

Edit:编辑:

Updated based on feedback.根据反馈更新。 You can place the previous URL in the viewModel, add it to a hidden field then use it again in the action that saves the edits.您可以将之前的 URL 放在 viewModel 中,将其添加到隐藏字段,然后在保存编辑的操作中再次使用它。

For instance:例如:

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

The BeginForm method for your view doesn't need to use this return URL either, you should be able to get away with:您的视图的 BeginForm 方法也不需要使用此返回 URL,您应该能够逃脱:

@model ViewModel

@using (Html.BeginForm())
{
    ...
    <input type="hidden" name="PreviousUrl" value="@Model.PreviousUrl" />
}

Going back to your form action posting to an incorrect URL, this is because you are passing a URL as the 'id' parameter, so the routing automatically formats your URL with the return path.回到发布到错误 URL 的表单操作,这是因为您将 URL 作为 'id' 参数传递,因此路由会自动使用返回路径格式化您的 URL。

This won't work because your form will be posting to an controller action that won't know how to save the edits.这将不起作用,因为您的表单将发布到不知道如何保存编辑的控制器操作。 You need to post to your save action first, then handle the redirect within it.您需要先发布到您的保存操作,然后处理其中的重定向。

For ASP.NET Core You can use asp-route-* attribute:对于ASP.NET Core,您可以使用 asp-route-* 属性:

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

An example: Imagine that you have a Vehicle Controller with actions一个例子:假设你有一个带有动作的 Vehicle Controller

Index指数

Details细节

Edit编辑

and you can edit any vehicle from Index or from Details, so if you clicked edit from index you must return to index after edit and if you clicked edit from details you must return to details after edit.并且您可以从索引或详细信息编辑任何车辆,因此如果您单击从索引编辑,则必须在编辑后返回索引,如果单击从详细信息编辑,则必须在编辑后返回详细信息。

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

In your controller:在您的控制器中:

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

I know this is very late, but maybe this will help someone else.我知道这已经很晚了,但也许这会对其他人有所帮助。

I use a Cancel button to return to the referring url.我使用取消按钮返回到引用 url。 In the View, try adding this:在视图中,尝试添加以下内容:

@{
  ViewBag.Title = "Page title";
  Layout = "~/Views/Shared/_Layout.cshtml";

  if (Request.UrlReferrer != null)
  {
    string returnURL = Request.UrlReferrer.ToString();
    ViewBag.ReturnURL = returnURL;
  }
}

Then you can set your buttons href like this:然后你可以像这样设置你的按钮 href:

<a href="@ViewBag.ReturnURL" class="btn btn-danger">Cancel</a>

Other than that, the update by Jason Enochs works great!除此之外,Jason Enochs 的更新效果很好!

Here is just another option you couold apply for ASP NET MVC.这只是您可以申请 ASP NET MVC 的另一个选项。

Normally you shoud use BaseController class for each Controller class.通常你应该为每个Controller类使用BaseController类。

So inside of it's constructor method do following.所以在它的构造函数方法内部执行以下操作。

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

And now in ANY view you can do like现在在任何视图中你都可以这样做

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

Enjoy!享受!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM