I have an index action that can be filtered and is done so by using a query string. When I choose a record I move to the Details action. From there I can navigate to other actions related to this record which will then lead me back to the Details action. I would like to be able to save the URL from the Index page which will have the query string parameters intact. Obviously I can't do this with a straight Request.UrlReferrer since it won't be correct if the previous action wasn't Index. I have come up with a solution but I was wondering if there was a better way. Thanks!
public ActionResult Details(int? id)
{
var url = Request.UrlReferrer;
// Save URL if coming from the Employees/Index page
if (url != null && url.AbsolutePath == "/Employees")
Session.Add("OfficeURL", url.ToString());
// Model Stuff
return View();
}
Details View
#Html.ActionLink("Back to List", "Index", null, new { #href = Session["OfficeURL"] })
You need to pass a "return URL" with your links to the other views. Essentially:
Index.cshtml
#Html.ActionLink("View Details", "Details", "Foo", new { returnUrl = Request.RawUrl })
This will have the effect of putting the current index URL in the query string of the link. Then, in your other actions, you'll accept this as a param and store it in ViewBag:
public ActionResult Details(int? id, string returnUrl = null)
{
...
ViewBag.ReturnUrl = returnUrl;
return View();
}
Then, in these other views, you'll utilize this ViewBag member in the same way as above:
Details.cshtml
#Html.ActionLink("Click Me!", "Foo", "Foo", new { returnUrl = ViewBag.ReturnUrl })
When you're ready to go back to the index, then, you'd link/redirect to this return URL that you've been passing around.
Related
I want to redirect to a certain div of a webpage after handling some data in a controller. Is their any way to add the '#' to the end of the url? Or should I handle it with javascript?
Example:
[HttpPost]
public async Task<IActionResult> Edit(ViewModel model){
....
return RedirectToAction("Info", new { id = model.Id, "#" = "item_55" });
}
=> Should redirect to /Info/id=4#item_55
RedirectToAction has an overload that allows you to specify the fragment. Here's an example:
return RedirectToAction("Info", "Controller", new { id = model.Id }, "item_55");
Note that you also need to specify the controller as one of the arguments, as I've done above.
I currently have separate views and controller actions for my details and delete methods. I would like to place the delete button on the details view so a user doesn't have to click delete, then delete again on they are on the delete view. I have this most of the way by not having a "get" delete method and using an ajax.actionlink helper within the details view to call the post method:
#Ajax.ActionLink("Delete", "Delete",
new { id = Model.DepartmentId },
new AjaxOptions { HttpMethod="POST", UpdateTargetId="output", Confirm= "Are you sure you want to delete this item?" },
new { #class = "btn btn-danger" })
The only problem is when the delete is successful, I want to redirect to a search view. Currently, my delete controller "post" method is as follows:
//
// POST: /Department/Delete/5
[HttpPost]
//[ValidateAntiForgeryToken]
public ActionResult Delete(DepartmentViewModel vmNotUsed, int id = 0)
{
if (id != 0)
{
// check to see if the department item is associated with an asset assignment
bool InUseByAssetAssignment = AssetAssignmentService.ValueInUse(x => x.DepartmentId == id);
if (InUseByAssetAssignment == false)
{
DepartmentService.DeleteDepartment(id);
return RedirectToAction("Search");
}
else
{
return Content("<p style='color:#f00';>This department cannot be deleted because there are items associated with it.</p>");
}
}
else
{
return Content("You must select a Department to delete!");
}
}
Unfortunately, it returns the view INSIDE of the current details view:
I don't know if this makes sense or not.
As your request is AJAX based, you need to return javascript to perform the redirect - something like:
return JavaScript(string.format("window.location = '{0}'", Url.Action("Search")));
Should do what you are asking.
straight forward question , can't seem to get my viewBag value to display in a view that the user is directed to after completing a form.
Please advise..thanks
My Index ActionResult simple returns model data..
public ActionResult Index()
{
var source = _repository.GetByUserID(_applicationUser.ID);
var model = new RefModel
{
test1 = source.test1,
};
return View(model);
}
My Get Edit" ActionResult , simply uses the same model data as Index.
My Post "Edit" ActionResult, assigns the new values if any to the model and redirects to the Index page, but Index page does not display ViewBag value ??
[HttpPost]
public ActionResult Edit(RefModell model)
{
if (ModelState.IsValid)
{
var source = _repository.GetByUserID(_applicationUser.ID);
if (source == null) return View(model);
source.test1 = model.test1;
_uow.SaveChanges();
#ViewBag.Message = "Profile Updated Successfully";
return RedirectToAction("Index");
}
return View(model);
}
And in my Index view...
#if(#ViewBag.Message != null)
{
<div>
<button type="button">#ViewBag.Message</button>
</div>
}
ViewBag only lives for the current request. In your case you are redirecting, so everything you might have stored in the ViewBag will die along wit the current request. Use ViewBag, only if you render a view, not if you intend to redirect.
Use TempData instead:
TempData["Message"] = "Profile Updated Successfully";
return RedirectToAction("Index");
and then in your view:
#if (TempData["Message"] != null)
{
<div>
<button type="button">#TempData["Message"]</button>
</div>
}
Behind the scenes, TempData will use Session but it will automatically evict the record once you read from it. So it's basically used for short-living, one-redirect persistence storage.
Alternatively you could pass it as query string parameter if you don't want to rely on sessions (which is probably what I would do).
RedirectToAction causes an HTTP 302 response, which makes the client make another call to the server and request a new page.
You should be returning a view instead of redirecting.
The RedirectToAction(msdn) instructs your browser to make a new request.
So your server will be called again but it will be a new request with a blank viewbag and all
You could do a sort of internal redirect by just calling the index method, this way the viewbag will still have its data.
Edit : you'll also have to modify your index method or your View(model) line will try to render the edit. Full code below
public ActionResult Index()
{
var source = _repository.GetByUserID(_applicationUser.ID);
var model = new RefModel
{
test1 = source.test1,
};
return View("Index",model);
}
[HttpPost]
public ActionResult Edit(RefModell model)
{
if (ModelState.IsValid)
{
var source = _repository.GetByUserID(_applicationUser.ID);
if (source == null) return View(model);
source.test1 = model.test1;
_uow.SaveChanges();
#ViewBag.Message = "Profile Updated Successfully";
return Index();
}
return View(model);
}
You can try this way also
Controller
public ActionResult Test()
{
ViewBag.controllerValue= "testvalue";
..................
}
View -
define top of razor page
#{string testvalue= (string)ViewBag.controllerValue;}
$(function () {
var val= '#testvalue';
});
I have a single controller and view working that calls a web service, and returns a result. At the moment, it's my default controller, called Home, and it uses the Index view page.
It's working. I can post data and then put something on the refreshed screen. It reloads the same view.
Now, once I submit, and I get a good reply, I want to load a different controller/view.
My routes look like this right now:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Home",
"{lang}",
new { controller = "Home", action = "Index", lang="English" });
routes.MapRoute(
"Location",
"{lang}",
new { controller = "Location", action = "Index", lang = "English" });
I created a controlled called Location, and it just has this:
//LocationController
public class LocationController : Controller
{
public ActionResult Index()
{
return View();
}
}
In my home controller, I am doing the logic, and then attempting to load the new page.
[HttpPost]
public ActionResult Index(HomeModel model)
{
var proxy = new Proxy();
var r = proxy.GetLocationByAddress(model.SearchString, o.ToString());
if(r==null)
{
ViewBag.Error = "Error during search";
return View(model);
}
ViewBag.Error = string.Format("Found {0} at {1}, {2}", r.StreetName, r.Latitude, r.Longitude);
return RedirectToAction("Index", "Location");
}
But when I run it, submit it, step through, it hits the RedirectToAction - but ... the Home screen simply refreshes. I never see the new Location view. What am I doing wrong here? I have't grasped Routes yet... I need to pass a new object to the Location.Index screen to display...
Your route mapping is incorrect, check this out: http://www.asp.net/mvc/tutorials/controllers-and-routing/creating-custom-routes-cs
routes.MapRoute(
"Location",
"Location/{lang}",
new { controller = "Location", action = "Index", lang = "English" });
I don't think so you need to make any changes. As in your case you want to load different controller with its respecting view you need below change only
replace this code return RedirectToAction("Index", "Location");
with this code return Redirect("http://www.yoursite.com/Location/Index");
Your change is like redirection from one page to another therefore you need to put your complete path here
please try & reply if any problem
I'll show what I'm trying to do with a simple example.
I have the routes
routes.MapRoute("",
"Message",
new { controller = "Home", action = "Index", myEnum = MyEnum.Message});
routes.MapRoute("",
"",
new { controller = "Home", action = "Index" });
And the action
public ActionResult Index(/*other values*/, MyEnum? myEnum = null)
{
// do some logic
var redirectToHomeUrl = userLoggedIn && myEnum.HasValue && myEnum.Value == MyEnum.Message;
if (redirectToHomeUrl)
{
// do some logic
return RedirectToAction("Index"); <-- problem here
}
// Other logic
}
Basically the user gets sent to mysite.com/Message and is logged out and shown a model dialogue message over the home page. When they act on this message and log back in, the page reloads. I detect that they still have the url for the message and want to redirect them back to the home url "mysite.com/".
However return RedirectToAction("Index") still retains myEnum = MyEnum.Message.
RouteData is persisted after the redirect so I get an infinite loop.
I've tried RedirectToRoute(null, new { action = "Index", controller = "Home"});
I've tried RedirectToAction("Index", new {})
I've tried RouteData.Values.Clear()
I've tried RouteData.Values["myEnum"] = null;
If your wondering RedirectToAction("Index", new { myEnum = null }) doesn't compile :)
Any idea's on how to redirect to the same Action but removing existing route values?
Cheers in advance.
RedirectToAction("Index", new { myEnum = null })
might not compile, but this does:
RedirectToAction("Index", new { myEnum = (MyEnum?)null })
if you're wondering :)
I don't get the point of redirecting to the same action though. If all you want is to remove a value, set it to null manually (or ignore it). If you actually want to call a different function (but the same action) (doesn't seem to be the case, but who knows), just return that function's result from yours directly.