翻译|使用教程|编辑:颜馨|2023-04-18 13:49:00.143|阅读 90 次
概述:本章讲述dhtmlxGantt在ASP.NET Core上的使用方法,欢迎查阅!
# 慧都年终大促·界面/图表报表/文档/IDE等千款热门软控件火热促销中 >>
DHTMLX甘特图是用于跨浏览器和超平台应用程序的功能齐备的甘特图。可满足项目管理应用程序的大部分需求,具备完善的甘特图表库,功能强大,价格方便,提供丰厚而灵活的JavaScript API接口,与各种服务端技术(PHP,ASP.NET,Java等)简单集合,满足多种定制开发需求。
DHTMLX JavaScript UI 库所开发的 JavaScript 组合易于使用和功能丰富,非常适合结合任何领导地位和任何复合性的解决方案,能力足足够省创造和维保业务应用程序的时间,提供高生产力。
本教程将逐步指导您如何使用 ASP.NET Core 在服务端创建甘特图。
启动Visual Studio 2022并创建一个新的项目。选择:创建一个新的项目。
接下来来选择“ASP.NET Core Web App”并命名为DHX.Gantt。
自此,你已经创建了一个项目,可以继续为甘特图添加标记和脚本。
进入wwwroot并创建一个index.html文件。
在新创建的文件中,为甘特图制作一个简单的页面。
请注意,甘特图文件是在此演示中从 CDN 添加的。如果您有该组件的专业版本, 您需要手动将甘特图文件添加到项目中。
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>Index</title> <link href="//cdn.dhtmlx.com/gantt/edge/dhtmlxgantt.css" rel="stylesheet" type="text/css" /> <script src="//cdn.dhtmlx.com/gantt/edge/dhtmlxgantt.js"></script> <script> document.addEventListener("DOMContentLoaded", function(event) { // specifying the date format gantt.config.date_format = "%Y-%m-%d %H:%i"; // initializing gantt gantt.init("gantt_here"); // initiating data loading gantt.load("/api/data"); // initializing dataProcessor var dp = new gantt.dataProcessor("/api/"); // and attaching it to gantt dp.init(gantt); // setting the REST mode for dataProcessor dp.setTransactionMode("REST"); }); </script> </head> <body> <div id="gantt_here" style="width: 100%; height: 100vh;"></div> </body> </html>
当页面被加载时,除了初始化甘特图的数据加载外,还立即调用dataProcessor,所以用户对甘特图的所有修改都将被保存到后台。后台还没有实现,所以以后会更有意义。
接下来进入Program.cs,告诉应用程序使用index.html页面。为了做到这一点,你需要将应用程序配置为从wwwroot文件夹中提供静态文件。为此,你需要添加app.UseDefaultFiles()方法。你可以在这里找到更多细节。
var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddRazorPages(); var app = builder.Build(); // Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Error"); // The default HSTS value is 30 days. // You may want to change this for production scenarios, // see //aka.ms/aspnetcore-hsts. app.UseHsts(); } app.UseHttpsRedirection(); app.UseDefaultFiles(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.MapRazorPages(); app.Run();
该方法允许提供默认文件。它将搜索wwwroot文件夹中的以下文件:app.UseDefaultFiles()
因此,你可以选择其中的任何一个,而在本教程中使用的是 "index.html"。只是一个URL-rewriter,并不实际提供文件。为此,你还需要添加文件。UseDefaultFiles()UseStaticFiles()
一旦你完成了它,当你运行应用程序时,一个空的甘特图就会出现在页面上。注意,右上角的 "无效数据 "标签显示,因为因为仍然没有合适的后台来提供数据,所以被调用。当控制器实现后,gantt将能够显示任务和链接。gantt.load()
现在基本部分已经完成,是时候实现后端了。让我们从实现模型类开始,之后再进行WebAPI控制器。
让我们从数据模型开始。甘特的数据模型包括链接和任务,从.NET世界的角度来看,dhtmlxGantt对模型属性使用非常规的名称。有时客户端的模型也包含一些客户端或后端逻辑的属性,但这些属性不应该存储在数据库中。
为了处理这个问题,将使用数据传输对象(DTO)模式。两种模型将被定义:
然后,这两种模型之间的映射应该被实现。
模型
在项目文件夹中创建一个名为Models的新文件夹。这是实现模型类和 EF 上下文的位置。
任务模型
首先,为任务创建一个类。在Models文件夹中创建一个文件,命名为Task.cs。这可以通过调用Models文件夹的上下文菜单并选择Add->Class来完成。
这个模型必须是这样的:
namespace DHX.Gantt.Models { public class Task { public int Id { get; set; } public string? Text { get; set; } public DateTime StartDate { get; set; } public int Duration { get; set; } public decimal Progress { get; set; } public int? ParentId { get; set; } public string? Type { get; set; } } }
你可以查询任务对象的所有属性列表。
链接模型
再添加一个文件,为链接创建一个类:
namespace DHX.Gantt.Models { public class Link { public int Id { get; set; } public string? Type { get; set; } public int SourceTaskId { get; set; } public int TargetTaskId { get; set; } } }
模型已经准备好了,你可以开始配置数据库连接。
为了配置数据库连接,你需要采取下面列出的步骤:
安装Entity Framework Core
Entity Framework Core将被用来管理应用程序与数据库的通信。让我们来安装该框架:
或者使用软件包管理器命令行:
PM> Install-Package Microsoft.EntityFrameworkCore.SqlServer PM> Install-Package Microsoft.EntityFrameworkCore PM> Install-Package Microsoft.EntityFrameworkCore.Design
实体框架核心将用来管理应用程序与数据库的通信。
创建实体上下文
接下来你需要定义一个与数据库的会话,并启用加载和保存数据。为此,创建Context:
using Microsoft.EntityFrameworkCore; namespace DHX.Gantt.Models { public class GanttContext : DbContext { public GanttContext(DbContextOptions<GanttContext> options) : base(options) { } public DbSet<Task> Tasks { get; set; } = null; public DbSet<Link> Links { get; set; } = null; } }
向数据库添加第一批记录
现在你可以向数据库添加记录了。让我们创建数据库初始化器,将任务填充到数据库中。在Models文件夹中定义一个类,并将其称为GanttSeeder。该类将有Seed()方法,将添加任务和链接到数据库。
using Microsoft.EntityFrameworkCore; namespace DHX.Gantt.Models { public static class GanttSeeder { public static void Seed(GanttContext context) { if (context.Tasks.Any()) { return; // DB has been seeded } using (var transaction = context.Database.BeginTransaction()) { List<Task> tasks = new List<Task>() { new Task() { Id = 1, Text = "Project #2", StartDate = DateTime.Today.AddDays(-3), Duration = 18, Progress = 0.4m, ParentId = null }, new Task() { Id = 2, Text = "Task #1", StartDate = DateTime.Today.AddDays(-2), Duration = 8, Progress = 0.6m, ParentId = 1 }, new Task() { Id = 3, Text = "Task #2", StartDate = DateTime.Today.AddDays(-1), Duration = 8, Progress = 0.6m, ParentId = 1 } }; tasks.ForEach(s => context.Tasks.Add(s)); context.Database.ExecuteSqlRaw("SET IDENTITY_INSERT Tasks ON;"); context.SaveChanges(); context.Database.ExecuteSqlRaw("SET IDENTITY_INSERT Tasks OFF;"); List<Link> links = new List<Link>() { new Link() {Id = 1, SourceTaskId = 1, TargetTaskId = 2, Type = "1"}, new Link() {Id = 2, SourceTaskId = 2, TargetTaskId = 3, Type = "0"} }; links.ForEach(s => context.Links.Add(s)); context.Database.ExecuteSqlRaw("SET IDENTITY_INSERT Links ON;"); context.SaveChanges(); context.Database.ExecuteSqlRaw("SET IDENTITY_INSERT Links OFF;"); transaction.Commit(); } } } }
注册数据库
现在你应该在Program.cs中注册数据库。但首先你需要一个连接字符串。它将被存储在应用程序设置的JSON文件中。创建appsettings.json文件(如果你已经有了,则打开它),并为数据库添加一个连接字符串:
{ "ConnectionStrings": { "DefaultConnection": "Server=(localdb)\\mssqllocaldb; Database=GanttDatabase;Trusted_Connection=True;" } }
数据库上下文将通过依赖关系注入进行注册。
将以下命名空间添加到 Program.cs:
using Microsoft.EntityFrameworkCore; using DHX.Gantt.Models;
该声明将看起来像这样:
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection"); builder.Services.AddDbContext<GanttContext>( options => options.UseSqlServer(connectionString));
要启用控制器,需要调用services.AddControllers()方法:
builder.Services.AddControllers();
然后我们调用app.MapControllers()来注册我们的控制器路线:
app.MapControllers();
下面是Program.cs的完整代码:
using Microsoft.EntityFrameworkCore; using DHX.Gantt.Models; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddRazorPages(); var connectionString = builder.Configuration.GetConnectionString("DefaultConnection"); builder.Services.AddDbContext<GanttContext>( options => options.UseSqlServer(connectionString)); builder.Services.AddControllers(); var app = builder.Build(); // Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Error"); // The default HSTS value is 30 days. // You may want to change this for production scenarios, // see //aka.ms/aspnetcore-hsts. app.UseHsts(); } app.UseHttpsRedirection(); app.UseDefaultFiles(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.MapRazorPages(); app.MapControllers(); app.Run();
最后,你需要在应用启动时初始化和播种数据库。通常情况下,你会希望使用迁移来完成这个任务,但为了简单起见,这里没有使用迁移。
让我们首先创建一个初始化的类。在Models文件夹中创建GanttInitializerExtension.cs文件:
namespace DHX.Gantt.Models { public static class GanttInitializerExtension { public static IHost InitializeDatabase(this IHost webHost) { var serviceScopeFactory = (IServiceScopeFactory?)webHost.Services.GetService(typeof(IServiceScopeFactory)); using (var scope = serviceScopeFactory!.CreateScope()) { var services = scope.ServiceProvider; var dbContext = services.GetRequiredService<GanttContext>(); dbContext.Database.EnsureDeleted(); dbContext.Database.EnsureCreated(); GanttSeeder.Seed(dbContext); } return webHost; } } }
接下来调用InitializeDatabase():
app.InitializeDatabase();
正如上面提到的,本教程中没有使用迁移。而是使用简单的EnsureCreated和种子。
当前部分已经完成,让我们回到甘特图。
定义DTOs和映射
现在是定义将用于Web API的DTO类的时候了。让我们从任务的DTO类开始。在Models文件夹中创建一个文件并定义WebApiTask.cs类:
namespace DHX.Gantt.Models { public class WebApiTask { public int id { get; set; } public string? text { get; set; } public string? start_date { get; set; } public int duration { get; set; } public decimal progress { get; set; } public int? parent { get; set; } public string? type { get; set; } public bool open { get { return true; } set { } } public static explicit operator WebApiTask(Task task) { return new WebApiTask { id = task.Id, text = task.Text, start_date = task.StartDate.ToString("yyyy-MM-dd HH:mm"), duration = task.Duration, parent = task.ParentId, type = task.Type, progress = task.Progress }; } public static explicit operator Task(WebApiTask task) { return new Task { Id = task.id, Text = task.text, StartDate = task.start_date != null ? DateTime.Parse(task.start_date, System.Globalization.CultureInfo.InvariantCulture) : new DateTime(), Duration = task.duration, ParentId = task.parent, Type = task.type, Progress = task.progress }; } } }
而这是定义在Models文件夹中名为WebApiLink.cs的文件中的Link的DTO类:
namespace DHX.Gantt.Models { public class WebApiLink { public int id { get; set; } public string? type { get; set; } public int source { get; set; } public int target { get; set; } public static explicit operator WebApiLink(Link link) { return new WebApiLink { id = link.Id, type = link.Type, source = link.SourceTaskId, target = link.TargetTaskId }; } public static explicit operator Link(WebApiLink link) { return new Link { Id = link.id, Type = link.type, SourceTaskId = link.source, TargetTaskId = link.target }; } } }
当你完成这一步骤时,你应该得到以下的文件夹结构:
现在你可以运行该应用程序,以检查一切是否到位。如果你没有看到一个运行时错误,那么一切都很好。
现在是实际实现REST API的时候了。
添加控制器
创建控制器文件夹并创建三个空的API控制器:一个用于任务,另一个用于链接,还有一个用于整个数据集:
任务控制器
让我们为任务创建一个控制器。它将定义甘特任务的基本CRUD操作。
它是如何工作的:
在GET请求中,任务从数据库加载,输出是任务的数据传输对象;
在PUT/POST请求中,任务作为WebAPITask类来自客户端。它们在dhtmlxGantt中以这种方式表示。因此,你应该把它们转换为我们的EntityFramework数据模型的格式(任务类)。之后,就可以在DatabaseContext中保存更改。
using Microsoft.AspNetCore.Mvc; using DHX.Gantt.Models; namespace DHX.Gantt.Controllers { [Produces("application/json")] [Route("api/task")] public class TaskController : Controller { private readonly GanttContext _context; public TaskController(GanttContext context) { _context = context; } // GET api/task [HttpGet] public IEnumerable<WebApiTask> Get() { return _context.Tasks .ToList() .Select(t => (WebApiTask)t); } // GET api/task/5 [HttpGet("{id}")] public Models.Task? Get(int id) { return _context .Tasks .Find(id); } // POST api/task [HttpPost] public ObjectResult Post(WebApiTask apiTask) { var newTask = (Models.Task)apiTask; _context.Tasks.Add(newTask); _context.SaveChanges(); return Ok(new { tid = newTask.Id, action = "inserted" }); } // PUT api/task/5 [HttpPut("{id}")] public ObjectResult? Put(int id, WebApiTask apiTask) { var updatedTask = (Models.Task)apiTask; var dbTask = _context.Tasks.Find(id); if (dbTask == null) { return null; } dbTask.Text = updatedTask.Text; dbTask.StartDate = updatedTask.StartDate; dbTask.Duration = updatedTask.Duration; dbTask.ParentId = updatedTask.ParentId; dbTask.Progress = updatedTask.Progress; dbTask.Type = updatedTask.Type; _context.SaveChanges(); return Ok(new { action = "updated" }); } // DELETE api/task/5 [HttpDelete("{id}")] public ObjectResult DeleteTask(int id) { var task = _context.Tasks.Find(id); if (task != null) { _context.Tasks.Remove(task); _context.SaveChanges(); } return Ok(new { action = "deleted" }); } } }
链接控制器
接下来你应该为链接创建一个控制器:
using Microsoft.EntityFrameworkCore; using Microsoft.AspNetCore.Mvc; using DHX.Gantt.Models; namespace DHX.Gantt.Controllers { [Produces("application/json")] [Route("api/link")] public class LinkController : Controller { private readonly GanttContext _context; public LinkController(GanttContext context) { _context = context; } // GET api/Link [HttpGet] public IEnumerable<WebApiLink> Get() { return _context.Links .ToList() .Select(t => (WebApiLink)t); } // GET api/Link/5 [HttpGet("{id}")] public Link? Get(int id) { return _context .Links .Find(id); } // POST api/Link [HttpPost] public ObjectResult Post(WebApiLink apiLink) { var newLink = (Link)apiLink; _context.Links.Add(newLink); _context.SaveChanges(); return Ok(new { tid = newLink.Id, action = "inserted" }); } // PUT api/Link/5 [HttpPut("{id}")] public ObjectResult Put(int id, WebApiLink apiLink) { var updatedLink = (Link)apiLink; updatedLink.Id = id; _context.Entry(updatedLink).State = EntityState.Modified; _context.SaveChanges(); return Ok(new { action = "updated" }); } // DELETE api/Link/5 [HttpDelete("{id}")] public ObjectResult DeleteLink(int id) { var Link = _context.Links.Find(id); if (Link != null) { _context.Links.Remove(Link); _context.SaveChanges(); } return Ok(new { action = "deleted" }); } } }
数据控制器
最后,你需要为一个数据动作创建一个控制器:
using Microsoft.AspNetCore.Mvc; using DHX.Gantt.Models; namespace DHX.Gantt.Controllers { [Produces("application/json")] [Route("api/data")] public class DataController : Controller { private readonly GanttContext _context; public DataController(GanttContext context) { _context = context; } // GET api/data [HttpGet] public object Get() { return new { 数据 = _context.Tasks.ToList().Select(t => (WebApiTask)t), 链接 = _context.Links.ToList().Select(l => (WebApiLink)l) }; } } }
一切都准备好了。你可以运行该应用程序,看到成熟的甘特图。
你也可以在 GitHub 上查看完整的源代码。
DHTMLX甘特图享有超过十年的声望,支持跨浏览器和跨平台,性能比高,可满足项目管理应用程序的所有需求,是最擅长的甘特图表库。
甘特图控件交流群:764148812
欢迎加入群交流讨论,获得更多帮助请联系
本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@pclwef.cn