I am working on ASP.NET MVC and I have a View on which form data is retrieved in the HttpPost action. It works fine when the HttpPost action is called. I use the form data to query a database and the result from the database is bound to a TELERIK Grid control. It displays data fine, but paging is not working.
The issue is that when I try to switch to another page, it calls the HTTPGET action method and not the HttpPost action method and hence no data is retrieved from the database.
Any help is appreciated.
Here is the code for the View and Controller:
//-------------View------------------------------------
#(Html.Telerik().Grid(Model)
.Name("Grid")
.Columns(columns =>
{
columns.Bound(o => o.DealerName);
columns.Bound(o => o.DealerNumber);
columns.Bound(o => o.ServiceDealerNumber);
columns.Bound(o => o.CMDealerNumber);
columns.Bound(o => o.PurchaseDealerNumber);
columns.Bound(o => o.Address);
columns.Bound(o => o.City);
columns.Bound(o => o.State);
columns.Bound(o => o.Zip);
})
.DataBinding(dataBinding =>
{
dataBinding.Server().Select("DealerProfile", "DealerManagement", new { testVal = "test" }).Enabled(true);
dataBinding.Ajax().Select("DealerProfile", "DealerManagement", new { testVal = "test" } ).Enabled(true);
})
.Scrollable(scrolling => scrolling.Enabled(true))
.Sortable(sorting => sorting.Enabled(true))
.Pageable(paging =>
paging.PageSize(20)
.Style(GridPagerStyles.NextPreviousAndNumeric)
.Position(GridPagerPosition.Bottom)
)
.Filterable(filtering => filtering.Enabled(true))
.Groupable(grouping => grouping.Enabled(true))
.Footer(true)
)
//---------------Controller Actions---------------------------------------
//
// GET: /DealerManagement/DealerProfile/
public ActionResult DealerProfile()
{
return View();
}
//
// POST: /DealerManagement/DealerProfile/
[HttpPost]
public ActionResult DealerProfile(FormCollection formValues)
{
string dealerNumber = Request.Form["DealerNumber"];
string dealerName = Request.Form["DealerName"];
DealerProfilesViewModel dealerProfilesViewModel = new DealerProfilesViewModel();
dealerProfilesViewModel.DealerProfiles = new List<DealerProfileViewModel>();
if (!dealerNumber.Trim().Equals(string.Empty))
{
DealerInfoCollection dealers = _iDealerProfileService.GetDealerInfoFromDealerNumber(dealerNumber);
foreach (var item in dealers)
{
DealerProfileViewModel dealerProfileViewModel = new DealerProfileViewModel();
dealerProfileViewModel.DealerName = item.Dealer_Name;
dealerProfileViewModel.DealerNumber = item.Dealer_No;
dealerProfileViewModel.ServiceDealerNumber = item.Service_Dealer_No;
dealerProfileViewModel.CMDealerNumber = item.CM_Dealer_No;
dealerProfileViewModel.PurchaseDealerNumber = item.PUR_Dealer_No;
dealerProfileViewModel.Address = item.Address;
dealerProfileViewModel.City = item.City;
dealerProfileViewModel.State = item.State;
dealerProfileViewModel.Zip = item.Zip;
dealerProfilesViewModel.DealerProfiles.Add(dealerProfileViewModel);
}
}
else if (!dealerName.Trim().Equals(string.Empty))
{
DealerInfoCollection dealers = _iDealerProfileService.GetDealerInfoFromDealerName(dealerName);
foreach (var item in dealers)
{
DealerProfileViewModel dealerProfileViewModel = new DealerProfileViewModel();
dealerProfileViewModel.DealerName = item.Dealer_Name;
dealerProfileViewModel.DealerNumber = item.Dealer_No;
dealerProfileViewModel.ServiceDealerNumber = item.Service_Dealer_No;
dealerProfileViewModel.CMDealerNumber = item.CM_Dealer_No;
dealerProfileViewModel.PurchaseDealerNumber = item.PUR_Dealer_No;
dealerProfileViewModel.Address = item.Address;
dealerProfileViewModel.City = item.City;
dealerProfileViewModel.State = item.State;
dealerProfileViewModel.Zip = item.Zip;
dealerProfilesViewModel.DealerProfiles.Add(dealerProfileViewModel);
}
}
if (!String.IsNullOrEmpty(dealerName) && !String.IsNullOrEmpty(dealerNumber))
{
dealerProfilesViewModel = null;
}
return View(dealerProfilesViewModel.DealerProfiles);
}
First your controller method needs the GridAction attribute. Second it must use the GridModel type as a model. This is required for ajax binding. You can check the ajax binding help article as well as the ajax binding online demo which show what the required steps are. Most probably you should define a separate action method just for the ajax binding.
Lastly it seems that the JavaScript of the grid does not kick in - the fact that it is making HTTP GET requests indicate that. Check that there is a ScriptRegistrar component declared AFTER the grid.
Related
I have a kendo grid that returns all the results except for the first column, being the date. It is showing as blank. In my viewmodel the reviewdate is of type string. In my controller I have the reviewdate converted to a string. I know that reviewdate returns MM/dd/yyyy from debug.
Controller snippet:
foreach (var item in query)
{
model.Add(new PreviousReviewViewModel()
{
ReviewId = item.ReviewId,
ReviewDate = item.NextReviewDt.ToString("MM/dd/yyyy"),
Rating = item.Rating,
SubmittedFl = item.SubmittedFl
});
}
In my view i have the grid as follows:
#(Html.Kendo().Grid<PreviousReviewViewModel>()
.Name("Grid")
//.HtmlAttributes(new { style = "width:450px;" })
.Columns(columns =>
{
columns.Template(
#<text>
#Html.ActionLink(Model.ReviewDate, "SavedFormsIndex", new { Controller = "Forms", id = Model.ReviewId })
</text>).ClientTemplate(#"").Title("Review Date");
columns.Bound(m => m.Rating).Title("Composite Rating"); //rating is the avg
columns.Bound(m => m.SubmittedFl).Title("Submitted");
})
.Pageable(p => p.Numeric(false).PreviousNext(false).Refresh(true))
.Resizable(resize => resize.Columns(true))
.Scrollable()
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(2147483647)
.Read(read => read.Action("read_PrevProjReviews", "Forms", new { id = ViewBag.ProjectId }))
)
try change your client template
.ClientTemplate(#"#=ReviewDate#
I have a kendo Grid which pulls loads of data. To increase the performance i have set the ServerOperation(true), which hits the database for each pagination click to load only 20 records each time it hits.
But, kendo Grid Filter is not working when ServerOperation(true).
Here is the code.If we make ServerOperation false, the grid retrieves all the data at once which will hit the performance. Please suggest any solution to have the filter with ServerOperation true.
#(Html.Kendo().Grid<ViewModel>().Name("Grid")
.Columns(columns =>
{
columns.Bound(p => p.Id).Hidden();
columns.Bound(p => p.Number).Filterable(filterable => filterable.UI("NumberFilter")).Width("150px").Locked(true);
})
.Filterable().Sortable()
.Resizable(resizing => resizing.Columns(true))
.Reorderable(reordering => reordering.Columns(true))
.Pageable().Scrollable(scr => scr.Height(580))
.DataSource(dataSource => dataSource.Ajax().PageSize(20)
.Read(read => read.Action("LoadTransaction", ControllerName.).Data("geton"))
))
public ActionResult LoadTransaction(int clientid, string id)
{
PagingInfo gvpi = UiControls.GetGridViewPagingInfo(Request.Form);
gvpi.FilterColumns.Add(new PagingColumn() { Name = "ClientId", Value = clientId.ToString(), IsFullTextFilter = true });
gvpi.FilterColumns.Add(new PagingColumn() { Name = "Id", Value = Id, IsFullTextFilter = true });
gvpi.PageSize = 20;
var pagedResult = _contextservice.GetAllByPage(gvpi);
return UiControls.GetGridViewDataAsJson(pagedResult.GridData, pagedResult.RecordCount);
}
function geton()
{
var clientId = $('#ClientId').val();
var Id = $('#Id').val();
return { clientId: clientId, Id: divisionId }
}
Thanks,
Namitha
I have a Kendo MVC grid that contains a nullable property (short) that is bound as a foreign key and uses a dropdown list as an editor template. I am also using inline editing.
When the property value is null, the dropdown list selected value does not get set into the grid cell after the update button is clicked. This works fine if incell editing is used. I am looking for a workaround that will solve my problem. I am including a stripped down version of my code below
Everything works if the nullable value is set to a non-null value.
GRID
#(Html.Kendo().Grid<AssetViewModel>()
.Name("DealAssets")
.Columns(c =>
{
c.Bound(x => x.Name);
c.ForeignKey(x => x.AssetTypeID, (IEnumerable<SelectListItem>)ViewBag.AssetTypeList, "Value", "Text");
c.ForeignKey(x => x.SeniorityTypeID, seniorityTypeList, "Value", "Text").EditorTemplateName("GridNullableForeignKey");
c.ForeignKey(x => x.RateBaseID, rateBaseList, "Value", "Text").EditorTemplateName("GridNullableForeignKey"); ;
c.Command(m => { m.Edit(); m.Destroy(); });
})
.ToolBar(toolbar => toolbar.Create().Text("Add New Asset"))
.Editable(x => x.Mode(GridEditMode.InLine))
.DataSource(ds => ds
.Ajax()
.Model(model => model.Id(request => request.ID))
.Read(read => read.Action("ReadAssets", "Deal", new { id = Model.ID }))
.Create(create => create.Action("CreateAsset", "Deal", new { currentDealID = Model.ID }))
.Update(update => update.Action("UpdateAsset", "Deal"))
.Destroy(destroy => destroy.Action("DeleteAsset", "Deal"))
)
)
EDITOR TEMPLATE
#model short?
#{
var controlName = ViewData.TemplateInfo.GetFullHtmlFieldName("");
}
#(
Html.Kendo().DropDownListFor(m => m)
.Name(controlName)
.OptionLabel("- Please select -")
.BindTo((SelectList)ViewData[ViewData.TemplateInfo.GetFullHtmlFieldName("") + "_Data"])
)
UPDATE ACTION
public ActionResult UpdateAsset([DataSourceRequest] DataSourceRequest request, int ID)
{
var dealAsset = DataContext.DealAssets.SingleOrDefault(o => o.ID == ID);
if (dealAsset != null)
{
if (TryUpdateModel(dealAsset.Asset, new[] {"Name","AssetTypeID","SeniorityTypeID","RateBaseID" }))
{
DataContext.SaveChanges();
}
}
return Json(new[] { new AssetViewModel(dealAsset) }.ToDataSourceResult(request, ModelState), JsonRequestBehavior.AllowGet);
}
Telerik just recently added a new HTML attribute, data_value_primitive, to their selectlist that addresses the issue above. The new attribute should be added in the foreign key editor template and set to true.
Html.Kendo().DropDownListFor(m => m)
.Name(controlName)
.OptionLabel("- Please select -")
.BindTo((SelectList)ViewData[ViewData.TemplateInfo.GetFullHtmlFieldName("") + "_Data"])
**.HtmlAttributes(new { data_value_primitive = true})**
This last section is a modification to the update method to account for the grid not passing back null properties when doing the ajax call. I think this has more to do with how the TryUpdateModel method works
...
if (TryUpdateModel(dealAsset.Asset, new[] {"Name","AssetTypeID","SeniorityTypeID","RateBaseID" }))
{
// If no property passed back then set it to null
var senorityTypeID = ValueProvider.GetValue("SeniorityTypeID");
if (senorityTypeID == null)
{
dealAsset.Asset.SeniorityTypeID = null;
} else {
dealAsset.Asset.SeniorityTypeID = (short)senorityTypeID.ConvertTo(typeof(short));
}
var rateBaseID = ValueProvider.GetValue("RateBaseID");
if (rateBaseID == null)
{
dealAsset.Asset.RateBaseID = null;
} else {
dealAsset.Asset.RateBaseID = (byte)rateBaseID.ConvertTo(typeof(byte));
}
DataContext.SaveChanges();
}
'''
I'm using the Kendo UI Server Side Wrappers to create a grid to manage (CRUD) a list of messages in our system. The model is very simple and it only requires that the message is 150 characters or less. To enforce the message length I'm using the following data annotation in my model:
[StringLength(150, ErrorMessage = "Message exceeded the maximum length allowed. Please ensure you message is no longer than 150 characters")]
Here's what my grid looks like:
#model OperatorMessageListModel
#{
TransactionStatusType status = Model.TransactionStatus;
ViewBag.Title = String.Format("{0} Transaction Operator Messages", status);
string header = string.Format("{0} Transaction Messages", status);
string messagesTableId = string.Format("{0}TransactionOperatorMessagesGrid", status);
}
<h2>#header</h2>
#(Html.Kendo().Grid(Model.OperatorMessages)
.Name(messagesTableId)
.TableHtmlAttributes(new { style = "width: 50% height:75%" })
.Columns(columns =>
{
columns.Bound(m => m.Message).Title("");
columns.Bound(m => m.Index).Hidden(true);
if (!Model.IsInherited) //only edit if you own the list and there's anyhting to edit
{
columns.Command(cmd =>
{
cmd.Edit().UpdateText("Save");
cmd.Destroy();
}).Width("20%");
}
})
.Pageable()
.Scrollable(s => s.Enabled(false))
.ToolBar(cmd =>
{
if (!Model.IsInherited) //you can add messages to the lists that you own
{
cmd.Create().Text("Add new message");
}
if (!Model.OwnedByRoot && Model.OperatorMessages.Any()) //if the root owns this it can't override or inherit its own list.
{
var actionName = Model.IsInherited ? "OverrideTrasactionMessageList" : "InheritTrasactionMessageList";
cmd.Custom().Text(Model.OverrideOrInheritButtonText).Action(actionName, "OperatorMessage", new { Model.OrgId, Model.TransactionStatus });
}
}
)
.Editable(editable => editable.Mode(GridEditMode.InLine))
.DataSource(ds => ds
.Server()
.Model(model => model.Id(m => m.Index))
.Create(c => c.Action("CreateTransactionMessage", "OperatorMessage", new { #Model.OrgId, #Model.TransactionStatus }))
.Read(c => c.Action("List", "OperatorMessage", new { #Model.OrgId, #Model.TransactionStatus }))
.Update(c => c.Action("EditTransactionMessage", "OperatorMessage"))
.Destroy(c => c.Action("DeleteTrasactionMessage", "OperatorMessage"))
)
)
Here's the controller code:
[HttpPost]
public ActionResult CreateTransactionMessage([DataSourceRequest] DataSourceRequest request,
OperatorMessageModel newMessage, string OrgId,
string TransactionStatus)
{
_transactionOperatorMessageService.AddOperatorMessage(OrgId, TransactionStatus, newMessage,
CurrentUser.Name());
return RedirectToAction("List", new {OrgId, TransactionStatus});
}
When the user enters a message longer than 150 characters, I expect the validation message to be displayed to the user. Additionally, the form not to be posted back to the controller. Everything works as expcted in Chrome and Firefox. However, in IE8 the message is displayed but the form is still posted back to the controller. Has anyone seen this?
I am getting a null value passed to my ajax .Update("_SaveAjaxEditing", "AptProfile") in my controller when using the dropdownlist client Edit Template.
property in my FormViewModel that my grid is bound to:
[UIHint("BuildingsGrid"), Required]
[DisplayName("Building ID")]
public int BuildingID
{
get;
set;
}).
Here is my view:
<%= Html.Telerik().Grid<PayRent.Models.AptProfileFormViewModel1>()
.Name("Profiles")
.DataKeys(dataKeys => dataKeys.Add(c => c.AptProfileID))
.ToolBar(commands => commands.Insert())
.DataBinding(binding =>
{
binding.Ajax()
.Select("GetProfiles", "AptProfile")
.Insert("_InsertAjaxEditing", "AptProfile")
.Update("_SaveAjaxEditing", "AptProfile")
.Delete("_DeleteAjaxEditing", "AptProfile");
})
.Columns(columns =>
{
columns.Bound(o => o.AptProfileID);
columns.Bound(o => o.BuildingID);
columns.Bound(o => o.AptID);
columns.Bound(o => o.AptRate);
columns.Bound(o => o.AptSize);
columns.Bound(o => o.MoveInDate);
columns.Command(s =>
{
s.Edit();
s.Delete();
});
})
.Editable(editing => editing.Mode(GridEditMode.InLine))
.ClientEvents(events => events.OnEdit("onEdit"))
.Pageable()
%>
</p>
<script type="text/javascript">
function onEdit(e) {
// $(e.form).find('#BuildingsGrid').data('tDropDownList').select(function (dataItem) {
// return dataItem.Text == e.dataItem['BuildingGrid'];
// });
}
</script>
My EditTemplate:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<%= Html.Telerik().DropDownList()
.Name("BuildingsGrid")
.BindTo(new SelectList((IEnumerable)ViewData["Buildings"], "BuildingID", "Name"))
%>)
Here is my Controller:
[AcceptVerbs(HttpVerbs.Post)]
//[CultureAwareAction]
[GridAction]
public ActionResult _SaveAjaxEditing(int id, int? BuildingGrid)
{
ApartmentProfileRepository repo = new ApartmentProfileRepository();
AptProfile profile = repo.Get(id);
TryUpdateModel(profile);
repo.Save();
return View(new GridModel(GetAllProfiles()));
}
If you want to keep everything Ajax-ified, you have do it without using the viewbag. My combobox is in a separate editor template. All you have to do is return the SelectList as a JsonResult. That said, I only recommended doing it that way if you expect the data in that combobox to change while the user is on the page, because it calls the server method every time the combo is opened.
In my example below, because the user can add a Category on the same page as they're selecting a Category, I need it to hit the server each time. But on other pages, I use server-side binding (via the ViewBag/ViewData) so that it only hits the server once.
My editor template:
#(Html.Telerik().ComboBox()
.Name("YourNameGoesHere")
.DataBinding(binding => binding.Ajax().Select("SelectCategoriesForComboBox","Shared")))
Then in the controller:
public EquipmentEntities db = new EquipmentEntities();
public List<SelectListItem> CategoryList
{
get
{
var m = db.Categories
.Select(e => new{ Id = e.Id, Name = e.Name })
.OrderBy(e => e.name);
List<SelectListItem> sl = new SelectListItem(m.ToList(), "Id", "Name").ToList();
//insert a blank item as the first entry
sl.Insert(0, (new SelectListItem { Text = "", Value = string.Empty }));
return sl;
}
}
[HttpPost]
public ActionResult SelectCategoryForComboBox()
{
return new JsonResult { Data = CategoryList };
}
Maybe I'm a little bit late, but hopefully it helps someone out.
First, you need to match up the name of your column in the view with the name of your edit template and controller action parameter. I don't think the int parameter needs to be nullable in the controller action.
Then in your controller action you need to set the ViewData["Buildings"] for the edit template; then select the current value in your profile object before returning the view.
e.g.
public ActionResult _SaveAjaxEditing(int id, int BuildingsGrid)
{
ApartmentProfileRepository repo = new ApartmentProfileRepository();
AptProfile profile = repo.Get(id);
// Save the building ID in the profile
profile.BuildingID = BuildingsGrid;
TryUpdateModel(profile);
repo.Save();
// Load the Building objects into the ViewData
ViewData["Buildings"] = GetBuildings();
return View(new GridModel(GetAllProfiles()));
}