I have an MVC3 Telerik app. This is my controller:
[GridAction]
public ActionResult Index(GridCommand command)
{
IEnumerable<Order> data = GetData(command);
var dataContext = new NorthwindDataContext();
//Required for pager configuration
ViewData["total"] = dataContext.Orders.Count();
return View(data);
}
[GridAction(EnableCustomBinding = true)]
public ActionResult _CustomBinding(GridCommand command)
{
IEnumerable<Order> data = GetData(command);
var dataContext = new NorthwindDataContext();
return View(new GridModel
{
Data = data,
Total = dataContext.Orders.Count()
});
}
//Utility method which does custom paging and sorting using Linq
private static IEnumerable<Order> GetData(GridCommand command)
{
var dataContext = new NorthwindDataContext();
IQueryable<Order> data = dataContext.Orders;
if (command.PageSize > 0)
{
data = data.Skip((command.Page - 1) * command.PageSize);
}
data = data.Take(5);
return data;
}
This is my razor View:
#model IEnumerable<Telerik.Order>
#(Html.Telerik().Grid(Model)
.Name("Grid")
.Columns(columns =>
{
columns.Bound(o => o.OrderID).Width(100);
columns.Bound(o => o.Customer.ContactName).Width(200);
columns.Bound(o => o.ShipAddress);
columns.Bound(o => o.OrderDate).Format("{0:MM/dd/yyyy}").Width(100);
})
.DataBinding(dataBinding =>
{
dataBinding.Ajax().Select("_CustomBinding", "Home").Enabled(true);
})
.Pageable(pager => pager.Total((int)ViewData["total"]))
.EnableCustomBinding(true)
.Sortable()
)
When I run the app, it loads fine, but when I click on a number in the paging row at the bottom, I get :
Error! The requested URL returned 500- Internal server error
It calls my function _CustomBinding and doesnt throw an error when i step through it. Whats causing this error?
This means that a server side exception has occurred in _CustomBinding method. You can check what the actual server response is - it would contain the stacktrace. Use Fiddler or your browser's developer tools to check what the server response is.
Related
I am trying to display a tree of categories with remote data binding.
here is the Controller method:
public JsonResult KendoTree(Guid? id)
{
var categoriesBO = _categoryManager.GetAllCategory().
Where(c=> id==null ? c.ParentId==null : c.ParentId == id).
Select(c=> new
{
id = c.Id,
Name = c.Name,
hasChildren = c.CategoryChilds.Any()
});
return Json(categoriesBO, JsonRequestBehavior.AllowGet);
}
here is the cshtml file
#{
ViewBag.Title = "KendoTree";
}
<h2>KendoTree</h2>
#Html.Kendo().TreeView().Name("Categories").DataSource(dataSource => dataSource
.Read(read => read.Action("KendoTree", "CategoryManagement")
)).DataTextField("Name")
The browser display the Json result(an array) on behalf of the tree.
Am I missing something?
I got it: I have to have a Controller action that returns a view then call the kendo Html helper from inside the related view.
I'm trying to find an example of a Kendo Grid MVC server wrapper using a Web API 2 controller and not having much luck. Is there a way to use those server wrappers with the controller generated by VS using "Add" -> "Controller" -> "Web API 2 Controller with actions, using Entity Framework?" Does using async controller actions affect this?
I've looked at the tutorials at Telerik (http://docs.telerik.com/kendo-ui/tutorials/asp.net/asp-net-hello-services) and at the sample project (http://www.telerik.com/support/code-library/binding-to-a-web-apicontroller-6cdc432b8326), but neither of those are using the new Web API 2 controllers that VS can automatically generate.
I'd prefer to be able to use the VS generated controllers, but my skills are apparently not up to adapting the existing examples to them (this is my first project with MVC/Web API). Has anyone else done this or should I just write controllers like in those two-year-old examples?
ETA: Just to include the starting point I've currently got:
I created models using EF Code First from database. The simple one I'm using to test this with is this one:
namespace TestProject.Models
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
[Table("TP.Industry")]
public partial class Industry
{
public Industry()
{
Companies = new HashSet<Company>();
}
public int IndustryId { get; set; }
public int IndustryCode { get; set; }
[Required]
[StringLength(150)]
public string IndustryName { get; set; }
public virtual ICollection<Company> Companies { get; set; }
}
}
I then created controllers using the "Web API 2 Controller with actions, using Entity Framework" option and checked "Use async controller actions" to get the following controller for that model:
using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Description;
using TestProject.Models;
namespace TestProject.Controllers
{
public class IndustryController : ApiController
{
private TestProjectContext db = new TestProjectContext();
// GET api/Industry
public IQueryable<Industry> GetIndustries()
{
return db.Industries;
}
// GET api/Industry/5
[ResponseType(typeof(Industry))]
public async Task<IHttpActionResult> GetIndustry(int id)
{
Industry industry = await db.Industries.FindAsync(id);
if (industry == null)
{
return NotFound();
}
return Ok(industry);
}
// PUT api/Industry/5
public async Task<IHttpActionResult> PutIndustry(int id, Industry industry)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (id != industry.IndustryId)
{
return BadRequest();
}
db.Entry(industry).State = EntityState.Modified;
try
{
await db.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!IndustryExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return StatusCode(HttpStatusCode.NoContent);
}
// POST api/Industry
[ResponseType(typeof(Industry))]
public async Task<IHttpActionResult> PostIndustry(Industry industry)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.Industries.Add(industry);
await db.SaveChangesAsync();
return CreatedAtRoute("DefaultApi", new { id = industry.IndustryId }, industry);
}
// DELETE api/Industry/5
[ResponseType(typeof(Industry))]
public async Task<IHttpActionResult> DeleteIndustry(int id)
{
Industry industry = await db.Industries.FindAsync(id);
if (industry == null)
{
return NotFound();
}
db.Industries.Remove(industry);
await db.SaveChangesAsync();
return Ok(industry);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
private bool IndustryExists(int id)
{
return db.Industries.Count(e => e.IndustryId == id) > 0;
}
}
}
Finally, I put the following Kendo UI MVC wrapper code in my view for the grid:
#(Html.Kendo().Grid<TestProject.Models.Industry>()
.Name("Grid")
.Columns(columns =>
{
columns.Bound(c => c.IndustryId);
columns.Bound(c => c.IndustryCode);
columns.Bound(c => c.IndustryName);
columns.Command(c =>
{
c.Edit();
c.Destroy();
});
})
.ToolBar(tools =>
{
tools.Create();
})
.Sortable()
.Pageable(pageable => pageable
.Refresh(true)
.PageSizes(true)
.ButtonCount(5))
.Filterable()
.DataSource(dataSource => dataSource
.Ajax()
.Model(model =>
{
model.Id(c => c.IndustryId);
})
.Read(read => read.Url("../api/Industry").Type(HttpVerbs.Get))
.Create(create => create.Url("../api/Industry").Type(HttpVerbs.Post))
.Update(update => update.Url("../api/Industry").Type(HttpVerbs.Put))
.Destroy(destroy => destroy.Url("../api/Industry").Type(HttpVerbs.Delete))
)
)
<script>
$(function () {
var grid = $("#Grid").data("kendoGrid");
// WebAPI needs the ID of the entity to be part of the URL e.g. PUT /api/Product/80
grid.dataSource.transport.options.update.url = function (data) {
return "api/Industry/" + data.IndustryId;
}
// WebAPI needs the ID of the entity to be part of the URL e.g. DELETE /api/Product/80
grid.dataSource.transport.options.destroy.url = function (data) {
return "api/Industry/" + data.IndustryId;
}
});
</script>
The grid returns no data and request for the api returns this 500 Internal Server Error:
This XML file does not appear to have any style information associated with it. The document tree is shown below.
<Error>
<Message>An error has occurred.</Message>
<ExceptionMessage>
The 'ObjectContent`1' type failed to serialize the response body for content type 'application/xml; charset=utf-8'.
</ExceptionMessage>
<ExceptionType>System.InvalidOperationException</ExceptionType>
<StackTrace/>
<InnerException>
<Message>An error has occurred.</Message>
<ExceptionMessage>
Type 'System.Data.Entity.DynamicProxies.Industry_5BBD811C8CEC2A7DB96D23BD05DB137D072FDCC62C2E0039D219F269651E59AF' with data contract name 'Industry_5BBD811C8CEC2A7DB96D23BD05DB137D072FDCC62C2E0039D219F269651E59AF:http://schemas.datacontract.org/2004/07/System.Data.Entity.DynamicProxies' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.
</ExceptionMessage>
<ExceptionType>
System.Runtime.Serialization.SerializationException
</ExceptionType>
<StackTrace>
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeAndVerifyType(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, Boolean verifyKnownType, RuntimeTypeHandle declaredTypeHandle, Type declaredType) at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithXsiTypeAtTopLevel(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle originalDeclaredTypeHandle, Type graphType) at System.Runtime.Serialization.DataContractSerializer.InternalWriteObjectContent(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver) at System.Runtime.Serialization.DataContractSerializer.InternalWriteObject(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver) at System.Runtime.Serialization.XmlObjectSerializer.WriteObjectHandleExceptions(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver) at System.Runtime.Serialization.XmlObjectSerializer.WriteObjectHandleExceptions(XmlWriterDelegator writer, Object graph) at System.Runtime.Serialization.DataContractSerializer.WriteObject(XmlWriter writer, Object graph) at System.Net.Http.Formatting.XmlMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, HttpContent content) at System.Net.Http.Formatting.XmlMediaTypeFormatter.WriteToStreamAsync(Type type, Object value, Stream writeStream, HttpContent content, TransportContext transportContext, CancellationToken cancellationToken) --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at System.Web.Http.WebHost.HttpControllerHandler.<WriteBufferedResponseContentAsync>d__1b.MoveNext()
</StackTrace>
</InnerException>
</Error>
In fact, if I just scaffold a view on that model, like this:
#model IEnumerable<TestProject.Models.Industry>
#{
ViewBag.Title = "Industries";
}
<h2>Industries</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.IndustryCode)
</th>
<th>
#Html.DisplayNameFor(model => model.IndustryName)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.IndustryCode)
</td>
<td>
#Html.DisplayFor(modelItem => item.IndustryName)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.IndustryId }) |
#Html.ActionLink("Details", "Details", new { id=item.IndustryId }) |
#Html.ActionLink("Delete", "Delete", new { id=item.IndustryId })
</td>
</tr>
}
</table>
The "#foreach (var item in Model) {" line generates a "NullReferenceException: Object reference not set to an instance of an object." error.
It seems like even if the Kendo part wasn't right, at the very least all of the VS generated code should work correctly and it doesn't seem to be.
So, based on my research so far, there just don't seem to be any examples of using the Kendo MVC wrappers with Web API 2 controllers with async actions.
However, there now seems to be a Web API Editing section in the Kendo UI Getting Started docs (that I swear wasn't there before) that has a more up to date example that doesn't rely on adding the DataSourceRequestModelBinder.cs file to the project.
The controller setup is basically like the previous examples, but the .DataSource on the grid wrapper now looks like this:
.DataSource(dataSource => dataSource
.WebApi()
.Model(model =>
{
model.Id(i => i.IndustryId);
model.Field(i => i.IndustryId).Editable(false);
})
.Create(create => create.Url(Url.HttpRouteUrl("DefaultApi", new { controller = "Industries" })))
.Read(read => read.Url(Url.HttpRouteUrl("DefaultApi", new { controller = "Industries" })))
.Update(update => update.Url(Url.HttpRouteUrl("DefaultApi", new { controller = "Industries", id = "{0}" })))
.Destroy(destroy => destroy.Url(Url.HttpRouteUrl("DefaultApi", new { controller = "Industries", id = "{0}" })))
)
That .WebApi() method just wasn't showing up in any of my searches. This seems to work though, so I'm going to run with it. Thanks, all!
Here you can find a repository with more examples regarding the MVC technology. There should be an example that you are searching for.
I want to check if username already exists in database using telerik mvc grid (batch edit). But The problem is in order to validate it, I need to pass applconst_id as a parameter in CheckDuplicateType function. But it always return "undefined", I don't know how to get the right value.
this is my model class:
public class masterTypeCont
{
[Key]
public Int32 applconst_id { get; set; }
[Required(ErrorMessage = "This field needs a value!")]
[Remote("CheckDuplicateType",
"Type",
AdditionalFields = "applconst_id",
ErrorMessage = "Code already exists.")]
public String note1 { get; set; }
}
and this is my controller:
[HttpGet]
public virtual JsonResult CheckDuplicateType(masterTypeCont tipe, String applconst_id)
{
Int32 intID = Convert.ToInt32(applconst_id);
return Json(typeEnt.ValidateCustomer(intID, tipe.note1), JsonRequestBehavior.AllowGet);
}
And this is ValidateCustomer function:
public bool ValidateCustomer(Int32 id, String nama) {
Int32 x = db.appl_const.Where(a =>
a.group_id == "CH_COMP_CODE" &&
a.note1.Trim() == nama.Trim() &&
a.applconst_id != id).Count();
Boolean res = x == 0 ? true : false;
return res;
}
This is my view:
#{
ViewBag.Title = "Type List";
Layout = "../Shared/_Layout.cshtml";
}
<div class="direct-content">
#using (Html.BeginForm())
{
#(Html.Telerik().Grid<ComplaintHandling.Models.masterTypeCont>()
.Name("TypeGrid")
.Localizable("id-ID")
.ToolBar(commands =>
{
commands.Insert();
commands.SubmitChanges();
})
.DataKeys(keys => keys
.Add(o => o.applconst_id)
.RouteKey("applconst_id"))
.DataBinding(dataBinding =>
{
dataBinding.Ajax()
.Select("_SelectAllType", "Type")
.Update("_SaveBatchType", "Type");
})
.Columns(columns =>
{
columns.Bound(o => o.applconst_id).Hidden();
columns.Bound(o => o.note1).Title("Name");
columns.Command(commands =>
{
commands.Delete().ButtonType(GridButtonType.Text);
}).Title("Command");
})
.ClientEvents(events => events
.OnEdit("OnEditGrid")
)
.Editable(editing => editing.Mode(GridEditMode.InCell))
.Selectable()
.Pageable(pager => pager.PageSize(15))
.Filterable()
.Sortable()
.Scrollable(x => x.Height("450px"))
.KeyboardNavigation()
.Resizable(x => x.Columns(true))
)
<input type="hidden" name="applconst_id" id="applconst_id" value="1">
}
</div>
I write hidden input there to contains the applconst_id, but still it value doesn't passed to controller.
Sorry for my bad english.
Any help will be deeply appreciated.
Thanks.
Try like this:
[HttpGet]
public virtual ActionResult CheckDuplicateType(masterTypeCont tipe)
{
var result = typeEnt.ValidateCustomer(tipe.applconst_id, tipe.note1);
return Json(result, JsonRequestBehavior.AllowGet);
}
Thanks for the answers before.
After doing some research, I finally found solution for my own problem.
I create a little trick there, maybe this isn't a good way, but at least it can solve my problem.
Basically, I just play with the name attribute of an element so that it value can be passed to controller.
Here, I will explain in detail how I've done this.
First, I changed Grid columns in my View to be like this:
Please concern on applconst_id hidden field. I add client template there.
columns.Bound(o => o.applconst_id).Hidden()
.ClientTemplate("<input class='typeID' name='common_id' value='<#= applconst_id #>'>");
columns.Bound(o => o.note1).Title("Nature of complaint");
Second, I add this code in "onEdit" function:
//this code change ID that is being edited, so that it can be passed to controller
var $inputID = $('.t-grid-edit-cell').prev().find('.typeID');
$inputID.attr('name', 'applconst_id');
//change back ID that is not being edited, so that it's not passed to controller
$('td:not(.t-grid-edit-cell)').prev().find('.typeID').attr('name','common_id');
Third, this is my controller:
[HttpGet]
public JsonResult CheckDuplicateType(String applconst_id, String note1)
{
Int32 IntID = Convert.ToInt32(applconst_id);
return Json(typeEnt.ValidateCustomer(IntID, note1), JsonRequestBehavior.AllowGet);
}
And my "ValidateCustomer" function stay the same.
I hope my solution can help other people who have the same problem with me.
Thanks.
Regards,
L.W.
What I'm attempting to do is have a "Super" entity class for saved products. Depending on where the product is in the application, certain extra attributes are necessary (but not always).
For example, when the product is being used within a grid, I want to have a ViewModel that derives from the Entity (inheriting all of the common fields) and then add a unique identifier attribute like "rowNumber" for easy searching by the kendo ui grid CRUD.
I thought I had all of this working, but I've hit a snag... Everything renders fine and operates correctly until I click "save" for the batch grid. It executes the function and all the data is present, but when it returns from the CRUD, it breaks. In firebug, I see that an exception is being thrown, but it never finishes (the ajax spinner stays there) and all information within the exception is empty...
I'm not sure if this is some issue with c# not playing well with CSLA or not. I'm unsure.
Any help would be appreciated! I can't upload images because my rep isn't high enough or else I would put a picture of the exception, but I'll at least put what appears in the Firebug console. Everything else about it is empty though...
Exception with endless execution and no response:
GET http://localhost:32574/Exception/SystemException/00000000-0000-0000-0000-000000000000
Entity:
This file is auto-generated by a CodeSmith template so it is kind of nonsensical, but it holds field values that appear in the view (see below). The exception to what is on the view vs what is in the entity are fields that are not 'flattened' in the entity, as Kendo UI does not currently support this inside of editable grids.
ViewModel:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
namespace Project.MVC.Models
{
//The MetaData Class is where to put all annotations and validations
[MetadataType(typeof(Project.Business.Shipment.ItemMetaDataClass))]
public class ItemModel : Project.Business.Shipment.Item
{
public ItemModel()
{
}
public long rowNumber { get; set; }
public decimal Length { get; set; }
public decimal Width { get; set; }
public decimal Height { get; set; }
[Display(Name = "UoMDim")]
[UIHint("ItemGrid_RefUnitOfMeasurementListingDimension")]
public string DimensionUnitOfMeasure { get; set; }
[Display(Name = "UoMW")]
[UIHint("ItemGrid_RefUnitOfMeasurementListingWeight")]
public string WeightUnitOfMeasure { get; set; }
[Display(Name = "Weight")]
public decimal WeightValue { get; set; }
[Display(Name = "Type")]
[UIHint("ItemGrid_RefUnitTypeListing")]
public string QuantityUnitOfMeasure { get; set; }
[Display(Name = "Units")]
public decimal QuantityValue { get; set; }
}
}
Grid Controller:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Kendo.Mvc.UI;
using Kendo.Mvc.Extensions;
namespace Project.MVC.Controllers
{
[Authorize]
public class ItemGridController : Csla.Web.Mvc.Controller
{
public ActionResult GetProducts([DataSourceRequest]DataSourceRequest request)
{
Project.MVC.Models.ShipmentModel shipmentModel = (Project.MVC.Models.ShipmentModel)ControllerBase.State.Object;
return Json(shipmentModel.ItemModelList.ToDataSourceResult(request));
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult CreateProducts([DataSourceRequest]DataSourceRequest request, [Bind(Prefix = "models")]IEnumerable<Models.ItemModel> itemsToAdd)
{
Project.MVC.Models.ShipmentModel shipmentModel = (Project.MVC.Models.ShipmentModel)ControllerBase.State.Object;
var results = new List<Models.ItemModel>();
if (ModelState.IsValid)
{
foreach (Models.ItemModel newItem in itemsToAdd)
{
if (shipmentModel.ItemModelList.Count > 0)
{
var nextID = (from i in shipmentModel.ItemModelList
select i.rowNumber).Max() + 1;
newItem.rowNumber = nextID;
}
shipmentModel.ItemModelList.Add(newItem);
results.Add(newItem);
}
}
return Json(results.ToDataSourceResult(request, ModelState));
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult UpdateProducts([DataSourceRequest]DataSourceRequest request, [Bind(Prefix = "models")]IEnumerable<Models.ItemModel> itemsToUpdate)
{
Project.MVC.Models.ShipmentModel shipmentModel = (Project.MVC.Models.ShipmentModel)ControllerBase.State.Object;
var results = new List<Models.ItemModel>();
foreach (var item in itemsToUpdate)
{
Models.ItemModel target = shipmentModel.ItemModelList.Find(i => i.rowNumber == item.rowNumber);
if (target != null)
{
target = item;
}
}
return Json(ModelState.ToDataSourceResult());
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult DeleteProducts([DataSourceRequest]DataSourceRequest request, [Bind(Prefix = "models")]IEnumerable<Models.ItemModel> itemsToDelete)
{
Project.MVC.Models.ShipmentModel shipmentModel = (Project.MVC.Models.ShipmentModel)ControllerBase.State.Object;
foreach (var item in itemsToDelete)
{
shipmentModel.ItemModelList.Remove(item);
}
return Json(ModelState.ToDataSourceResult());
}
}
}
View:
#model Project.MVC.Models.ShipmentModel
#using Kendo.Mvc.UI
#(Html.Kendo().Grid<Project.MVC.Models.ItemModel>()
.Name("QuoteItemGrid")
.Columns(columns =>
{
columns.Bound(i => i.FreightClass)
.EditorTemplateName("ItemGrid_RefFreightClassListing")
.Width(50);
columns.Bound(i => i.Length).Width(30);
columns.Bound(i => i.Width).Width(30);
columns.Bound(i => i.Height).Width(30);
columns.Bound(i => i.DimensionUnitOfMeasure)
.EditorTemplateName("ItemGrid_RefUnitOfMeasurementListingDimension")
.Width(50);
columns.Bound(i => i.QuantityValue).Width(30);
columns.Bound(i => i.QuantityUnitOfMeasure)
.EditorTemplateName("ItemGrid_RefUnitTypeListing")
.Width(50);
columns.Bound(i => i.WeightValue).Width(30);
columns.Bound(i => i.WeightUnitOfMeasure)
.EditorTemplateName("ItemGrid_RefUnitOfMeasurementListingWeight")
.Width(50);
columns.Bound(i => i.NmfcCode).Width(50);
columns.Bound(i => i.ItemDescription).Width(100);
columns.Command(command =>
{
command.Destroy();
}).Width(60);
})
.ToolBar(toolbar =>
{
toolbar.Create();
toolbar.Save();
})
.Editable(editable => editable.Mode(GridEditMode.InCell).CreateAt(GridInsertRowPosition.Bottom))
.Pageable()
.Sortable()
.Scrollable()
.Resizable(resize => resize.Columns(true))
.DataSource(dataSource => dataSource
.Ajax()
.Batch(true)
.ServerOperation(false)
.Events(events => events.Error("QuoteItemGrid_ErrorHandler"))
.Model(model =>
{
model.Id(i => i.rowNumber);
model.Field(i => i.DimensionUnitOfMeasure).DefaultValue("in");
model.Field(i => i.WeightUnitOfMeasure).DefaultValue("lbs");
})
.Create(create => create.Action("CreateProducts", "ItemGrid"))
.Read(read => read.Action("GetProducts", "ItemGrid"))
.Update(update => update.Action("UpdateProducts", "ItemGrid"))
.Destroy(destroy => destroy.Action("DeleteProducts", "ItemGrid"))
)
)
I agree entirely. Ideally your CSLA .NET based objects are domain objects, not data objects, and so match the shape needed by the business requirements not by database tables or queries.
Sadly a lot of people end up (mis)using CSLA like an ORM and so have data-centric objects, thus missing a lot of the value of the framework, and necessitating the creation and maintenance of overly complex viewmodel types in addition to what (should have been) business types.
From an architectural perspective, my group ultimately thought it unwise to tie our database generated entities so closely to our view. Especially now that the project is being used in multiple places (.Net application, Webservices application, etc...).
So, in the end we ended up creating ViewModels for each entity so that we could be flexible with our entities across multiple platforms. This restructuring removed the issue above, as the entities are now never present within the view.
word of caution however: If you're using Kendo UI, you'll have to 'flatten' your view models that you want presented within a singular component that are deep objects (e.g. object within another object). At the moment, Kendo does not support this. We are using ValueInjecter.
Hopefully, this information will help someone else too.
I have been using Telerik controls, I was using server binding, but I have to use Ajax binding, that is not working properly, I am getting Error "Error! The requested URL did not return JSON asp.net mvc"
Following is the Code in My Controller
[GridAction]
[Authorize(Roles = "Admin")]
public ActionResult Edit(int id)
{
Contact model = _cService.getContact(id, applicationID);
GetContactType();
if (model != null)
return View(model);
else
return View();
}
//
// POST: /Contact/Edit/5
[GridAction]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(int id, Contact model)
{
try
{
_cService.SaveContact(model, applicationID);
return RedirectToAction("Index");
}
catch
{
return View(model);
}
}
and following Code in my view
#(Html.Telerik().Grid(Model)
.Name("Contact")
// .ToolBar(commands => commands.Insert())
.DataKeys(keys => keys.Add(c => c.Id))
.DataBinding(dataBinding =>
{
dataBinding.Ajax()
.Update("Edit", "Contact", new { mode = GridEditMode.InForm, type = GridButtonType.Text })
.Delete("Delete", "Contact", new { mode = GridEditMode.InLine, type = GridButtonType.Text });
})
What I can do this Error, this error arise using Alert box, I have tried Modifying telerik.grid.min.js I have removed the line that shows an alert box,then it does not shows me error but also does not work.
Can somebody please give me Some suggestions.
Thank You
This is not a prompt response but as I'm addressing this issue now I can answer it. This is likely caused by the fact that your session has timed out, resulting in IIS to redirect to your login page. As it's the login page which is being returned, not the expected JSON, you get this message. You can trap for this error as follows:
var checkForSessionTimeout = function (e) {
logOnResponse = e.XMLHttpRequest.responseText.match(/.*<title.*>(Log On)<\/title>.*/);
if (logOnResponse.length > 0 || e.XMLHttpRequest.status === 401) {
alert("Your session has expired. You will be redirected to log on.");
location.href = logOnUrl;
}
}
Of course, you'll have to define logOnUrl to point to your page.
A follow on question, should you have found the answer on your own, any idea how to prevent the actual error alert since we're providing our own?