Good day,
I have a button
<a class="btn btn-primary btn-large" href="/servicios/ChangeFieldToFalse?Id=4">change field to false</a>
and this in my backend
public ActionResult ChangeFieldToFalse(Guid Id)
{
var userId = User.Identity.GetUserId();
var result= _myclass.changeFieldToFalse(servicioId, userId);
return .....
}
Is it possible to avoid refreshing the page without using ajax? if so, how would I do it? I mean, I click on the button, a field in a table is changed to false.
Thank you .
Related
I use ASP.NET Core 6 MVC and Entity Framework 6.0.11 and I have trouble when deleting data from SQL Server.
When I click delete button, it makes the deletePage show 0 values, when I back to the list the data I just deleted, it does not disappear (see screenshot).
My controller:
public IActionResult deletePackage (long ID)
{
ForDeletePackage = LQHVContext.Packages.Where(s => s.PackagesId == ID).FirstOrDefault();
if (ForDeletePackage == null)
{
return NotFound();
}
return View(ForDeletePackage);
}
[HttpPost]
public IActionResult Delete(long ID)
{
Package package = new Package() { PackagesId = ID };
LQHVContext.Packages.Attach(package);
LQHVContext.Packages.Remove(package);
if (LQHVContext.SaveChanges() == 1)
{
//redirect to package list
return RedirectToAction("packageList", "Packages");
}
return View("deletePackage", package);
}
My razor page:
<form asp-action="Delete">
<input type="submit" value="Delete" class="btn btn-danger" /> |
<a asp-action="listPackage">Back to List</a>
</form>
Screenshots:
My ConfirmDelete page
After I click delete btn
when I back to List, the data still there
I doubt HTML forms can do a DELETE HTTP operation against our API. The only two options are POST and GET
See this question as well Should PUT and DELETE be used in forms?
I have a cshtml view, for which I am sending a viewmodel. That viewmodel consist of two list of albums (music albums). I then ask the user to check up to 3 of these albums (a checkbox next to the title) to vote for his favorite music. I use javascript to ensure he doesn't check anymore than 3 (The security is a detail right now, I'm more concerned about getting it to work, but I'm open to suggestion if people have a better solution).
Since all albums are displayed in a table, I would love to send back to the controller through the submit button, the same model after updating it.
Basically, one of the list contain the current vote the user has made before loading the page (can be empty), and the second one should be empty until sent back to the controller containing the list of votes that are currently selected. I then use these two lists to compare them and update the database, removing the votes he removed, and adding the vote he added.
But I am unable to create a proper form to return these informations as I am not used to forms.
I tried to put the whole list in a form, but it didn't work. My reserach when I look for "sending model back to controller" usually do just that and get it to work.
View model
public class CategoryVotesUserViewModels
{
public CategoryVoteViewModels categoryVoteViewModels;
public List<int> listVotesEntry = new List<int>();
public List<int> listVotesOutput = new List<int>();
}
Relevant CSHTML and javascript
#section Header{
<script>
var MAX_VOTES = 3;
function checkNumberVotes($this) {
console.log($("input[name='listVoteOutput']:checked"));
if ($("input[name='listVoteOutput']:checked").length > MAX_VOTES) {
$this.checked = false;
}
}
</script>
}
#using (Html.BeginForm("VoteInCategory", "Votes", new { SearchModel = Model }, FormMethod.Post))
{
<ul>
#foreach (var av in Model.categoryVoteViewModels.listVotes)
{
<li>
#av.album.Title | #av.votes |
<input type="checkbox"
name="listVoteOutput"
value=#av.album.ID
onclick="checkNumberVotes(this)"
#if (Model.listVotesEntry.Contains(av.album.ID))
{ <text> checked </text> } />
</li>
}
</ul>
<div class="form-group text-center">
<input type="submit" class="btn btn-primary" value="Submit" />
</div>
}
Controller
[HttpPost]
public ActionResult VoteInCategory(CategoryVotesUserViewModels categoryVotesUserViewModels)
{
if (ModelState.IsValid)
{
List<int> toAdd = categoryVotesUserViewModels.listVotesOutput.Except(categoryVotesUserViewModels.listVotesEntry).ToList();
List<int> toRemove = categoryVotesUserViewModels.listVotesEntry.Except(categoryVotesUserViewModels.listVotesOutput).ToList();
VoteService.updateVoteUserCategory(User.Identity.GetUserId(), toRemove, toAdd, categoryVotesUserViewModels.categoryVoteViewModels.categoryID);
//TODO Redirect to success
return RedirectToAction("Index", "Home");
}
return View(categoryVotesUserViewModels);
}
If the user already had voted, all album whose ID is in "ListVotesEntry" should begin checked. If the user hasn't voted, or voted for nothing previously, "ListVotesEntry" should be empty.
When the User press the submit button, if an album is checked, the album's id should be added to the "ListVotesOutput" list. Also, both "ListVotesEntry" and "ListVotesOutput" should be sent back to the controller. The list with the names of the albums and their titles/ID is no longer necessary for the rest of the treatment
Found the solution. The problem was that my model needed to use "{get; set;}" on its attributes, otherwise the binding doesn't work, which mean that it send back an empty model.
I am asking a simple login page to get the user to enter a pin on a mobile responsive app its in house not online.
When the page is posted the user clicks the submit button the SaveUsers is the function that is called first this is on the Login Controller.
[HttpPost]
[ActionName("Index")]
public ActionResult SaveUsers(Users model)
{
BrianScott_SOMEntities usr = new BrianScott_SOMEntities();
var s = usr.GetUsers(model.Pin);
var item = s.FirstOrDefault();
if (item == "Success")
{
var sageDetails = usr.Users.Where(w => w.Pin ==model.Pin).FirstOrDefault();
HttpCookie cookie = new HttpCookie("BScotSalesOrderManagerLogin");
cookie.Values.Add("SageUserName", sageDetails.SageUserName.ToString());
cookie.Values.Add("SagePassword", sageDetails.SagePassWord.ToString());
cookie.Expires = DateTime.Now.AddDays(30);
Response.Cookies.Add(cookie);
return View("~/Views/Home/Index.cshtml");
}
else if (item == "User Does not Exists")
{
ViewBag.NotValidUser = item;
}
else
{
ViewBag.Failedcount = item;
}
return View("Index.cshtml");
}
The below form is the form that is represented with the above controller which prompts the user for their pin number.
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
#model Web.SOM.Models.Users
#using (Html.BeginForm())
{
<div class="bs-example" style="border:2px solid gray;">
<label>#ViewBag.SageUserName</label>
<div class="form-group centerlook">
<h1> Login </h1>
</div>
<div class="form-group centerlook">
<label>Pin: </label>
#Html.EditorFor(model => model.Pin )*
#Html.ValidationMessageFor(model => model.Pin)
</div>
<div class="form-group error">
#if (#ViewBag.Failedcount != null)
{
<label> Failed Attempt count is: #ViewBag.Failedcount</label>
}
#if (#ViewBag.NotValidUser != null)
{
<label> #ViewBag.NotValidUser</label>
}
</div>
<div class="loginbtn">
<input type="submit" value="Login" class="btn btn-primary" />
</div>
</div>
}
The home controller is what the controller in the first piece of codes redirects to it is the index action to which I want to hit.
public ActionResult Index()
{
if (Request.Cookies["BScotSalesOrderManagerLogin"] != null)
{
ViewBag.SageUserName = Request.Cookies["BScotSalesOrderManagerLogin"].Values["SageUserName"];
ViewBag.SagePassword = Request.Cookies["BScotSalesOrderManagerLogin"].Values["SagePassword"];
}
return View();
}
But the method is not getting hit unless I do a hard reload is there another way of moving to the other view and making sure that the index method is being hit ?.
Because when I look at the viewbag the items are null when they should contain a username and a password of the related row when I debug on the first page the values are their but then lost on the other page.
On my page i am wanting to display the information I am just doing
<label>Sage Username : #ViewBag.SageUserName </label>
But the value is blank? I am coming from a web forms background so please excuse me better late than never jumping ship
Your sequence of events is...
User POSTs to SaveUsers on Login (aliased as the action Index)
You return a view
User POSTs from that view to Index, still on Login
When you do this:
return View("~/Views/Home/Index.cshtml");
You're essentially overriding the framework's standard behavior. You're returning a specific file to be used as the view, but not telling the framework to switch any context or change the URL in any way. So from the browser's perspective, even though you returned a view from your server-side Home folder, the page is still /Login/Index and any form actions, links, etc. will be from there.
In general you should prefer redirects to manually specifying views. So a sensible sequence of events might be:
User POSTs to SaveUsers on Login (aliased as the action Index)
Server-side code performs its logic, redirects the user to Index on Home
User GETs Index on Home
Server returns the view
User POSTs to Index on Home
So your SaveUsers action method, when successful, can do something like:
return RedirectToAction("Index", "Home");
This will then cause the user to make a GET request to Index on Home, which can just return View() and that will default to the view you're manually returning now. Now from the browser's perspective it's on /Home/Index and all form actions, links, etc. will be from that context.
Additionally, if you always want a given form, link, etc. to point to a specific controller action regardless of where it was loaded from, you can specify that. For example, when you do this:
using (Html.BeginForm())
You are telling the framework that this form will "POST to the current URL, whatever that URL is". But when you do this:
using (Html.BeginForm("Index", "Home"))
This tells the framework that the form will always post to the Index action on the Home controller, regardless of the current URL.
can you try using
#using (Html.BeginForm(yourActionName, yourControllerName))
{
}
And use RedirectToAction to return to your Home Index..
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>
I have to allow the user to move to the next or previous form, I just need to save the model on navigation. Is there another way to pass back the model to the controller besides using submit? Since I need to redirect to other possible pages.
You could put your model object in the TempData collection on submit, redirect, then read it back out again. For example:
[HttpPost]
public ActionResult FirstForm(FirstFormModel model) {
TempData["TempModelStorage"] = model;
return RedirectToAction("SecondForm");
}
public ActionResult SecondForm() {
var firstModel = TempData["TempModelStorage"] as FirstFormModel;
// check for null, use as appropriate, etc.
return View(...);
}
More details here: http://msdn.microsoft.com/en-us/library/dd394711(v=vs.100).aspx
You may save the data asynchronously using jQuery ajax on those button click events.
Assuming your View is something like this
#using(Html.BeginForm("Save","Items"))
{
<div>
Name : #Html.TextBoxFor(s=>s.Name)
<input type="button" class="navigBtns" value="Prev" />
<input type="button" class="navigBtns" value="Next" />
</div>
}
And your script is
$(function(){
$(document).on("click",".navigBtns",function() {
e.preventDefault();
var _this=$(this);
$.post(_this.closest("form").attr("action"), _this.closest("form").serialize(),
function(res){
//check res variable value and do something as needed
// (may be redirect to another page /show/hide some widgets)
});
});
});
Assuming you have an action method called Save in your controller to handle the saving part.
Was given a neat article about this.
MVC Wizard Example
Basically this, you literally pass the name of the html button.
In the view form
<input type="submit" name="btnPrev" />
<input type="submit" name="btnNext" />
In the Controller
Controller
public ActionResult DoStuff(ModelClass mc,string btnPrev,string btnNext)
{
string actionString = "previousPage";
if(btnNext != null)
actionString = "nextPage";
return RedirectToAction(actionString,"Controller")
}