The requested page is not available for the requested platform. You are viewing the content for Default platform.

Data Binding

All DevExtreme ASP.NET MVC controls that operate with data collections have the DataSource() method. Unlike other control methods, DataSource() do not have a direct counterpart in the DevExtreme JavaScript API, although its purpose resembles that of the Stores in the DevExtreme Data Layer. You can use the DataSource() method to configure data access from different sources.

Data-bound controls (except PivotGrid) also have the DataSourceOptions() method. It exposes a builder that configures initial sorting, filtering, grouping, and other data shaping operations. The builder's methods have JavaScript API counterparts described in this section.

Static Collections

A static collection is serialized to JSON and embedded into a control's configuration.

@(Html.DevExtreme().SelectBox()
    .DataSource(new[] { "red", "green", "blue" })
)

View Demo

ASP.NET MVC and Web API Controllers

Note

In Visual Studio, you can generate a scaffolded controller. Refer to the Scaffold API Controller article for details.

MVC 5 Controller

Access to MVC controllers is configured using the Mvc() method the DataSource()'s lambda parameter exposes. The following example shows the DataGrid control accessing a GridDataController whose actions (GetOrders, InsertOrder, UpdateOrder, and DeleteOrder) implement CRUD operations:

@(Html.DevExtreme().DataGrid()
    .DataSource(ds => ds
        .Mvc()
        .Controller("GridData")
        .Key("OrderID")
        .LoadAction("GetOrders")
        .InsertAction("InsertOrder")
        .UpdateAction("UpdateOrder")
        .DeleteAction("DeleteOrder")
    )
)

The code below illustrates the GridDataController. CRUD operations are performed on the Northwind database's "Orders" collection, and the DevExtreme.AspNet.Data library facilitates writing a controller.

using System;
using System.Linq;
using System.Net;
using System.Web.Mvc;
using DevExtreme.AspNet.Data;
using DevExtreme.AspNet.Mvc;
using Newtonsoft.Json;
using ProjectName.Models;

namespace ProjectName.Controllers {

    public class GridDataController : Controller {
        NorthwindContext _nwind = new NorthwindContext();
        const string ValidationErrorMessage = "The record cannot be saved due to a validation error";

        // Fetch items from the "Orders" collection
        public ActionResult GetOrders(DataSourceLoadOptions loadOptions) {
            var result = DataSourceLoader.Load(_nwind.Orders, loadOptions);
            var resultJson = JsonConvert.SerializeObject(result);
            return Content(resultJson, "application/json");
        }

        // Insert a new item into the "Orders" collection
        public ActionResult InsertOrder(string values) {
            var newOrder = new Order();                             // Create a new item
            JsonConvert.PopulateObject(values, newOrder);           // Populate the item with the values
            if (!TryValidateModel(newOrder))                        // Validate the item
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest, ValidationErrorMessage);
            _nwind.Orders.Add(newOrder);                            // Add the item to the database
            _nwind.SaveChanges();
            return new HttpStatusCodeResult(HttpStatusCode.OK);
        }

        // Update an item in the "Orders" collection
        public ActionResult UpdateOrder(int key, string values) {
            var order = _nwind.Orders.First(o => o.OrderID == key); // Find the item to be updated by key
            JsonConvert.PopulateObject(values, order);              // Populate the found item with the changed values
            if (!TryValidateModel(order))                           // Validate the updated item
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest, ValidationErrorMessage);
            _nwind.SaveChanges();
            return new HttpStatusCodeResult(HttpStatusCode.Created);
        }

        // Remove an item from the "Orders" collection
        public void DeleteOrder(int key) {
            var order = _nwind.Orders.First(o => o.OrderID == key); // Find the item to be removed by key
            _nwind.Orders.Remove(order);                            // Remove the found item
            _nwind.SaveChanges();
        }
    }
}

Web API Controller

If you use a Web API controller in your app, use the DataSource()'s lambda parameter's WebApi() method to configure access to the controller. The WebApi() exposes the same methods as Mvc() to specify the controller and action names, but with one addition: you can pass true to the UpdateAction, InsertAction, and DeleteAction methods for routing based on Http[Verb] attributes.

@(Html.DevExtreme().DataGrid()
    .DataSource(ds => ds
        .WebApi()
        .Controller("GridDataWebApi")
        .Key("OrderID")
        .UpdateAction(true)
        .InsertAction(true)
        .DeleteAction(true)
    )
)

The controller looks like this:

using System;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using DevExtreme.AspNet.Data;
using DevExtreme.AspNet.Mvc;
using System.Net.Http.Formatting;
using Newtonsoft.Json;
using ProjectName.Models;

namespace ProjectName.Controllers {

    public class GridDataWebApiController : ApiController {
        NorthwindContext _nwind = new NorthwindContext();
        const string ValidationErrorMessage = "The record cannot be saved due to a validation error";

        [HttpGet] // Fetch items from the "Orders" collection
        public HttpResponseMessage Get(DataSourceLoadOptions loadOptions) {
            return Request.CreateResponse(DataSourceLoader.Load(_nwind.Orders, loadOptions));
        }

        [HttpPost] // Insert a new item into the "Orders" collection
        public HttpResponseMessage Post(FormDataCollection form) {
            var values = form.Get("values");                        // Get JSON-formatted values for the new item
            var newOrder = new Order();                             // Create the new item
            JsonConvert.PopulateObject(values, newOrder);           // Populate the item with values
            Validate(newOrder);                                     // Validate the item
            if(!ModelState.IsValid)
                return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ValidationErrorMessage);
            _nwind.Orders.Add(newOrder);                            // Add the item to the database
            _nwind.SaveChanges();
            return Request.CreateResponse(HttpStatusCode.Created);
        }

        [HttpPut] // Update an item in the "Orders" collection
        public HttpResponseMessage Put(FormDataCollection form) {
            var key = Convert.ToInt32(form.Get("key"));             // Get the key of the item to be updated
            var values = form.Get("values");                        // and changed values for this item
            var order = _nwind.Orders.First(o => o.OrderID == key);  // Find the item to be updated by key
            JsonConvert.PopulateObject(values, order);              // Populate the found item with the changed values
            Validate(order);                                        // Validate the updated item
            if(!ModelState.IsValid)
                return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ValidationErrorMessage);
            _nwind.SaveChanges();
            return Request.CreateResponse(HttpStatusCode.OK);
        }

        [HttpDelete] // Remove an item from the "Orders" collection
        public void Delete(FormDataCollection form) {
            var key = Convert.ToInt32(form.Get("key"));             // Get the key of the item to be removed
            var order = _nwind.Orders.First(o => o.OrderID == key);  // Find the item to be removed by key
            _nwind.Orders.Remove(order);                            // Remove the found item
            _nwind.SaveChanges();
        }
    }
}

View Demo

Controller on a Different Site

Previous examples show use-cases in which a control is on the same site as the data it accesses, and routing finds the right controller and actions. If the data is on a different site, you can use the URL to access it via the RemoteController() method of the DataSource()'s lambda parameter. This method opens a chain whose members mirror the client-side method fields in the DevExtreme.AspNet.Data library.

@(Html.DevExtreme().DataGrid()
    .DataSource(ds => ds
        .RemoteController()
        .Key("OrderID")
        .LoadUrl("http://www.example.com/Orders/GetOrders")
        .InsertUrl("http://www.example.com/Orders/InsertOrder")
        .UpdateUrl("http://www.example.com/Orders/UpdateOrder")
        .DeleteUrl("http://www.example.com/Orders/DeleteOrder")
    )
)

Controller in a Different Area

In an app organized into areas, a control from a view that belongs to one area may need to access a data controller that belongs to another. Use the Area() method to specify the data controller's area in this case.

@(Html.DevExtreme().DataGrid()
    .DataSource(ds => ds
        .Mvc()
        .Area("DifferentArea")
        // ...
    )
)

Pass Additional Load Parameters

DevExtreme ASP.NET MVC controls internally transform your Razor code into HTML and JavaScript. However, you cannot use Razor to pass load parameters. Instead, you need to access JavaScript variables directly.

The following code example implements the master-detail interface in the DataGrid control. This interface is a grid inside a grid. The inner grid filters its data source according to the master row key. The API reference states that the master row key and data are available in the master-detail template through the key and data JavaScript variables. Only the key's value is needed for the master-detail, and it is accessed using the new JS() construction. This construction inserts JavaScript expressions passed to it to the resulting JavaScript code.

@(Html.DevExtreme().DataGrid()
    .DataSource(d => d.MVC().Controller("Employees").Key("ID"))
    .Columns(columns => {
        columns.Add().DataField("FirstName");
        columns.Add().DataField("LastName");
        // ...
    })
    .MasterDetail(md => md
        .Enabled(true)
        .Template(@<text>
            @(Html.DevExtreme().DataGrid()
                .DataSource(d => d.MVC()
                    .Controller("Employees")
                    .LoadAction("TasksDetails")
                    .LoadParams(new { id = new JS("key") })
                )
            )
        </text>)
    )
)

If the control is not in a template and no variables are provided, you can use a JavaScript function accessed with the same new JS() construct to get data for a load parameter. In the following code, the DataGrid control uses the getDateBoxValue() function to get a value for the orderDate load parameter from the DateBox control. The refreshGrid() function is called each time the DateBox value changes. This function calls the DataGrid's refresh() method that makes a new load query with the updated load parameter.

@(Html.DevExtreme().DateBox()
    .ID("orderDate")
    .Type(DateBoxType.Date)
    .Value(DateTime.Now)
    .OnValueChanged("refreshGrid")
)

@(Html.DevExtreme().DataGrid()
    .ID("targetDataGrid")
    .DataSource(ds => ds.MVC()
        .Controller("Orders")
        .LoadAction("GetOrdersByDate")
        .LoadParams(new { orderDate = new JS("getDateBoxValue") })
    )
    .Columns(cols => {
        cols.Add().DataField("OrderID");
        cols.Add().DataField("OrderDate");
        // ...
    })
)

<script type="text/javascript">
    function getDateBoxValue () {
        return $("#orderDate").dxDateBox("option", "text");
    }

    function refreshGrid() {
        $("#targetDataGrid").dxDataGrid("refresh");
    }
</script>

Read-Only Data in JSON Format

A server-side control can access JSON data returned from a resource by an AJAX request. For this purpose, the lambda parameter of the DataSource() method exposes the StaticJson() method. It opens a chain of methods configuring access to JSON data.

@(Html.DevExtreme().SelectBox()
    .DataSource(ds => ds
        .StaticJson()
        .Url("http://www.example.com/dataservices/jsondata")
        .Key("ID")
        .CacheAllData(true) // loads all data at once and saves it in cache; true by default
    )
)

In the previous code, the Url() method accepts the absolute URL. However, this method can also accept virtual paths:

@(Html.DevExtreme().SelectBox()
    .DataSource(ds => ds
        .StaticJson()
        .Url(@Url.Content("~/dataservices/jsondata"))
    )
)

You can also use a JSONP callback parameter supported by jQuery.ajax().

@(Html.DevExtreme().SelectBox()
    .DataSource(ds => ds
        .StaticJson()
        .Url("http://www.example.com/dataservices/jsonpdata?callback=?")
    )
)

In addition, the DataSource() method has several overloads. You can use them to configure access to JSON data, for example, specify the data's URL...

@(Html.DevExtreme().SelectBox()
    .DataSource("http://www.example.com/dataservices/jsondata")
)

... or the URL and the key field.

@(Html.DevExtreme().SelectBox()
    .DataSource("http://www.example.com/dataservices/jsondata", "ID")
)

OData

DevExtreme ASP.NET MVC controls can also operate with an OData service out of the box. To address an OData service, call the DataSource() method and pass a lambda expression to it. The lambda parameter exposes the OData() method that configures access to the OData service.

@(Html.DevExtreme().DataGrid()
    .DataSource(ds => ds
        .OData()
        .Version(4)
        .Url("http://services.odata.org/V4/Northwind/Northwind.svc/Products")
        .JSONP(true)
        .Key("ProductID")
        .Expand("Category")
    )
)

View Demo

OLAP Cube

An OLAP cube is a multi-dimensional dataset that allows data mining and analysis. DevExtreme provides the PivotGrid control to display data from an OLAP cube. You can call the DataSource() method as shown in the following code to access the OLAP cube. The lambda expression passed to this method configures the XmlaStore data store.

@(Html.DevExtreme().PivotGrid()
    .DataSource(ds => ds
        .Store(s => s.Xmla()
            .Url("http://my-web-srv01/OLAP/msmdpump.dll")
            .Catalog("AdventureWorksDW2012")
            .Cube("Adventure Works")
        )
    )
)

View Demo

Refresh Data

Use the JavaScript API to refresh server-side controls' data. Any data-bound control has the getDataSource() method. It returns the control's DataSource instance. Call its reload() method to refresh the control's data, as shown in the following DataGrid example:

@(Html.DevExtreme().DataGrid()
    .ID("targetDataGrid")
    .DataSource(ds => ds.Mvc()
        .Controller("GridData")
        .Key("OrderID")
        .LoadAction("GetOrders")
        .InsertAction("InsertOrder")
        .UpdateAction("UpdateOrder")
        .DeleteAction("DeleteOrder")
    )
)

@(Html.DevExtreme().Button()
    .Text("Refresh Grid")
    .OnClick("reloadData")
)

<script type="text/javascript">
    function reloadData() {
        $("#targetDataGrid").dxDataGrid("getDataSource").reload();
    }
</script>