Your search did not match any results.
Scheduler

SignalR Service

Documentation

This demo shows how two users can edit data in the Scheduler simultaneously. A SignalR service is used to broadcast push notifications.

Each Scheduler has an individual store to emulate the situation when Schedulers are being edited on two different clients. Changes made in one Scheduler are repeated in the other and persist until the browser session has expired.

<div class="schedulers"> @for(int i = 1; i <= 2; i++) { <div class="column-@i"> @(Html.DevExtreme().Scheduler() .ID(string.Format("{0}{1}", "scheduler", i)) .DataSource(d => d.WebApi() .Controller("SchedulerSignalR") .Key("AppointmentId") .DeleteAction(true) .UpdateAction(true) .InsertAction(true) .Key("AppointmentId") ) .Views(new[] { SchedulerViewType.Day, SchedulerViewType.WorkWeek }) .CurrentView(SchedulerViewType.Day) .CurrentDate(new DateTime(2021, 5, 25)) .StartDayHour(9) .EndDayHour(19) .Height(600) .DateSerializationFormat("yyyy-MM-ddTHH:mm:ssZ") .TextExpr("Text") .DescriptionExpr("Description") .StartDateExpr("StartDate") .EndDateExpr("EndDate") .AllDayExpr("AllDay") ) </div> } </div> <script src="~/Scripts/signalr/jquery.signalR-2.2.2.js"></script> <script src="~/signalr/hubs"></script> <script> $(function () { var store1 = $("#scheduler1").dxScheduler("getDataSource").store(); var store2 = $("#scheduler2").dxScheduler("getDataSource").store(); var hub = $.connection.schedulerSignalRHub; hub.client.update = function (key, data) { store1.push([{ type: "update", key: key, data: data }]); store2.push([{ type: "update", key: key, data: data }]); }; hub.client.insert = function (data) { store1.push([{ type: "insert", data: data }]); store2.push([{ type: "insert", data: data }]); }; hub.client.remove = function (key) { store1.push([{ type: "remove", key: key }]); store2.push([{ type: "remove", key: key }]); }; $.connection.hub.start({ waitForPageLoad: false }); }); </script>
using DevExtreme.MVC.Demos.Models.SampleData; using DevExtreme.MVC.Demos.ViewModels; using System; using System.Collections.Generic; using System.Linq; using System.Web.Mvc; namespace DevExtreme.MVC.Demos.Controllers { public class SchedulerController : Controller { public ActionResult SignalRService() { return View(); } } }
using DevExtreme.AspNet.Data; using DevExtreme.AspNet.Mvc; using DevExtreme.MVC.Demos.Hubs; using DevExtreme.MVC.Demos.Models; using Microsoft.AspNet.SignalR; 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; using System.Web.Http; namespace DevExtreme.MVC.Demos.Controllers.ApiControllers { public class SchedulerSignalRController : ApiController { InMemoryAppointmentsDataContext _data = new InMemoryAppointmentsDataContext(); IHubContext hubContext; public SchedulerSignalRController() { hubContext = GlobalHost.ConnectionManager.GetHubContext<SchedulerSignalRHub>(); } [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(); var groupName = GetGroupName(); if(groupName != null) { hubContext.Clients.Group(GetGroupName()).insert(newAppointment); } 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(); var groupName = GetGroupName(); if(groupName != null) { hubContext.Clients.Group(GetGroupName()).update(key, appointment); } 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(); var groupName = GetGroupName(); if(groupName != null) { hubContext.Clients.Group(GetGroupName()).remove(key); } } string GetGroupName() { var cookie = Request.Headers.GetCookies(SchedulerSignalRHub.GroupIdKey).FirstOrDefault(); if(cookie != null) { return cookie[SchedulerSignalRHub.GroupIdKey].Value; } return null; } } }
using System; using System.Collections.Generic; using System.Linq; namespace DevExtreme.MVC.Demos.Models { public class Appointment { public int AppointmentId { get; set; } public string Text { get; set; } public string Description { get; set; } public string StartDate { get; set; } public string EndDate { get; set; } public bool AllDay { get; set; } public string RecurrenceRule { get; set; } public string RecurrenceException { get; set; } } }
using System; using System.Collections.Generic; namespace DevExtreme.MVC.Demos.Models.SampleData { public partial class SampleData { public static readonly IEnumerable<Appointment> Appointments = new[] { new Appointment { AppointmentId = 1, Text = "Website Re-Design Plan", StartDate = "2021-05-24T06:30:00.000Z", EndDate = "2021-05-24T08:30:00.000Z" }, new Appointment { AppointmentId = 2, Text = "Book Flights to San Fran for Sales Trip", StartDate = "2021-05-24T09:00:00.000Z", EndDate = "2021-05-24T10:00:00.000Z", AllDay = true }, new Appointment { AppointmentId = 3, Text = "Install New Router in Dev Room", StartDate = "2021-05-24T11:30:00.000Z", EndDate = "2021-05-24T12:30:00.000Z" }, new Appointment { AppointmentId = 4, Text = "Approve Personal Computer Upgrade Plan", StartDate = "2021-05-25T07:00:00.000Z", EndDate = "2021-05-25T08:00:00.000Z" }, new Appointment { AppointmentId = 5, Text = "Final Budget Review", StartDate = "2021-05-25T09:00:00.000Z", EndDate = "2021-05-25T10:35:00.000Z" }, new Appointment { AppointmentId = 6, Text = "New Brochures", StartDate = "2021-05-25T11:30:00.000Z", EndDate = "2021-05-25T12:45:00.000Z" }, new Appointment { AppointmentId = 7, Text = "Install New Database", StartDate = "2021-05-26T06:45:00.000Z", EndDate = "2021-05-26T08:15:00.000Z" }, new Appointment { AppointmentId = 8, Text = "Approve New Online Marketing Strategy", StartDate = "2021-05-26T09:00:00.000Z", EndDate = "2021-05-26T11:00:00.000Z" }, new Appointment { AppointmentId = 9, Text = "Upgrade Personal Computers", StartDate = "2021-05-26T12:15:00.000Z", EndDate = "2021-05-26T13:30:00.000Z" }, new Appointment { AppointmentId = 10, Text = "Customer Workshop", StartDate = "2021-05-27T08:00:00.000Z", EndDate = "2021-05-27T09:00:00.000Z", AllDay = true }, new Appointment { AppointmentId = 11, Text = "Prepare 2021 Marketing Plan", StartDate = "2021-05-27T08:00:00.000Z", EndDate = "2021-05-27T10:30:00.000Z" }, new Appointment { AppointmentId = 12, Text = "Brochure Design Review", StartDate = "2021-05-27T11:00:00.000Z", EndDate = "2021-05-27T12:30:00.000Z" }, new Appointment { AppointmentId = 13, Text = "Create Icons for Website", StartDate = "2021-05-28T07:00:00.000Z", EndDate = "2021-05-28T08:30:00.000Z" }, new Appointment { AppointmentId = 14, Text = "Upgrade Server Hardware", StartDate = "2021-05-28T11:30:00.000Z", EndDate = "2021-05-28T13:00:00.000Z" }, new Appointment { AppointmentId = 15, Text = "Submit New Website Design", StartDate = "2021-05-28T13:30:00.000Z", EndDate = "2021-05-28T15:00:00.000Z" }, new Appointment { AppointmentId = 16, Text = "Launch New Website", StartDate = "2021-05-28T09:20:00.000Z", EndDate = "2021-05-28T11:00:00.000Z" } }; } }
using System; using System.Threading.Tasks; using System.Web; using Microsoft.AspNet.SignalR; namespace DevExtreme.MVC.Demos.Hubs { public class SchedulerSignalRHub : Hub { public static string GroupIdKey = "dx-SchedulerSignalRHub-groupId"; private static readonly Random random = new Random(); public override Task OnConnected() { Cookie cookie; Context.RequestCookies.TryGetValue(GroupIdKey, out cookie); string groupId; if(cookie != null) { groupId = cookie.Value; } else { groupId = random.Next(0, int.MaxValue).ToString(); var newCookie = new HttpCookie(GroupIdKey, groupId); Context.Request.GetHttpContext().Response.Cookies.Add(newCookie); } Groups.Add(Context.ConnectionId, groupId); return base.OnConnected(); } } }
.schedulers { display: flex; } .column-1 { padding-right: 5px; } .column-2 { padding-left: 5px; } .dx-scheduler-small .dx-scheduler-view-switcher.dx-tabs { display: table; }