MVC3 TempData exists when clicking back button - c#

I'm using TempData to pass additional messages to show a notification accross requests:
public ActionResult Address()
TempData["NotificationType"] = "error";
TempData["NotificationMessage"] = "There was an error updating the address.";
return RedirectToAction("Index", "Home");
}
public ActionResult Index()
{
if (TempData["NotificationType"] != null && TempData["NotificationMessage"] != null)
{
model.NotificationMessage = TempData["NotificationMessage"].ToString();
model.NotificationType = TempData["NotificationType"].ToString();
}
return View();
}
Index View:
<div id="NotificationType" data-notification_type="#Model.NotificationType"/>
<div id="NotificationMessage" data-notification_message="#Model.NotificationMessage" />
<script type=text/javascript>
if($('#NotificationType').data('notification_type') == 'error'){
Notify('error', "Error!", $('#NotificationMessage').data('notification_message'));
}
</script>
I then display the error notification in the view and it works great.
My problem comes in after that if I click another link and then press the back button in the browser the notification displays again.
Is there a way to prevent the notification from redisplaying?
EDIT: Looks like its because its caching the index view as it doesn't hit a breakpoint in the action when I hit the back button.

Fixed this by preventing caching on the index view:
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public ActionResult Index()

For .net core 3.0 or higher you can make use of this on your index view
[ResponseCache(Duration = 30, NoStore = true)]
public ActionResult Index()
{
//Your code here..
}
Happy coding.

Related

How to run LogOut Action In Home Controller that can not run by ActionLink?

My Home Controller Like this:
public class HomeController : Controller
{
....
[ActionName("Login")]
public ActionResult Login()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Login(string UserName, string Password)
{
try
{
var query = user_Repository.Login(UserName, Password);
if (query != null)
{
Session["UserName"] = query.UserName;
Session["IsAdmin"] = query.IsAdmin;
return RedirectToAction("Index", "News");
}
ViewBag.ErrorMessage = "نام كاربري يا رمز عبور صحيح نمي باشد";
return View();
}
catch (Exception e)
{
ViewBag.ErrorMessage = " خطا!!! ";
return View();
}
}
public ActionResult LogOut()
{
if (Request.Cookies["user"] != null)
{
var user = new HttpCookie("user")
{
Expires = DateTime.Now.AddDays(-1),
Value = null
};
Response.SetCookie(user);
Response.Cookies.Clear();
}
if(Session["UserName"] != null)
{
Session["UserName"] = null;
Session["IsAdmin"] = null;
}
Session.Clear();
return RedirectToActionPermanent("Index");
}
}
When i Use ActionLink in _Layout to Run Logout Action in Home Controller , this ActionLink Instead of executing Logout Action, Login will be executed!!!
My ActionLink Like this:
#Html.ActionLink("Log Off", "LogOut", "Home")
where is my wrong??? why #Html.ActionLink("Log Off", "LogOut", "Home") run Login Action????????????????????
i use this code for run that LogOut Action in my _Layout and this code work Correct...
#using (Html.BeginForm("LogOut", "Home", FormMethod.Post, new { role = "form" }))
{
#Html.AntiForgeryToken()
<input type="submit" value="خروج" class="btn btn-primary" />
}
This is a text that stackOverflow lets me send the text because stackOverflow says i should give more explanations and say "it looks like your post is mostly code; please add some more details"!!! i dont have any more detail.... i explain all of that ;)
Do not put your Logout action in a Form. Your ActionLink should work correctly if you have given the correct parameters to it.
Your ActionLink would look like this:
<a href='#Url.Action("LogOut", "Home")'>Log Out</a>
And your Controller action result would look like this:
public ActionResult Logout()
{
if (Request.Cookies["user"] != null)
{
var user = new HttpCookie("user")
{
Expires = DateTime.Now.AddDays(-1),
Value = null
};
Response.SetCookie(user);
Response.Cookies.Clear();
}
if(Session["UserName"] != null)
{
Session["UserName"] = null;
Session["IsAdmin"] = null;
}
//Session.Abandon();
//Session.Clear();
return RedirectToAction("Login", "Home");
}
Use RedirectPermanent if the resource has been moved permanently and will no longer be accessible in its previous location. Most browsers will cache this response and perform the redirect automatically without requesting the original resource again.
Use Redirect if the resource may be available in the same location (URL) in the future.
So in your case Redirect would be the option since this would be hit by any user logging out of your system.
Session.Abandon removes all the objects stored in a Session. If you do not call the Abandon method explicitly, the server removes these objects and destroys the session when the session times out. It also raises events like Session_End
Session.Clear removes all keys and values from the session-state collection.
Think of it like this: Session.Clear can be compared to removing all items from a cart, while Session.Abandon is more like abandoning the entire cart itself.
You can use either of these two methods for destroying or clearing your Session. Currently you are doing a Clear explicitly by assigning your UserName and IsAdmin to null.

MVC form load calling both controller method and its overload method instead of calling on click methos ? Code attached

i am saving data on click button but view when load first time entering to overload method ?
my view code is like,
#using (Html.BeginForm("ManageQuestion", "Questions", FormMethod.Post))
{
<input type="submit" value="Save" />
}
and my Controller is like,
public ActionResult ManageQuestion()
{
//List<SelectListItem> QuestionType = Survey();
//return View(QuestionType);
return View();
}
[HttpPost]
public ActionResult ManageQuestion(Question Objquest)
{
if (ModelState.IsValid)
{
SurveyAppEntities ObjEntity = new SurveyAppEntities();
string strDDLValue = Request.Form["DDlDemo"].ToString();
Objquest.QuestionType = strDDLValue;
ObjEntity.Questions.Add(Objquest);
ObjEntity.SaveChanges();
ViewData["error"] = "Question Saved successfully";
if (Objquest.ID > 0)
{
// ViewBag.Success = "Inserted";
}
ModelState.Clear();
}
return View();
}
}
I am thinking that it must call overload ManageQuestion method on button click but when view load first time it is entering in overload methos resulting in error.
I got one example from net having same scenario but overload method is not calling there on first form load ?
Hopes for your suggestion
Thanks

GET method executing before POST method after a page submit?

After editing a form and clicking a Save button, the HttpGet method is being executed before the HttpPost method. The page is reloading with the query string in the URL, and the old data still populating the fields, but the data has been saved on the server side. If I remove the query string and reload the page, the new data appears.
My expectation is that only the HttpPost method would be called, changes would be saved saved, then the page would be loaded back up with the saved changes.
Using the Microsoft.AspNetCore.Mvc": "1.0.0 package.
Here are my HttpGet and HttpPost methods:
[HttpGet]
[Route("~/Home/Activity/{activityId}")]
public IActionResult Activity(int activityId)
{
ViewData["Title"] = "Activity Detail";
FundraiserDBContext context = new FundraiserDBContext(_ServerName, EnvironmentCode);
Engagement activity;
if (activityId == -1)
{
activity = new Engagement();
context.Engagement.Add(activity);
}
else
{
activity = context.Engagement.FirstOrDefault(a => a.Id == activityId);
}
if (activity != null)
{
ActivityViewModel vmActivity = new ActivityViewModel(activity, context);
return View("Activity", vmActivity);
}
else
{
ActivityViewModel vmActivity = new ActivityViewModel(context);
return View("Activity", vmActivity);
}
}
[HttpPost]
[ValidateAntiForgeryToken]
//[Route("~/Home/Activity/{activityId}")]
public IActionResult Activity(ActivityViewModel vmActivity)
{
FundraiserDBContext db = new FundraiserDBContext(_ServerName, EnvironmentCode);
if (ModelState.IsValid)
{
db.Engagement.Update(vmActivity.ToEngagement(db));
db.SaveChanges();
}
return View("Activity", vmActivity); //this was vm.EngagementId
}
And here is the code for the Save button:
<button type="submit" class="btn-success pull-right" style="width:80px;" onclick="location.href='#Url.Action("Activity", "Home", #Model)'">Save</button>
Remove redirect from post method, because before returning the View its redirecting to the Index method without updated model
Redirect($"~/Home/Index"); // remove this line
Matjaž Mav found my error and described it in the comment below the original post. I mistakenly thought I needed the onclick event on my button. Removing this resulted in the expected behavior I was looking for.
The button code now looks like this:
<button type="submit" class="btn-success pull-right" style="width:80px;">Save</button>

How to maintain an Edit URL and existing data in a Save action

I have a Save method that has some additional server-side validation to it. If it fails, I want to maintain the "/Edit/id" URL in the browser so that refreshes will stay on the page. (If that's not possible in this situation, please let me know.)
Here's an abbreviated view of how I'm trying to do this right now:
[HttpPost]
public ActionResult Save(UserEditModel model) {
try {
repository.SaveUser(model.CopyTo());
}
catch (InvalidOperationException ex) {
// Doing this to just display it at the top of the page as it is not property-specific.
TempData["UserError"] = ex.Message;
// Doing this to maintain the "Edit/id" URL.
return RedirectToAction("Edit", "Users", new { id = model.Id });
}
// Want to keep the URL on the Index page as "Users", instead of "Users/Save".
return RedirectToAction("Index", "Users", new { page = model.Page });
}
Other than the URL, the biggest issue I'm coming across with this is that because I'm redirecting, I also lose all of the data the User already entered in the field on the failed Save attempt.
I already tried adding an optional UserEditModel parameter to the Edit action that would default to null, but when navigating to the Edit action from links on the page (not redirecting from the Save action), the optional Model parameter was getting defaulted to a new UserEditModel() instead of the default value of null I gave it in the parameter list.
You can either use a TempData to put your data in in your controller. And in your view put some conditions if it is not null then retreive the data from the viewbag and put it back.
in your Controller:
[HttpPost]
public ActionResult Save(UserEditModel model) {
try {
TempData["Field1"] = model.Field1;
TempData["Field2"] = model.Field2;
.....
repository.SaveUser(model.CopyTo());
}
catch (InvalidOperationException ex) {
// Doing this to just display it at the top of the page as it is not property-specific.
TempData["UserError"] = ex.Message;
// Doing this to maintain the "Edit/id" URL.
return RedirectToAction("Edit", "Users", new { id = model.Id });
}
// Want to keep the URL on the Index page as "Users", instead of "Users/Save".
return RedirectToAction("Index", "Users", new { page = model.Page });}
And then in your view:
#{if(TempData["Field1"] != null)
//Assign your textbox here
else
//your first code to display the textBox
}
I hope it will help you.
You should have a [HttpGet] action and return View(model); will save your data and url
public ActionResult Save(int id)
{
return View(repository.GetUserById(id));
}
[HttpPost]
public ActionResult Save(UserEditModel model) {
try {
repository.SaveUser(model.CopyTo());
return RedirectToAction("Index", "Users", new { page = model.Page });
}
catch (InvalidOperationException ex) {
TempData["UserError"] = ex.Message;
return View(model);
}
}

A view that was not created gets displayed

I don't have a view called Test. But, there's a method in the Home controller called Test.
Everything works fine, the Test method gets executed and redirected to Index view as given in the code. However, in the browser the URL is ../Home/Test and not ../Home/Index. I don't have a View called Test so why is this getting displayed ? I don't want this URL to be displayed in the browser. How can i solve this ?
View:
#using (Html.BeginForm("Test", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<input type="file" name="file" />
..// Other code
}
C#
public ActionResult Test(HttpPostedFileBase f)
{
var m = new HomeModel();
..// Other code goes here
return View("../Home/Index", m); // Will be returning the Index View
}
In URL
"../Home/Test"
Test is action thus it is working fine.
If you don't want this URL to be displayed, renamed the Action "Test" to "Index" and also update its references
and use (optional)
return View("Index", m)
If you are using the standard setting for MVC, it is not the View, but The Method, that is displayed in the browser. The method then by default returns the View (but that is optional).
So what you need to do is rename you Test Method to Index and place [HttpPost] on top of it.
[HttpPost]
public ActionResult Index(HttpPostedFileBase f)
{
var m = new HomeModel();
..// Other code goes here
return View(m);
}
return View("../Home/Index", m);
This will not redirect you to Index; it will simply display your Index view. If you want browser to automatically change your URL from /Test to /Index you have to instead do this:
return RedirectToAction("Index");
Try this:
public ActionResult Test(HttpPostedFileBase f)
{
var m = new HomeModel();
..// Other code goes here
return RedirectToAction("Index");
}

Categories

Resources