Here is my PUT code in Web Api. (ASP.NET MVC 6).
public class VendorManagementController : ApiController
{
// GET
[Microsoft.AspNet.Mvc.HttpGet]
public dynamic GetVendors(string sidx, string sortOrder, int page, int rows,int pkey)
{
var vendors = _vendorRespository.GetAllVendors().AsQueryable();
var pageIndex = Convert.ToInt32(page) - 1;
var pageSize = rows;
var totalRecords = vendors.Count();
var totalPages = (int)Math.Ceiling((float)totalRecords / (float)pageSize);
if (sidx != null)
{
vendors = sortOrder == "asc" ? vendors.OrderBy(sidx) : vendors.OrderBy(sidx + " descending");
}
else
{
vendors = vendors.OrderBy(x => x.pkey);
}
vendors = vendors.Skip(pageIndex * pageSize).Take(pageSize);
return new
{
total = totalPages,
page = page,
records = totalRecords,
rows = (from vendor in vendors
select new
{
cell = new string[]
{
vendor.pkey.ToString(),
vendor.Company,
vendor.ContactName,
vendor.ContactPhone,
vendor.UserName,
Encoding.UTF8.GetString(vendor.UserKey),
vendor.Active.ToString(),
vendor.FacilityId.ToString(),
vendor.ClientID.ToString(),
vendor.PhotoURL,
vendor.PushToGP.ToString()
}
}).ToArray()
};
}
In the view, I have:
jQuery(gridSelector).jqGrid({
url: API_URL + 'GetVendors',
datatype: 'json',
mtype: 'GET',
height: 'auto',
colNames: ['pkey', 'Company', 'ContactName', 'ContactPhone', 'UserName', 'UserKey', 'Active', 'FacilityId', 'ClientId', 'PhotoURL', 'PushToGP'],
colModel: [
{ name: 'pkey', index: 'pkey', width: 50, hidden: true },
{ name: 'Company', width: 120 },
{ name: 'ContactName', width: 110 },
{ name: 'ContactPhone', width: 120 },
{ name: 'UserName', align: "right", width: 90 },
{ name: 'UserKey', align: "right", width: 120, hidden: true },
{ name: 'Active', width: 50, edittype: "checkbox", editoptions: { value: "True:False" }, unformat: aceSwitch },
{ name: 'FacilityId', align: "right", width: 100, formatter: "integer" },
{ name: 'ClientID', align: "right", width: 100, formatter: "integer" },
{ name: 'PhotoURL', align: "right", width: 80 },
{ name: 'PushToGP', align: "right", width: 80, edittype: "checkbox", editoptions: { value: "True:False" }, unformat: aceSwitch }
],
cmTemplate: { autoResizable: true, editable: true },
rowNum: 10,
rowList: [10, 20, 30],
pager: pagerSelector,
sortname: 'company',
sortorder: "asc",
viewrecords: true,
jsonreader: {
root: "rows",
page: "page",
total: "total",
records:"records"
},
caption: "Vendor Managerment"
});
However I inspect the page, I find a 500 error. See the image.
And in Home Controller:
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
public IActionResult VendorManagement()
{
return View();
}
In Startup.cs
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
// Configure the HTTP request pipeline.
// Add the following to the request pipeline only in development environment.
if (env.IsDevelopment())
{
app.UseBrowserLink();
app.UseErrorPage();
}
else
{
// Add Error handling middleware which catches all application specific errors and
// send the request to the following path or controller action.
app.UseErrorHandler("/Home/Error");
}
// Add static files to the request pipeline.
app.UseStaticFiles();
// Add MVC to the request pipeline.
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
// Uncomment the following line to add a route for porting Web API 2 controllers.
// routes.MapWebApiRoute("DefaultApi", "api/{controller}/{id?}");
});
}
}
I am new to ASP.NET Web Api. Is there anything wrong on my mapping? Why I get 500 error?
As per jqGrid documentation, it requires following default JSON format,
{
"total": "xxx",
"page": "yyy",
"records": "zzz",
"rows" : [
{"id" :"1", "cell" :["cell11", "cell12", "cell13"]},
{"id" :"2", "cell":["cell21", "cell22", "cell23"]},
...
]
}
If I understand your code correctly then your method should return JSON result
Please try to modify code like this and see if it helps,
I have added id = vendor.pkey
var result = new
{
total = totalPages,
page = page,
records = totalRecords,
rows = (from vendor in vendors
select new
{
id = vendor.pkey,
cell = new string[]
{
vendor.pkey.ToString(),
vendor.Company,
vendor.ContactName,
vendor.ContactPhone,
vendor.UserName,
Encoding.UTF8.GetString(vendor.UserKey),
vendor.Active.ToString(),
vendor.FacilityId.ToString(),
vendor.ClientID.ToString(),
vendor.PhotoURL,
vendor.PushToGP.ToString()
}
}).ToArray()
};
return Json(result, JsonRequestBehavior.AllowGet);
Related
i use laravel6,vue. in my project i use vue2Dropzone.
i made photo update fuction. but it does not work.
I want to load and delete the image of the server on dropzone.
but after delete image on dropzone and i refresh page or go to another page delete method called as many images as it does.
i cant solve this problem.
In chrome network tab, Requests are generated by the number of photoLen in loadPhoto .
enter image description here
photoEdit.vue
<div class="mt-4">
<vue-dropzone ref="myVueDropzone" id="dropzone" :options="dropzoneOptions" #vdropzone-removed-file="imageRemoved"></vue-dropzone>
</div>
data(){
dropzoneOptions: {
url: `/api/photo/${this.$route.params.id}`,
addRemoveLinks: true,
dictRemoveFile: 'delete',
createImageThumbnails: true,
thumbnailWidth: 150,
parallelUploads: 50,
autoProcessQueue: true,
maxFileSize: 100,
timeout: 100000,
maxFiles: 50,
maxThumbnailFilesize: 100,
uploadMultiple: true,
dictDefaultMessage: "click and drag",
acceptedFiles: 'image/*',
headers: {
"X-CSRF-TOKEN": document.head.querySelector("[name=csrf-token]").content,
}
},
}
mounted() {
this.loadPhoto();
},
methods:{
loadPhoto() {
axios.get(this.apiUrl).then((response) => {
this.photo = response.data.data[0];
var photoLen = this.photo.photo_images.length;
console.log(photoLen);
for (var i = 0; i < photoLen; i++) {
var file = {size: 123, name: this.photo.photo_images[i].image_name};
var url = this.photo.photo_images[i].path;
this.$refs.myVueDropzone.manuallyAddFile(file, url);
}
}).catch(error => {
this.$router.push({name: 'adminPhoto'});
});
},
//vdropzone-removed-file called when dismount the component
imageRemoved(file, error, xhr) {
// alert(file);
//todo 해당경로로 갈시 삭제
var name = file.name;
console.log(file);
axios.post('/api/photo/delete',{
image_name : name,
})
.then((response) => {
console.log(response);
}, (error) => {
// error callback
console.log(error);
})
var _ref;
return (_ref = file.previewElement) != null ? _ref.parentNode.removeChild(file.previewElement) : void 0;
},
}
rowData: any = [];rowModelType = 'serverSide';
defaultColDef: any = { width: 50, sortable: true, resizable: true, };
columnDefs: any = [];rowSelection = 'single'; public getRowHeight: any;
private paramRefreshAgGrid: any; private gridColumnApi: any;
private gridApi: any;
constructor() {
this.gridOption()
} gridOption() {
this.columnDefs = [
{ headerName: 'نوع ارز',field: 'currencyCode',width: 200,
},{ headerName: 'خرید',field: 'buyEts', width: 200, },
{ headerName: 'انتخاب', field: 'sellEts2', width: 200, },
{ headerName: 'خرید', field: 'buyEts3', width: 200, },
{ headerName: 'انتخاب', field: 'sellEts',width: 200, },
{ headerName: 'خرید اضافه', field: 'buyExternalCheque', width: 200 }
,{ headerName: 'مبلغ', field: 'buyMoney', width: 200,}, ]; }
onGridReady(params: any) {
const $this = this;
if (params) {
this.gridApi = params.api;this.gridColumnApi = params.columnApi;
this.paramRefreshAgGrid = params; }
const datasource = {
getRows(params: any) {
const data: any = [
{currencyCode: 'Ford2', buyEts: 'Mondeo', sellEts: 32000, sellEts2: 32000 , sellEts3: 32000 , buyExternalCheque: 500 ,
buyMoney: 100000},
]
params.successCallback(data, data.total);
$this.gridApi.sizeColumnsToFit();
}
};
if (params) {
params.api.setServerSideDatasource(datasource);
}
}
<ag-grid-angular
style="width: 100%;"
[ngStyle]="{'height': '50vh' }"
id="logGrid"
class="ag-theme-balham"
[columnDefs]="columnDefs"
[defaultColDef]="defaultColDef"
[enableRtl]="true"
[rowModelType]="rowModelType"
[animateRows]="false"
[rowSelection]="rowSelection"
[debug]="true"
[rowData]="rowData"
[getRowHeight]="getRowHeight"
(gridReady)="onGridReady($event)"
[paginationPageSize]="100"
[suppressDragLeaveHidesColumns]="true"
</ag-grid-angular>
I use the "ag-grid-angular": "20.2.0", in Angular 11 when I scroll the header The header cells are not aligned with the body cells.
What solution do you have to fix this error?
thanks !!
Version 20.2.0 of ag-grid-angular is 2 years old. Try installing the latest version of ag-grid-community and ag-grid-angular - I would also delete node_modules folder afterwards and do a clean npm install
This may solve the problem (or at least narrow it down)
Note You should highlight in the question that the issue is only occurring in Chrome
I want to add some styling to the last row in my grid. I wont know what the row number is as there could be any number of rows. How can I go about this? I've seen rowClass and rowRenderer but not a working example. Here is the code I have:
var displayData = function (itemViewModelList) {
var fields = [
{
name: 'ConsultantName', type: 'text', width: 100, title: 'Consultant Name'
},
{
name: 'BranchName', type: 'text', width: 100, title: 'Branch Name', css: "red"
},
{ name: 'NumberOfInvestments', type: 'text', title: 'Number Of Investments' },
{
name: 'ValueOfInvestments', type: 'money', width: 150, title: 'Value Of Investments',
itemTemplate: function (value) {
return tisCommon.formatForMoney(value);
}
},
{
name: 'AverageValueOfInvestments', type: 'money', width: 150, title: 'Average Value Of Investments',
itemTemplate: function (value) {
return tisCommon.formatForMoney(value);
}
},
{
name: 'Month', type: 'text', width: 100, title: 'Month',
itemTemplate: function (value) {
return moment(value, 'M').format('MMMM');;
}
},
];
var options = {
inserting: false,
editing: false,
pageSize: 20,
fields: fields,
rowHeaders: false,
colHeaders: false,
data: itemViewModelList,
controller: controller = {
loadData: function () {
},
},
};
$('#investment-grid').tisGrid('', options);
if (itemViewModelList[0].ConsultantName != null) {
$("#investment-grid").jsGrid("fieldOption", "BranchName", "visible", false);
} else {
$("#investment-grid").jsGrid("fieldOption", "ConsultantName", "visible", false);
}
};
My data being passed "itemViewModelList" is an array of objects
I resolved this by using rowClass as follows:
controller: controller =
{
loadData: function () {},
},
rowClass: function (item, itemIndex) //item is the data in a row, index is the row number.
{
if ((item.ConsultantName == "Totals") || (item.BranchName == "Totals"))
{
return "totalItem highlight";
}
}
I have my if statement where I find the item in the last row based on my conditions. When they are met, I add my custom CSS classes to that row.
I've seen this problem in many places but I can't seem to find a solution. So I have defined a Kendo grid with CRUD operations the thing is that the previous fired operations get fired again.
Say you delete entry X and then you add entry Y, the create operation fires and after that the delete operation (for X - which has been deleted) fires again. Same thing if you first create an element and then edit another, it edits the 2nd element and then it re-fires the 1st create statement and inserts a duplicate for the 1st inserted element. If you go on an on with several operations a nightmare happens with all the other previous operations being fired and sent to the controller.
My grid is:
function InitializeIPAddressesGrid(userID) {
selectedUserID = userID;
$(".ipAddresses").kendoGrid({
dataSource: IPAdressesDataSource,
sortable: {
mode: "single",
allowUnsort: false
},
remove: function (e) {
this.refresh();
var canDelete = confirm("Are you sure you want to delete this record?");
if (!canDelete) {
e.preventDefault();
}
},
height: 420,
resizable: true,
pageable: {
refresh: true,
pageSize: 10
},
selectable: "row",
toolbar: ["create"],
editable:{mode: "inline", confirmation:false} ,
columns: [{
field: "IpAddress",
title: "IP Address"
},
{
field: "Status",
title: "Status"
},
{
field: "LockedUntil",
title: "Locked until",
template: "#=kendo.toString(LockedUntil, 'yyyy/MM/dd' )#"
},
{ command: ["edit", "destroy"], title: " ", width: "180px" }
]
});
}
var IPAdressesDataSource = new kendo.data.DataSource({
type: "json",
serverPaging: true,
serverSorting: true,
serverFiltering: true,
pageSize: 10,
//scrollable:false,
transport: {
read: {
url: websiteRootUrl + '/PortalAuthorization/GetIPAddressesList',
},
update: {
url: websiteRootUrl + "/PortalAuthorization/UpdateIP",
dataType: "json",
type: 'POST',
complete: function (e) {
if (e.status != 200) {
alert(eval('(' + e.responseText + ')').Message);
}
}
},
create: {
url: websiteRootUrl + "/PortalAuthorization/CreateIP",
dataType: "json",
type: 'POST',
complete: function (e) {
if (e.status != 200) {
alert(eval('(' + e.responseText + ')').Message);
}
}
},
destroy: {
url: websiteRootUrl + "/PortalAuthorization/DeleteIP",
dataType: "json",
type: 'DELETE',
complete: function (e) {
if (e.status != 200) {
alert(eval('(' + e.responseText + ')').Message);
}
}
},
parameterMap: function (options, operation) {
if (operation == "update" && options) {
return {ipAddress: options.IpAddress ,
status: options.Status ,
lockedUntil: kendo.toString(options.LockedUntil, 'yyyy/MM/dd' ),
pkey: options.ID,
databaseID: selectedDatabaseID };
}
else
if (operation == "destroy" && options)
{
return {
databaseID: selectedDatabaseID,
pkey: options.ID,
userIDParam: selectedUserID
};
}
else
if (operation == "create" && options) {
return {ipAddress: options.IpAddress ,
status: options.Status ,
lockedUntil: kendo.toString(options.LockedUntil, 'yyyy/MM/dd' ),
pkey: options.ID,
userIDParam: selectedUserID,
databaseID: selectedDatabaseID };
}
else
{
options.databaseID = selectedDatabaseID;
options.userID = selectedUserID;
return options;
}
}
},
schema: {
model: {
id: "ID",
fields: {
IpAddress: { type: "string" },
Status: { type: "string" },
LockedUntil: { type: "date" }
}
},
data: function (data) {
return data.Items;
},
total: function (data) {
return data.TotalCount;
}
}
});
My controllers are:
public object UpdateIP(int databaseID, long pkey, string status, string lockedUntil, string ipAddress)
{
var database = [...];
DynamicDataRepository repository = [...];
string query = "...";
repository.ExecuteNonQuery(query);
return new HttpResponseMessage(HttpStatusCode.OK);
}
public object DeleteIP(int databaseID, long pkey, int? userIDParam)
{
var database = [...];
DynamicDataRepository repository = [...];
string query = "...";
repository.ExecuteNonQuery(query);
return new HttpResponseMessage(HttpStatusCode.OK);
}
public object CreateIP(int databaseID, long? pkey, string status, string lockedUntil, string ipAddress, int? userIDParam)
{
var database = [...];
DynamicDataRepository repository = [...];
string query = "...";
repository.ExecuteNonQuery(query);
return new HttpResponseMessage(HttpStatusCode.OK);
}
Do you have any ideea? where I've done something wrong? thanks in advance. P.S. the queries in the controllers work fine.
I fixed the problem, followed OnaBai's suggestion of returning the Updated/Created entity, and in the case of a Delete I returned the ID of the deleted entry.
public object UpdateIP(int databaseID, long pkey, string status, string lockedUntil, string ipAddress)
{
var database = [...];
DynamicDataRepository repository = [...];
string query = [...];
IPList updatedIP = new IPList { ID = pkey, IpAddress = ipAddress, Status = status, LockedUntil = DateTime.Today };
return Json(updatedIP, JsonRequestBehavior.AllowGet);
// return new HttpResponseMessage(HttpStatusCode.OK);
}
Only one mention: in the case of a CREATE, the method didn't seem to work so what I did is in the .complete event of the CREATE operation I did a ipGrid.dataSource.read();
ipGrid.refresh(); - so the operation doesn't repeat itself. ( I read that in this case there might be problem with the model definition - setting the ID field - but I did set that one). Many thanks to OnaBai
I am trying Kendo UI out and I am using the examples provided for studying purpose. Let's suppose I am using a large data source of several hundreds of thousand elements. If I'm using paging and the page size is 10, I would really like to be able to get only 10 elements from the web-page and if Kendo UI was able to know that in reality the number of elements is much bigger, but we are showing only 10.
This is what I currently have:
var initGrid = true;
var grid2Data;
function getDataSource()
{
return grid2Data.Data;
}
var grid;
function getPageIndex()
{
if (!(grid)) {
return 0;
}
return grid.pager.page() - 1;
}
function getPageSize() {
if (!(grid)) {
return 10;
}
return grid.pager.pageSize();
}
function getFilters() {
if (!(grid)) {
return "";
}
return grid.dataSource.filter();
}
function getSorts() {
if (!(grid)) {
return "";
}
return grid.dataSource.sort();
}
function getParams() {
return getPageSize();
}
function postTest() {
if (initGrid) {
$.post('myurl' + getParams(), function (data) {
grid2Data = data;
$("#grid").kendoGrid({
dataBound: onDataBound,
dataSource: {
data: getDataSource(),
schema: {
model: {
fields: {
Email: { type: "string" },
FullName: { type: "string" },
LogCreateDate: { type: "date" },
RoleName: { type: "string" },
UserName: { type: "string" }
}
}
},
pageSize: 10
},
height: 300,
scrollable: false,
sortable: true,
filterable: true,
pageable: {
input: true,
numeric: false
},
columns: [
{
field: "Email",
title: "Email",
width: 100
},
{
field: "FullName",
title: "Full Name",
width: 100
},
{
field: "LogCreateDate",
title: "Created",
template: '#= kendo.toString(LogCreateDate,"MM/dd/yyyy") #'
},
{
field: "RoleName",
title: "Role",
width: 50
},
{
field: "UserName",
width: 100
}
]
});
grid = $("#grid").data("kendoGrid");
});
}
else {
}
initGrid = false;
}
$(document).ready(function () {
postTest();
});
My problem is that the grid is showing that this is element 1-10 from 10 and it's the first page. I would like the grid to show me a page index and item count given by me. How can I set the number of elements and the page index of the grid? Is this possible? Thanks.
When you choose serverPaging in the DataSource by setting it to true. You receiver in the server information about the page number (page), the page size (pageSize), number of records to skip (skip)... (look for serverPaging in http://docs.kendoui.com/api/framework/datasource) and in exchange you should return not only the array with the data of that page but also the total number of rows. Then you implement in schema.total the function for accessing the number of records. I.e. Lets assume that you return as result the following object:
{
rows: [
{ id: 1, col1: "col1.1", col2: "col1.2" },
{ id: 2, col1: "col2.1", col2: "col2.2" },
{ id: 3, col1: "col3.1", col2: "col3.2" }
],
totalRows : 1000
}
Then you might implement schema.total as:
schema: {
total: function (response) {
return response.totalRows;
}
}
Where response is the object received from the server.
NOTE: Actually in this case would be enough defining the schema as:
schema: {
total: "totalRows";
}
}
Since total is directly stored in totalRows field.
Check http://demos.kendoui.com/web/grid/remote-data.html for an example.