I want to return some JSON data from my WebAPI controller and I want the returned data to be like this.
{"rows":[{"id":1,"cell":["1","amila","amila","False"]},{"id":2,"cell":["2","rakhitha","rakhitha","False"]},{"id":3,"cell":["3","Chathura","Chathura","False"]},{"id":4,"cell":["4","Geethaga","Geethaga","False"]}]}
But when I use the below code,
return new System.Web.Mvc.JsonResult()
{
Data = jsonData,
JsonRequestBehavior = System.Web.Mvc.JsonRequestBehavior.AllowGet
};
the data is returned like this.
{"Data":{"rows":[{"id":1,"cell":["1","amila","amila","False"]},{"id":2,"cell":["2","rakhitha","rakhitha","False"]},{"id":3,"cell":["3","Chathura","Chathura","False"]},{"id":4,"cell":["4","Geethaga","Geethaga","False"]}]},"JsonRequestBehavior":0}
There is an additional JSON key as "Data". I dont want that parameter and as my implementation I cant remove this "Data" part after getting it to the client side. Because the data received from the server is directly used to fill a jqGrid. The code is below.
$("#Grid1").jqGrid({
url: 'api/matchingservicewebapi/GetUser',
datatype: 'json',
mtype: 'GET',
colNames: ['', 'Name', 'FullName', 'IsActive'],
colModel: [
{ name: 'Id', index: 'Id', width: 200 },
{ name: 'Name', index: 'Name', width: 300 },
{ name: 'FullName', index: 'FullName', width: 300 },
{ name: 'IsActive', index: 'IsActive', width: 300 }
],
rowNum: 10,
rowList: [10, 20, 30],
pager: '#pager',
sortname: 'Id',
viewrecoreds: true,
sortorder: "desc",
imgpath: 'Themes/images'
}).navGrid(pager, { edit: true, add: true, del: true, refresh: true, search: true });
How do I remove this "Data" part? Because when you have this "Data" key in the returned JSON, jqGrid is not capable of filling that data to the grid.
I am using WebAPI Controller to return this data. But I tried using MVC3 controller, then this "Data" key was not in the returned JSON and data filled to the grid successfully. But I want to use WebAPI Controller. Please help to solve this.
Thank you in advance.
JsonResult is an MVC concept. For Web API, your controller can simply return a CLR object and it will be serialized into JSON (assuming the client asks for JSON).
The result you're seeing is because the entire JsonResult object is getting serialized into JSON.
To get started with Web API, see: http://www.asp.net/web-api/overview/getting-started-with-aspnet-web-api/tutorial-your-first-web-api
(Or you could continue to use an MVC controller ... is there a particular reason that you wanted to use a Web API controller?)
Json.NET works well for me. Just return the JObject in the Web API
http://james.newtonking.com/projects/json/help/html/CreatingLINQtoJSON.htm
JObject o = JObject.FromObject(new
{
channel = new
{
title = "James Newton-King",
link = "http://james.newtonking.com",
description = "James Newton-King's blog.",
item =
from p in posts
orderby p.Title
select new
{
title = p.Title,
description = p.Description,
link = p.Link,
category = p.Categories
}
}
})
set jsonreader option in jqGrid. like
jQuery("#gridid").jqGrid({
...
jsonReader : {root:"Data"},
...
});
http://www.trirand.com/jqgridwiki/doku.php?id=wiki:retrieving_data#json_string
Use data.d instead of data in your code.
success: function(data){
//create jquery object from the response html
var response=$(data.d);
//Your binding logic here
}
You can return the data in jqgrid required format. If you don't want to create a separate class for this, use dynamic return type in apicontroller. See working example here.
Related
I am having trouble filtering a kendo data source on related data (many to many). I am using ASP.NET WebAPI2 and DataSourceRequest to catch the request on the server. The data is then fetched using the .ToDataSourceResult() extension method on an IQueryable.
I am aware of this article http://blogs.telerik.com/kendoui/posts/12-11-29/the_facts_on_using_kendo_ui_with_asp_net_webapi
My Data is structured as follows:-
Customer -> CustomerAddress -> Address
Where CustomerAddress is the join table between the Customer & Address tables. There is a navigational property on the Customer and also on the CustomerAddress.
Kendo datasource is as follows:-
var customers = new kendo.data.DataSource({
transport: {
read: {
url: "api/customers", type: "GET"
}
},
pageSize: 10,
page: 1,
serverPaging: true,
serverFiltering: true,
type: "webapi",
schema: {
data: "Data",
total: "Total",
errors: "Errors",
model: {
id: "CustomerID"
}
}
});
The filter need to be applied on a field in the Address table. ie. AddressLine1 = "{search param}"
I have tried the following:-
var filters = {
logic: "or",
filters: [
{field: "FirstName",operator: "contains",value: "xyz"},
{field: "LastName",operator: "contains",value: "xyz"},
{field: "CustomerAddress.Address.AddressLine1",operator: "contains",value: "xyz"},
]
};
customers.filter(filters);
Out of these the first 2 filters work absolutely fine. I have done a .Include() on the queryable and the address information is loaded fine.
How do I do this using the kendo DataSourceRequest ?
I am converting my application to use Server Side Paging with the Kendo Grid UI. Prior to switching serverPaging to true, I was properly displaying my grid contents, and paging on the client side. However, once I turned on the serverPaging, my data was no longer visible. I have checked the network call, and my data is returning (only 2 records of 8 total) as expected, but I am not seeing it in the grid.
Here is the grid construction:
$v.KendoGrid.makeGrid(gridName, {
columns: [
{ field: 'IdentifierCode', title: 'User Name' },
{ field: 'CompanyName', title: 'Company' },
{ field: 'Email', title: 'Email' }
],
dataSource: {
pageSize: 2,
schema: {
data: 'Data', // records are returned in the data section of the response
model: {
id: 'Id',
fields: {
IdentifierCode: { type: 'string' },
CompanyName: { type: 'string' },
Email: { type: 'string' }
}
},
total: 'Total' // total number of records are in the total section of the response
},
serverPaging: true,
transport: {
read: {
url: window.urlConfigs.root + "Security/UserAccount/PagedListing"
dataType: "json",
type: "GET"
}
}
},
editable: false,
filterable: true,
height: 464,
pageable: true,
scrollable: true,
sortable: true
});
Here is the MVC Controller method:
public ActionResult PagedListing(int pageSize, int skip)
{
var entities = ReadRepo.All();
var total = entities.Count();
var data = entities.Skip(skip).Take(pageSize).Select(MapEntityToViewModel).ToList();
return Json(new { Total = total, Data = data }, JsonRequestBehavior.AllowGet);
}
And here is the data I get back on the network call:
{"Total":8,"Data":[{"Id":"928f0bb2-608b-417b-bf6e-e5c58f85fec2","IdentifierCode":"admin","FirstName":"Administrator","MiddleName":"of","MiddleNameHuman":"of","LastName":"GasStream","DisplayName":"Administrator of GasStream","Email":"admin#example.com","IsExternal":false,"UserTypeHuman":"Internal","CompanyId":"75bb05a4-1ec2-4042-aeba-a229008aca9f","CompanyName":"Entessa Pipeline & Terminal, MLP","CompanyIdentifierCode":"SHA","Password":"wFg/a/NEU6WM8z4YZBUduitIDROfeFz/+Za6leAHnBE=","PasswordChanged":false,"ForceNewPasswordFlag":false,"Settings":[],"RoleGroups":[]},{"Id":"47c29025-cfa8-4447-9ab7-a229008ad088","IdentifierCode":"contractcarl","FirstName":"Carl","MiddleName":null,"MiddleNameHuman":"","LastName":"Smithers","DisplayName":"Carl Smithers","Email":"carl#entessa.com","IsExternal":false,"UserTypeHuman":"Internal","CompanyId":"75bb05a4-1ec2-4042-aeba-a229008aca9f","CompanyName":"Entessa Pipeline & Terminal, MLP","CompanyIdentifierCode":"SHA","Password":"IWdH+qDIOucNrre6V4AgI6Exm2Vq5qkIdXdsWfP6jn4=","PasswordChanged":false,"ForceNewPasswordFlag":false,"Settings":[],"RoleGroups":[]}]}
I suspect I have missed something small, but after looking at this and trying all sorts of possible work-arounds, I cannot see it, so I am asking for some help. I thought once I got the data to return small sets from the Server, things would get simpler.
Thanks in advance,
Drew
I ended up finding the answer. the $v.KendoGrid was a method that wrapped the kendoGrid call itself, and in there something was getting reset to not allow the data to be parsed properly when it came back from the server properly paged.
I have since re-worked the mess so I can establish the necessary parameters in the $v.KendoGrid call for just my type of grid.
Thanks for the help, and the eyes to catch the comma, Brett.
Drew
ByVal datax As ObjectI'm trying to use ASP.NET with webmethod to retrieve data and save data for jqgrid.
I can retrieve data from the webmethod but no luck to do the save.
The server side seems never get my post data. Would someone please help?
grid code:
$('#list99').jqGrid({
datatype: function(postdata) {
$.ajax({
url: 'dbtest.aspx/getdata',
editurl: 'dbtest.aspx/updatedb',
type: 'POST',
data: '{}',
dataType: "json",
contentType: "application/json; charset=utf-8",
error: function(data, textStatus) {
alert('Error loading json');
},
success: function(data, st) {
if (st == 'success') {
var grid = $("#list99");
var gridData = JSON.parse(data.d);
grid.clearGridData();
for (var i = 0; i < gridData.length; i++) {
grid.addRowData(i + 1, gridData[i]);
}
}
$("#list99").jqGrid('navGrid', '#pager99', { add: true, edit: true, del: true });
}
});
},
type: 'POST',
editurl: 'dbtest.aspx/updatedb',
colNames: ['customerid', 'customername'],
colModel: [
{ name: 'customerid', index: 'customerid', width: 80, align: 'left', editable: true, edittype: 'text' },
{ name: 'customername', index: 'customername', width: 120, align: 'left', editable: true, edittype: 'text'}],
pager: $('#pager99'),
rowNum: 5,
rowList: [10],
sortname: 'customerid',
sortorder: 'desc',
viewrecords: true,
//width: 300
autowidth: true
});
server side code:
Public Class customer
Public customerid As String
Public customername As String
End Class
<System.Web.Services.WebMethod()> _
Public Shared Function getdata() As String
Dim c1 As New customer
Dim c2 As New customer
c1.customerid = "1"
c1.customername = "pete"
c2.customerid = "2"
c2.customername = "joah"
Dim lstcustomer As New List(Of customer)
lstcustomer.Add(c1)
lstcustomer.Add(c2)
Dim jsonserial As New JavaScriptSerializer
Dim result As String
result = jsonserial.Serialize(lstcustomer)
Return result
End Function
<System.Web.Services.WebMethod()> _
Public Shared Function updatedb(ByVal datax As Object) As String
//attempt to do save
End Function
The function updatedb just never being called after i clicked "sumbit" after add/edit/delete.
After that i checked with firebug and i got the error message:
"Invalid web service call, missing value for parameter: 'data'."
I've also tried to add the following:
jQuery.extend(jQuery.jgrid.edit, {
ajaxEditOptions: { contentType: "application/json" },
recreateForm: true,
serializeEditData: function(data) {
//alert('in2');
//alert(postData.customerid);
//alert(JSON.stringify(postData));
if (data.customerid == undefined) { data.customerid = null; }
var postData = { 'data': data };
//alert(postData.customerid);
return JSON.stringify(postData);
}
});
It still didnt work =(
I don't recommend you ever use datatype defined as function especially if you do just jQuery.ajax to communicate with the server. jqGrid provide many ways to customize data which will be send to the server (see serializeGridData callback and ajaxGridOptions option of jqGrid for example) and to change the server response before the server response will be processed by jqGrid (beforeProcessing callback for example). The current code use addRowData to fill the data. It' the slowest way to fill the grid which I know. Moreover you call navGrid on every loading of the data instead of calling it once directly after the grid will be created. All other calls will be just ignored. You can find many examples how to use web servicing together with jqGrid. Look at the answer for example
Your current code mix the options of jQuery.ajax with the options of jqGrid. You placed editurl option of jqGrid into the list of options of $.ajax.
One more important error is the usage of correct names of variables in updatedb method. You use currently datax As Object instead of usage customerid and customername as parameters.
I have a grid where user and add new rows as many as they want. After adding all the rows, they click the "Save" button. On Save button click, I want to send all the data entered by the user in JSON format to the server side code (i.e. a servlet in my case)
Below is the model and store definition:
Ext.define('Plant', {
extend: 'Ext.data.Model',
fields: [
// the 'name' below matches the tag name to read, except 'availDate'
// which is mapped to the tag 'availability'
{name: 'common', type: 'string'},
{name: 'botanical', type: 'string'},
{name: 'light'},
{name: 'price', type: 'float'},
// dates can be automatically converted by specifying dateFormat
{name: 'availDate', mapping: 'availability', type: 'date', dateFormat: 'm/d/Y'},
{name: 'indoor', type: 'bool'}
]
});
// create the Data Store
var store = Ext.create('Ext.data.Store', {
// destroy the store if the grid is destroyed
autoDestroy: true,
model: 'Plant'
});
On click of the save button, I am able to get the store like this:
{
text: 'Save',
handler : function(){
//Getting the store
var records = grid.getStore();
console.log(records.getCount());
Ext.Ajax.request({
url: '/CellEditing/CellEditingGridServlet',
method: 'POST',
jsonData: {
//How to assign the store here such that
//it is send in a JSON format to the server?
},
callback: function (options, success, response) {
}
});
}
But I don't know like how to convert the store content into JSON and send it in the jsonData of the ajax request.
I want the JSON data something like this in the server side:
{"plantDetails":
[
{
"common": Plant1,
"light": 'shady',
"price": 25.00,
"availDate": '05/05/2013',
"indoor": 'Yes'
},
{
"common": Plant2,
"light": 'most shady',
"price": 15.00,
"availDate": '12/09/2012',
"indoor": 'No'
},
]
}
Please let me know how to achieve this.
Regards,
Agreed with Neil, the right way to do this is through an editable store outfited with a proxy and a writer. See example here: http://docs.sencha.com/ext-js/4-1/#!/example/grid/cell-editing.html
Store
writer :
{
type : 'json',
allowSingle : true
}
Experiment with allowSingle as per your use case
In your controller
//if you want to set extra params
yourStore.getProxy().setExtraParam("anyParam",anyValue);
// sync the store
yourStore.sync({success : function() {
yourGrid.setLoading(false);
.. },
scope : this // within the scope of the controller
});
You should be creating the model with a new id ( you can ignore it at the server side and use your own key generation , but it lets extjs4 for its internal purposes know that a new record has been created).
creating a model instance
var r = Ext.create('yourModel', { id: idGen++, propA : valA , ... });
insert to grid
store.insert(0,r);
var editPlugin = grid.getPlugin(editPluginId);
editPlugin.startEdit(0,1);
Once you receive a response back the id's can be update to their true value.
in the Store
reader :
{
type : 'json',
root : 'yourdata',
successProperty : 'success',
idProperty : 'id'
}
If you were to use the same grid for handling and editing then you could use the write event or the appropriate event
for more advanced handling in the Store
listeners :
{
write : function(store,operation, eOpts)
{
var insertedData = Ext.decode(operation.response.responseText);
.. do something
}
}
I would recommend using the mvc architecture of Extjs4
This is what I tried and it seems to work:
var store = Ext.create('Ext.data.Store', {
// destroy the store if the grid is destroyed
autoDestroy: true,
model: 'Plant',
proxy: {
type: 'ajax',
url: '/CellEditing/CellEditingGridServlet',
writer: {
type: 'json',
root: 'plantDetails'
}
}
handler : function(){
grid.getStore().sync();
But I am getting an additional parameter in the JSON at the server side:
"id": null
I don't have this id set in my model then where is this coming from? Is there some way to set some values to it rather than having a default null value?
I have implemented a simple jqGrid in my ASP.NET MVC 3 application. It shows the data correctly, so that's fine. But now I want my application to show the details of a row if I doubleclick on a row.
I have a Detail action method that actually gets called with the correct ID, the details are retrieved from database and the Details view is returned, so that seems to be OK, but in my application nothing happens.
I have the following script for the grid:
jQuery(document).ready(function ()
{
jQuery("#list").jqGrid({
url: '/Incident/ListData/',
datatype: 'json',
mtype: 'GET',
colNames: ['TicketNumber', 'Title', 'CreatedOn'],
colModel: [
{ name: 'TicketNumber', index: 'TicketNumber', width: 75, align: 'left' },
{ name: 'Title', index: 'Title', width: 250, align: 'left' },
{ name: 'CreatedOn', index: 'CreatedOn', width: 90, align: 'left'}],
pager: jQuery('#pager'),
rowNum: 10,
rowList: [10, 50, 100],
sortname: 'CreatedOn',
sortorder: "desc",
viewrecords: true,
width: 650,
imgpath: '/Content/themes/base/images',
caption: 'Incidents',
ondblClickRow: function (id) { $.get('/Incident/Detail/' + id); }
});
});
I've tried using $.ajax instead of $.get, but in both cases the details method gets called and nothing happens.
This is the Details action method
public ViewResult Detail(Guid id)
{
var query = from inc in _repository.Incidents
where inc.Id == id
select
new IncidentModel(inc)
{
CreatedOn = inc.CreatedOn,
Description = inc.Description,
ModifiedOn = inc.ModifiedOn,
TicketNumber = inc.TicketNumber,
Title = inc.Title,
Status = inc.Status
};
var incident = query.FirstOrDefault();
return View(incident);
}
$.get sends an AJAX request and gives you the server's reply.
It doesn't actually do anything with the server's reply; it's up to you to do something useful.
It sounds like you don't want AJAX at all; instead, you want to navigate to that page:
location = '/Incident/Detail/' + id
As Slaks said, you're not doing anything with the content. Should your double click event actually be redirecting the browser to that action?
(Just a side note, why double click? Nearly everything else net based uses a single click to browse).