Trigger update action from checkboxfor with AnitForgeryToken from ajax call - javascript

I have this view that brings in all data from an entity:
#model MyApplication.Application.TableModel<Entities.FPDrinkingWater>
#{
Layout = null;
var insertionMode = InsertionMode.Replace;
var fail = "displayFailure";
var target = "UnverifiedDrinkingWatersContent";
var ajax = "UnverifiedDrinkingWaterLogLoader";
var verify = Html.UserHasClaim("FP/DrinkingWater/VerifyDrinkingWater");
var action = "VerifyDrinkingWater";
string form = action + "Form";
}
<br />
#if (Model != null && Model.Alert != null && Model.Alert.Message != null)
{
#Html.Alert(Model.Alert)
}
#MyHelper.Loader(ajax)
<div class="form-group">
<table id="UnverifiedDrinkingWaterTable" class="table table-hover">
<thead>
<tr>
<th>#Html.LabelFor(m => m.Data.FirstOrDefault().SID)</th>
<th>#Html.LabelFor(m => m.Data.FirstOrDefault().Location)</th>
<th>#Html.LabelFor(m => m.Data.FirstOrDefault().Replicate)</th>
<th>#Html.LabelFor(m => m.Data.FirstOrDefault().CollectionDate)
</th>
<th>#Html.LabelFor(m => m.Data.FirstOrDefault().CollectionTime)
</th>
<th>#Html.LabelFor(m => m.Data.FirstOrDefault().Collectors)</th>
<th>#Html.LabelFor(m => m.Data.FirstOrDefault().Clorinated)</th>
<th>#Html.LabelFor(m => m.Data.FirstOrDefault().Comments)</th>
<th>#Html.LabelFor(m => m.Data.FirstOrDefault().Verified)</th>
</tr>
</thead>
<tbody>
#for (int i = 0; i < Model.Data.Count(); i++)
{
using (Ajax.BeginForm(actionName: action, routeValues: null,
htmlAttributes: new { id = form, #class = "form-horizontal" },
ajaxOptions:
new AjaxOptions
{
InsertionMode = InsertionMode.Replace,
UpdateTargetId = target,
OnSuccess = "success",
LoadingElementId = ajax
}))
{
#Html.AntiForgeryToken()
<tr>
<td>#Html.DisplayFor(m => m.Data[i].SID)</td>
<td>#Html.DisplayFor(m => m.Data[i].Location)</td>
<td>#Html.DisplayFor(m => m.Data[i].Replicate)</td>
<td>#Html.DisplayFor(m => m.Data[i].CollectionDate)</td>
<td>#Html.DisplayFor(m => m.Data[i].CollectionTime)</td>
<td>#Html.DisplayFor(m => m.Data[i].Collectors)</td>
<td>#Html.DisplayFor(m => m.Data[i].Clorinated)</td>
<td>#Html.DisplayFor(m => m.Data[i].Comments)</td>
<td>#Html.CheckBoxFor(v => v.Data[i].Verified, new {
data_url = Url.Action("VerifyDrinkingWater", "DrinkingWater"), id =
"checkboxid" }) </td>
</tr>
}
}
</tbody>
</table>
</div>
<hr />
#if (Model.Data.Count > 0)
{
<script>
$(document).ready(function () {
makeDataTable('UnverifiedDrinkingWaterTable');
});
(function () {
$('#checkboxid').change(function () {
var data = {};
data[$(this).attr('name')] = $(this).is('checked');
$.ajax({
url: $(this).data('url'),
type: 'POST',
data: data,
success: function (result) {
}
});
});
});
</script>
}
What my goal is that I want to update 3 fields on the record displayed in the table by checking the "Verified" checkbox. I followed This Link to enable a click event on the checkboxfor. However, I receive an error claiming that The required anti-forgery form field __RequestVerificationToken is not present.. This is the only error I receive.
So my question is, how can I combine the AntiForgeryToken creation by the Ajax call AND pass the checked status of the checkbox at the same time and then pass it to the controller? Right now it's not even touching the controller and just giving me the AntiForgeryToken Error.

just get the token using
var token = $('input[name="__RequestVerificationToken"]').val();
and put it in data like this
var data = {
__RequestVerificationToken: token
}
please note that you render the AntiForgeryToken multiple times, so modify your code to have the ability to get the right AntiForgeryToke of each form

Related

Cascaded Drop Down List with search box

I'm trying to use cascaded Drop Down for a project, but with a bit of a twist. For Power Users, they can enter a stock code and search. The retrieved information then updates the Parent Drop Down and the cascaded Drop Down selection.
Using a click event, I can search the entered value and it returns all the needed information. I can update the Parent to Display the correct information, But unable to get the child to display. It's stuck on showing " -- Select --" Populating the drop down's with data to select from works great. Could really use some insight and help.. Got myself stumped on the child. Thanks..
I followed this example to setup the Dropdowns. asp.net MVC cascading dropdown lists
<Controller>
public ActionResult Create()
{
ViewData["User"] = User.Identity.GetUserName();
BindPartType();
return View();
}
public void BindPartType()
{
partsmanagementEntities5 parttypelist = new partsmanagementEntities5(); //Parts
var parttype = parttypelist.parttypes.ToList();
List<SelectListItem> pli = new List<SelectListItem>();
pli.Add(new SelectListItem { Text = "--Select Catagory--", Value = "0" });
foreach (var m in parttype)
{
pli.Add(new SelectListItem { Text = m.PartType1, Value = m.idPartType.ToString() });
ViewBag.PartType = pli;
}
}
public JsonResult GetInventory(int? id)
{
partsmanagementEntities5 partlist = new partsmanagementEntities5();
var ddlpart = partlist.parts.Where(x => x.PartType == id).ToList();
List<SelectListItem> lipart = new List<SelectListItem>();
lipart.Add(new SelectListItem { Text = "--Select Inventory--", Value = "0" });
if (ddlpart != null)
{
foreach (var x in ddlpart)
{
lipart.Add(new SelectListItem { Text = x.PartDescription, Value = x.idParts.ToString() });
}
}
return Json(new SelectList(lipart, "Value", "Text", JsonRequestBehavior.AllowGet));
}
public JsonResult Check(string id)
{
partsmanagementEntities5 partlist = new partsmanagementEntities5();
StringBuilder test = new StringBuilder();
if(id != null && id != "")
{
foreach (char c in id)
{
if (!char.IsNumber(c))
test.Append(c);
}
var ddlpartnumber = partlist.parts.Where(x => x.PartNumber == id.ToString());
PartDetails li = new PartDetails();
foreach (var item in ddlpartnumber.ToList())
{
li.PartNumber = item.PartNumber;
li.PartPrice = item.PartPrice;
li.idParts = item.idParts;
li.EHF = item.EHF;
li.PartDescription = item.PartDescription;
li.PartImage = item.PartImage;
li.partImageContentType = item.partImageContentType;
li.unit = item.unit;
li.PartType = item.PartType;
li.VendorPartNumber = item.VendorPartNumber;
}
return Json(li, JsonRequestBehavior.AllowGet);
}
return Json("", JsonRequestBehavior.AllowGet);
}
<View>
<table>
<tr>
<td style="padding-left:0.8ex;padding-top:0.8ex">#Html.Label("Catagory: ")</td>
<td>
#Html.DropDownListFor(model => model.PartType, ViewBag.PartType as List<SelectListItem>, new { style = "width: 800px;" })
#Html.ValidationMessageFor(model => model.PartType, "", new { #class = "text-danger" })
</td>
<td style="padding-left:6ex;padding-top:0.8ex"></td>
</tr>
<tr>
<td style="width:1px;white-space:nowrap;padding-left:0.8ex">#Html.Label("Inventory: ")</td>
<td>
#Html.DropDownListFor(model => model.PartNumber, new SelectList(string.Empty, "Value", "Text"), "--Select Inventory--", new { style = "width:900px" })
#Html.ValidationMessageFor(model => model.PartNumber, "", new { #class = "text-danger" })
</td>
</tr>
<tr>
<td style="width:1px;white-space:nowrap;padding-left:6ex">#Html.Label("Or choose:")</td>
</tr>
<tr>
<td style="width:1px;white-space:nowrap;padding-left:0.8ex">#Html.Label("Enter Valid Part #: ")</td>
<td><input type="text" name="CheckPartNumber" id="CheckPartNumber"> <input type="button" id="Search" value="Search" class="btn btn-default" />
</tr>
</table>
<script src="~/Scripts/jquery-3.0.0.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$("#PartType").change(function () {
$("#PartNumber").empty();
$.ajax({
type: 'POST',
url: '#Url.Action("GetInventory", "partrequests")',
dataType: 'json',
data: { id: $("#PartType").val() },
success: function (PartNumber) {
$.each(PartNumber, function (i, PartNumber) {
$("#PartNumber").append('<option value="'
+ PartNumber.Value + '">'
+ PartNumber.Text + '</option>');
});
},
error: function (ex) {
alert('Failed.' + ex);
}
});
return false;
})
});
$(document).ready(function () {
$("#Search").click(function () {
$.ajax({
type: 'POST',
url: '#Url.Action("Check","partrequests")',
dataType: 'json',
data: { id: $("#CheckPartNumber").val() },
success: function (Data) {
var selectedValue = Data.PartType
$('#PartType option').map(function () {
if ($(this).val() == selectedValue) return this;
}).attr('selected', 'selected').change();
var selectedValue2 = Data.idParts;
$('#PartNumber option').map(function () {
if ($(this).val() == selectedValue2) return this;
}).attr('selected', 'selected');
},
error: function (ex) {
alert('Failed.' + ex);
}
});
return false;
})
});
</script>

MVC foreach loop unique id C#

I have a foreach to loop through and populate rows in a table. Within the table I have calls to functions and need unique ids to execute the function for each row. It works for the first row as it recognizes the ids for that row but the next row has the same id. What I am trying to do is when the field of one of the rows changes it calculates a value and enters it another field in the corresponding row.
My table is the following
<table class="table">
<tr>
<th></th>
<th class="col1">MFC DRV</th>
<th class="col1">REF Flow (slpm)</th>
<th class="col1">Calibration Flow (slpm)</th>
<th class="col1">% Diff</th>
</tr>
#foreach (var item in Model.DILlist)
{
<tr>
<td>
#Html.HiddenFor(modelItem => item.MFC_PointsID, new { htmlAttributes = new { #id = item.MFC_PointsID } })
</td>
<td>
#Html.DropDownListFor(modelItem => item.selectedDRV, item.DRVs, htmlAttributes: new { style = "Width:75px", #id = "mfc" })
</td>
<td>
#Html.EditorFor(modelItem => item.RefFlow, new { htmlAttributes = new { #id = "refFlow", style = "Width:75px", onkeyup = "myFunction(this)" } })
</td>
<td>
#Html.EditorFor(modelItem => item.CalFlow, new { htmlAttributes = new { #id = "calFlow", #disabled = "disabled", style = "Width:75px" } })
</td>
<td>
#Html.EditorFor(modelItem => item.Diff, new { htmlAttributes = new { #id = "Diff", #disabled = "disabled", #class = item.Background, style = "Width:75px" } })
</td>
</tr>
}
<tr>
</table>
and my javascript function
function myFunction(a) {
var number = a.id;
$.ajax({
type: "POST",
//Dev
url: "/CertsHelper/FlowMeterDiffCheck",
//Test and Production
//url: "/RMS_SMM/CertsHelper/FlowMeterDiffCheck",
data: { calFlow: $('#calFlow').val(), refFlow: $('#refFlow').val() },
dataType: "json",
success: function (index) {
$("#Diff").val(index);
if ($("#Diff").val() <= 2 && $("#Diff").val() >= -2) {
$("#Diff").css('background', "lightGreen");
$("#Diff").val(index);
}
else {
$("#Diff").css('background', "indianred");
$("#Diff").val(index);
}
},
error: function (error) {
alert("%Diff not working: " + error);
}
});
}
I think the issue is that you are assigning duplicate IDs to DOM elements. Give each HTML element a unique ID by concatenating the property name and the item ID.
#Html.EditorFor(modelItem => item.RefFlow,
new { htmlAttributes =
new {
#id = $"refFlow_{item.MFC_PointsID}",
style = "Width:75px",
onkeyup = "myFunction(this)"
}
})
#Html.EditorFor(modelItem => item.RefFlow,
new { htmlAttributes =
new {
#id = $"Diff_{item.MFC_PointsID}",
style = "Width:75px"
}
})
In your JavaScript function, retrieve the item ID by splitting the element ID. There are other ways to accomplish this, but for me this approach is straightforward and simple to understand.
function myFunction(a) {
var itemID = a.id.split('_')[1];
...other code...
$('#Diff_' + itemID).val();
}

Sort list of objects in MVC

I am trying to build page that shows all selected movies depending on genre,
with $.post
If genre is not selected page should show all movies.It is default selection.
This is Controller code:
public class BrowseController : Controller
{
private MovieContext context = new MovieContext();
// GET: Browse
public ActionResult Index()
{
ViewBag.Genres = context.Genre.ToList();
IEnumerable<Movie> mov = TempData["movies"] as IEnumerable<Movie>;
if (mov == null)
{
IEnumerable<Movie> movies = context.Movies.ToList();
return View(movies);
}
return View(mov);
}
[HttpPost]
public ActionResult Index(int id = -1)
{
IEnumerable<Movie> model;
if (id != -1)
{
model = context.Movies.Where(x => x.GenreId == id);
}
else
{
model = context.Movies.ToList();
}
ViewBag.Genres = context.Genre.ToList();
TempData["movies"] = model;
return RedirectToAction("", "Browse");
}
}
And this is the view code:
#model IEnumerable<Movies.Models.Movie>
#using Movies.Models
#{
ViewBag.Title = "Index";
var Movie = Model.FirstOrDefault();
List<Genre> Genres = ViewBag.Genres;
}
#Html.DropDownListFor(m => Movie.GenreId, new SelectList(Genres, "Id",
"Name"), "")
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.Name)
</th>
<th>
#Html.DisplayNameFor(model => model.Rating)
</th>
<th>
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Rating)
</td>
<td></td>
</tr>
}
</table>
#section Scripts{
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script>
$('select#Movie_GenreId').on('change', function () {
var value = $(this).find(':selected').val();
var url = "/Browse/Index";
$.post(url, { id: value });
});
</script>
}
I checked Chrome Debugging tool and Network tab and I see in Preview tab of response that there are no errors and Get Browse/Index action is returning expected results but I don't see them in View. Not sure why.
You make a POST request , but you don't handle the response. For instance, you forget to update the DOM structure.
For doing this, you have to attach a callback function to the returned response.
$.post(url, { id: value },function(response){
//here is request response
});
Also, when you use AJAX, the purpose is to update DOM without refresh page to see the updates.
The solution is to return a JSON object with all the informations and then, handle them in the callback function of $.post method.

JQuery Postback triggered by nested DropDownListFor returning only the first row

I have a list of objects, which are shown using Editor Template. When a task's dropdownlistfor changes, the JSON postback always returns the values of the first task, regardless of which row's dropdownlist is updated.
I see many of the same problem, but not when the trigger is in a nested element inside a editor template. I'm lost as to what i'm missing out here. Help?
#model NSCEngineering.Models.task
#Html.HiddenFor(model => model.task_id, new { #id = "taskID" })
#Html.HiddenFor(model => model.task_name, new { #id = "TaskName" })
#Html.HiddenFor(model => model.task_desc, new { #id = "TaskDesc" })
#Html.HiddenFor(model => model.completion_date, new { #id = "CompletionDate" })
<table style="width:80%">
<tr style="width:60%">
<th colspan="3">#Html.DisplayFor(model => model.task_name)</th>
<th align="left">
#Html.DropDownListFor(model => model.task_state_id,
new SelectList((System.Collections.IEnumerable)ViewData["TaskStates"], "task_state_id", "state"),
new { #class = "ddlState"})
</th>
<td>
#Html.EditorFor(model => model.notes, new { #Id = "Notes" })
#Html.ValidationMessageFor(model => model.notes, "", new { #class = "text-danger" })
</td>
</tr>
<tr>
<td colspan="3">#Html.DisplayFor(model => model.task_desc)</td>
<td>#Html.Label("Completed by ")#Html.DisplayFor(model => model.user_completed)#Html.Label(", ")#Html.DisplayFor(model => model.completion_date)</td>
</tr>
</table>
<div class="tasks">
#Html.EditorFor(m => m.Tasks, new { #class = "Tasks"})
</div>
</div>
}
<p>
#Html.ActionLink("Back to List", "Index")
</p>
#section Scripts{
<script type="text/javascript">
$(this.document).ready(function () {
$('.ddlState').change(function ()
{
var task = {
"task_id": $("#taskID").val(),
"task_state_id": $('#ddlState').val(),
"task_name": $('#TaskName').val(),
"task_desc": $('#TaskDesc').val(),
"notes": $('#Notes').val(),
}
var url = '#Url.Action("UpdateTaskState")';
$.ajax({
type: 'POST',
url: url,
data: JSON.stringify(task),
dataType: 'json',
contentType: 'application/json; charset=utf-8',
success: function (result) {
alert("success");
$("#message").html("Success");
location.reload(true);
},
error: function (xhr, status, error) {
// Show the error
$('#message').html(xhr.responseText);
}
})
})
});
</script>
}
your code is : new { #class = "ddlState"}) so you shoud use "task_state_id": $('.ddlState').val(), with "." not "task_state_id": $('#ddlState').val(), with "#" because it's class not id

form.valid() returns true when form is invalid

I have a form consisting of listboxes and radiobuttons. I submit the form through ajax which sends a post. The actionlink in my controller returns a partial view. If the form is invalid I don't want to clear the selected items in the listboxes, but if the form is valid then everything should be unselected. For some reason form.valid() is always true. The error message shows perfectly so I think there is nothing wrong with the validation. Here are some snippets of my code:
View: Form
<div id="researchContainer">
#using (Html.BeginForm("ResearchCompetence", "Planning", FormMethod.Post, new { #id = "researchForm" }))
{
#Html.HiddenFor(x => x.Input.PlanningId)
#Html.ValidationSummary()
<h1>#Html.Label("OverviewResearchCompetences", Labels.OverviewResearchCompetences)</h1>
<table class="table-output">
<thead>
<tr>
<td>#Html.Label("Name", Labels.Name)</td>
<td>#Html.Label("Level", Labels.Level)</td>
<td class="text-align-right"></td>
</tr>
</thead>
<tbody>
#if (Model.CurrentResearchCompetences.Count == 0)
{
<tr>
<td>#Html.Label("NoCurrentCompetencesRes", Labels.NoCurrentCompetencesRes)</td>
</tr>
}
else
{
foreach (var item in Model.CurrentResearchCompetences)
{
<tr>
<td>#item.Vtc</td>
#{
var scoreOutput = new ILVO.Services.EmployeeManagement.ScoreOutput(item.VtcLevel);
}
<td>
#scoreOutput.ToString()
#if (!scoreOutput.ToString().Equals("Gevorderd"))
{
<span class="arrow-up">
#Html.ImageLink("IncreaseLevel", "Planning", new { id = #item.Id, planningId = Model.Input.PlanningId, actionMethod = "JobCompetence" },
"/Content/arrow-icon.png", Labels.IncreaseLevel, "")
</span>
}
#if (!scoreOutput.ToString().Equals("Basis"))
{
#Html.ImageLink("DecreaseLevel", "Planning", new { id = #item.Id, planningId = Model.Input.PlanningId, actionMethod = "JobCompetence" },
"/Content/arrow-icon.png", Labels.DecreaseLevel, "")
}
</td>
<td class="text-align-right deleteLink">
#Html.ImageLink("DeleteVtc", "Planning", new { id = #item.Id, planningId = #Model.Input.PlanningId, actionMethod = "JobCompetence" },
"/Content/delete-icon.png", Labels.Delete, "")
</td>
</tr>
}
}
</tbody>
</table>
<br />
<h1>#Html.Label("AddResearchCompetence", Labels.AddResearchCompetence)</h1>
<table>
<thead>
<tr>
<td>#Html.Label("Disciplines", Labels.Disciplines)</td>
<td>#Html.Label("Organisms", Labels.Organisms) <a id="clear-organisme" class="button-clear-vtc">Clear</a></td>
<td>#Html.Label("Techniques", Labels.Techniques) <a id="clear-technique" class="button-clear-vtc">Clear</a></td>
</tr>
</thead>
<tbody>
<tr>
<td>
#Html.ListBoxFor(x => x.Input.SelectedDiscipline, Model.Disciplines, new { #class = "vtc-listbox-height", #size = 1 })
</td>
<td>
#Html.ListBoxFor(x => x.Input.SelectedOrganism, Model.Organisms, new { #class = "vtc-listbox-height" })
</td>
<td>
#Html.ListBoxFor(x => x.Input.SelectedTechnique, Model.Techniques, new { #class = "vtc-listbox-height" })
</td>
</tr>
</tbody>
</table>
<div id="after-selection-ok">
<h1>#Html.Label("ChooseLevel", Labels.ChooseLevel)</h1>
#Html.RadioButtonFor(x => x.Input.Score, 0, new { #id = "radio1" }) #Html.Label("radio1", Labels.Basic, new { #class = "radio-label" })<br />
#Html.RadioButtonFor(x => x.Input.Score, 1, new { #id = "radio2" }) #Html.Label("radio2", Labels.Intermediate, new { #class = "radio-label" })<br />
#Html.RadioButtonFor(x => x.Input.Score, 2, new { #id = "radio3" }) #Html.Label("radio3", Labels.Expert, new { #class = "radio-label" })<br />
<br />
<input class="button" type="submit" name="AddResearchCompetence" value="#Labels.Submit" />
#Html.ActionLink(Labels.GoBack, "Detail", new { id = #Model.Input.PlanningId }, new { #class = "button margin-left" })
</div>
}
Controller : Actionlink
[HttpPost]
public ActionResult ResearchCompetence(ResearchCompetenceInputModel input)
{
// do some validations
// if validations are ok = add competence else return view
return PartialView("ResearchCompetence", new ResearchCompetenceModel(researchCompetences, currentResearchCompetences, input.PlanningId));
}
My Ajax Call
$("#researchForm").submit(function () {
$.ajax({
type: 'POST',
url: '#Url.Action("ResearchCompetence")',
data: $("#researchForm").serialize(),
success: function (data) {
$("#researchContainer").html(data);
$("#researchForm").validate();
if ($("#researchForm").valid()) { // always true
$("#Input_SelectedOrganism").val('');
$("#Input_SelectedTechnique").val('');
$("input[name='Input.Score']").attr('checked', false);
}
}
});
return false;
});
I also have these scripts loaded:
#Scripts.Render("~/bundles/modernizr")
#Scripts.Render("~/Scripts/jquery-1.10.2.js")
#Scripts.Render("~/Scripts/jquery.validate.min.js")
#Scripts.Render("~/Scripts/jquery.validate.unobtrusive.js")
#Scripts.Render("~/Scripts/jquery-ui-1.10.3.js")
#Scripts.Render("~/Scripts/tinymce/tinymce.min.js")
#Scripts.Render("~/Scripts/ckeditor/ckeditor.js")
#Scripts.Render("~/Scripts/site.js")
#Scripts.Render("~/Scripts/jquery.ui.datepicker-nl-BE.js")

Categories

Resources