i added a kendo grid in my view.The datasource of that grid is coming from the action method
Products_Read in my controller.I had used entity data model in my project.I had added out controller and view code of my index action.The problem is that the data is not coming in grid.
Controller Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Kendo.Mvc.UI;
using Kendo.Mvc.Extensions;
using MvcApplication1.Models;
namespace MvcApplication1.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";
return View();
}
public ActionResult About()
{
ViewBag.Message = "Your app description page.";
return View();
}
public ActionResult Contact()
{
ViewBag.Message = "Your contact page.";
return View();
}
public ActionResult Products_Read([DataSourceRequest]DataSourceRequest request)
{
using (var northwind = new productTableEntities())
{
IQueryable<product> products = northwind.products;
DataSourceResult result = products.ToDataSourceResult(request);
return Json(result);
}
}
}
}
View Code(section where I have used Grid):
<%: Html.Kendo().Grid<MvcApplication1.Models.product>()
.Name("grid")
.DataSource(dataSource => dataSource // Configure the grid data source
.Ajax() // Specify that ajax binding is used
.Read(read => read.Action("Products_Read", "Home")) // Set the action method which will return the data in JSON format
)
.Columns(columns =>
{
columns.Bound(product => product.id);
columns.Bound(product => product.name);
}).Pageable().Sortable()
%>
After a "comment-chat" with Ajay he identified the problem in 3rd party JS.
However Ajay I propose you a small enhancement in your Products_Read action: 1 line and with AllowGet behaviour.
using (var northwind = new productTableEntities())
{
return Json(northwind.products.ToDataSourceResult(request), JsonRequestBehavior.AllowGet);
}
Have a nice day,
Alberto
You have used ActionResult return type for Products_Read Method. I would suggest you to change it to JsonResult.
public JsonResult Products_Read([DataSourceRequest]DataSourceRequest request)
{
using (var northwind = new productTableEntities())
{
IQueryable<product> products = northwind.products;
DataSourceResult result = products.ToDataSourceResult(request);
return Json(result);
}
}
Related
I've searched for all over the place (understatement) for a solution to my case to no avail until now. First, I'll explain my scenario:
I have an OpenAccess Model exposed as a WCF Data Service (oData v3);
I have an Kendo MVC Application;
I have a View with a grid, set for PopUp editing, AJAX Bound;
Before posting some code, let me explain my issue/difficulty. I have an entity with these properties:
TextoID
Titulo;
Corpo;
TipoTextoID;
TipoTexto;
There is a ForeignKey column set to the TipoTextoID property which get's correctly populated either in in-line or pop-up mode. But when it comes to changing data, it only works in-line mode. This is my issue I need it to work in a popup, since the "Corpo" property is bound to a KEndoUI Editor.
When in the popup, it does not show the correct value on the dropdown neither changes it when we select it.
Honestly I'm feeling stupid. I tried almost every sample, post, article I could find to no avail and I'm clueless.
I hope someone can help me on this. Thanks in advance to all!
So, here's the code.
The view:
#model IEnumerable<KendoMVC.CostSimulatorService.Texto>
#{
ViewBag.Title = "Textos";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Textos</h2>
#(Html.Kendo().Grid(Model) // Bind the grid to the Model property of the view
.Name("Grid")
.Columns(columns =>
{
columns.Bound(p => p.Titulo); //Create a column bound to the "ProductID" property
//columns.Bound(p => p.IsPrivado).ClientTemplate("<input type='checkbox' #= IsPrivado ? checked='checked': '' # class='chkbx' />"); //Create a column bound to the "ProductName" property
columns.Template(#<text></text>).ClientTemplate("<input type='checkbox' #= IsPrivado ? checked='checked': '' # class='chkbx' />"); //Create a column bound to the "ProductName" property
//columns.Bound(p => p.TiposTexto);
columns.ForeignKey(p => p.TipoTextoID,
(System.Collections.IEnumerable)ViewData["TiposTexto"],
"TipoTextoID",
"Designacao")
.Title("Tipo de texto").Width(150);
columns.Command(command =>
{
command.Edit();
command.Destroy();
}).Width(200);
})
.ToolBar(commands => commands.Create())
.Editable(editable => editable.Mode(GridEditMode.PopUp).TemplateName("Texto"))
.DataSource(dataSource => dataSource
.Ajax() //specify server type
.Model(model =>
{
model.Id(texto => texto.TextoID); // Specify the property which is the unique identifier of the model
model.Field(texto => texto.TextoID).Editable(false); // Make the ProductID property not editable
})
.Create(create => create.Action("CreateTexto", "BackOffice"))
.Read(read => read.Action("ReadTextos", "BackOffice"))
.Update(update => update.Action("UpdateTexto", "BackOffice"))
.Destroy(destroy => destroy.Action("DestroyTexto", "BackOffice")))
.Pageable() // Enable paging
.Sortable() // Enable sorting
.Selectable()
.Filterable()
.Scrollable()
)
<script type="text/javascript">
$(document).ready(function() {
$("form.k-edit-form").kendoValidator();
});
</script>
Next, then template:
#using System.Web.Mvc.Html;
#model KendoMVC.CostSimulatorService.Texto
Introduza o conteúdo que deseja
#Html.HiddenFor(model => model.TextoID)
<div id="divWrapper" style="width:99%; float:left;">
<div>
#Html.LabelFor(model => model.Titulo)
</div>
<div>
#Html.EditorFor(model => model.Titulo)
#Html.ValidationMessageFor(model => model.Titulo)
</div>
<div>
#Html.LabelFor(model => model.Corpo)
</div>
<div>
#(Html.Kendo().EditorFor(model => model.Corpo))
#Html.ValidationMessageFor(model => model.Corpo)
</div>
<div>
#Html.LabelFor(model => model.TipoTextoID)
</div>
<div>
#*#(Html.Kendo().DropDownListFor(model => model.TiposTexto))
#Html.ValidationMessageFor(model => model.TiposTexto)*#
#(Html.Kendo().DropDownListFor(m => m.TipoTextoID)
.Name("TiposTexto")
.DataTextField("Designacao")
.DataValueField("TipoTextoID")
.BindTo((System.Collections.IEnumerable)
ViewData["TiposTexto"]))
</div>
</div>
The controller:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Kendo.Mvc.Extensions;
using Kendo.Mvc.UI;
using KendoMVC.CostSimulatorService;
namespace KendoMVC.Controllers
{
public partial class BackOfficeController : Controller
{
#region CRUD
#region ReadTextos
public ActionResult ReadTextos([DataSourceRequest]DataSourceRequest request)
{
CostSimulatorModel modelo = new CostSimulatorModel(new Uri(#"http://localhost:53212/CostSimulatorModelService.svc/"));
IQueryable<Texto> textos = modelo.Textos;
DataSourceResult resultado = textos.ToDataSourceResult(request);
ViewData["Textos"] = textos;
return Json(resultado, JsonRequestBehavior.AllowGet);
}
#endregion
#region CreateTexto
public ActionResult CreateTexto([DataSourceRequest]DataSourceRequest request, Texto texto)
{
if (ModelState.IsValid)
{
CostSimulatorModel modelo = new CostSimulatorModel(new Uri(#"http://localhost:53212/CostSimulatorModelService.svc/"));
// Create a new Product entity and set its properties from the posted ProductViewModel
Texto entity = new Texto
{
TextoID = texto.TextoID,
Titulo = texto.Titulo,
Corpo = texto.Corpo,
IsPrivado = texto.IsPrivado,
TipoTextoID = texto.TipoTextoID,
TiposTexto = texto.TiposTexto
};
modelo.AddToTextos(entity);
// Insert the entity in the database
modelo.SaveChanges();
// Get the ProductID generated by the database
texto.TextoID = entity.TextoID;
}
// Return the inserted product. The grid needs the generated ProductID. Also return any validation errors.
return Json(new[] { texto }.ToDataSourceResult(request, ModelState));
}
#endregion
#region UpdateTexto
public ActionResult UpdateTexto([DataSourceRequest]DataSourceRequest request, Texto texto)
{
if (ModelState.IsValid)
{
CostSimulatorModel modelo = new CostSimulatorModel(new Uri(#"http://localhost:53212/CostSimulatorModelService.svc/"));
// Create a new Product entity and set its properties from the posted ProductViewModel
var entity = new Texto
{
TextoID = texto.TextoID,
Titulo = texto.Titulo,
Corpo = texto.Corpo,
IsPrivado = texto.IsPrivado,
TipoTextoID = texto.TipoTextoID,
TiposTexto = texto.TiposTexto
};
// Attach the entity
modelo.AttachTo("Textos", entity);
modelo.UpdateObject(entity);
// Update the entity in the database
modelo.SaveChanges();
}
// Return the updated product. Also return any validation errors.
return Json(new[] { texto }.ToDataSourceResult(request, ModelState));
}
#endregion
#region DestroyTexto
public ActionResult DestroyTexto([DataSourceRequest]DataSourceRequest request, Texto texto)
{
if (ModelState.IsValid)
{
CostSimulatorModel modelo = new CostSimulatorModel(new Uri(#"http://localhost:53212/CostSimulatorModelService.svc/"));
// Create a new Product entity and set its properties from the posted ProductViewModel
var entity = new Texto
{
TextoID = texto.TextoID
//Titulo = texto.Titulo,
//Corpo = texto.Corpo,
//IsPrivado = texto.IsPrivado,
//TipoTextoID = texto.TipoTextoID
};
// Attach the entity
modelo.AttachTo("Textos", entity);
// Delete the entity
modelo.DeleteObject(entity);
// Delete the entity in the database
modelo.SaveChanges();
}
// Return the removed product. Also return any validation errors.
return Json(new[] { texto }.ToDataSourceResult(request, ModelState));
}
#endregion
#endregion
}
}
I've finally got this sorted out with the precious help from KendoUI's premium forums.
So, to stop this from happening, one should use the default editor template for the ForeignKeyColumn as an editor for the "TipoTextoID", like so:
Model:
[UIHint("GridForeignKey")]
public int EmployeeID { get; set; }
Custom popup template:
#(Html.EditorFor(m => m.EmployeeID))
instead of using #(Html.Kendo().DropDownListFor(m => m.TipoTextoID)
Hope this may help others struggling with same thing.
All the best!
In addition to Stargazer's answer (Thanks!!!), below custom popup template (Views\Shared\EditorTemplates\GridForeignKey.cshtml) worked for me.
#model object
#(
Html.Kendo().DropDownListFor(m => m)
.BindTo((SelectList)ViewData[ViewData.TemplateInfo.GetFullHtmlFieldName("") + "_Data"])
)
Also, no need of specifying custom template so do below on grid view:
.Editable(editable => editable.Mode(Kendo.Mvc.UI.GridEditMode.PopUp))
Last clarification, add below to main grid model (not foreign key viewmodel) also name matches with custom template.
[UIHint("GridForeignKey")]
this is my Get actionresult :
public ActionResult Add()
{
ViewData["categoryList"]= _categoryRepository.GetAllCategory().
ToSelectList(c => c.Id, c => c.Name);
return View("Add");
}
this my razor that render the categoryList , and I have no trouble with that !
<div>
#Html.LabelFor(b => b.Category)
#Html.DropDownList("Category", ViewData["categoryList"] as IEnumerable<SelectListItem>)
#Html.ValidationMessageFor(b => b.Category)
</div>
finally after submitting the page , category select send via null value to post this action
[HttpPost]
public ActionResult Add(BlogPost blogPost)
{
if (ModelState.IsValid)
{
blogPost.PublishDate = DateTime.Now;
_blogPostRepository.AddPost(blogPost);
_blogPostRepository.Save();
return RedirectToAction("Add");
}
return new HttpNotFoundResult("An Error Accoured while requesting your order!");
}
could anybody tell me why ??
controller
public ActionResult Add()
{
ViewBag.CategoryList = new SelectList(_categoryRepository.GetAllCategory(), "Id", "Name");
// you dont need the specify View name
// like this: return View("Add")
// you need to pass your model.
return View(new BlogPost());
}
view
#Html.DropDownListFor(model => model.CategoryId, ViewBag.CategoryList as SelectList, "--- Select Category ---", new { #class = "some_class" })
controller post action
[HttpPost]
public ActionResult Add(BlogPost blogPost)
{
if (ModelState.IsValid)
{
blogPost.PublishDate = DateTime.Now;
_blogPostRepository.AddPost(blogPost);
_blogPostRepository.Save();
// if you want to return "Add" page you should
// initialize your viewbag and create model instance again
ViewBag.CategoryList = new SelectList(_categoryRepository.GetAllCategory(), "Id", "Name");
return View(new BlogPost());
}
return new HttpNotFoundResult("An Error Accoured while requesting your order!");
}
I have a generic list method that returns a CategoryID and CategoryName.
I have spent enough time researching and cant seem to put it together. I very new at MVC.
Here is my DropdownList Method in a repository. I get back the data... So far so good.
public List<DropdownList> GetDDl()
{
return catDDL;
}
Here is my CONTROLLER CODE(attempt at it)
IEnumerable<SelectListItem> liCat =
userRepository.Getddl().Select(c => new SelectListItem
{
Value = c.DropDownID.ToString(),
Text = c.DropDownText
}
ViewBag.catItems = new SelecList(liCat,"Value","Text");
Here is my VIEW
#Html.Dropdownlist("catItems","Select Category)
Try to avoid dynamic stuff like ViewBag and ViewData. Use strongly typed views.
ViewModel is just a POCO class which we will use to transfer data between your view and the action method. It will be specific to the view.
ex : if you want to create a view which creates a product. So create a viewmodel like this
public class Product
{
public string Name { set;get;}
public IEnumerable<SelectListItem> Categories{ get; set; }
public string SelectedCategoryId { get; set; }
//Other Properties as needed
}
now in your GET action method, you create an object of this view model and initialize the values and send to the view.
public ActionResult Create()
{
var vm=new Product();
vm.Categories=userRepository.Getddl().
Select(c => new SelectListItem
{
Value = c.DropDownID.ToString(),
Text = c.DropDownText
});
return View(vm);
}
Now make your view strongly typed to our Product class and use the Html.DropDownListFor helper method.
#model PersonsProduct
#using (Html.BeginForm())
{
#Html.DropDownListFor(x => x.SelectedCategoryId,
new SelectList(Model.Categories,"Value","Text"), "Select")
<input type="submit" value="save" />
}
Now in your HttpPost , you can get the form values like this
[HttpPost]
public ActionResult Create(Product model)
{
if(ModelState.IsValid)
{
//check model.SelectedCategoryId
//save and redirect
}
//to do :reload the dropdown again.
return view(model);
}
Should just be:
Controller:
IEnumerable<SelectListItem> liCat = userRepository.Getddl().Select(c => new SelectListItem
{
Value = c.DropDownID.ToString(),
Text = c.DropDownText
}
ViewBag.catItems = liCat
View:
#Html.Dropdownlist("catItems", ViewBag.catItems)
My Telerik MVC 3 grid is filled via Ajax. After inserting a row I need to rebind my grid. When I'm doing a rebind on the OnSave() event the data rebind is still sending on the Controller Action. I need something like an OnInserted event.
Any idea?
Use the following criteria,
#(Html.Telerik().Grid<PackageDetails>()
.Name("gvPackage")
.DataKeys(keys => keys.Add(k => k.PKG_CODE))
.Columns(column =>
{
column.Bound(c => c.PKG_NAME).Title("Description").Width(200);
column.Bound(c => c.MESG_UNIT).Title("Measuring Unit").Width(100);
column.Bound(c => c.STD_QNT).Title("Quantity").Width(100);
column.Bound(c => c.MODEL).Title("Model").Width(100);
column.Bound(c => c.COMP_CODE).ClientTemplate("<input type='text' id='txtSerial<#=COMP_CODE#>' value='<#=PKG_NAME#>' />").Title("Serial Number");
column.Bound(c => c.COMP_DESC).Title("Model").Width(100);
})
.DataBinding(dbBindings => dbBindings.Ajax().Select("_PackageDetailsLoad", "SalesDept"))
)
Controller Code
[GridAction]
public ActionResult _PackageDetailsLoad(string programID, string projectID, string packageID)
{
objLoginHelper = (LoginHelper)Session["LogInInformation"];
return View(new GridModel<PackageDetails>
{
Data = salesDal.ReadPackageDetails(programID, projectID, packageID)
});
}
In JavaScript use the following Code
$('#ddlProgram').change(function () {
LoadPackageAndBindGrid();
});
function LoadPackageAndBindGrid() {
var params = {
programID: $('#ddlProgram').val(),
projectID: $('#ddlProject').val(),
packageID: $('#ddlPackage').val()
};
var grid = $('#gvPackage').data('tGrid');
grid.dataSource._data = [];
// Reload The Package Details
grid.ajaxRequest(params);
}
You can rebind your grid by returning a GridModel from your controller after performing your insert code:
[AcceptVerbs(HttpVerbs.Post)]
[GridAction]
public ActionResult _ItemInsert(int id, MyObject obj)
{
//Rebind the grid by sending the GridModel back
return View(new GridModel(myData)); // where myData is your grid data
}
Don't forget to decorate your controller with [GridAction].
This assumes your grid has an ajax DataBinding declaration as follows:
dataBinding.Ajax()
.Insert("_ItemInsert", "Item" })
It depends on how you're adding the row. The grid should update automatically if you're doing in-grid editing. If you're adding a record from a form, you can use the client-side rebind() method to refresh the grid data.
http://www.telerik.com/help/aspnet-mvc/telerik-ui-components-grid-client-api-and-events.html#rebind
On Complete Of Your Action you can call:
jQuery("#gvPackage").data("t-grid").ajaxRequest()
I have a property in my model very simple one:
Now this dropDown doesn't work right
#Html.DropDownListFor(m => m.Camp, new SelectList(ViewBag.Camps, "Id", "Name"))
it returns null instead of a chosen Camp, but if I change that into:
#Html.DropDownListFor(m => m.Camp.Id, new SelectList(ViewBag.Camps, "Id", "Name"))
It would return me a Camp object with correct Id, but the Name would be still null.
Why?
UPD:
And now another problem is if I choose the second approach it would screw up with unobtrusive validation. Although I'll be able to get the right camp based on the chosen id.
That's normal. Only the Id is posted to the controller action. That's how dropdown inside forms work. So that's all you can hope to get there. You will then use this Id to get the corresponding Camp object from the database:
[HttpPost]
public ActionResult Foo([Bind(Prefix = "Camp")]int id)
{
Camp camp = Repository.GetCamp(id);
...
}
Also please get rid of this ViewBag and use a real view model:
public class CampViewModel
{
public int Id { get; set; }
public IEnumerable<SelectListItem> Camps { get; set; }
}
and in the controller:
public ActionResult Index()
{
var model = new CampViewModel
{
Camps = Repository.GetCamps().Select(x => new SelectListItem
{
Value = x.Id.ToString(),
Text = x.Name
})
};
return View(model);
}
[HttpPost]
public ActionResult Index(int id)
{
Camp camp = Repository.GetCamp(id);
...
}
and the view:
#model CampViewModel
#using (Html.BeginForm())
{
#Html.DropDownListFor(
x => x.Id,
new SelectList(Model.Camps, "Value", "Text")
)
<input type="submit" value="OK" />
}