dhtmlxScheduler 与 ASP.NET MVC
本指南将带您一步步使用 ASP.NET 和服务器端的 REST API 构建一个 Scheduler。
如果您对 Scheduler 的其他服务器端集成方式感兴趣,可以参考以下教程:
- dhtmlxScheduler와 ASP.NET Core
- dhtmlxScheduler와 Node.js
- dhtmlxScheduler와 PHP
- dhtmlxScheduler와 PHP:Slim
- dhtmlxScheduler와 PHP:Laravel 연동하기
- dhtmlxScheduler와 SalesForce LWC 통합하기
- dhtmlxScheduler와 Ruby on Rails 연동하기
- dhtmlxScheduler와 dhtmlxConnector 연동하기
本文将使用 ASP.NET MVC 5 及 Web API 控制器来搭建 Scheduler 应用。数据库交互将依赖 Entity Framework。开发环境选用 Visual Studio IDE。
您可以在 GitHub 上找到完整的源代码。
步骤 1. 创建项目
启动 Visual Studio 2022,选择 Create a new project(创建新项目)。

然后选择 "ASP.NET Web Application",将其命名为 DHX.Scheduler.Web。如果未找到该模板,请参考 Troubleshooting 部分。


从模板中选择 Empty(空项目),并勾选右侧的 MVC 和 Web API 选项:

步骤 2. 向页面添加 Scheduler
创建控制器
空项目准备好后,下一步是添加一个 MVC 控制器,用于显示调度页面。
右键点击 Controllers 文件夹,选择 Add -> Controller。在弹出的对话框中,选择 MVC 5 Controller -> Empty,然后点击 Add。将控制器命名为 "HomeController"。

HomeController 默认包含 Index() 方法,返回 ActionResult 类型,因此无需额外逻辑。我们只需为其添加一个视图。
using System.Web.Mvc;
namespace DHX.Scheduler.Web.Controllers
{
public class HomeController : Controller
{
// GET: Home
public ActionResult Index()
{
return View();
}
}
}
创建视图
接下来创建 index 页面。进入 Views/Home,添加一个空视图,命名为 Index:

打开新建的视图,并插入以下代码:
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width="device-width"" />
<title>Index</title>
<link href="https://cdn.dhtmlx.com/scheduler/edge/dhtmlxscheduler.css"
rel="stylesheet" type="text/css" />
<script src="https://cdn.dhtmlx.com/scheduler/edge/dhtmlxscheduler.js"></script>
<script>
document.addEventListener("DOMContentLoaded", function(event) {
// initializing scheduler
scheduler.init("scheduler_here", new Date(2022,0,15));
// initiating data loading
scheduler.load("/api/scheduler");
// initializing dataProcessor
var dp = scheduler.createDataProcessor("/api/scheduler");
// and attaching it to scheduler
dp.init(scheduler);
// setting the REST mode for dataProcessor
dp.setTransactionMode("REST");
});
</script>
</head>
<body>
<div id="scheduler_here" className="dhx_cal_container">
<div className="dhx_cal_navline">
<div className="dhx_cal_prev_button"> </div>
<div className="dhx_cal_next_button"> </div>
<div className="dhx_cal_today_button"></div>
<div className="dhx_cal_date"></div>
<div className="dhx_cal_tab" name="day_tab"></div>
<div className="dhx_cal_tab" name="week_tab"></div>
<div className="dhx_cal_tab" name="month_tab"></div>
</div>
<div className="dhx_cal_header"></div>
<div className="dhx_cal_data"></div>
</div>
</body>
</html>
此代码实现了以下功能:
- 设置了 Scheduler 应用的基本页面布局
- 引入了 dhtmlx scheduler 的 JS 和 CSS(通过 CDN 链接)
- 在页面上创建了 scheduler
同时,将 scheduler 配置为与 RESTful API 后端 "/api/scheduler/" 协作,在加载数据时以及作为默认路由使用:
scheduler.load("/api/scheduler");
// initializing dataProcessor
var dp = scheduler.createDataProcessor("/api/scheduler");
// and attaching it to scheduler
dp.init(scheduler);
// setting the REST mode for dataProcessor
dp.setTransactionMode("REST");
服务器端实现将在后续完成。现在,您可以运行应用并看到调度组件已显示。

步骤 3. 创建模型和数据库
创建模型
接下来需要为 scheduler 定义模型类。您需要一个用于表示调度事件的类。请注意,dhtmlxScheduler 对数据模型有特定的命名要求,这与常规 C# 风格不同。有些客户端属性可能不会存储在数据库中,而是在客户端或后端逻辑中使用。
为了解决这个问题,我们将遵循 Data Transfer Object 模式:为 EF 及内部使用定义领域模型类,为 Web API 通信定义单独的 DTO 类。稍后会配置模型之间的映射。
Scheduler 事件模型
首先创建 Event 类。以下是一个基本示例:
using System;
namespace DHX.Scheduler.Web.Models
{
public class SchedulerEvent
{
public int Id { get; set; }
public string Text { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
}
}
请注意,调度事件还可以包含许多其他属性,以增强日历功能。此示例仅涵盖了基本字段。
配置数据库连接
安装 Entity Framework
您可以通过 NuGet 包管理器添加 Entity Framework:

或者在包管理器控制台中运行以下命令:
PM> Install-Package EntityFramework
创建数据库上下文
接下来创建 Context 类。它代表与数据库的会话,负责数据的获取和保存。
右键点击 Models 文件夹,选择 Add -> Class,命名为 "SchedulerContext",并添加如下代码:
using System.Data.Entity;
namespace DHX.Scheduler.Web.Models
{
public class SchedulerContext : DbContext
{
public DbSet<SchedulerEvent> SchedulerEvents { get; set; }
}
}
向数据库添加初始记录
现在我们来添加一些示例数据。
Entity Framework 可以在应用启动时自动创建数据库。我们希望每当模型发生变化时,数据库会自动删除并重建。
首先,在 App_Start 下添加一个继承自 DropCreateDatabaseIfModelChanges 的数据库初始化类,命名为 "SchedulerInitializer"。
在此类中,重写 Seed() 方法,通过向 context 添加实体来填充测试数据。
以下是完整的 SchedulerInitializer 类:
using System;
using System.Collections.Generic;
using System.Data.Entity;
using DHX.Scheduler.Web.Models;
namespace DHX.Scheduler.Web.App_Start
{
public class SchedulerInitializer:DropCreateDatabaseIfModelChanges<SchedulerContext>
{
protected override void Seed(SchedulerContext context)
{
List<SchedulerEvent> events = new List<SchedulerEvent>()
{
new SchedulerEvent()
{
Id = 1,
Text = "Event 1",
StartDate = new DateTime(2022, 1, 11, 2, 0, 0),
EndDate = new DateTime(2022, 1, 11, 4, 0, 0)
},
new SchedulerEvent()
{
Id = 2,
Text = "Event 2",
StartDate = new DateTime(2022, 1, 14, 3, 0, 0),
EndDate = new DateTime(2022, 1, 14, 6, 0, 0)
},
new SchedulerEvent()
{
Id = 3,
Text = "Multiday event",
StartDate = new DateTime(2022, 1, 11, 0, 0, 0),
EndDate = new DateTime(2022, 1, 16, 0, 0, 0)
}
};
events.ForEach(s => context.SchedulerEvents.Add(s));
context.SaveChanges();
}
}
}
打开 Global.asax。该文件包含应用启动时执行的代码。添加所需命名空间,并在 Application_Start() 中为 context 设置初始化器:
using System;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using System.Web.Http;
using System.Data.Entity;
using DHX.Scheduler.Web.App_Start;
namespace DHX.Scheduler.Web
{
public class Global : HttpApplication
{
void Application_Start(object sender, EventArgs e)
{
// Code that runs on application startup
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
RouteConfig.RegisterRoutes(RouteTable.Routes);
Database.SetInitializer(new SchedulerInitializer()); /*!*/
}
}
}
定义 DTO 及映射
接下来,我们要定义 Web API 使用的 DTO 类。为了在 Model 和 DTO 之间进行映射,我们会在类中实现显式转换操作符。
以下是 WebAPIEvent 类的结构:
using System;
namespace DHX.Scheduler.Web.Models
{
public class WebAPIEvent
{
public int id { get; set; }
public string text { get; set; }
public string start_date { get; set; }
public string end_date { get; set; }
public static explicit operator WebAPIEvent(SchedulerEvent schedulerEvent)
{
return new WebAPIEvent
{
id = schedulerEvent.Id,
text = schedulerEvent.Text,
start_date = schedulerEvent.StartDate.ToString("yyyy-MM-dd HH:mm"),
end_date = schedulerEvent.EndDate.ToString("yyyy-MM-dd HH:mm")
};
}
public static explicit operator SchedulerEvent(WebAPIEvent schedulerEvent)
{
return new SchedulerEvent
{
Id = schedulerEvent.id,
Text = schedulerEvent.text,
StartDate = DateTime.Parse(
schedulerEvent.start_date,
System.Globalization.CultureInfo.InvariantCulture),
EndDate = DateTime.Parse(
schedulerEvent.end_date,
System.Globalization.CultureInfo.InvariantCulture)
};
}
}
}