Web API Service
To access a Web API service from the client, use the createStore method which is part of the DevExtreme.AspNet.Data extension. This extension also allows you to process data for DevExtreme components on the server. The server-side implementation is available under the SchedulerDataController.cs
tab in the ASP.NET MVC version of this demo.
Feel free to share demo-related thoughts here.
If you have technical questions, please create a support ticket in the DevExpress Support Center.
Thank you for the feedback!
If you have technical questions, please create a support ticket in the DevExpress Support Center.
Backend API
<template>
<DxScheduler
time-zone="America/Los_Angeles"
:data-source="dataSource"
:current-date="currentDate"
:views="views"
:height="600"
:start-day-hour="9"
:end-day-hour="19"
:remote-filtering="true"
current-view="day"
date-serialization-format="yyyy-MM-ddTHH:mm:ssZ"
text-expr="Text"
start-date-expr="StartDate"
end-date-expr="EndDate"
all-day-expr="AllDay"
recurrence-rule-expr="RecurrenceRule"
recurrence-exception-expr="RecurrenceException"
/>
</template>
<script>
import DxScheduler from 'devextreme-vue/scheduler';
import * as AspNetData from 'devextreme-aspnet-data-nojquery';
const url = 'https://js.devexpress.com/Demos/Mvc/api/SchedulerData';
export default {
components: {
DxScheduler,
},
data() {
return {
views: ['day', 'workWeek', 'month'],
currentDate: new Date(2021, 3, 27),
dataSource: AspNetData.createStore({
key: 'AppointmentId',
loadUrl: `${url}/Get`,
insertUrl: `${url}/Post`,
updateUrl: `${url}/Put`,
deleteUrl: `${url}/Delete`,
onBeforeSend(_, ajaxOptions) {
ajaxOptions.xhrFields = { withCredentials: true };
},
}),
};
},
};
</script>
import { createApp } from 'vue';
import App from './App.vue';
createApp(App).mount('#app');
<!DOCTYPE html>
<html>
<head>
<title>DevExtreme Demo</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<link rel="stylesheet" type="text/css" href="https://cdn3.devexpress.com/jslib/23.1.5/css/dx.light.css" />
<script src="https://unpkg.com/core-js@2.6.12/client/shim.min.js"></script>
<script src="https://unpkg.com/systemjs@0.21.3/dist/system.js"></script>
<script type="text/javascript" src="config.js"></script>
<script type="text/javascript">
System.import("./index.js");
</script>
</head>
<body class="dx-viewport">
<div class="demo-container">
<div id="app"> </div>
</div>
</body>
</html>
window.exports = window.exports || {};
window.config = {
transpiler: 'plugin-babel',
meta: {
'*.vue': {
loader: 'vue-loader',
},
'*.ts': {
loader: 'demo-ts-loader',
},
'*.svg': {
loader: 'svg-loader',
},
'devextreme/localization.js': {
'esModule': true,
},
'devextreme-aspnet-data-nojquery': {
'esModule': true,
},
},
paths: {
'root:': '../../../../../',
'npm:': 'https://unpkg.com/',
},
map: {
'vue': 'npm:vue@3.3.4/dist/vue.esm-browser.js',
'vue-loader': 'npm:dx-systemjs-vue-browser@1.1.1/index.js',
'demo-ts-loader': 'root:utils/demo-ts-loader.js',
'svg-loader': 'root:utils/svg-loader.js',
'devextreme-aspnet-data-nojquery': 'npm:devextreme-aspnet-data-nojquery@2.9.0/index.js',
'mitt': 'npm:mitt/dist/mitt.umd.js',
'rrule': 'npm:rrule@2.6.4/dist/es5/rrule.js',
'luxon': 'npm:luxon@1.28.1/build/global/luxon.min.js',
'es6-object-assign': 'npm:es6-object-assign@1.1.0',
'devextreme': 'npm:devextreme@23.1.6/cjs',
'devextreme-vue': 'npm:devextreme-vue@23.1.6',
'jszip': 'npm:jszip@3.7.1/dist/jszip.min.js',
'devextreme-quill': 'npm:devextreme-quill@1.6.2/dist/dx-quill.min.js',
'devexpress-diagram': 'npm:devexpress-diagram@2.2.2/dist/dx-diagram.js',
'devexpress-gantt': 'npm:devexpress-gantt@4.1.49/dist/dx-gantt.js',
'@devextreme/runtime': 'npm:@devextreme/runtime@3.0.12',
'inferno': 'npm:inferno@7.4.11/dist/inferno.min.js',
'inferno-compat': 'npm:inferno-compat/dist/inferno-compat.min.js',
'inferno-create-element': 'npm:inferno-create-element@7.4.11/dist/inferno-create-element.min.js',
'inferno-dom': 'npm:inferno-dom/dist/inferno-dom.min.js',
'inferno-hydrate': 'npm:inferno-hydrate@7.4.11/dist/inferno-hydrate.min.js',
'inferno-clone-vnode': 'npm:inferno-clone-vnode/dist/inferno-clone-vnode.min.js',
'inferno-create-class': 'npm:inferno-create-class/dist/inferno-create-class.min.js',
'inferno-extras': 'npm:inferno-extras/dist/inferno-extras.min.js',
'plugin-babel': 'npm:systemjs-plugin-babel@0.0.25/plugin-babel.js',
'systemjs-babel-build': 'npm:systemjs-plugin-babel@0.0.25/systemjs-babel-browser.js',
// Prettier
'prettier/standalone': 'npm:prettier@2.8.4/standalone.js',
'prettier/parser-html': 'npm:prettier@2.8.4/parser-html.js',
},
packages: {
'devextreme-vue': {
main: 'index.js',
},
'devextreme': {
defaultExtension: 'js',
},
'devextreme/events/utils': {
main: 'index',
},
'devextreme/events': {
main: 'index',
},
'es6-object-assign': {
main: './index.js',
defaultExtension: 'js',
},
},
packageConfigPaths: [
'npm:@devextreme/*/package.json',
'npm:@devextreme/runtime@3.0.12/inferno/package.json',
],
babelOptions: {
sourceMaps: false,
stage0: true,
},
};
System.config(window.config);
using DevExtreme.AspNet.Data;
using DevExtreme.AspNet.Mvc;
using DevExtreme.MVC.Demos.Models;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Web.Http;
namespace DevExtreme.MVC.Demos.Controllers.ApiControllers {
public class SchedulerDataController : ApiController {
InMemoryAppointmentsDataContext _data = new InMemoryAppointmentsDataContext();
[HttpGet]
public HttpResponseMessage Get(DataSourceLoadOptions loadOptions) {
return Request.CreateResponse(DataSourceLoader.Load(_data.Appointments, loadOptions));
}
[HttpPost]
public HttpResponseMessage Post(FormDataCollection form) {
var values = form.Get("values");
var newAppointment = new Appointment();
JsonConvert.PopulateObject(values, newAppointment);
Validate(newAppointment);
if(!ModelState.IsValid)
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState.GetFullErrorMessage());
_data.Appointments.Add(newAppointment);
_data.SaveChanges();
return Request.CreateResponse(HttpStatusCode.Created);
}
[HttpPut]
public HttpResponseMessage Put(FormDataCollection form) {
var key = Convert.ToInt32(form.Get("key"));
var values = form.Get("values");
var appointment = _data.Appointments.First(a => a.AppointmentId == key);
JsonConvert.PopulateObject(values, appointment);
Validate(appointment);
if(!ModelState.IsValid)
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState.GetFullErrorMessage());
_data.SaveChanges();
return Request.CreateResponse(HttpStatusCode.OK);
}
[HttpDelete]
public void Delete(FormDataCollection form) {
var key = Convert.ToInt32(form.Get("key"));
var appointment = _data.Appointments.First(a => a.AppointmentId == key);
_data.Appointments.Remove(appointment);
_data.SaveChanges();
}
}
}