--- title: Custom DataSource page_title: Custom DataSource | Telerik UI for ASP.NET MVC description: "Use the CustomDataSource builder available for the Telerik UI for ASP.NET MVC HtmlHelpers." slug: customdatasource_aspnetmvc previous_url: /custom-datasource position: 5 --- # Custom DataSource This article provides information on how to use the CustomDataSource builder available for the Telerik UI for ASP.NET MVC HtmlHelpers that support DataSource. ## Getting Started ### The Basics The CustomDataSource builder is created to allow a full control over the DataSource options listed in the [client-side API](http://docs.telerik.com/kendo-ui/api/javascript/data/datasource). By applying the CustomDataSource builder, you benefit from using the MVC wrappers. For example, the wrappers are enabled to generate validation attributes, editors, etc., while utilizing the flexibility of JavaScript. The CustomDataSource builder can also be used in more advanced scenarios where the regular DataSource builders prevent you from fully customizing the options of the DataSource. ### Initial Setup Using the CustomDataSource builder, even for small customizations, requires additional attention as all predefined settings, introduced by the regular DataSource builders, are removed. The example below demonstrates how to convert a regular [Grid](http://demos.telerik.com/kendo-ui/grid/index) AjaxDataSourceBuilder to a CustomDataSource builder. ###### Example @(Html.Kendo().Grid() .Name("grid") .DataSource(dataSource => dataSource .Ajax() .ServerOperation(true) .Model(model => { model.Id(p => p.OrderID); model.Field(p => p.OrderID).Editable(false); }) .Read(read => read.Action("Read", "Home")) ) ) The example below demonstrates how the CustomDataSourceBuilder equivalent. ###### Example @(Html.Kendo().Grid() .Name("grid") .DataSource(dataSource => dataSource .Custom() .Type("aspnetmvc-ajax") .PageSize(10) .ServerPaging(true) .ServerSorting(true) .ServerFiltering(true) .Transport(transport => transport .Read(read => read.Action("Read", "Home")) ) .Schema(schema => schema .Data("Data") .Total("Total") .Errors("Errors") .Parse(@function (data) { // configure a parse function only if the response (data) must be // transformed in some way before data binding return data; }) .Model(model => { model.Id("OrderID"); model.Field("OrderID", typeof(int)); model.Field("OrderDate", typeof(DateTime)); model.Field("OrderDescription", typeof(string)); model.Field("IsCompleted", typeof(bool)); }) ) ) ) ## Common Scenarios ### Function and Object Setup as DataSource Objects To set a JavaScript function or object as an option for the DataSource, use the `ClientHandlerDescriptor` class. The example below demonstrates how to set a JavaScript function for the `Read` operation of the Scheduler by utilizing the `ClientHandlerDescriptor` type included in the `Kendo.Mvc` namespace. This class allows code rendering as-is, without the need of string wrapping. In this way the JavaScript functions and objects can be set to apply various options from the CustomDataSource. ###### Example @(Html.Kendo().Scheduler() .Name("scheduler") .Editable(false) .DataSource(ds => ds .Custom() .Batch(true) .Schema(schema => schema .Model(m => { m.Id(f => f.MeetingID); m.Field("title", typeof(string)).DefaultValue("No title").From("Title"); m.Field("start", typeof(DateTime)).From("Start"); m.Field("end", typeof(DateTime)).From("End"); m.Field("description", typeof(string)).From("Description"); m.Field("recurrenceID", typeof(int)).From("RecurrenceID"); m.Field("recurrenceRule", typeof(string)).From("RecurrenceRule"); m.Field("recurrenceException", typeof(string)).From("RecurrenceException"); m.Field("isAllDay", typeof(bool)).From("IsAllDay"); m.Field("startTimezone", typeof(string)).From("StartTimezone"); m.Field("endTimezone", typeof(string)).From("EndTimezone"); })) .Transport(new { //the ClientHandlerDescriptor is a special type that allows code rendering as-is (not as a string) read = new Kendo.Mvc.ClientHandlerDescriptor() {HandlerName = "customRead" } }) ) ) ### Model Fields Setup as Functions The example below demonstrates how to set the default value of the `EmployeeID` field to a JavaScript function. This is applicable in the cases where the default value should be dynamic. For instance, a case when the user inserts a new record while the `EmployeeID` column specifies a filter value different from the default one. ###### Example @(Html.Kendo().Grid() .Name("grid") .ToolBar(toolbar => toolbar.Create()) .Filterable() .DataSource(dataSource => dataSource .Custom() .Type("aspnetmvc-ajax") .PageSize(10) .ServerPaging(false) .ServerSorting(false) .ServerFiltering(false) .Transport(transport => transport .Read(read => read.Action("Read", "Home")) .Create(create => create.Action("Create", "Home")) ) .Schema(schema => schema .Data("Data") .Total("Total") .Errors("Errors") .Model(model => { model.Id("OrderID"); model.Field("OrderID", typeof(int)); model.Field("EmployeeID", typeof(int)).DefaultValue(new Kendo.Mvc.ClientHandlerDescriptor() { HandlerName = "defaultValue" }); model.Field("OrderDate", typeof(DateTime)); model.Field("OrderDescription", typeof(string)); model.Field("IsCompleted", typeof(bool)); }) ) ) ) ### Custom DataType CRUD Operations Setup The example below demonstrates how to bind the Grid to the Kendo UI online demo service that serves `jsonp` data. To see the full demo, refer to the [introductory article on Telerik UI for ASP.NET MVC]({% slug overview_aspnetmvc %}#sample-application). ###### Example @(Html.Kendo().Grid() .Name("Grid") .Columns(columns => { columns.Bound(p => p.ProductName); columns.Bound(p => p.UnitPrice).Width(140); columns.Bound(p => p.UnitsInStock).Width(140); columns.Bound(p => p.Discontinued).Width(100); columns.Command(command => command.Destroy()).Width(110); }) .ToolBar(toolbar => { toolbar.Create(); toolbar.Save(); }) .Editable(editable => editable.Mode(GridEditMode.InCell)) .Pageable() .Navigatable() .Sortable() .Scrollable() .DataSource(dataSource => dataSource .Custom() .Batch(true) .PageSize(20) .Schema(schema => schema.Model(m => m.Id(p => p.ProductID))) .Transport(transport => { transport.Read(read => read.Url("http://demos.telerik.com/kendo-ui/service/products") .DataType("jsonp") ); transport.Create(create => create.Url("http://demos.telerik.com/kendo-ui/service/products/create") .DataType("jsonp") ); transport.Update(update => update.Url("http://demos.telerik.com/kendo-ui/service/products/update") .DataType("jsonp") ); transport.Destroy(destroy => destroy.Url("http://demos.telerik.com/kendo-ui/service/products/destroy") .DataType("jsonp") ); transport.ParameterMap("parameterMap"); }) ) ) ### Grid Binding to oData The example below demonstrates how to bind the Grid to the oData service. To see the full demo, refer to the [introductory article on Telerik UI for ASP.NET MVC]({% slug overview_aspnetmvc %}#sample-application). ###### Example @(Html.Kendo().Grid() .Name("grid") .Columns(columns => { columns.Bound(e => e.OrderID).Filterable(false); columns.Bound(e => e.Freight); columns.Bound(e => e.OrderDate).Width(120).Format("{0:MM/dd/yyyy}"); columns.Bound(e => e.ShipName).Width(260); columns.Bound(e => e.ShipCity).Width(150); }) .DataSource(dataSource => dataSource .Custom() .Type("odata") .Transport(transport => transport.Read(read => read.Url("http://demos.telerik.com/kendo-ui/service/Northwind.svc/Orders")) ) .PageSize(20) .ServerPaging(true) .ServerSorting(true) .ServerFiltering(true) ) .Pageable() .Sortable() .Filterable() ) ### Grid Binding to oData v4 The example below demonstrates how to use the CustomDataSource builder to bind the Grid wrapper to oData v4 service. To see the full demo, refer to this [Grid how-to example]({% slug howto_useodata4webapicontroller_gridaspnetmvc %}). ###### Example @(Html.Kendo().Grid() .Name("products") .Columns(columns => { columns.Bound(e => e.ProductName).Width(200); columns.Bound(e => e.ProductID).Width(300); columns.Bound(e => e.UnitPrice).Width(300); columns.Command(cmd => cmd.Edit()).Width(300); }) .Scrollable() .ToolBar(tb => tb.Create()) .DataSource(dataSource => dataSource .Custom() .Schema(sch => { sch.Model(m=>{ m.Id("ProductID"); m.Field(f=>f.ProductID).Editable(false); m.Field("UnitPrice", typeof(Decimal)); }); }) .Type("odata-v4") .Transport(transport => { transport.Read(read => read.Url("/odata/Products").Data("{'$expand': 'Category'}"); }) .Events(ev => ev.RequestEnd("onRequestEnd")) .PageSize(20) .ServerPaging(true) .ServerSorting(true) .ServerFiltering(true) ) ) ## See Also * [Telerik UI for ASP.NET MVC Overview]({% slug overview_aspnetmvc %}) * [Validation with Telerik UI for ASP.NET MVC]({% slug validation_aspnetmvc %}) * [Globalization with Telerik UI for ASP.NET MVC]({% slug globalization_aspnetmvc %}) * [ASP.NET Core](http://docs.telerik.com/aspnet-core/introduction) * [Tutorials on Telerik UI for ASP.NET MVC]({% slug overview_timeefficiencyapp_aspnetmvc6 %}) * [Telerik UI for ASP.NET MVC Fundamentals]({% slug fundamentals_aspnetmvc %}) * [Scaffolding with Telerik UI for ASP.NET MVC]({% slug scaffolding_aspnetmvc %}) * [Telerik UI for ASP.NET MVC Troubleshooting]({% slug troubleshooting_aspnetmvc %})