手把手教你开发档案软件C/S版模块,含完整代码
一、开发环境准备与项目初始化
为了确保本文档的实操性,我们将采用目前主流且跨平台的 .NET 8 SDK 作为基础框架。服务端使用 ASP.NET Core 构建 Web API 提供数据接口,客户端使用 WinForms 构建桌面操作界面,数据存储采用轻量级的 SQLite 数据库,无需用户额外安装数据库服务。
1. 安装必要的开发工具
你需要确保系统中已安装 .NET 8 SDK。打开命令行工具(CMD 或 PowerShell),输入以下命令检查版本。如果未安装,请直接访问 https://dotnet.microsoft.com/download 下载并安装 .NET 8.0 SDK。
```bash dotnet --version ```建议安装 Visual Studio 2022 Community(免费版)以便进行可视化窗体设计,下载地址:https://visualstudio.microsoft.com/downloads/。在安装时,务必勾选“.NET 桌面开发”和“ASP.NET 和 Web 开发”两个工作负载。
2. 创建解决方案目录结构
在本地磁盘(例如 D 盘)创建一个名为 ArchiveSystem 的文件夹。在该目录下打开命令行,依次执行以下命令来创建服务端和客户端的项目骨架:
```bash 创建服务端 Web API 项目 dotnet new webapi -n ArchiveServer 创建客户端 WinForms 项目 dotnet new winforms -n ArchiveClient 将两个项目添加到同一个解决方案中,方便管理 dotnet new sln -n ArchiveSystem dotnet sln add ArchiveServer/ArchiveServer.csproj dotnet sln add ArchiveClient/ArchiveClient.csproj ```二、服务端开发:基于 ASP.NET Core 的档案管理接口
服务端负责档案数据的持久化存储和对外提供 API 接口。我们将使用 Entity Framework Core (EF Core) 来操作 SQLite 数据库。
1. 配置依赖包与数据库连接
进入服务端目录,添加 EF Core 和 SQLite 的驱动包。在命令行执行:
```bash cd ArchiveServer dotnet add package Microsoft.EntityFrameworkCore.Sqlite dotnet add package Microsoft.EntityFrameworkCore.Design ```接下来,我们需要创建档案数据模型。在 ArchiveServer 项目根目录下新建一个文件夹 Models,并在其中创建 ArchiveItem.cs 文件,完整代码如下:
```csharp using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace ArchiveServer.Models { // 档案实体类 public class ArchiveItem { [Key] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int Id { get; set; } [Required] [MaxLength(100)] public string Title { get; set; } = string.Empty; // 档案标题 [MaxLength(50)] public string Category { get; set; } = string.Empty; // 档案分类 public DateTime CreateDate { get; set; } = DateTime.Now; // 归档日期 [MaxLength(500)] public string? Description { get; set; } // 档案描述 } } ```在 Models 文件夹下继续创建数据库上下文类 ArchiveDbContext.cs:
```csharp using Microsoft.EntityFrameworkCore; namespace ArchiveServer.Models { public class ArchiveDbContext : DbContext { public ArchiveDbContext(DbContextOptions2. 编写完整的 CRUD 业务逻辑
打开 Program.cs,删除所有默认生成的代码,替换为以下完整的配置代码。这段代码配置了数据库连接、跨域访问(CORS)策略以及完整的增删改查接口。
```csharp using Microsoft.EntityFrameworkCore; using ArchiveServer.Models; var builder = WebApplication.CreateBuilder(args); // 1. 配置 SQLite 数据库 builder.Services.AddDbContext此时,服务端代码已编写完毕。在命令行输入 dotnet run 即可启动服务端,默认监听地址为 http://localhost:5000 或 https://localhost:5001。
三、客户端开发:WinForms 界面与通信实现

客户端部分我们将构建一个简洁的 Windows 窗体应用,包含数据列表展示和新增/编辑/删除功能。
1. 创建客户端项目并配置
确保当前目录在解决方案根目录,进入客户端项目:
```bash cd ArchiveClient ```为了简化 HTTP 请求和 JSON 处理,我们引入 Newtonsoft.Json 库:
```bash dotnet add package Newtonsoft.Json ```2. 设计档案管理界面
为了方便大家直接复现,我们不使用可视化设计器拖拽控件,而是直接通过代码生成界面。打开 Form1.cs,将代码替换为以下内容。这包含了一个 DataGridView 用于显示列表,以及右侧的输入框和操作按钮。
```csharp using System; using System.Collections.Generic; using System.Net.Http; using System.Net.Http.Json; using System.Text; using System.Windows.Forms; using Newtonsoft.Json; namespace ArchiveClient { public partial class Form1 : Form { // 声明控件 private DataGridView dgvArchives; private TextBox txtTitle, txtCategory, txtDescription, txtId; private DateTimePicker dtpDate; private Button btnAdd, btnUpdate, btnDelete, btnRefresh; private static readonly HttpClient client = new HttpClient(); // 注意:这里的服务端地址需要根据实际启动情况调整,通常为 http://localhost:5xxx private const string ApiBaseUrl = "http://localhost:5000/api/archives"; public Form1() { InitializeComponent(); LoadDataAsync(); // 启动时加载数据 } private void InitializeComponent() { this.Text = "档案管理系统 C/S 版"; this.Width = 800; this.Height = 500; this.StartPosition = FormStartPosition.CenterScreen; // 表格控件 dgvArchives = new DataGridView { Dock = DockStyle.Left, Width = 450, AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill, ReadOnly = true, AllowUserToAddRows = false }; dgvArchives.SelectionMode = DataGridViewSelectionMode.FullRowSelect; dgvArchives.CellClick += DgvArchives_CellClick; // 点击行选择数据 // 输入面板 var panelRight = new Panel { Dock = DockStyle.Fill, Padding = new Padding(10) }; txtId = new TextBox { Visible = false }; // 隐藏ID字段 var lblTitle = new Label { Text = "档案", Top = 20, Left = 0, AutoSize = true }; txtTitle = new TextBox { Top = 40, Left = 0, Width = 300 }; var lblCategory = new Label { Text = "档案分类:", Top = 80, Left = 0, AutoSize = true }; txtCategory = new TextBox { Top = 100, Left = 0, Width = 300 }; var lblDate = new Label { Text = "归档日期:", Top = 140, Left = 0, AutoSize = true }; dtpDate = new DateTimePicker { Top = 160, Left = 0, Width = 300, Format = DateTimePickerFormat.Short }; var lblDesc = new Label { Text = "档案描述:", Top = 200, Left = 0, AutoSize = true }; txtDescription = new TextBox { Top = 220, Left = 0, Width = 300, Height = 80, Multiline = true }; // 按钮 btnAdd = new Button { Text = "新增档案", Top = 320, Left = 0, Width = 90, Height = 30 }; btnAdd.Click += BtnAdd_Click; btnUpdate = new Button { Text = "修改保存", Top = 320, Left = 100, Width = 90, Height = 30 }; btnUpdate.Click += BtnUpdate_Click; btnDelete = new Button { Text = "删除选中", Top = 320, Left = 200, Width = 90, Height = 30, ForeColor = System.Drawing.Color.Red }; btnDelete.Click += BtnDelete_Click; btnRefresh = new Button { Text = "刷新列表", Top = 360, Left = 0, Width = 290, Height = 30 }; btnRefresh.Click += (s, e) => LoadDataAsync(); // 添加控件到面板 panelRight.Controls.AddRange(new Control[] { txtId, lblTitle, txtTitle, lblCategory, txtCategory, lblDate, dtpDate, lblDesc, txtDescription, btnAdd, btnUpdate, btnDelete, btnRefresh }); // 添加控件到窗体 this.Controls.Add(dgvArchives); this.Controls.Add(panelRight); } // 业务逻辑方法 // 加载数据 private async void LoadDataAsync() { try { var data = await client.GetFromJsonAsync- >(ApiBaseUrl);
dgvArchives.DataSource = data;
}
catch (Exception ex)
{
MessageBox.Show($"加载失败: {ex.Message}");
}
}
// 点击表格行回显数据
private void DgvArchives_CellClick(object? sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex >= 0)
{
var row = dgvArchives.Rows[e.RowIndex];
txtId.Text = row.Cells["Id"].Value?.ToString();
txtTitle.Text = row.Cells["Title"].Value?.ToString();
txtCategory.Text = row.Cells["Category"].Value?.ToString();
txtDescription.Text = row.Cells["Description"].Value?.ToString();
if (DateTime.TryParse(row.Cells["CreateDate"].Value?.ToString(), out var dt))
{
dtpDate.Value = dt;
}
}
}
// 新增
private async void BtnAdd_Click(object? sender, EventArgs e)
{
var newItem = new ArchiveItem
{
Title = txtTitle.Text,
Category = txtCategory.Text,
Description = txtDescription.Text,
CreateDate = dtpDate.Value
};
var response = await client.PostAsJsonAsync(ApiBaseUrl, newItem);
if (response.IsSuccessStatusCode)
{
MessageBox.Show("新增成功");
LoadDataAsync();
ClearInputs();
}
}
// 修改
private async void BtnUpdate_Click(object? sender, EventArgs e)
{
if (string.IsNullOrEmpty(txtId.Text)) { MessageBox.Show("请先选择一条记录"); return; }
var updateItem = new ArchiveItem
{
Id = int.Parse(txtId.Text),
Title = txtTitle.Text,
Category = txtCategory.Text,
Description = txtDescription.Text,
CreateDate = dtpDate.Value
};
var response = await client.PutAsJsonAsync($"{ApiBaseUrl}/{updateItem.Id}", updateItem);
if (response.IsSuccessStatusCode)
{
MessageBox.Show("修改成功");
LoadDataAsync();
}
}
// 删除
private async void BtnDelete_Click(object? sender, EventArgs e)
{
if (string.IsNullOrEmpty(txtId.Text)) { MessageBox.Show("请先选择一条记录"); return; }
var dlg = MessageBox.Show("确认删除?", "提示", MessageBoxButtons.OKCancel);
if (dlg == DialogResult.OK)
{
var response = await client.DeleteAsync($"{ApiBaseUrl}/{txtId.Text}");
if (response.IsSuccessStatusCode)
{
MessageBox.Show("删除成功");
LoadDataAsync();
ClearInputs();
}
}
}
private void ClearInputs()
{
txtId.Clear();
txtTitle.Clear();
txtCategory.Clear();
txtDescription.Clear();
}
}
// 定义与服务端对应的实体类(用于反序列化)
public class ArchiveItem
{
public int Id { get; set; }
public string Title { get; set; }
public string Category { get; set; }
public DateTime CreateDate { get; set; }
public string? Description { get; set; }
}
}
```
- 新增测试: 在右侧输入标题“2023年度财务报表”,分类“财务”,选择日期,点击“新增档案”。左侧列表应立即刷新显示该条目。
- 查询测试: 启动时列表会自动加载,点击“刷新列表”可重新从服务端获取最新数据。
- 修改测试: 点击左侧列表中的某一行,右侧文本框会自动填充内容。修改“档案描述”字段,点击“修改保存”,观察列表内容是否更新。
- 删除测试: 选中一行,点击“删除选中”,确认弹窗后,该行应从列表中移除。
注意: 由于 WinForms 默认未启用 System.Net.Http.Json 的扩展方法支持,如果 PostAsJsonAsync 报错,请确保项目文件 ArchiveClient.csproj 中包含以下框架引用,或者手动使用 StringContent 和 JsonConvert.SerializeObject 发送请求。上述代码为了稳健性,已引入 Newtonsoft.Json,但使用了 .NET 6+ 自带的扩展方法。如遇编译错误,请修改 ArchiveClient.csproj 为:
四、编译运行与功能验证
至此,所有代码已准备就绪。现在我们将启动整个 C/S 系统并进行功能测试。
1. 启动服务端
打开第一个命令行窗口,进入 ArchiveServer 目录,运行以下命令启动服务端:
```bash cd D:\ArchiveSystem\ArchiveServer dotnet run ```观察控制台输出,你会看到类似 Now listening on: http://localhost:5000 的提示。请记住这个端口号,如果系统自动分配了 5001 或其他端口,请务必修改客户端代码 Form1.cs 中的 ApiBaseUrl 常量,使其与实际地址一致。
2. 启动客户端
打开第二个命令行窗口,进入 ArchiveClient 目录,运行以下命令启动客户端:
```bash cd D:\ArchiveSystem\ArchiveClient dotnet run ```3. 实操验证增删改查功能
客户端窗体弹出后,按照以下步骤验证:
以上步骤完成了从零构建一个档案软件 C/S 版模块的全过程。服务端负责数据逻辑,客户端负责交互,两者通过 HTTP 协议进行高效通信,且无需配置复杂的 IIS 或 SQL Server,实现了零门槛落地。