Get a boolean value from database to checkbox with option to update in .NET MVC using AJAX - ajax

I need to do the following table with .NET MVC and AJAX:
The idea is a list with users with the option to lock each of them (i am using the standard identity model):
Email | Username | LockoutEnabled
user1#domain.com | User1 | [x]
user2#domain.com | User2 | [0]
user3#domain.com | User3 | [0]
For the moment I successfully update the current status in the view from the db to the checkbox using this approach
<td>
#Html.EditorFor(modelItem => user.LockoutEnabled)
</td>
What i want to do next is:
1. Update the db on the current checkbox status without reloading the page
2. Show a notification on successful DB update from the view (no reload)
This is the controller returning the status
[Authorize(Roles = "Admin")]
public ActionResult LockUser(string id, bool status)
{
PFMDbContext db = new PFMDbContext();
db.Users.FirstOrDefault(user => user.Id == id).LockoutEnabled = status;
db.SaveChanges();
return new HttpStatusCodeResult(HttpStatusCode.OK);
}

This is a simple job using Ajax.
Create a ViewModel that will be passed to the view.
public class ApplicationUserViewModel
{
public string Id { get; set; }
public string Name { get; set; }
public bool IsLocked { get; set; }
}
The controller methods.
[HttpGet]
public ActionResult LockUsers()
{
var db = new PFMDbContext();
var model = db.Users
.Select(p => new ApplicationUserViewModel
{
Id = p.Id,
Name = p.Name, // Or whatever properties you have
IsLocked = p.LockoutEnabled
}).ToList();
}
[HttpPost]
public ActionResult LockUser(string id, bool isLocked)
{
var db = new PFMDbContext();
try
{
var user = db.Users.FirstOrDefault(user => user.Id == id);
user.LockoutEnabled = isLocked;
db.SaveChanges();
return Json(true);
}
catch
{
return Json(false);
}
}
In your view
#model List<ApplicationUserViewModel>
<!-- This is just an example. Use your own template. -->
#foreach (var user in Model)
{
<div>
<p>#user.Name</p>
<input id="#user.Id" type="checkbox" data-userid="#user.Id" class="js-islocked" value="#user.IsLocked" />
</div>
}
Then using javascript you can bind the select event.
$(document).ready(function () {
$(this).on('change', 'js-islocked', function () {
var userId = $(this).data('userid');
var isLocked = $(this).prop('checked');
// Use ajax to save the modification
$.ajax({
type: 'POST',
url: '/Users/LockUser',
data:{ id: userId, isLocked: isLocked },
contentType: 'application/json',
success:function(data) {
// Update a div or show a message
}
})
});
});

Related

Ajax POST insert half data(some data is missed) Asp.Net MVC Ajax

I am inserting data via Ajax Post method. Data is inserted in one table but the data for secod table is not inserting. I have checked the code but I am not sure that what is mising in my code.
When I use the direct controller method then the data is inserted in both table but when I use the Ajax then data is inserted in only one table.
My Old working Controller code:
[HttpPost]
public ActionResult Create(StudentModel model)
{
if(ModelState.IsValid)
{
int id = stude.AddStudent(model);
if(id>0)
{
ModelState.Clear();
ViewBag.Success = "Data added Successfully";
}
}
return View();
}
My Ajax Controller Code:
[HttpPost]
public JsonResult Creates(StudentModel model)
{
if (ModelState.IsValid)
{
int id = stude.AddStudent(model);
if (id > 0)
{
ModelState.Clear();
ViewBag.Success = "Data added Successfully";
return Json("success", JsonRequestBehavior.AllowGet);
}
}
return Json("issue", JsonRequestBehavior.AllowGet);
}
My Model Code:
public int AddStudent(StudentModel stu)
{
student stud = new student()
{
FName = stu.FName,
LName = stu.LName,
Email = stu.Email
};
if (stu.address != null) {
stud.address= new address()
{
Details = stu.address.Details,
Country = stu.address.Country,
State = stu.address.State
};
}
using (var context = new StudentEntities())
{
context.students.Add(stud);
context.SaveChanges();
}
return stud.Id;
}
My Js/Ajax Code:
$(document).ready(function () {
//Add record
$("#add").click(function (e) {
e.preventDefault();
// var id = $();
var fname = $("#FName").val();
var lname = $("#LName").val();
var email = $("#Email").val();
var details = $("#Details").val();
var country = $("#Country").val();
var state = $("#State").val();
$.ajax({
async: true,
method: "POST",
url: '#Url.Action("Creates")',
data: JSON.stringify({
FName: fname, LName: lname, Email: email, Details: details,County: country, State: state
}),
dataType: 'JSON',
contentType: "application/json; charset=utf-8",
success: function (data) {
//window.location = data.newurl;
console.log(data);
},
error: function (err) {
alert('Failed to get data' + err);
}
});
return false;
});
});
Data is inserted in only student table and for the address table it returns null/empty and the data is skipped, although the same code will work if I remove the Ajax. But I want to use the Ajax so things will work smoothly.
Any help will be appreciated.
Update: Student Model class:
I am using N-Tire/3-Tire Architecture
My Student class Properties
public class StudentModel
{
public int Id { get; set; }
public string FName { get; set; }
public string LName { get; set; }
public string Email { get; set; }
public Nullable<int> AddressId { get; set; }
public AddressModel address { get; set; }
}
My Address Class Properties
public class AddressModel
{
public int Id { get; set; }
public string Details { get; set; }
public string State { get; set; }
public string Country { get; set; }
}
}
There were a lot of issues in my code. I am listing it below.
The main, which I think case the problem is the Id's of my textboxes, as I am using Razor Engine and it creates the id automatic, which cause the issue, So I fix it by adding the Id and Name manually, like
#Html.EditorFor(model => model.address.Details, new { htmlAttributes = new { #class = "form-control", Name="Details", Id="Details"} })
I have changed my ajax data code to:
FName: fname, LName: lname, Email: email, address: { Details: details, Country: country, State: state }
For success message I have change Return message in my controller like:
var scess = "Data added Successfully";
return Json(new { success = true, scess }, JsonRequestBehavior.AllowGet);
and in my view I have add this line in my ajax success call:
success: function (data) {
$("#msg").text(data.scess);
console.log(data);
},
Hope this will also help other users in future.

Like button in MVC using 'Ajax.Beginform()' not able to display total likes on page

I am beginner in MVC and Ajax development and want a like button in my web, which should work like this: if the user clicks on it total likes will be incremented by 1 and if the user clicks it again (dislike) then it will decremented by 1. What I have done so far is this:
Here's the Model:
public class Like
{
public int Id { get; set; }
public virtual Video Video { get; set; }
public int VideoID { get; set; }
public string UserId { get; set; }
public virtual ApplicationUser ApplicationUser { get; set; }
}
Here is the Controller:
Post Method
[HttpPost]
public ActionResult Like(int Id, Like like)
{
if (ModelState.IsValid && User.Identity.IsAuthenticated == true)
{
like.Video = storeDB.Videos.Find(Id);
like.UserId = User.Identity.GetUserId();
var userlike = storeDB.Likes.Where(l => l.UserId == like.UserId && l.VideoID == Id);
if (userlike.Count() == 0)
{
storeDB.Likes.Add(like);
storeDB.SaveChanges();
}
else if (userlike.Count() == 1)
{
var likeDel = storeDB.Likes.FirstOrDefault(l => l.UserId == like.UserId && l.VideoID == Id);
storeDB.Likes.Remove(likeDel);
storeDB.SaveChanges();
}
List<Like> videoLikes = storeDB.Likes.Where(v => v.VideoID == Id).ToList();
int nooflikes = videoLikes.Count();
ViewBag.noLikes = nooflikes;
return Json(ViewBag.noLikes, JsonRequestBehavior.AllowGet);
}
else
{
ViewBag.Message = "Login to like this video";
return PartialView("Like", ViewBag.noLikes);
}
This is the Get method of Like:
public ActionResult Like(int id)
{
List<Like> videoLikes = storeDB.Likes.Where(v => v.VideoID == id).ToList();
int nooflikes = videoLikes.Count();
ViewBag.noLikes = nooflikes;
return Json(ViewBag.noLikes, JsonRequestBehavior.AllowGet);
}
and I have created a Partial View for this:
#if (ViewBag.Message != null)
{
<script>
$(document).ready(function () {
alert('#ViewBag.Message');
});
</script>
}
//to display total likes
<input type="text" id="likes" name="likes" value='#ViewBag.noLikes' readonly="readonly" style="border:none; background-color:transparent; width:20px" /><span style="color:black">likes</span>
and this is the main view in which I am using Ajax.BeginForm()
#using (Ajax.BeginForm("Like", "VOD", new { Id = Model.Id },
new AjaxOptions
{
HttpMethod = "Post",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "likecount"
}))
{
<button type="submit" id="like" value="Like" class=" btn btn-primary btn-xs"> Like <span class="glyphicon glyphicon-thumbs-up" aria-hidden="true"></span> </button>
}
<span id="likecount">
#Html.Partial("Like", new Models.Like())
</span>
Now the issue is that when the page is first loaded it is not displaying total likes, and when I click on like button it returns 1 and when I click like button again it returns 0 but when I refresh the page or when I post back to another page total likes again disappear.
Can anybody help me?
Instead of doing so much code you can do above functionality in simple way.
You will required following to do so,
2 Action Methods,
1. Increment Like Count.
2. Decrease Like Count.
2 Buttons on web page
1. Like Button (Initially visible)
2. DisLike Button (Initially Invisible)
you can create a ajax request on both buttons something like bellow,
$("#btnLike").click(function () {
$.ajax({
type: "POST",
url: "Controller/LikeAction",
data: { /* Your Data */ };
success: function (result) {
// Hide Like Button & Show Dislike Button
},
error: function (error) {
alert("error = " + error);
}
});
});
Same way you can create ajax request for dislike button also. You just need to hide and show buttons.

How to send Model value as parameter while submitting #Ajax.Beginform()

I am using #Ajax.Beginform in my View which is tightly bound to the ViewModel.
I've #Html.ListBoxFor inside my form. I add and delete items from the listbox using jQuery. Now what I am want to achieve is that onpress of the submit button, it should send full data present in the listbox regardless of which are selected. Currently it sends the list to controller if I select all the item in the listbox and press submit button. But I don't want to do that. Any idea as to how to achieve this?
Can it be sent as a form parameter.
#using (Ajax.BeginForm("SaveTextComponent", "LoanFilterEditor", new{ param1 = Model.listBoxItem}, new AjaxOptions { HttpMethod = "POST", OnSuccess = "SUCCESS" }))
I try to accept the parameter in the controller like this
public ActionResult SaveTextComponent(TextComponentViewModel model, List<SelectListItem> list)
{
}
But list is null.. Please help.
Maybe you can use this javascript to select all items at your listbox and then, send it to controller:
function listbox_selectall(listID, isSelect) {
var listbox = document.getElementById(listID);
for(var count=0; count < listbox.options.length; count++) {
listbox.options[count].selected = isSelect;
}
}
And after that, you can call the function on your form in this way:
<script>
function submit() {
listbox_selectall('righthand_side_listbox_id', true);
return true;
}
</script>
<form onsubmit="return submit()">
...
</form>
Credits to Viral Patel blog
You can follow my example:
Model:
pulic class TextComponentViewModel {
public int[] SelectedListItem { get; set; }
public List<Item> ListItem { get; set; }
}
public class Item {
public int Id { get; set; }
public String Name { get; set; }
}
View:
#model TextComponentViewModel
#using (Ajax.BeginForm("SaveTextComponent", "LoanFilterEditor", null, new AjaxOptions { HttpMethod = "POST", OnSuccess = "SUCCESS" }, new {name = "mainForm", id = "mainForm"}))
{
#Html.ListBoxFor(model => model.SelectedListItem , new MultiSelectList(Model.ListItem, "ID", "Name"))
for(var i = 0; i < Model.ListItem.Count();i++ )
{
#Html.HiddenFor(m => m.ListItem[i].Id)
#Html.HiddenFor(m => m.ListItem[i].Name)
}
<input type = "submit" id="submitButton" />
}
Controller:
public ActionResult SaveTextComponent(TextComponentViewModel model)
{
}
Script:
$("#submitButton").click(function(){
$("#mainForm").submit();
});

Cascading Dropdown in Mvc3

I am using Mvc3 I have 2 dropdown,BankBranch and city.
On first time load of view i am binding both the dropdon without cascading. then if user select city i want to change bankbranch according to that.
I am confused how i can achieve both the things together.
Thanks in advance.
This blog post should get you on your way. It provides examples for normal form posts, microsoft ajax form post, jquery ajax and others.
http://weblogs.asp.net/raduenuca/archive/2011/03/06/asp-net-mvc-cascading-dropdown-lists-tutorial-part-1-defining-the-problem-and-the-context.aspx
EDIT:
Generalized Code Explanation
Model
public class CascadeModel {
public SelectList<City> Cities { get; set; }
public SelectList<BankBranch> BankBranches { get; set;}
public int CityId { get; set; }
public int BranchId { get; set; }
}
public class Branch {
public int Id { get; set;}
public string Name { get; set; }
}
Controller:
public ActionResult BranchSelector() {
var viewData = new CascadeModel();
viewData.Cities = new SelectList(Repository.GetAllCities(), "Id", "Name", selectedCity);
viewData.BankBranches = new SelectList(Repository.GetBranchesByCity(selectedCity), "Id", "Name", "");
return View(viewData);
}
public JsonResult GetBranches(int id) {
return Json(Repository.GetBranchesByCity(id), JsonRequestBehavior.AllowGet);
}
View:
#model CascadeModel
#Html.DropDownListFor(m => m.CityId, Model.Cities, new { style = "width:250px" })
<br />
#Html.DropDownListFor(m => m.BranchId, Model.BankBranches, new { style = "width:250px" })
<script type="text/javascript">
$(document).ready(function() {
$("#CityId").bind('change', function() {
$.ajax({
url: '/Controller/GetBranches/' + $(this).val(),
success: function(data) {
//Clear the current branch ddl
//Load the new Branch data returned from the jquery call in the branches ddl
}
});
};
});
</script>

serialize List<SelectListItem> from View to Controller in MVC 3

I'm having issues passing my list object to my controller - using an ajax post.
in the view I have this:
try {
var id = schedule.value;
var data2 = #Html.Raw(Json.Encode(Model.SavedScheduleList));
var url = '#Url.Action("SetActiveSchedule", "Frame")';
$.post(url, { savedScheduleList: data2, signScheduleDataId: id }, function (data) {
});
}
catch (err)
{
alert(err);
}
My Controller looks like this:
[HttpPost]
public ActionResult SetActiveSchedule(List<SelectListItem> savedScheduleList, int signScheduleDataId)
{
try
{
return Json(null);
}
catch (Exception ex)
{
throw;
}
}
So when my Action is executed, my savedScheduleList contains a list object with 7 objects (which is the correct number of items I'm sending through. However each item seems to be "blank". ie, of the SelectListItem class, these are the property values for each item: Selected = false, Text = null, Value = null.
The Model class (which has been strongly typed to this view) is:
public class ScheduleModel
{
private SignSchedule activeSignSchedule = new SignSchedule();
private List<SelectListItem> savedSignScheduleList = new List<SelectListItem>();
public int SignDataId { get; set; }
public ScheduleFrameList ListFrames { get; set; }
public DateTime Start { get; set; }
public LogMessage LogMessage { get; set; }
public bool CommsLogVisible { get; set; }
public SignSchedule SignScheduleToMakeActive { get; set; }
public int ActiveSignScheduleId { get; set; }
//public List<SignSchedule> SavedSignScheduleList { get { return savedSignScheduleList; } }
public List<SelectListItem> SavedScheduleList { get { return savedSignScheduleList; } }
}
Examining data2 before the post, shows the correct data in Json format and examining the Request property within the Action I can see the correct values in the Form.AllKeys property as well as the Params property but it doesn't seem to correctly resolve it back to my parameter object of the Controller Action.
Is it possible what I'm trying to do?
Thanks
EDIT
Here's a string representation of data2 variable:
var data2 = [{"Selected":false,"Text":"9","Value":"2589"},false,"Text":"afsdfs","Value":"2585"},false,"Text":"sdfas","Value":"2588"}....]
I'm just showing 3 items here but there is in fact 7 as expected.
The easiest way to send complex objects and lists is to use a JSON request, like this:
var id = schedule.value;
var data2 = #Html.Raw(Json.Encode(Model.SavedScheduleList));
$.ajax({
url: url,
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify({ savedScheduleList: data2, signScheduleDataId: id }),
traditional: true,
success: function(result) {
// TODO: do something with the results
}
});
Note that the JSON.stringify function is natively built into modern browsers. But if you need to support legacy browsers you could include the json2.js script into your page.

Resources