翻譯|使用教程|編輯:顏馨|2023-04-18 13:49:00.143|閱讀 220 次
概述:本章講述dhtmlxGantt在ASP.NET Core上的使用方法,歡迎查閱!
# 界面/圖表報(bào)表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
相關(guān)鏈接:
DHTMLX甘特圖是用于跨瀏覽器和超平臺(tái)應(yīng)用程序的功能齊備的甘特圖。可滿足項(xiàng)目管理應(yīng)用程序的大部分需求,具備完善的甘特圖表庫,功能強(qiáng)大,價(jià)格方便,提供豐厚而靈活的JavaScript API接口,與各種服務(wù)端技術(shù)(PHP,ASP.NET,Java等)簡(jiǎn)單集合,滿足多種定制開發(fā)需求。
DHTMLX JavaScript UI 庫所開發(fā)的 JavaScript 組合易于使用和功能豐富,非常適合結(jié)合任何領(lǐng)導(dǎo)地位和任何復(fù)合性的解決方案,能力足足夠省創(chuàng)造和維保業(yè)務(wù)應(yīng)用程序的時(shí)間,提供高生產(chǎn)力。
本教程將逐步指導(dǎo)您如何使用 ASP.NET Core 在服務(wù)端創(chuàng)建甘特圖。
啟動(dòng)Visual Studio 2022并創(chuàng)建一個(gè)新的項(xiàng)目。選擇:創(chuàng)建一個(gè)新的項(xiàng)目。
接下來來選擇“ASP.NET Core Web App”并命名為DHX.Gantt。
自此,你已經(jīng)創(chuàng)建了一個(gè)項(xiàng)目,可以繼續(xù)為甘特圖添加標(biāo)記和腳本。
進(jìn)入wwwroot并創(chuàng)建一個(gè)index.html文件。
在新創(chuàng)建的文件中,為甘特圖制作一個(gè)簡(jiǎn)單的頁面。
請(qǐng)注意,甘特圖文件是在此演示中從 CDN 添加的。如果您有該組件的專業(yè)版本, 您需要手動(dòng)將甘特圖文件添加到項(xiàng)目中。
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>Index</title> <link rel="stylesheet" type="text/css" /> <script src="http://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>
當(dāng)頁面被加載時(shí),除了初始化甘特圖的數(shù)據(jù)加載外,還立即調(diào)用dataProcessor,所以用戶對(duì)甘特圖的所有修改都將被保存到后臺(tái)。后臺(tái)還沒有實(shí)現(xiàn),所以以后會(huì)更有意義。
接下來進(jìn)入Program.cs,告訴應(yīng)用程序使用index.html頁面。為了做到這一點(diǎn),你需要將應(yīng)用程序配置為從wwwroot文件夾中提供靜態(tài)文件。為此,你需要添加app.UseDefaultFiles()方法。你可以在這里找到更多細(xì)節(jié)。
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();
該方法允許提供默認(rèn)文件。它將搜索wwwroot文件夾中的以下文件:app.UseDefaultFiles()
因此,你可以選擇其中的任何一個(gè),而在本教程中使用的是 "index.html"。只是一個(gè)URL-rewriter,并不實(shí)際提供文件。為此,你還需要添加文件。UseDefaultFiles()UseStaticFiles()
一旦你完成了它,當(dāng)你運(yùn)行應(yīng)用程序時(shí),一個(gè)空的甘特圖就會(huì)出現(xiàn)在頁面上。注意,右上角的 "無效數(shù)據(jù) "標(biāo)簽顯示,因?yàn)橐驗(yàn)槿匀粵]有合適的后臺(tái)來提供數(shù)據(jù),所以被調(diào)用。當(dāng)控制器實(shí)現(xiàn)后,gantt將能夠顯示任務(wù)和鏈接。gantt.load()
現(xiàn)在基本部分已經(jīng)完成,是時(shí)候?qū)崿F(xiàn)后端了。讓我們從實(shí)現(xiàn)模型類開始,之后再進(jìn)行WebAPI控制器。
讓我們從數(shù)據(jù)模型開始。甘特的數(shù)據(jù)模型包括鏈接和任務(wù),從.NET世界的角度來看,dhtmlxGantt對(duì)模型屬性使用非常規(guī)的名稱。有時(shí)客戶端的模型也包含一些客戶端或后端邏輯的屬性,但這些屬性不應(yīng)該存儲(chǔ)在數(shù)據(jù)庫中。
為了處理這個(gè)問題,將使用數(shù)據(jù)傳輸對(duì)象(DTO)模式。兩種模型將被定義:
然后,這兩種模型之間的映射應(yīng)該被實(shí)現(xiàn)。
模型
在項(xiàng)目文件夾中創(chuàng)建一個(gè)名為Models的新文件夾。這是實(shí)現(xiàn)模型類和 EF 上下文的位置。
任務(wù)模型
首先,為任務(wù)創(chuàng)建一個(gè)類。在Models文件夾中創(chuàng)建一個(gè)文件,命名為Task.cs。這可以通過調(diào)用Models文件夾的上下文菜單并選擇Add->Class來完成。
這個(gè)模型必須是這樣的:
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; } } }
你可以查詢?nèi)蝿?wù)對(duì)象的所有屬性列表。
鏈接模型
再添加一個(gè)文件,為鏈接創(chuàng)建一個(gè)類:
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; } } }
模型已經(jīng)準(zhǔn)備好了,你可以開始配置數(shù)據(jù)庫連接。
為了配置數(shù)據(jù)庫連接,你需要采取下面列出的步驟:
安裝Entity Framework Core
Entity Framework Core將被用來管理應(yīng)用程序與數(shù)據(jù)庫的通信。讓我們來安裝該框架:
或者使用軟件包管理器命令行:
PM> Install-Package Microsoft.EntityFrameworkCore.SqlServer PM> Install-Package Microsoft.EntityFrameworkCore PM> Install-Package Microsoft.EntityFrameworkCore.Design
實(shí)體框架核心將用來管理應(yīng)用程序與數(shù)據(jù)庫的通信。
創(chuàng)建實(shí)體上下文
接下來你需要定義一個(gè)與數(shù)據(jù)庫的會(huì)話,并啟用加載和保存數(shù)據(jù)。為此,創(chuàng)建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; } }
向數(shù)據(jù)庫添加第一批記錄
現(xiàn)在你可以向數(shù)據(jù)庫添加記錄了。讓我們創(chuàng)建數(shù)據(jù)庫初始化器,將任務(wù)填充到數(shù)據(jù)庫中。在Models文件夾中定義一個(gè)類,并將其稱為GanttSeeder。該類將有Seed()方法,將添加任務(wù)和鏈接到數(shù)據(jù)庫。
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(); } } } }
注冊(cè)數(shù)據(jù)庫
現(xiàn)在你應(yīng)該在Program.cs中注冊(cè)數(shù)據(jù)庫。但首先你需要一個(gè)連接字符串。它將被存儲(chǔ)在應(yīng)用程序設(shè)置的JSON文件中。創(chuàng)建appsettings.json文件(如果你已經(jīng)有了,則打開它),并為數(shù)據(jù)庫添加一個(gè)連接字符串:
{ "ConnectionStrings": { "DefaultConnection": "Server=(localdb)\\mssqllocaldb; Database=GanttDatabase;Trusted_Connection=True;" } }
數(shù)據(jù)庫上下文將通過依賴關(guān)系注入進(jìn)行注冊(cè)。
將以下命名空間添加到 Program.cs:
using Microsoft.EntityFrameworkCore; using DHX.Gantt.Models;
該聲明將看起來像這樣:
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection"); builder.Services.AddDbContext<GanttContext>( options => options.UseSqlServer(connectionString));
要啟用控制器,需要調(diào)用services.AddControllers()方法:
builder.Services.AddControllers();
然后我們調(diào)用app.MapControllers()來注冊(cè)我們的控制器路線:
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();
最后,你需要在應(yīng)用啟動(dòng)時(shí)初始化和播種數(shù)據(jù)庫。通常情況下,你會(huì)希望使用遷移來完成這個(gè)任務(wù),但為了簡(jiǎn)單起見,這里沒有使用遷移。
讓我們首先創(chuàng)建一個(gè)初始化的類。在Models文件夾中創(chuàng)建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; } } }
接下來調(diào)用InitializeDatabase():
app.InitializeDatabase();
正如上面提到的,本教程中沒有使用遷移。而是使用簡(jiǎn)單的EnsureCreated和種子。
當(dāng)前部分已經(jīng)完成,讓我們回到甘特圖。
定義DTOs和映射
現(xiàn)在是定義將用于Web API的DTO類的時(shí)候了。讓我們從任務(wù)的DTO類開始。在Models文件夾中創(chuàng)建一個(gè)文件并定義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 }; } } }
當(dāng)你完成這一步驟時(shí),你應(yīng)該得到以下的文件夾結(jié)構(gòu):
現(xiàn)在你可以運(yùn)行該應(yīng)用程序,以檢查一切是否到位。如果你沒有看到一個(gè)運(yùn)行時(shí)錯(cuò)誤,那么一切都很好。
現(xiàn)在是實(shí)際實(shí)現(xiàn)REST API的時(shí)候了。
添加控制器
創(chuàng)建控制器文件夾并創(chuàng)建三個(gè)空的API控制器:一個(gè)用于任務(wù),另一個(gè)用于鏈接,還有一個(gè)用于整個(gè)數(shù)據(jù)集:
任務(wù)控制器
讓我們?yōu)槿蝿?wù)創(chuàng)建一個(gè)控制器。它將定義甘特任務(wù)的基本CRUD操作。
它是如何工作的:
在GET請(qǐng)求中,任務(wù)從數(shù)據(jù)庫加載,輸出是任務(wù)的數(shù)據(jù)傳輸對(duì)象;
在PUT/POST請(qǐng)求中,任務(wù)作為WebAPITask類來自客戶端。它們?cè)赿htmlxGantt中以這種方式表示。因此,你應(yīng)該把它們轉(zhuǎn)換為我們的EntityFramework數(shù)據(jù)模型的格式(任務(wù)類)。之后,就可以在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" }); } } }
鏈接控制器
接下來你應(yīng)該為鏈接創(chuàng)建一個(gè)控制器:
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" }); } } }
數(shù)據(jù)控制器
最后,你需要為一個(gè)數(shù)據(jù)動(dòng)作創(chuàng)建一個(gè)控制器:
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 { 數(shù)據(jù) = _context.Tasks.ToList().Select(t => (WebApiTask)t), 鏈接 = _context.Links.ToList().Select(l => (WebApiLink)l) }; } } }
一切都準(zhǔn)備好了。你可以運(yùn)行該應(yīng)用程序,看到成熟的甘特圖。
DHTMLX甘特圖享有超過十年的聲望,支持跨瀏覽器和跨平臺(tái),性能比高,可滿足項(xiàng)目管理應(yīng)用程序的所有需求,是最擅長的甘特圖表庫。
甘特圖控件交流群:764148812
歡迎加入群交流討論,獲得更多幫助請(qǐng)聯(lián)系
本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請(qǐng)務(wù)必注明出處、不得修改原文相關(guān)鏈接,如果存在內(nèi)容上的異議請(qǐng)郵件反饋至chenjj@fc6vip.cn