I'm trying my hand at jTables with MVC 3, but have run into an issue. When my page loads, I'm not getting any calls to my [HttpPost] method. I think because of this, I keep getting the 'error connecting to database' message.
Can someone explain why my [HttpPost] method isn't getting called? Here's the relevant code:
<div id="CompetitionTable""></div>
<script type="text/javascript">
$(document).ready(function () {
//Prepare jtable plugin
$('#CompetitionTable').jtable({
title: 'The Events List',
paging: true, //Enable paging
pageSize: 10, //Set page size (default: 10)
sorting: true, //Enable sorting
defaultSorting: 'Name ASC', //Set default sorting
actions: {
listAction: '#Url.Action("EventList", "CompetitionController")'
},
fields: {
EventID: {
key: true,
create: false,
edit: false,
list: false
},
EventName: {
title: 'Name',
width: '15%'
},
CompetitorEmail: {
title: 'Email address',
list: false
},
CompetitorName: {
title: 'Competitor',
width: '15%',
},
Score: {
title: 'Score',
width: '10%',
}
}
});
//Load list from server
$('#CompetitionTable').jtable('load');
});
</script>
[HttpPost]
public JsonResult EventList(int compId)
{
try
{
//Get data from database
List<Event> events = Event.getEventsByCompetitionId(compId);
//Return result to jTable
return Json(new { Result = "OK", Records = events});
}
catch (Exception ex)
{
return Json(new { Result = "ERROR", Message = ex.Message });
}
}
The way you call listAction is wrong. you should call it like this '/CompetitionController/EventList'
Your MVC action waits for a parameter (compId). But your lisAction does not provide that:
listAction: '#Url.Action("EventList", "CompetitionController")'
It must be something like that:
listAction: '#Url.Action("EventList", "CompetitionController")compId=5'
Probably, this table is populated dynamically for every competition and it's known on the server side. So, it must be something like:
listAction: '#Url.Action("EventList", "CompetitionController")compId=#ViewBag.compId'
Surely, you must set compId in the action of this view.
Related
I am trying to create batch insert , update , delete using kendo ui grid and MVC.
Here is my code for View and Controller.
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<link href="~/Content/kendo.custom.css" rel="stylesheet" />
<link href="~/Content/kendo.common.min.css" rel="stylesheet" />
<script src="~/Scripts/kendo.all.min.js"></script>
<script src="~/Scripts/kendo.custom.js"></script>
<div>
<div id="grid"></div>
<script>
$(document).ready(function () {
$("#grid").kendoGrid({
editable: true,
pageable: true,
sortable: true,
filterable: true,
toolbar: ["create", "save", "cancel"],
columns: [
"Name",
{ command: "destroy", title: "Delete", width: "110px" }
],
dataSource: {
transport: {
create: {
url: "#Url.Action("Create", "VendorType")",
dataType: "json",
type: "POST"
},
read: {
url: "#Url.Action("Read", "VendorType")",
contentType: "application/json",
type: "POST"
}
},
serverPaging: true,
serverFiltering: true,
serverSorting: true,
pageSize: 5,
schema: {
data: "Data",
total: "Total",
model: {
id: "Id",
fields: {
Id: { editable: false, nullable: true },
Name: { validation: { required: true } }
}
}
}
}
});
});
</script>
</div>
Controller :
[HttpPost]
public ActionResult Read(int take, int skip, IEnumerable<Sort> sort, Kendo.DynamicLinq.Filter filter)
{
var result = db.VendorTypes
.OrderBy(p => p.Id)
.ToDataSourceResult(take, skip, sort, filter);
return Json(result);
}
[HttpPost]
public ActionResult Create(IEnumerable<VendorType> types)
{
var result = new List<VendorType>();
try
{
foreach (var category in types)
{
result.Add(category);
// Add the entity
db.VendorTypes.Add(category);
}
db.SaveChanges();
}
catch (DbEntityValidationException e)
{
foreach (var eve in e.EntityValidationErrors)
{
Console.WriteLine("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:",
eve.Entry.Entity.GetType().Name, eve.Entry.State);
foreach (var ve in eve.ValidationErrors)
{
Console.WriteLine("- Property: \"{0}\", Error: \"{1}\"",
ve.PropertyName, ve.ErrorMessage);
}
}
}
return Json(result);
}
Now the read operation works fine. but when i try to save the entries the list of objects in CREATE , UPDATE Or DELETE methods are always null. I can see the values being passed in the browser but in the controller they are not available. Can any one point out a mistake i am making ?
I found the solution for this. The model name which you have as parameter in controller need to be mapped using "ParameterMap" of kendo UI.
parameterMap: function (data, operation) {
if (operation != "read") {
var result = {};
for (var i = 0; i < data.models.length; i++) {
var site = data.models[i];
for (var member in site) {
result["projects[" + i + "]." + member] = site[member];
}
}
return result;
} else {
return JSON.stringify(data)
}
}
As my parameters collection is defined as "projects" my controller action method should have the same name for the argument.
i.e
public ActionResult Create(IEnumerable<Project> projects)
{
}
Hope this will help some one.
I've been doing alot of searching but haven't found a clear answer for this. I have a set up textboxes that and a submit button and a Kendo UI grid. I want to post the data to the grid's datasource so that it will return the results based on the criteria. I am not using the MVC wrappers.
EDIT:
I've gotten closer but I can't seem to get the datasource to send the post data when I click submit. I've debugged and in my $("#fmSearch").submit it is hitting the jquery plugin and I've confirmed that it is converting the form data to JSON properly, but it seems as though it it not sending the updated information to the server so that the Action can read it.
Javascript
var dsGalleryItem = new kendo.data.DataSource({
transport: {
read: {
url: '#Url.Content("~/Intranet/GalleryItem/SearchGalleryItems")',
type: "POST",
data: $("#fmSearch").serializeFormToJSON(),
cache: false
}
},
schema: {
model: {
id: "galleryItemID",
fields: {
galleryItemID: {
nullable: true
},
imageName: {},
collectionName: {},
categoryName: {},
lastUpdatedOn: { type: "date" }
}
}
}
});
var gvResults = $("#gvResults").kendoGrid({
autoBind:false,
columns: [{
field: "imageName",
title: "Item Name",
template: "<a href='#Url.Content("~/Intranet/GalleryItem/Details/")#=galleryItemID#'> #=imageName#</a>"
}, {
field: "collectionName",
title: "Collection"
}, {
field: "categoryName",
title: "Category"
}, {
field: "lastUpdatedOn",
title: "Last Updated",
format: "{0:M/d/yyyy}"
}
],
selectable: "row",
change: onRowSelect,
dataSource: dsGalleryItem
});
$("#fmSearch").submit(
function (event) {
event.preventDefault();
dsGalleryItem.read({ data: $("#fmSearch").serializeFormToJSON() });
});
MVC Action
[HttpPost]
public JsonResult SearchGalleryItems(string keyword, int? category, int? collection, DateTime? startDate, DateTime? endDate)
{
var galleryItemList = (from g in db.GalleryItems
//where g.imageName.Contains(keyword)
select new GalleryItemViewModel
{
galleryItemID = g.galleryItemID,
imageName = g.imageName,
collectionName = g.collection.collectionName,
categoryName = g.category.categoryName,
lastUpdatedOn = g.lastUpdatedOn
});
var galleryItemCount = Json(galleryItemList.ToList());
return Json(galleryItemList.ToList()); ;
}
The action is not setup to retrieve different data right now I just need to know how to connect the form to the grid.
Found the problem. I had this:
dsGalleryItem.read({ data: $("#fmSearch").serializeFormToJSON() });
It needed to be this:
dsGalleryItem.read($("#fmSearch").serializeFormToJSON());
I am trying to get this basic kendo ui with expandable rows working:
<div id="grid"></div>
<script type="text/javascript">
$(function () {
$("#grid").kendoGrid({
columns: [
{
field: "ProductId",
title: "ProductId"
}
],
dataSource: {
type: "json",
transport: {
read: '#Url.Action("GetData1", "MockForms")'
}
},
height: 450,
sortable: true,
pageable: true,
detailTemplate: "<h2 style='background-color: yellow;'>Expanded!</h2>",
detailExpand: function (e) {
this.collapseRow(this.tbody.find(' > tr.k-master-row').not(e.masterRow));
}
});
});
</script>
The json is generated like this:
public ActionResult GetData1([DataSourceRequest] DataSourceRequest request)
{
var list = new List<Product>
{
new Product {ProductId = 1, ProductType = "SomeType 1", Name = "Name 1", Created = DateTime.UtcNow},
new Product {ProductId = 1, ProductType = "SomeType 2", Name = "Name 2", Created = DateTime.UtcNow},
new Product {ProductId = 1, ProductType = "SomeType 3", Name = "Name 3", Created = DateTime.UtcNow}
};
return Json(list.AsQueryable().ToDataSourceResult(request));
}
and seems to be send OK (according to firebug). However, nothing is bound (there are no javascript errors). Any ideas?
PS:
OnaBai's 2nd comment helped me to get this to work. I changed:
return Json(list.AsQueryable().ToDataSourceResult(request));
=>
return Json(list);
which produces this JSON:
[{"ProductId":1,"ProductType":"SomeType 1","Name":"Name 1","Created":"\/Date(1371022051570)\/"},{"ProductId":1,"ProductType":"SomeType 2","Name":"Name 2","Created":"\/Date(1371022051570)\/"},{"ProductId":1,"ProductType":"SomeType 3","Name":"Name 3","Created":"\/Date(1371022051570)\/"}]
Still I would like to use:
return Json(list.AsQueryable().ToDataSourceResult(request));
as this will eventually make paging and sorting easier. It currently produces:
{"Data":[{"ProductId":1,"ProductType":"SomeType 1","Name":"Name 1","Created":"\/Date(1371022186643)\/"},{"ProductId":1,"ProductType":"SomeType 2","Name":"Name 2","Created":"\/Date(1371022186648)\/"},{"ProductId":1,"ProductType":"SomeType 3","Name":"Name 3","Created":"\/Date(1371022186648)\/"}],"Total":3,"AggregateResults":null,"Errors":null}
I tried to use:
field: "Data.ProductId",
instead of:
field: "ProductId",
in the JavaScript code with no avail.
If you want to use ToDataSourceResult you should use the ASP.NET MVC wrappers. More info is available in the documentation: http://docs.kendoui.com/getting-started/using-kendo-with/aspnet-mvc/helpers/grid/ajax-binding
I have two views in database. Bonuses and employees. One(employee)-to-many(bonuses).
I have kendo ui grid (kendo web), which displays ajax results from controller called Bonuses
And an autocompliting element - Employee Combobox binded with Employee filed of a grid.
Grid's datasource:
// bind json result from /Bonuses/GetPagedJsonBonuses
var bonusesDataSource = new kendo.data.DataSource({
transport: {
read: "#Url.Action("GetPagedJsonBonuses", "Bonuses")",
update: {
url: "#Url.Action("Edit", "Bonuses")",
type: "PUT"
},
create: {
url: "#Url.Action("Create", "Bonuses")",
type: "POST"
},
parameterMap: function(options, operation) {
if (operation === "update" || operation === "create") {
// updates the BonusDTO.EmployeeId with selected value
if (newValueEmployeeId !== undefined)
options.EmployeeId = newValueEmployeeId;
}
return options;
}
},
schema: {
data: "Data", // PagedResponse.Data
total: "TotalCount", // PagedResponse.TotalCount
model: {
id: "BonusId", // Data
fields: {
EmployeeId: { type: "number" },
EmployeeLastName: {
type: "string",
editable: true,
//validation: { required: {message: "Employee's last name is required"}}
},
Amount: {
type: "number",
editable: true,
nullable: false,
validation: {
required: { message: "Amount is required to be set" }
}
}
} // fields
} // model
}// schema
});
Grid element looks like this:
// creates bonuses grid control
$("#bonusesGrid").kendoGrid({
dataSource: bonusesDataSource,
toolbar: ["create"],
editable: "inline",
columns: [
"BonusId",
"EmployeeId",
{
field: "EmployeeLastName",
editor: employeeAutocompletingEditor,
template: "#=EmployeeLastName#"
},
"Amount",
{
command: ["edit"],
title: " "
}
],
save: function(e) {
if (newValueEmployeeId !== undefined && newValueEmployeeLastName !== undefined) {
e.model.EmployeeId = newValueEmployeeId; // it's a hack to bind model and autocomplete control
e.model.EmployeeLastName = newValueEmployeeLastName;
}
},
edit: function(e) {
setCurrentValueEmployeeIdAndLastName(e.model.EmployeeId, e.model.EmployeeLastName);
},
cancel: function(e) {
setCurrentValueEmployeeIdAndLastName(e.model.EmployeeId, e.model.EmployeeLastName);
}
});
Autocompleting combobox has it's own datasource using ajax:
// datasource for autocomlete combobox to lookup employees names from
var employeesDataSource = new kendo.data.DataSource({
transport: {
read: "#Url.Action("GetJsonEmployeesByLastName", "Bonuses")",
},
parameterMap: function(options, operation) {
if (operation === "update" || operation === "create") {
setNewValueEmployeeIdAndLastName(options.Id, options.LastName);
}
return options;
},
});
Autocompliting combobox look's like this:
function employeeAutocompletingEditor(container, options) {
$('<input required data-text-field="LastName" data-value-field="EmployeeId" data-bind="value:' + options.field + '"/>')
.appendTo(container)
.kendoComboBox({
// sets the local variables to update values of current row.
change: function() {
setNewValueEmployeeIdAndLastName(this.value(), this.text());
},
dataBinding: function (e) {
console.log("dataBinding: ", e, this.dataItem());
},
dataBound: function (e) {
console.log("dataBound: ", e, this.dataItem());
},
dataSource: employeesDataSource
});
}
I use Editor binding to pass values(EmployeeId) and Text (EmployeeLastName) from grid to combobox.
I also use a hack like temporal variables (newValueEmployeeId, currentValueEmployeeId) to
send selected Employee in combobox and pass it to grid for correct save. A found it's a most common practice to pass a value back to grid.
My problems is:
If I press Edit button on my grid first time The combobox displays current employee's name from grid row:
If I press Cancel button and again press Edit button, combobox doesn't display current value of grid (employee's name)
IF I type some name, change some other values, and Udate(save) value, next time combobox again displays employees name, but only once before Cancel was pressed.
I'm very new in Kendo UI and this problem drives me crazy...
I think that combobox losts it's binding or doesn't update smth. I tried to set values while onBound and onBinding events, but this doesn't help. Please help me with an advice and example.
PS all evenets and functions is my try to debug and find solution.
only one fix helped me:
var employeeList = new List<Employee>()
employeeList.add(new Emplpyee()) // add fake employee record.
return Json(employeeList)
I don't know why, but grid control start make cyclying empty ajax requests if I return empty list of employees or null. This doesn't work:
return Json(new List<Employee>());
return Json(null);
I think it's a problem in kendo combobox itself ,because it's not ready to receive and handle empty list or null as json result.
Also I heared something, that JQuery doesn't support empty or null results anymore...maybe that's the reason
I am facing this problem for quite a while now with the problem that I am unable to bind JSON data that my controller action is passing to the kendo UI Grid, there were few JavaScript issues before but now they are gone but still my grid is not showing any results:
In Model:
public object GetResult(string id)
{
var sqlCom = new SqlCommand("SELECT [No],[Desc],[Date],[Height],[Final] FROM [cr_form] WHERE [uId]=#id;", sqlConn);
sqlCom.Parameters.AddWithValue("#id", id);
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
JsonWriter jsonWriter = new JsonTextWriter(sw);
var rcrds = GETSQLRESULTS(sqlCom);
try
{
int i = 0;
if (rcrds != null || rcrds.HasRows)
{
//jsonWriter.WriteStartObject();
while (rcrds.Read())
{
jsonWriter.WriteStartObject(); //Changed
for (int j = 0; j < rcrds.FieldCount; j++)
{
jsonWriter.WritePropertyName(rcrds.GetName(j)); // column name
jsonWriter.WriteValue(rcrds.GetValue(j)); // value in column
}
i++;
jsonWriter.WriteEndObject(); //Changed
}
//jsonWriter.WriteEndObject();
}
}
catch (Exception ex) { }
return jsonWriter;
}
In Controller:
public ActionResult GetRecords()
{
var usrObj = new User();
var jsnRslt = usrObj.GetResult(Session["Id"].ToString());
//Till here jsnRslt contains this string: “{"No":null,"Desc":"asfasfasfasfasfasfasfasfasfasfasfasf","Date":"2013-03-27T00:00:00","Height":0,"Final":null,"No":null,"Desc":"etwetwetwetwet","Date":"2013-03-27T00:00:00","Height":0,"Final":0,"No":null,"Desc":"asfasfasfskfjklajsfkjasklfjklasjfklajsfkljaklsfjklasjfkljasfkljlasf","Date":"2013-03-27T00:00:00","Height":0,"Final":0,"No":null,"Desc":"askjfkajsfklaskjfkajsfklaskjfkajsfklaskjfkajsfklaskjfkajsfklaskjfkajsfklaskjfkajsfklaskjfkajsfklaskjfkajsfklaskjfkajsfklaskjfkajsfklaskjfkajsfkl","Date":"2013-03-27T00:00:00","Height":0,"Final":0,"No":null,"Desc":"safasfasfasfasfasf","Date":"2013-03-27T00:00:00","Height":0,"Final":0,"No":null,"Desc":"asfasf","Date":"2013-03-27T00:00:00","Height":0,"Final":0,"No":null,"Desc":"asfasfasf","Date":"2013-03-27T00:00:00","Height":2,"Final":0}”
//After Changes in the Model I am getting it in the required Array format:
//{"No":null,"Desc":"asfasfasfasfasfasfasfasfasfasfasfasf","Date":"2013-03-27T00:00:00","Height":0,"Final":null}
//{"No":null,"Desc":"etwetwetwetwet","Date":"2013-03-27T00:00:00","Height":0,"Final":0}
//{"No":null,"Des...
return Json(jsnRslt, JsonRequestBehavior.AllowGet);
}
In View:
<div>
<script type="text/javascript">
$(document).ready(function () {
$("#grid").kendoGrid({
dataSource: {
type: "json",
serverPaging: true,
pageSize: 5,
groupable: true,
selectable: "row",
transport: { read: { url: "Records", dataType: "json"} }
},
height: 400,
scrollable: true,
sortable: true,
filterable: true,
pageable: true,
columns: [
{ field: "No", title: " No" },
{ field: "Desc", title: "Description" },
{ field: "Date", title: "Date" },
{ field: "Height", title: "Height" },
{ field: "Final", title: "Final" }
],
dataBound: function () {
this.expandRow(this.tbody.find("tr.k-master-row").first());
}
});
});
</script>
</div>
But after all this all I can see is an empty grid. And no errors in JavaScript console.
Please help
The JSON that you return from the server should be array. You currently it seems that you are returning single objects with multiple fields that are the same.
Here is an example how the JSON should look like:
[{"No":null,"Desc":"asfasfasfasfasfasfasfasfasfasfasfasf","Date":"2013-03-27T00:00:00","Height":0,"Final":null},
{"No":null,"Desc":"etwetwetwetwet","Date":"2013-03-27T00:00:00","Height":0,"Final":0},
{"No":null,"Desc":"asfasfasfskfjklajsfkjasklfjklasjfklajsfkljaklsfjklasjfkljasfkljlasf","Date":"2013-03-27T00:00:00","Height":0,"Final":0}]
I think following code will be useful for you and let me know if you have any problem:
$('#gridName').kendoGrid({
dataSource: {
type: "odata",
transport: {
read: {
contentType: "application/json; charset=utf-8",
type: "POST",
url: 'YourURL'
}
},
pageSize: 10,
type: "json"
},
scrollable: true,
sortable: true,
resizable: true
});
Inside you dataSource set data.
data: #Html.Raw(Json.Encode(Model.RemoteObject)),
RemoteObject is you object containing all data.
First I check your tranport read URL. have you trace the controller if it fires the GetRecords command?
transport:
{
read: {
//if you don't use area then remove it
url: "#Url.Action("GetRecords", new { area = "YourAreaName", controller = "YourControllerName" })",
dataType: "json"
}
}
if it still doesn't fix your problem, then modify your Controller,
public ActionResult GetRecords([DataSourceRequest] DataSourceRequest request)
{
var usrObj = new User();
var jsnRslt = usrObj.GetResult(Session["Id"].ToString());
return Json(jsnRslt.ToDataSourceResult(request), JsonRequestBehavior.AllowGet);
}
here's the link to understand the Kendo's ToDataSourceResult