not able to display records as per page size in kendo grid - asp.net-mvc-4

i want to perform filtering,sorting and no of records in kendo grid but it is not working.
this is my view page:
<script>
$(document).ready(function () {
$("#categories-grid").kendoGrid({
dataSource: {
type: "json",
transport: {
read: {
url: "#Html.Raw(Url.Action("categoriesList", "Admin"))",
type: "POST",
dataType: "json",
data: '',
}
},
schema: {
data: "Data",
total: "Total",
errors: "Errors"
},
error: function(e) {
display_kendoui_grid_error(e);
// Cancel the changes
this.cancelChanges();
},
pageSize: 2,
serverPaging: true,
serverFiltering: true,
serverSorting: true
},
pageable: {
refresh: true,
pageSizes: [10,20,30]
},
editable: {
confirmation: false,
mode: "inline"
},
scrollable: false,
columns: [{
field: "CategoryName",
title: "CategoryName",
width: 100
}, {
field: "CategoryId",
title: "Edit",
width: 100,
template: 'Edit'
}]
});
});
</script>
This is my controller side http post action:
[HttpPost]
public ActionResult categoriesList(DataSourceRequest command)
{
Categories categoriesBal = new Categories();
List<CategoryModel> categoriesList = new List<CategoryModel>();
var category = GetCategory();
ViewBag.Category = GetCategory();
List<Category> categoryDetails = categoriesBal.fetchCategory();//here i am fetching categoryid,name
var gridModel = new DataSourceResult
{
Data = categoryDetails.Select(x =>
{
var categoryModel = new CategoryModel();
categoryModel.CategoryId = x.CategoryId;
categoryModel.CategoryName = x.Name;
return categoryModel;
}),
Total = categoryDetails.Count
};
return Json(gridModel);
}
This is my DataSourceRequest class
public class DataSourceRequest
{
public int Page { get; set; }
public int PageSize { get; set; }
public DataSourceRequest()
{
this.Page = 1;
this.PageSize = 10;
}
}
This is my Category model:
public class CategoryModel
{
public int CategoryId { get; set; }
public string CategoryName { get; set; }
public int frequency { get; set; }
public virtual ICollection<SubcategoryModel> subCategory { get; set; }
}
i am having 12 category.when i am setting item per page dat is 2 it display all records.
can any body tell me what is the problem in my code and how to perform sorting and filtering??

Change your schema to act as a function
schema: {
data: function(response) {
return response.Data ;
}
total: function(response) {
return response.Total;
}
},
and pageable to
pageable: {
refresh: true,
pageSizes: [2,10,20,30]
},
and do not see the use of DataSourceRequest in your code since you don't send the pageSize from the read . send a object of DataSourceRequest and return only what is specify in your DataSourceRequest . in this case only two records
transport: {
read: function (options) {
var commandOBJ=[{
Page: 1, // Once the first two item is loaded and you click for the next page you will have the page in "options" (should be like options.page)
PageSize:2
}];
$.ajax({
url:"#Html.Raw(Url.Action("categoriesList", "Admin"))",
data: { command: bookmarkID },
dataType: "json",
cache: false,
success: function (result) {
options.success(result);
},
error: function (result) {
options.error(result);
}
});
}
}
Now from your action categoriesList check the command and send data accordingly . and your read action can be a GET instead of POST . hope this Helps

Instead of using your custom DataSourceRequest class, use the KendoGridMvcRequest class from this project, this class correctly maps the paging, sorting and filtering.
Also available as nuget.
See this link for demo.

Related

How to create location select box in cshtml page without model

I want to create a select box for the location field, in which if one types any letter should call API and fetch location details in the dropdown
I tried the below code but didn't work
<select class="js-data-example-ajax form-control" id="FilterLocation"></select>
#Html.Hidden("FilterLocation", new { id = "locationId" })
In the script written below code
function setLocation() {
$('.js-data-example-ajax').select2({
ajax: {
type: 'PUT',
url: function (params) {
return '/api/GoogleCustomSearch/getLocation?matchingName=' + params.term
},
delay: 250,
data: function (params) {
var query = {
}
// Query paramters will be ?search=[term]&page=[page]
return query;
},
processResults: function (data) {
data = JSON.parse(data);
let results = []
if (data.location !== null) {
data.location.forEach((e) => {
results.push({
id: e,
text: e
})
})
}
return {
results: results
};
}
},
placeholder: "Search"
})
$('.js-data-example-ajax').on('change',function(e){
var selVal = $('#FilterLocation').val()
$('#locationId').val(selVal)
//getZipCodeForDynamic(selVal)
})
var $newOption = $("<option selected='selected'></option>")
$("#FilterLocation").append($newOption).trigger('change');
}
Dropdown options are not getting with above code.
Here is a working demo for select2:
View:
<select id="mySelect2" class="js-data-example-ajax" style="width:200px"></select>
js:
$('#mySelect2').select2({
ajax: {
type: 'PUT',
url: "GetSelect2Data",
delay: 250,
data: function(params) {
var query = {
search: params.term,
}
// Query parameters will be ?search=[term]
return query;
},
processResults: function(data) {
//data = JSON.parse(data);
let results = []
if (data.location !== null) {
data.location.forEach((e) => {
results.push({
id: e,
text: e
})
})
}
return {
results: results
};
}
},
placeholder: "Search"
});
model:
public class Select2Model {
public List<string> Location { get; set; }
}
action:
[HttpPut]
public ActionResult GetSelect2Data(string Search)
{
return Json(new Select2Model() { Location = new List<string> { "a"+Search,"b" + Search, "c" + Search } });
}
result:

KendoUI SignalR grid not update if data is posed via ajax in my ASP.NET Core 5 web application

I have a KendoUI grid which uses SignalR. Whilst the grid itself works fine if you update the data inline or incell, it doesn't work if I update the data in a form which uses ajax to post it to my controller.
It was my understanding that, if I injected my hub into my controller and then called (whichever I needed, create, update or destroy) :
await _fixtureHub.Clients.All.SendAsync("update", model);
or
await _fixtureHub.Clients.All.SendAsync("update", model);
That it would tell the clients that the data had been changed/created and the grid would update to reflect that change. This isn't happening however and I'm wondering what I've done wrong or missing.
To start, here is my signalR bound grid.
$('#fixture_grid').kendoGrid({
dataSource: {
schema: {
model: {
id: "Id",
fields: {
Created_Date: {
type: "date"
},
Commencement_Date: {
type: "date"
}
}
}
},
type: "signalr",
autoSync: true,
transport: {
signalr: {
promise: fixture_hub_start,
hub: fixture_hub,
server: {
read: "read",
update: "update",
create: "create",
destroy: "destroy"
},
client: {
read: "read",
update: "update",
create: "create",
destroy: "destroy"
}
}
}
},
autoBind: true,
sortable: true,
editable: false,
scrollable: true,
columns: [
{
field: "Created_Date",
title: "Created",
format: "{0:dd/MM/yyyy}"
},
{
field: "Commencement_Date",
title: "Commencement",
format: "{0:dd/MM/yyyy}"
},
{
field: "Charterer",
template: "#if(Charterer !=null){# #=Charterer_Name# #} else { #--# }#"
},
{
field: "Region",
template: "#if(Region !=null){# #=Region_Name# #} else { #--# }#"
}
]
});
Here is the relative hub for that grid:
var fixture_url = "/fixtureHub";
var fixture_hub = new signalR.HubConnectionBuilder().withUrl(fixture_url, {
transport: signalR.HttpTransportType.LongPolling
}).build();
var fixture_hub_start = fixture_hub.start({
json: true
});
Here is the KendoUI wizard with form integration which I update the grid with, this form can process either a creation or an update data, this is achieved by checking the Id that is passed in. Whereby 0 equals new and >0 is existing.
function wizard_fixture() {
let wizard_name = "#wizard-fixture";
//Load Wizard
$(wizard_name).kendoWizard({
pager: true,
loadOnDemand: true,
reloadOnSelect: false,
contentPosition: "right",
validateForms: true,
deferred: true,
actionBar: true,
stepper: {
indicator: true,
label: true,
linear: true
},
steps: [
{
title: "Step 01",
buttons: [
{
name: "custom",
text: "Save & Continue",
click: function () {
let wizard = $(wizard_name).data("kendoWizard");
var validatable = $(wizard_name).kendoValidator().data("kendoValidator");
if (validatable.validate()) {
$.ajax({
type: "POST",
traditional: true,
url: "/Home/Process_Fixture",
data: $(wizard_name).serialize(),
success: function (result) {
...do stuff
},
error: function (xhr, status, error) {
console.log("error")
}
});
}
}
}
],
form: {
formData: {
Id: fixtureviewmodel.Id,
Created_User: fixtureviewmodel.Created_User,
Created_Date: fixtureviewmodel.Created_Date,
Connected: fixtureviewmodel.Connected
},
items: [
{
field: "Fixture_Id",
label: "Id",
editor: "<input type='text' name='Id' id='Fixture_Id' /> "
},
{
field: "Created_User",
label: "Created user",
editor: "<input type='text' name='Created_User' id='Created_User_Fixture' />"
},
{
field: "Created_Date",
id: 'Created_Date_Fixture',
label: "Created date",
editor: "DatePicker",
}
]
}
},
],
});
I've shortened this to demonstrate the custom button and the ajax posting that happens to Process_Fixture. Here is my controller which handles that:
public async Task<JsonResult> Process_Fixture(Fixture model)
{
if (model.Id == 0)
{
if (ModelState.IsValid)
{
var fixture = await _fixture.CreateAsync(model);
Update connected clients
await _fixtureHub.Clients.All.SendAsync("create", model);
return Json(new { success = true, data = fixture.Id, operation = "create" });
}
return Json(new { success = false });
}
else
{
var fixture = await _fixture.UpdateAsync(model);
await _fixtureHub.Clients.All.SendAsync("update", model);
return Json(new { success = true, data = fixture.Id, operation = "update" });
}
}
As you can see, I have injected my hub and I have called the "create" message to it which I believed would force the grid to update with whatever had changed or been created.
Here is the hub itself:
public class FixtureHub : DynamicHub
{
private readonly IRepository<Fixture> _fixtures;
private readonly IRepository<ViewGridFixtures> _viewFixtures;
public FixtureHub(IRepository<Fixture> fixtures, IRepository<ViewGridFixtures> viewFixtures)
{
_fixtures = fixtures;
_viewFixtures = viewFixtures;
}
public override Task OnConnectedAsync()
{
Groups.AddToGroupAsync(Context.ConnectionId, GetGroupName());
return base.OnConnectedAsync();
}
public override Task OnDisconnectedAsync(Exception e)
{
Groups.RemoveFromGroupAsync(Context.ConnectionId, GetGroupName());
return base.OnDisconnectedAsync(e);
}
public class ReadRequestData
{
public int ViewId { get; set; }
}
public IQueryable<ViewGridFixtures> Read()
{
IQueryable<ViewGridFixtures> data = _viewFixtures.GetAll();
return data;
}
public string GetGroupName()
{
return GetRemoteIpAddress();
}
public string GetRemoteIpAddress()
{
return Context.GetHttpContext()?.Connection.RemoteIpAddress.ToString();
}
}
I need some help here in understanding how I can tell the hub that the update/create/destroy has been called and it needs to do something. At the moment, I feel like injecting the hub and then calling the clients.all.async isn't the right way. With ajax it seems to ignore it and I wonder if the two technologies are working against each other.

Vue Apollo "__typename" is undefined in updateQuery

I'm attempting to create a "Show More" button for my posts index. The index query loads fine with the first 5 posts, when I click the Show More button I can see new posts being returned, however I receive a bunch of errors like:
Missing field id in {
"__typename": "Post",
"posts": [
{
"id": "5f2b26600c3ec47b279d8988",
"title":
I receive one of each of these errors pretty much for each post attribute (id, title, content, slug, etc). This prevents the actual new posts from being added to the index. What causes this issue?
<script>
import postsQuery from '~/apollo/queries/blog/posts';
const pageSize = 5;
export default {
name: 'BlogIndex',
data: () => ({
loadingMorePosts: false,
page: 0,
pageSize,
}),
apollo: {
postsCount: {
prefetch: true,
query: postsQuery,
variables: {
page: 0,
pageSize,
}
},
posts: {
prefetch: true,
query: postsQuery,
variables: {
page: 0,
pageSize,
}
},
},
computed: {
morePosts() {
return this.posts.length < this.postsCount.aggregate.totalCount;
}
},
methods: {
async fetchMorePosts() {
this.page += this.pageSize;
this.$apollo.queries.posts.fetchMore({
variables: {
page: this.page,
pageSize,
},
updateQuery: (previousResult, { fetchMoreResult }) => {
const newPosts = fetchMoreResult.posts;
console.log('typename: ', previousResult.posts.__typename); <--- returns undefined
if (!newPosts.length) return previousResult;
return {
posts: {
__typename: previousResult.posts.__typename,
posts: [...previousResult.posts, ...newPosts],
}
}
}
})
},
},
}
</script>
UPDATE: added imported posts query
query Posts($page: Int!, $pageSize: Int!) {
posts(
start: $page
limit: $pageSize
sort: "published_at:desc"
where: { published: true }
) {
id
title
content
slug
published
createdAt
updatedAt
published_at
}
postsCount: postsConnection(where: { published: true }) {
aggregate {
totalCount
}
}
}
I think the problem is here:
return {
posts: {
__typename: previousResult.posts.__typename,
posts: [...previousResult.posts, ...newPosts],
}
}
I'm pretty sure __typename is supposed to belong to each post object, not part of the collection of posts. Let me know how if something like this fixes it:
return {
posts: {
posts: [...previousResult.posts, ...newPosts]
}
}
and changing the query to:
query Posts($page: Int!, $pageSize: Int!) {
posts(
start: $page
limit: $pageSize
sort: "published_at:desc"
where: { published: true }
) {
__typename // add this here
id
title
content
slug
published
createdAt
updatedAt
published_at
}
postsCount: postsConnection(where: { published: true }) {
aggregate {
totalCount
}
}
}

Pass selected item from drop down list to viewmodel

I have four controls on the page, a simple form with first and last names, date of birth and this drop down that contains some names of countries. When I make changes to the these controls I am able to see those changes in my viewModel that is passed in as a parameter in the SavePersonDetails POST below, but I never see the LocationId updated in that view model and I am not sure why.
This is what I have in my markup, Index.cshtml:
#model Mvc4withKnockoutJsWalkThrough.ViewModel.PersonViewModel
#using System.Globalization
#using Mvc4withKnockoutJsWalkThrough.Helper
#section styles{
#Styles.Render("~/Content/themes/base/css")
<link href="~/Content/Person.css" rel="stylesheet" />
}
#section scripts{
#Scripts.Render("~/bundles/jqueryui")
<script src="~/Scripts/knockout-2.1.0.js"></script>
<script src="~/Scripts/knockout.mapping-latest.js"></script>
<script src="~/Scripts/Application/Person.js"></script>
<script type="text/javascript">
Person.SaveUrl = '#Url.Action("SavePersonDetails", "Person")';
Person.ViewModel = ko.mapping.fromJS(#Html.Raw(Json.Encode(Model)));
var userObject = '#Html.Raw(Json.Encode(Model))';
var locationsArray = '#Html.Raw(Json.Encode(Model.Locations))';
var vm = {
user : ko.observable(userObject),
availableLocations: ko.observableArray(locationsArray)
};
ko.applyBindings(vm);
</script>
}
<form>
<p data-bind="with: user">
Your country:
<select data-bind="options: $root.availableLocations, optionsText: 'Text', optionsValue: 'Value', value: LocationID, optionsCaption: 'Choose...'">
</select>
</p>
</form>
This is my View Model:
public class PersonViewModel
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DateOfBirth { get; set; }
public string LocationId { get; set; }
public IEnumerable<SelectListItem> Locations { get; set; }
}
I have a simple controller that loads my Person and a drop down list containing three countries.
private PersonViewModel _viewModel;
public ActionResult Index()
{
var locations = new[]
{
new SelectListItem { Value = "US", Text = "United States" },
new SelectListItem { Value = "CA", Text = "Canada" },
new SelectListItem { Value = "MX", Text = "Mexico" },
};
_viewModel = new PersonViewModel
{
Id = 1,
FirstName = "Test",
LastName = "Person",
DateOfBirth = new DateTime(2000, 11, 12),
LocationId = "", // I want this value to get SET when the user changes their selection in the page
Locations = locations
};
_viewModel.Locations = locations;
return View(_viewModel);
}
[HttpPost]
public JsonResult SavePersonDetails(PersonViewModel viewModel)
{
int id = -1;
SqlConnection myConnection = new SqlConnection("server=myMachine;Trusted_Connection=yes;database=test;connection timeout=30");
try
{
// omitted
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
finally
{
myConnection.Close();
}
return Json(id, "json");
}
Lastly, here is my Person.js file, I am using knockout
var Person = {
PrepareKo: function () {
ko.bindingHandlers.date = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
element.onchange = function () {
var observable = valueAccessor();
observable(new Date(element.value));
}
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
var observable = valueAccessor();
var valueUnwrapped = ko.utils.unwrapObservable(observable);
if ((typeof valueUnwrapped == 'string' || valueUnwrapped instanceof String) && valueUnwrapped.indexOf('/Date') === 0) {
var parsedDate = Person.ParseJsonDate(valueUnwrapped);
element.value = parsedDate.getMonth() + 1 + "/" + parsedDate.getDate() + "/" + parsedDate.getFullYear();
observable(parsedDate);
}
}
};
},
ParseJsonDate: function (jsonDate) {
return new Date(parseInt(jsonDate.substr(6)));
},
BindUIwithViewModel: function (viewModel) {
ko.applyBindings(viewModel);
},
EvaluateJqueryUI: function () {
$('.dateInput').datepicker();
},
RegisterUIEventHandlers: function () {
$('#Save').click(function (e) {
// Check whether the form is valid. Note: Remove this check, if you are not using HTML5
if (document.forms[0].checkValidity()) {
e.preventDefault();
$.ajax({
type: "POST",
url: Person.SaveUrl,
data: ko.toJSON(Person.ViewModel),
contentType: 'application/json',
async: true,
beforeSend: function () {
// Display loading image
},
success: function (result) {
// Handle the response here.
if (result > 0) {
alert("Saved");
} else {
alert("There was an issue");
}
},
complete: function () {
// Hide loading image.
},
error: function (jqXHR, textStatus, errorThrown) {
// Handle error.
}
});
}
});
},
};
$(document).ready(function () {
Person.PrepareKo();
Person.BindUIwithViewModel(Person.ViewModel);
Person.EvaluateJqueryUI();
Person.RegisterUIEventHandlers();
});
As you can see, I have the data in the page but none of them show as selected
Your solution is overly complex and is leading to certain weirdness with your data. Instead of trying to patch the Titanic, your best bet is to start over and simplify:
Your page's model contains all the information you need. There's no need to try to create two totally separate view models to work with the user data versus locations. With the mapping plugin, you can specify different "view models" for various objects in your main view model, and there's a simpler pattern that can be followed to set all that up. Here's what I would do:
// The following goes in external JS file
var PersonEditor = function () {
var _init = function (person) {
var viewModel = PersonEditor.PersonViewModel(person);
ko.applyBindings(viewModel);
_wireEvents(viewModel);
}
var _wireEvents = function (viewModel) {
// event handlers here
}
return {
Init: _init
}
}();
PersonEditor.PersonViewModel = function (person) {
var mapping = {
'Locations': {
create: function (options) {
return new PersonEditor.LocationViewModel(options.data)
}
}
}
var model = ko.mapping.fromJS(person, mapping);
// additional person logic and observables
return model;
}
PersonEditor.LocationViewModel = function (location) {
var model = ko.mapping.fromJS(location);
// additional location logic and observables
return model;
}
// the following is all you put on the page
<script src="/path/to/person-editor.js"></script>
<script>
$(document).ready(function () {
var person = #Html.Raw(#Json.Encode(Model))
PersonEditor.Init(person);
});
</script>
Then all you need to bind the select list to the locations array is:
<p>
Your country:
<select data-bind="options: Locations, optionsText: 'Text', optionsValue: 'Value', value: LocationId, optionsCaption: 'Choose...'">
</select>
</p>
Based on your updated question, do this.
1.We do not need locationsArray actually. Its already in user.Locations (silly me)
2.On Index.cshtml, page change the JavaScript like this.
var userObject = #Html.Raw(Json.Encode(Model)); // no need for the quotes here
jQuery(document).ready(function ($) {
Person.PrepareKo();
Person.EvaluateJqueryUI();
Person.RegisterUIEventHandlers();
Person.SaveUrl = "#Url.Action("SavePersonDetails", "Knockout")";
Person.ViewModel = {
user : ko.observable(userObject)
};
Person.BindUIwithViewModel(Person.ViewModel);
});
3.On your Person.js page, inside RegisterUIEventHandlers #Save button click event, do this.
$('#Save').click(function (e) {
var updatedUser = Person.ViewModel.user();
updatedUser.Locations.length = 0; // not mandatory, but we don't need to send extra payload back to server.
// Check whether the form is valid. Note: Remove this check, if you are not using HTML5
if (document.forms[0].checkValidity()) {
e.preventDefault();
$.ajax({
type: "POST",
url: Person.SaveUrl,
data: ko.toJSON(updatedUser), // Data Transfer Object
contentType: 'application/json',
beforeSend: function () {
// Display loading image
}
}).done(function(result) {
// Handle the response here.
if (result > 0) {
alert("Saved");
} else {
alert("There was an issue");
}
}).fail(function(jqXHR, textStatus, errorThrown) {
// Handle error.
}).always(function() {
// Hide loading image.
});
}
});
5.Finally, our markup
<p data-bind="with: user">
Your country:
<select data-bind="options: Locations,
optionsText: 'Text',
optionsValue: 'Value',
value: LocationId,
optionsCaption: 'Choose...'">
</select>
</p>
On an unrelated side-note,
The jqXHR.success(), jqXHR.error(), and jqXHR.complete() callbacks are
deprecated as of jQuery 1.8. To prepare your code for their eventual
removal, use jqXHR.done(), jqXHR.fail(), and jqXHR.always() instead.

implementing jTable MVC 4

I have following
****** controller ***********
namespace DLM.Controllers{
public class BooksController : Controller
{
private IRepositoryContainer _repository;
//
// GET: /Books/
public ActionResult Index()
{
return View();
}
[HttpPost]
public JsonResult ListBooks(int jtStartIndex = 0, int jtPageSize = 0, string jtSorting = null)
{
try
{
//Get data from database
int bookCount = _repository.BookRepository.GetBooksCount();
List<Books> book = _repository.BookRepository.GetBooks(jtStartIndex, jtPageSize, jtSorting);
//Return result to jTable
return Json(new { Result = "OK", Records = book, TotalRecordCount = bookCount });
}
catch (Exception ex)
{
return Json(new { Result = "ERROR", Message = ex.Message });
}
}
***** ListBooks View ************
{
#Styles.Render("~/Scripts/jtable/jtable.2.3.0/themes/metro/darkgray/jtable.min.css")
<script src="/Scripts/jtable/jtable.2.3.0/jquery.jtable.min.js" type="text/javascript"></script>
<div id="BookTableContainer"></div>
<script type="text/javascript">
$(document).ready(function () {
$('#BookTableContainer').jtable({
title: 'The Student List',
paging: true, //Enable paging
pageSize: 10, //Set page size (default: 10)
sorting: true, //Enable sorting
defaultSorting: 'Book Title ASC', //Set default sorting
actions: {
listAction: '/Books/Index',
deleteAction: '/Books/DeleteBook',
updateAction: '/Books/UpdateBook',
createAction: '/Books/AddBook'
},
fields: {
BooksID: {
key: true,
create: false,
edit: false,
list: false
},
Code_No: {
title: 'Book Code',
width: '23%'
},
Title: {
title: 'Book Title',
list: false
},
Author: {
title: 'Author',
list: false
},
Page_No: {
title: 'Number of Pages',
width: '13%'
},
Y_of_P: {
title: 'Year of Publication',
width: '12%'
},
Language: {
title: 'Language',
width: '15%'
},
Subject: {
title: 'Subject',
list: false
},
Publisher: {
title: 'Publisher',
list: false
},
Keyword: {
title: 'Keywords',
type: 'textarea',
width: '12%',
sorting: false
}
}
});
//Load student list from server
$('#BookTableContainer').jtable('load');
});
</script>
}
ISSUE *****************
When I am trying to access /Books/ListBooks
There is an error The resource cannot be found.
Please help me out i am new to jTable and it's implementation.
Use ListBooks action instead of Index action in jtable listAction. Index action will be used to render the view and after the jquery will load the data from ListBooks
I think you are requesting /Books/Listbooks through browser URL. Browser by default uses get method to get data from server and you putted HttpPost DataAnnotation over the method thats why you are getting error so if you want output makes following two changes.
1)Remove HttpPost Data Annotation of ListBooks Method.
2)Add JsonRequestBehavior.AllowGet in return Json method as follows
return Json(new { Result = "OK", Records = book, TotalRecordCount = bookCount }, JsonRequestBehavior.AllowGet )
Now Your method will work Perfectly.