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>
Related
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
I want to redirect to a previous page after I submit some data in database. I am using a TempData to retrieve ID on current Page, then I am going on the page with the form I want to submit (which have an ID), but after the POST method is fired TempData gets overrided by current page ID which is the page with the form and I want to ReturnRedirect to initial page with its ID.
Here the code:
Controller with GET method where I retrieve the ID:
var currentID = Url.RequestContext.RouteData.Values["id"];
TempData["currentId"] = currentID;
Controller with POST method where I try to redirect:
if (ModelState.IsValid)
{
// Editing records in database
....
return RedirectToAction("Details", "Jobs",
new { controller = "JobsController", action = "Details", id = TempData["currentId"] });
}
ModelState.AddModelError("", "Something failed");
return View();
I am using this approach because its working if the current action with a POST method doesn't have an ID.
Thank you for any suggestions.
EDIT:
I have a Details of Jobs:
// GET: Jobs/Details/5
public ActionResult Details(Guid id)
{
var currentID = Url.RequestContext.RouteData.Values["id"];
TempData["currentId"] = currentID;
var currentUserTemp = LoggedUserId;
TempData["userID"] = currentUserTemp;
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Job job = db.Jobs.Find(id);
if (job == null)
{
return HttpNotFound();
}
return View(job);
}
But from this page I want a link to a page where I edit current user data.
View Details page Code:
#Html.ActionLink("Edit Company Details", "Edit", "UserAdmin", new { id = TempData["userID"] }, null)
Now I am on edit User Page, I edit the form and use save button (which triggers POST method) I want to use the other TempData variable to ReturnRedirect on Details Page but since both pages have ID`s, TempData gets overrided with last ID from the URL which is the ID of the user not ID.
Don't forget that TempData exists only during the time of a HTTP Request. Maybe it's a clue to your problem (I can't find all the interactions between Controllers and Views in your code so I can't be sure).
I have created a page that takes in a string that will search a list of vendors. My goal is to output them to a grid list on an HTML page. Oddly enough, the first page loads, and I can break point the code until the return view of the actual list page. However, it never actually loads. It is even more frustrating because if I don't pass the model to the grid page, it gives me the typical "You can't use a null model", but then it still doesn't load the new page. I have tried several versions. The most current is below.
[HttpPost]
public ActionResult Search(String searchString)
{
this.searchString = searchString;
List<VendorInvoice> v = VendorSearches.publicSearch(searchString);
test = v;
ViewData.Model = v;
TempData.Add("test",v);
return RedirectToAction("Search");
}
[HttpGet]
public ActionResult Search()
{
List<VendorInvoice> v = (List<VendorInvoice>)TempData["test"];
return View("Search",v);
}
So if I take the v out, then I get the error about not passing the model. If it is there, then nothing will happen. The new page won't load.
In your HttpPost search action method, you are setting the result data to show in TempData and doing calling the RedirectToAction method.
RedirectToAction returns an HTTP 302 response to the browser, which causes the browser to make a GET request to the specified action. That means, it will be totally new request coming to your search GET action again. Since Http is stateles, it does not have any idea about what you did in your previous request. The data stored in TempData won't be available to this request.
What you should be doing is, similar to your GET action method, simply
return the result to the view.
[HttpPost]
public ActionResult Search(String searchString)
{
this.searchString = searchString;
List<VendorInvoice> v = VendorSearches.publicSearch(searchString);
return View("Search",v);
}
That should fix your problem. But as Stephen Muecke mentioned, you can keep just your GET action method for your Initial view and search result view
public ActionResult Search(String searchString="")
{
List<VendorInvoice> v = new List<VendorInvoice>();
v = VendorSearches.publicSearch(searchString);
return View("Search",v);
}
And your view
#model List<VendorInvoice>
#using(Html.BeginForm("Search","YourControllerName",FormMethod.GET)
{
<input type="text" name="searchString" />
<input type="submit" />
}
<h2>Results</h2>
#foreach(var item in Model)
{
<p> #item.SomePropertyNameOfYourVendorInvoiceHere </p>
}
I have an #Html.ActionLink inside of a partial view that when clicked I'd like to have either send the user to another view or stay on the current view without changing anything. Is this possible?
Our controller looks like:
public ActionResult Edit(int id)
{
if (ShouldAllowEdit(id))
{
return this.View("Edit", ...edit stuff...)
}
return ????????
}
We tried return new EmptyResult(); but that just dumps the user to a blank page.
This is a little different approach to the issue, but it should do what you want.
Instead of giving the user a link to navigate to, do an ajax call on link/button click, and do the id check. Return either the url to navigate to in a JsonResult, or nothing if the id is invalid.
On return of the ajax call, navigate to the url if appropriate.
(swap out the hard coded ids and the == 0 with your ShouldAllowEdit function in the example of course)
In the View:
<div class="btn btn-danger" id="myButton">Button</div>
#section scripts{
<script>
$("#myButton").click(function () {
$.ajax("#Url.Action("Edit", new { id = 0 })", { type : "POST" })
.success(function (data) {
if (data.url !== "") {
window.location.href = data.url;
}
});
});
</script>
}
In the controller:
[HttpPost]
public JsonResult Edit(int id)
{
if (id == 0)
{
return Json(new {url = ""});
}
else
{
return Json(new { url = Url.Action("EditPage", new { id = id }) });
}
}
An answer is to redirect to the view action - and maybe give some feed back why they failed.
public ActionResult Edit(int id)
{
if (ShouldAllowEdit(id))
{
return this.View("Edit", ...edit stuff...)
}
ModelState.AddModelError("id", "Not allowed to edit this item");
return RedirectToAction(Edit(id));
}
If the user clicks a link they will be taken away. They might be sent back right to the same page, but the page will unload, be requested from the server again, and then re-rendered in the browser. If you don't want that to happen, you don't give the user the link in the first place. In other words, conditionally render the link or not based on the user's roles or whatever.
#if (userCanEdit)
{
#Html.ActionLink(...)
}
Where userCanEdit is whatever logic you need to make that determination.
If the user fails whatever check you determine, then they don't get the link. Simple.
However, since there's malicious people in the world, you can't just leave it entirely there. There's potential for the user to figure out the link to edit something and go there manually. So, to prevent that you check for the edit permission in your action (like you've already got in your code sample), but if the user is not allowed, then you just return a forbidden status code:
return new HttpStatusCodeResult(HttpStatusCode.Forbidden);
Or
return new HttpStatusCodeResult(403);
They both do the same thing.
UPDATE
Based on your comment above, it appears that the user is normally allowed to edit but can't in a particular instance because another user is editing. A 403 Forbidden is not appropriate in that case, so really all you've got is a simple redirect back to the page they were on, perhaps with a message explaining why they're back there.
TempData["EditErrorMessage"] = "Sorry another user is editing that right now.";
return RedirectToAction("Index");
I have this problem:
I go to a page such as:
/Auction/Details/37
and this calls this action method:
public ActionResult Details(int id)
A particular line in this method is:
return View("DetailsLub", auction);
This view contains this line:
#Html.Action("BidOnAuction", new { auctionId = Model.Id })
Which calls this action method:
public PartialViewResult BidOnAuction(int auctionId)
So far so good?
Now, I have a form in the BidOnAuction view, whcih has a button. When I click on this button, this action method is invloked:
[HttpPost]
public ActionResult BidOnAuction(BidOnAuctionViewModel model)
This action method has a catch statement with the following lines:
ModelState.AddModelError(string.Empty, operation + #" Failure: " + message);
return RedirectToAction("Details", new { id = model.AuctionId });
Now, both the DetailsLUB view and the BidOnAction view contain this line:
#Html.ValidationSummary(true)
But, the issue is that nothing ever gets printed to the screen. What am I doing wrong?
InOrder to get the validation Message on the page you need to return view with Model, as model has the Model State within it, something like this:
return View(Model);
This will return the model BidOnAuction with Validation Summary.
This line of code
return RedirectToAction("Details", new { id = model.AuctionId });
Returns instance of RedirectResult class. That is generally used for redirections and does not render view. If you want to render child action into parent view using #Html.Action, you need to return view from that child action, not RedirectResult. And that RedirectResult will not work even when there's no child action. Returning RedirectResult causes browser to issue fresh, all new request to that action. And model state is lost anyways. You should do something like
try
{
//some actions
return RedirectResult("Details", new { id = model.AuctionId });
}
catch
{
ModelState.AddModelError(string.Empty, operation + #" Failure: " + message);
return View("Details", new { id = model.AuctionId });
}
You can't redirect to a new action and expect the modelstate to be there.
If the modelState is invalid just return (with View(model))
else
redirect to details.
If you need the error information in the details view you will have add it to TempData or pass it in as an optional parameter.