Kendo UI Grid: update/save not working (_AntiForgeryToken not present) - c#

I have a KENDO grid that displays contract attachments, which has a column 'Status'. In that column the current status of the attachment/contract is displayed. When invoking the 'Edit' event a combobox appears in the cell with all available status options.
After selecting a status and clicking the "update" button, I get the following exception:
The required anti-forgery form field "__RequestVerificationToken" is not present.
I added the #Html.AntiForgeryToken() in the view with the grid, and the [ValidateAntiForgeryToken] annotation to my method.
What am I doing wrong here?
This is the grid:
#Html.AntiForgeryToken()
#(Html.Kendo().Grid<AttachmentGridViewModel>()
.Name("attachmentEditGrid")
.HtmlAttributes(new
{
style = "height:auto;",
#class = "kendoHover"
})
.Columns(columns =>
{
columns.Bound(c => c.number).Title(Resources.Number);
columns.Bound(c => c.Consultant.FirstName).Title(Resources.Consultant);
columns.Bound(c => c.StartDate).Title(Resources.StartDate).Format("{0:" + System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern + "}");
columns.Bound(c => c.EndDate).Title(Resources.EndDate).Format("{0:" + System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern + "}");
columns.Bound(c => c.Status).Title(Resources.Status).EditorTemplateName("ContractStatusEditor");
columns.Command(command =>
{
command.Custom(Resources.Delete).Text("<span class=\"glyphicon glyphicon-remove padding-deletebutton \"></span>" + Resources.Delete).Click("onClickAttachmentDelete").HtmlAttributes(new { #class = "btn btn-danger" });
command.Edit().Text(Resources.Edit).CancelText(Resources.Cancel);
}).Title(Resources.Action).Width(200);
})
.ToolBar(toolBar => toolBar.Template("<a class='k-button k-button-icontext' href='/FA/ContractAttachment/CreateContractAttachment?contractId=1'><span class='glyphicon glyphicon-plus'></span>" + Resources.CreateAttachment + "</a>"))
//.Scrollable()
.Pageable(pageable => pageable
.Refresh(true)
.PageSizes(new List<object> { 3, 6, 12, Resources.All })
.ButtonCount(5))
// .Sortable()
.Filterable(filterable => filterable
.Extra(true)
.Operators(operators => operators
.ForString(str => str.Clear()
.Contains(Resources.Contains)
.StartsWith(Resources.StartsWith)
.EndsWith(Resources.EndsWith)
.IsEqualTo(Resources.IsEqualTo)
.IsNotEqualTo(Resources.IsNotEqualTo)
)))
.Events(events => events
.Save("onSaveAttachStatus")
.Edit("onAttachEdit")
.DataBound("onAttachDataBound")
.Cancel("onCancelEditing")
)
.Editable(editable => editable.Mode(GridEditMode.InLine))
.Selectable(s => s.Enabled(ViewBag.Permissions.ReturnValue.FaEditStatusContractAttachments))
.DataSource(dataSource => dataSource
.Ajax()
.ServerOperation(true)
.Update(update => update.Action("ChangeStatus", "ContractAttachment").Data("getValues"))
.Read(read => read.Action("ReadAttachmentsGrid", "Contract", new { id = Id }))
.PageSize(10)
.Model(model =>
{
model.Id(c => c.ContractId);
model.Field(c => c.number).Editable(false);
model.Field(c => c.Consultant).Editable(false);
model.Field(c => c.StartDate).Editable(false);
model.Field(c => c.EndDate).Editable(false);
model.Field(c => c.Status).Editable(true);
}))/*End datasource*/
)
This is the actionmethod that is called to save changes:
[HttpPost]
[ValidateAntiForgeryToken]
[Auth(Permission.FaEditStatusContractAttachments)]
public JsonResult ChangeStatus(int idAttachment, string statusContractAttach)
{
var contractAttach = _getContractAttachmentByIdQueryHandler.Execute(idAttachment).ReturnValue;
var contractAttachStatus = (ContractStatus)Enum.Parse(typeof(ContractStatus), statusContractAttach);
if (contractAttach == null)
{
var json = new { result = "Failed" };
return Json(json, JsonRequestBehavior.AllowGet);
}
contractAttach.StatusContractAttachment = contractAttachStatus;
var result = _updateContractAttachmentCommandHandler.Execute(new UpdateContractAttachmentCommand(contractAttach));
if (result.HasError)
{
var json = new { result = "Failed" };
return Json(json, JsonRequestBehavior.AllowGet);
}
else
{
UpdateHistory(idAttachment, contractAttachStatus);
var json = new { result = "Success" };
return Json(json, JsonRequestBehavior.AllowGet);
}
}
This is the JQuery related to the grid :
//--------------------------Attachments EDIT Grid --------------------//
//save event
function onSaveAttachStatus(e) {
//post status data to action method
$.post('#Url.Action("ChangeStatus", "ContractAttachment")', { contractId: e.model.Id, status: e.model.StatusContract }).success(function(data) {
showErrorNotification('#Resources.ContractStatusChangedSuccessMessage', true);
});
};
//kendo notification with succesmessage
function showErrorNotification(message, success) {
var notification = $("#staticNotification").data('kendoNotification');
notification.show(message, success ? "success" : "error");
var container = $(notification.options.appendTo);
container.scrollTop(container[0].scrollHeight);
}
function onClickAttachmentDelete() {
//custom delete function
var idToDelete = $(this).closest('tr').data('attachid');
var attachNumber = $(this).closest('tr').data('number');
//initiates modal with data
$('#dialog-delete-attachnr').text(attachNumber);
$("#dialog-delete-attach").modal();
$('#dialog-delete-attach').data('attachid', idToDelete);
$('#dialog-delete-contract').data('attachnumber', attachtNumber);
}
//edit event
function onAttachEdit(e) {
var ddl = $("#Status").data('kendoDropDownList');
var oldData = ddl.dataSource._data;
var signedAccountStatus = #((int) ContractStatus.SignedByAccount);
for (var i = 0; i < oldData.length; i++) {
if (ddl.selectedIndex >= signedAccountStatus && parseInt(oldData[i].Value) < signedAccountStatus) {
ddl.dataSource.remove(oldData[i--]);
}
}
console.log("edit ok");
}
//resets grid data
function resetGrid() {
$("#attachmentEditGrid").data("kendoGrid").dataSource.read();
};
//returns data for the .Update action
function getValues(e) {
var id = e.Data.attachId;
var value = e.Data("kendoDropdownList").value();
console.log(id, value);
return { id, value };
}
//Hide edit button when status is finished and hide delete when anyone signed
//when data is loaded to the grid
function onAttachDataBound(e) {
var attachEditGrid = $("#attachmentEditGrid").data("kendoGrid");
var attachEditGridData = attachEditGrid.dataSource.view();
//loop through rows
for (var i = 0; i < attachEditGridData.length; i++){
var row = attachEditGrid.table.find("tr[data-uid='" + attachEditGridData[i].uid + "']");
var statusContractAttach = attachEditGridData[i].Status;
//hide delete when signed
if (statusContractAttach >= #((int) ContractStatus.SignedByAccount)){
row.find('.k-grid-Delete').hide();
}
//hide edit when contract is finished
if (statusContractAttach == #((int)ContractStatus.Finished)){
row.find(".k-grid-edit").hide();
}
}
};
//cancel edit
function onCancelEditing(e) {
resetGrid();
onAttachDataBound();
}

JQuery post method does not automatically add the __RequestVerificationToken parameter. I suggest add it manually.
var data = $.extend(true, { contractId: e.model.Id, status: e.model.StatusContract },
{ __RequestVerificationToken: $('input[name="__RequestVerificationToken"]').val() });
// maybe you need convert to json befor send data:
// data = data.toJSON();
$.post('#Url.Action("ChangeStatus", "ContractAttachment")', data )
.success(function(data) {
showErrorNotification('#Resources.ContractStatusChangedSuccessMessage', true);
});

Related

Kendo popup return null in asp.Net mvc

I have a Kendo grid in Mvc C# that displays a list of 'jobs'.I put an extra button in this grid that by clicking on that contact information of that job in a Kendo grid as open pop up.
But the pop-up does not show anything.and only show Null!!
this is my code:
Job List in Index.cshtml:
<div>
#(Html.MyGrid<JobListVm>("grid_job")
.Columns(c =>
{
c.Bound(b => b.Id).Width("6%");
c.Bound(b => b.CategoryName).Width("15%");
c.Bound(b => b.JobName).Width("15%");
c.ViewEditDeleteExtendColumn(d => d.Id,
extendColumn: "<button class='k-button' onclick='" +
"pageJobIndex3.JobConnectionList(#= Id#);" + "' title='" + "ارتباطات" + "'><span
class='k-icon k-i-password'></span></button> ",
viewHandler: "pageJobIndex.view(#= Id#);",
editHandler: "pageJobIndex.edit(#= Id#);",
deleteHandler: "pageJobIndex.delete(#= Id#);").Width(210);
})
.DataSource(d => d.Ajax()
.Read(r => r.Action("List", "Job", new { }).Type(HttpVerbs.Post))
.Sort(s => s.Add(a => a.Id).Descending()).Model(m => m.Id(a => a.Id)))
)
</div>
<script>
pageJobIndex3 = {
JobConnectionList: function (id)
{
var url = '#Url.Action("JobConnections", "Job", new { })' + '/' + id;
kashi.win.createNewAjaxSimple(
"#info",
url,
function (kashiWindow) {
kashiWindow.open();
},
function (kashiWindow) {
var page = kashiWindow.winData.page;
var result = page.result;
if (result && result.success) {
pageJobIndex3.refreshGrid();
}
},
function (kashiWindow) {
kashiWindow.destroy();
},
{
width: "30%"
}
);
}
}
</script>
in JobController:
[HttpGet]
public JsonResult JobConnections(DataSourceRequest request,int id)
{
var list = _jobConnectionService.GetJobConnections(id).ToList();
var items =list.ToDataSourceResult(request);
return Json(items);
}
In JobConnection.cshtml:
<div>
#(Html.MyGrid<JobConnectionVm>("grid_jobConnection")
.Columns(c =>
{
c.Bound(b => b.JobName).Width("15%");
c.Bound(b => b.NConnectionType).Width("15%");
c.Bound(b => b.ConnectionValue).Width("15%");
c.Bound(b => b.NCreationDate).Width("15%");
c.ViewEditDeleteColumn(d => d.Id,
viewHandler: "pageJobConnectionIndex.view(#= Id#);",
editHandler: "pageJobConnectionIndex.edit(#= Id#);",
deleteHandler: "pageJobConnectionIndex.delete(#= Id#);").Width(170);
})
.DataSource(d => d.Ajax()
.Read(r => r.Action("JobConnections","Job", new { }).Type(HttpVerbs.Get))
.Sort(s => s.Add(a => a.Id).Descending()).Model(m => m.Id(a => a.Id)))
)
</div>
<!--</div>-->
<script>
pageJobConnectionIndex = new genPageHandler(
'#grid_jobConnection',
'#info',
"#Url.Action("Create", "JobConnections", new { })",
"#Url.Action("Edit", "JobConnections", new { })",
"#Url.Action("Show", "JobConnections", new { })",
"#Url.Action("Delete", "JobConnections", new { })",
"500px",
""
);
</script>
Complete the explanations:
I get this error in console window:
Failed to set autoNumeric TypeError: $(...).find(...).autoNumeric is not a function
at Object.numericInputSet (kashi.ui.js:924)
at Object.createNew (kashi.win.js:395)
at kashi.win.js:197
at Object.success (kashi.lib.js:480)
at i (jquery.min.js:3)
at Object.fireWith [as resolveWith] (jquery.min.js:3)
at y (jquery.min.js:11)
at XMLHttpRequest.c (jquery.min.js:11) n.fn.init(1)
in kashi.ui.js:
numericInputSet: function (inputContainer) {
try {
$(inputContainer).find(".auto-numeric").autoNumeric("init", {
mDec: "0"
});
} catch (e) {
console.log("Failed to set autoNumeric", e, inputContainer);
}

How to Bind a DropDownList Text Value to another DropDownList using Kendo UI for MVC?

I'm using the Kendo UI for ASP.NET MVC and need to bind the selected value of a dropdown list to another dropdownlist. I want the user to only be shown the citiy entries that are applicable to the State selection they choose. My dropdownlist is as follows:
<div id="bindcity" class="inr_div" data-bind="visible: showFromChooseCity">
<h5 class="inr_hd">City<span>*</span>:</h5>
#(Html.Kendo().DropDownList()
.Name("fromCity")
.DataTextField("name")
.DataValueField("id")
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetCity", "Quote");
})
.ServerFiltering(true);
})
.SelectedIndex(0)
)
I setup several controller classes as follows:
public JsonResult GetZips()
{
FreightEntities freight = new FreightEntities();
var zips = freight.ZipCodes.AsQueryable();
var city = freight.ZipCodes.AsQueryable();
if (city != null)
{
zips = zips.Where(z => z.Zip = zips);
}
return Json(freight.ZipCodes.Select(z => new {Zip = z.Zip}), JsonRequestBehavior.AllowGet);
}
public JsonResult GetCity()
{
FreightEntities freight = new FreightEntities();
var state = freight.ZipCodes.AsQueryable();
var city = freight.ZipCodes.AsQueryable();
if (state != null)
{
city = city.Where(s => s.State = state);
}
return Json(freight.ZipCodes.Select(s => new { State = s.State }), JsonRequestBehavior.AllowGet);
}
public JsonResult GetState()
{
FreightEntities freight = new FreightEntities();
return Json(freight.ZipCodes.Select(s => new {State = s.State }), JsonRequestBehavior.AllowGet);
}
The above code now gives the error:
Cannot implicitly convert type 'System.Linq.IQueryable<FRCV2.Models.ZipCode>' to 'string'
Since I'm not using an ID field in my entities, what's the appropriate way of comparing the fields above?
How do I achieve this cascading dropdownlist effect?

Update rows from grid and database with Kendo UI and MVC

I'm using a MVC project with Visual Studio 2012 and Kendo UI 2014.
I can update a row from the grid and it changes, but when I reload the page, the row appears with the original info. I would like to update it in the database too.
This is my code:
.cshtml (View):
<div class="grid">
#(Html.Kendo().Grid<UsersModel>()
.Name("grid")
.Editable(editable => editable.Mode(GridEditMode.InCell))
.DataSource(dataSource => dataSource
.Ajax()
.Model(r => r.Id(p => p.Id))
.Read(r => r.Action("GetAccounts", "ManagerAccounts", new { area = "Admin" }))
.Destroy("Delete", "ManagerAccounts")
.Update("Update", "ManagerAccounts")
.Create("Create", "ManagerAccounts")
)
.Columns(columns =>
{
columns.Bound(c => c.Id);
columns.Bound(c => c.UserName);
columns.Bound(c => c.Email);
columns.Command(command => command.Destroy()).Width(120);
})
.Pageable(pageable => pageable
.Refresh(true)
.PageSizes(true)
.ButtonCount(5)
)
.Sortable()
.Navigatable()
.ToolBar(toolbar => {
toolbar.Create();
toolbar.Save();
})
)
</div>
Controller:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Update([DataSourceRequest] DataSourceRequest request, IEnumerable<UsersModel> users)
{
if (users != null && ModelState.IsValid)
{
foreach (var user in users)
{
AccountRepository.UpdateUsuarios(user);
}
}
return Json(ModelState.ToDataSourceResult());
}
Repository (AccountRepository):
public void UpdateUsuarios(UsersModel user)
{
var usuario = this.Context.Users.Where(l => l.Id == user.Id).FirstOrDefault();
if (usuario != null)
{
usuario.Id = user.Id;
usuario.UserName = user.UserName;
usuario.Email = user.Email;
this.Context.SaveChanges();
}
}
I tried with this.Context.SaveChanges(); but it doesn't work.
Could you please try this code:
if (usuario != null)
{
usuario.Id = user.Id;
usuario.UserName = user.UserName;
usuario.Email = user.Email;
this.Context.Entry(usuario).State = System.Data.Entity.EntityState.Modified;
this.Context.SaveChanges(); // Or you may try await this.Context.SaveChangesAsync();
}

NopCommerce - Page Navigation Issue with Telerik-Grid

I am using nopCommerce. I have used telerik-grid to bind data in a table and data binded successfully. I have create method named "EditContact" for Edit operation. but when i clicked Edit link to redirect page named "_CreateOrUpdateContact.cshtml", i got "Page not found" page.
telerik-grid code :
#(Html.Telerik().Grid<AddressModel>()
.Name("vendors-grid")
.Columns(columns =>
{
columns.Bound(x => x.CountryName)
.Width(200).Centered();
columns.Bound(x => x.FirstName)
.Width(200).Centered();
columns.Bound(x => x.LastName)
.Width(200).Centered();
columns.Bound(x => x.Title)
.Width(200).Centered();
columns.Bound(x => x.Email)
.Width(200).Centered();
columns.Bound(x => x.PhoneNumber)
.Width(200).Centered();
columns.Bound(x => x.Address1)
.Width(200).Centered();
columns.Bound(x => x.Id)
.Width(200)
.Centered()
.Template(x => Html.ActionLink(T("Admin.Common.Edit").Text, "Edit", new { id = x.Id }))
.ClientTemplate("" + T("Admin.Common.Edit").Text + "")
.Title(T("Admin.Common.Edit").Text);
columns.Bound(x => x.Id)
.Template(x => Html.ActionLink(T("Admin.Common.Delete").Text, "Delete", new { id = x.Id }))
.ClientTemplate("" + T("Admin.Common.Delete").Text + "")
.Centered().Width(200)
.HeaderTemplate(T("Admin.Common.Delete").Text);
})
.Pageable(settings => settings.PageSize(gridPageSize).Position(GridPagerPosition.Both))
.DataBinding(dataBinding => dataBinding.Ajax().Select("ListContacts", "VendorDetails",new { vendorId = Model.Id }))
.EnableCustomBinding(true))
EditContact.cshtml Code:
#model AddressModel
#using (Html.BeginForm())
{
<div class="section-header">
<div class="options">
<input type="submit" name="save" class="t-button" value="#T("Admin.Common.Save")" />
<input type="submit" name="save-continue" class="t-button" value="#T("Admin.Common.SaveContinue")" />
</div>
</div>
#Html.Partial("_CreateOrUpdateContact", Model)
}
#Html.DeleteConfirmation("vendor-delete")
VendorDetailsController Methods:
[HttpPost, GridAction(EnableCustomBinding = true)]
public ActionResult ListContacts(int vendorId,GridCommand command)
{
if (!_permissionService.Authorize(StandardPermissionProvider.ManageVendors))
return AccessDeniedView();
var Addresses = _addressService.GetVendorAddresses(vendorId);
var gridModel = new GridModel<AddressModel>
{
Data = Addresses.Select(x =>
{
var a = new AddressModel();
PrepareAddressModel(a, x, false);
return a;
}),
Total = Addresses.Count,
};
return new JsonResult
{
Data = gridModel
};
}
// edit vendor contact
public ActionResult EditContact(int id)
{
if (!_permissionService.Authorize(StandardPermissionProvider.ManageVendors))
return AccessDeniedView();
var address = _addressService.GetAddressById(id);
int vendorId = _vendorContactService.GetVendorIdByAddressId(address.Id);
if (address == null)
//No Address found
return RedirectToAction("Edit", new { id = vendorId });
var model = new AddressModel();
model.VendorId = vendorId;
//Ordering Method
model.AvailableCountries.Add(new SelectListItem() { Text = "-- Select --", Value = "0" });
foreach (var c in _countryService.GetAllCountries(true))
model.AvailableCountries.Add(new SelectListItem() { Text = c.Name, Value = c.Id.ToString() });
PrepareAddressModel(model, address, false);
return View(model);
}
Am i doing something wrong?
How can i redirect from telerik grid- Edit Link to _CreateOrUpdateContact.cshtml page?
Please, check if "_CreateOrUpdateContact.cshtml" is in the same location with "EditContact.cshtml". I will suggest you to debug the code. Put a breakpoint at "public ActionResult EditContact(int id)" then check if debug point is hit after clicking the edit link from grid. If it is not hit then there may be some problem in route.
It would be better if you can provide the screen shot of the error you found
you can check the route here in the telerik-grid
columns.Bound(x => x.Id)
.Width(200)
.Centered()
.Template(x => Html.ActionLink(T("Admin.Common.Edit").Text, "Edit", new { id = x.Id }))
.ClientTemplate("" + T("Admin.Common.Edit").Text + "")
.Title(T("Admin.Common.Edit").Text);
as I think the route had a problem I should be like that
columns.Bound(x => x.Id)
.Width(200)
.Centered()
.Template(x => Html.ActionLink(T("Admin.Common.Edit").Text, "EditContact", new { id = x.Id }))
.ClientTemplate("" + T("Admin.Common.Edit").Text + "")
.Title(T("Admin.Common.Edit").Text);

C# MVC Populate group of dropdown lists in datatable

So im using jquery.dataTables.js to display about a thousand rows, while only showing about twenty at a time. The problem is with the dropdownlist on every line it takes about 10 seconds to load the page and shows a lot more of the records while loading. I thought about doing it after page load with ajax but not sure how to do that cleanly with all of them. Any ideas.
#for (int i = 0; i < Model.billVersion.Count; i++)
{<tr>
<td>#Html.DisplayFor(model => model.billVersion[i].billNumber)#Html.HiddenFor(model => model.billVersion[i].billNumber)</td>
<td>#Html.DisplayFor(model => model.billVersion[i].lrNumber)</td>
<td>#Html.DisplayFor(model => model.billVersion[i].previousYear)</td>
<td>#Html.DisplayFor(model => model.billVersion[i].committeeRec)</td>
<td>#Html.DropDownListFor(model => model.billVersion[i].committeeID, #Model.committeDropDown, "")</td>
<td>#Html.CheckBoxFor(model => model.billVersion[i].save_Remove)</td>
</tr>
}
An application of Jquery UI autocomplete:
!function ($) {
var cache = {};
$("[data-options]").each(constructAjaxOptions);
function constructAjaxOptions() {
var el = $(this),
acEl = $(el.clone(false)),
url = el.attr('data-options'),
initialLabel = el.attr('data-initial-label') || el.val(),
myCache = cache[url];
if (!myCache) {
myCache = cache[url] = {};
}
el.hide();
acEl
.removeAttr('id').removeAttr('name')
.val(initialLabel)
.insertAfter(el)
.autocomplete({
autoFocus: true,
minLength: 0,
source: function (request, response) {
var term = request.term;
if (term in myCache) {
response(myCache[term]);
return;
}
$.getJSON(url, request, function (data, status, xhr) {
myCache[term] = data;
response(data);
});
},
focus: function (event, ui) {
// Overridden to keep the value of the field
// from flashing in the textbox.
return false;
},
select: function (event, ui) {
acEl.val(ui.item.label);
el.val(ui.item.value);
return false;
}
});
}
}(jQuery);
.cshtml
<input type="text" id="#Html.IdFor(model => model.billVersion[i].committeeID)" name="#Html.NameFor(model => model.billVersion[i].committeeID)" value="#Value"
data-options="#Url.Action("BillVersions", "Options")" data-initial-label="#model => model.billVersion[i].commiteeName" />
Within an MVC action:
var model = billVersions.Select(o => new
{
value = o.committeeID,
label = o.commiteeName
})
.ToList();
return new JsonResult { JsonRequestBehavior = JsonRequestBehavior.AllowGet, Data = model };

Categories