I have a basic Edit method in my controller that redirects back to a top level listing (“Index”) when the edit succeeds. Standard behavior after MVC scaffolding.
I am trying to change this Edit method to redirect back to the previous page (not 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.
In my Edit “get” method, I used this line to grab the previous URL and it worked fine:
ViewBag.ReturnUrl = Request.UrlReferrer;
I then sent this return URL to the Edit “post” method by using my form tag like this:
@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.
*** 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). Lesson learned: Only use the "id" parameter how it was intended to be used and keep it simple. 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.
//
// 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:
@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....
//
// 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);
}
This question is related to
c#
asp.net-mvc
asp.net-mvc-4
I know this is very late, but maybe this will help someone else.
I use a Cancel button to return to the referring 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:
<a href="@ViewBag.ReturnURL" class="btn btn-danger">Cancel</a>
Other than that, the update by Jason Enochs works great!
For ASP.NET Core You can use asp-route-* attribute:
<form asp-action="Login" asp-route-previous="@Model.ReturnUrl">
An example: Imagine that you have a Vehicle Controller with actions
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);
}
Here is just another option you couold apply for ASP NET MVC.
Normally you shoud use BaseController
class for each Controller
class.
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!
Source: Stackoverflow.com