ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

ASP.NET与SQL Server构建内部项目管理系统:架构、开发与避坑实践

ASP.NET与SQL Server构建内部项目管理系统:架构、开发与避坑实践 简介这是一套基于ASP.NET的B/S架构项目管理系统开发环境为VS2010采用C#语言配合Access数据库实现适合Web开发学习者、毕业设计或课程设计复用。系统完整覆盖管理员、员工、网管三类角色管理员可维护员工信息、管理项目任务、处理日志及历史项目员工可注册、查看参与项目、添加日志并回复建议网管则负责用户资料维护及数据库备份还原。压缩包共297个文件以aspx页面、cs源码、dll组件、css/js前端资源及mdb数据库文件为主整体约5.09MB目录结构清晰附带完整数据库文件登录地址为Web/login.aspx管理员账号密码admin/1便于直接部署测试。已有505人学习下载适合需要参考完整Web管理系统实现流程的开发者可用于理解角色权限设计、模块化分层及Access数据库操作。1. 为什么“ASP.NET SQL Server C# Web结构”还是内部项目管理系统的最优解拿到“asp.net项目管理系统VS开发sqlserver数据库web结构C#编程”这个标题本质上是一条完整的内部管理系统交付链路用Visual Studio当开发环境C#写业务逻辑SQL Server做数据存储最终以Web结构发布到浏览器里访问。项目管理系统的核心需求——立项、任务分派、进度反馈、工时统计、附件留痕——恰好落在ASP.NET最擅长的表单加表格交互区间。相对前后端分离那套全家桶这个组合在小团队、短周期、强定制需求下交付速度明显更快。这也是很多企业内网至今还在跑ASP.NET Web Forms的原因。适合谁接私活的开发者、刚走上.NET岗位的新人以及需要快速给公司搭一套可用项目管理后台的运维同学。2. 技术栈与架构选型Web Forms、SQL Server版本、三层架构怎么一锤定音2.1 选型Web Forms不是落后是适合“表单密集型”系统项目管理系统的大多数页面是什么项目列表、任务列表、详情页、编辑表单、统计报表。这类页面天然适合事件驱动模型拖一个GridView上去配好数据源页面加载时自动绑数据点“编辑”按钮后台写一段Update逻辑。Web Forms把页面生命周期封装好ViewState帮你保存控件状态这些在MVC里都要自己手动处理。我接这类项目时的判断标准很直接用户数在500以内、页面数不超过60个、交互以表格和表单为主用Web Forms加.NET Framework 4.8能在两周内拿出可用版本。MVC不是不能做但路由、模型绑定、防伪令牌这些概念新手就要消化一周。如果团队明确要长期演进、要前后端分离那就直接上ASP.NET Core MVC那已经不属于标题里这个组合的典型用法了。提示如果客户嫌界面老气不要急着换框架。Web Forms页面照样可以套Bootstrap加jQuery后面第六章会讲具体做法。2.2 环境准备VS版本、SQL Server版本与安装后第一件事开发环境我固定用Visual Studio 2022社区版免费支持.NET Framework 4.8和SQL Server数据工具。说到这个新手常把Visual Studio和VS Code搞混VS Code虽然也能写C#但要做ASP.NET Web Forms网站项目还是老老实实用Visual Studio项目模板、可视化设计器、数据源绑定这些功能只有VS里有。SQL Server方面生产环境推荐2019以上版本。2016以下版本缺一些常用函数比如后面会提到的STRING_SPLIT低版本直接报错。安装SQL Server时记下实例名默认实例是连“.”或“localhost”命名实例像“localhost\SQLEXPRESS”这种。网上SQL Server安装教程一大把但装完之后的配置没人讲这里必须补上关键一步。装完SQL Server第一件事不是建库是打开“SQL Server配置管理器”把TCP/IP协议启用。默认情况下TCP/IP可能是禁用的不开的话VS里连数据库会报超时或“远程主机强迫关闭连接”很多新手在这个地方卡一整天以为是代码问题其实协议没开。改完配置记得重启SQL Server服务配置才生效。2.3 连接字符串写给web.config的那几行别偷懒Web项目的数据访问入口是web.config里的connectionStrings节点。我常用的写法connectionStrings add namePMSConnection providerNameSystem.Data.SqlClient connectionStringData Source.;Initial CatalogProjectManager;User IDsa;PasswordYourPass123;Connect Timeout30;EncryptFalse;TrustServerCertificateTrue / /connectionStrings逻辑说明Data Source是数据库实例点号代表本机默认实例Initial Catalog是数据库名User ID和Password是SQL Server登录账号Connect Timeout30表示连接超过30秒报错避免页面长时间卡住EncryptFalse和TrustServerCertificateTrue是给.NET Framework的旧驱动用的防止新版驱动默认启用加密导致连接握手失败。如果用的是Windows认证登录数据库把User ID和Password整段删掉换成Integrated SecurityTrue就行。连接字符串写在web.config里发布前用web.config转换功能把开发库密码和正式库密码分开别把生产密码提交到代码仓库。2.4 三层架构什么时候值得按UI/BLL/DAL/Model拆我经手的项目管理系统九成用经典三层架构表示层放.aspx页面业务层放BLL类库数据访问层放DAL类库外加Model实体类。引用方向是UI引用BLLBLL引用DALDAL引用Model不允许反向引用。这样做的好处是换数据库时只改DAL换页面时不动业务逻辑。如果你翻过《C#高级编程》里的泛型章节就知道DAL层非常适合写一个泛型基类减少大量重复的增删改查代码。比如一个BaseDAL 里面放通用的ExecuteNonQuery和ExecuteReader方法每个实体表的数据访问类继承它就好。但要注意如果系统页面少于15个或者只是给部门内部临时用硬拆三层反而增加工作量。我见过一个项目就8个页面也拆了三层改个字段要跨三个项目点来点去纯粹给自己添堵。3. SQL Server数据库设计五张核心表、索引与存储过程怎么写才不返工3.1 五张核心表从项目到工时的主外键关系项目管理系统的数据模型可以精简到五张表用户表、项目表、任务表、工时表、附件表。成本、风险那些模块都可以在这五张表上演化先建这五张不会错。建表脚本CREATE TABLE Users ( UserId INT IDENTITY(1,1) PRIMARY KEY, UserName NVARCHAR(50) NOT NULL UNIQUE, PasswordHash NVARCHAR(128) NOT NULL, DisplayName NVARCHAR(50) NOT NULL, RoleName NVARCHAR(20) NOT NULL DEFAULT Member, IsActive BIT NOT NULL DEFAULT 1, CreatedAt DATETIME DEFAULT GETDATE() ); CREATE TABLE Projects ( ProjectId INT IDENTITY(1,1) PRIMARY KEY, ProjectNo NVARCHAR(20) NOT NULL UNIQUE, ProjectName NVARCHAR(100) NOT NULL, OwnerId INT NOT NULL REFERENCES Users(UserId), Status TINYINT NOT NULL DEFAULT 0, StartDate DATE NULL, EndDate DATE NULL, Description NVARCHAR(500) NULL, CreatedAt DATETIME DEFAULT GETDATE() ); CREATE TABLE Tasks ( TaskId INT IDENTITY(1,1) PRIMARY KEY, ProjectId INT NOT NULL REFERENCES Projects(ProjectId), TaskName NVARCHAR(100) NOT NULL, AssigneeId INT NULL REFERENCES Users(UserId), Priority TINYINT NOT NULL DEFAULT 1, Status TINYINT NOT NULL DEFAULT 0, PlannedHours DECIMAL(8,2) NULL, DueDate DATE NULL, CreatedAt DATETIME DEFAULT GETDATE() ); CREATE TABLE WorkLogs ( LogId INT IDENTITY(1,1) PRIMARY KEY, TaskId INT NOT NULL REFERENCES Tasks(TaskId), UserId INT NOT NULL REFERENCES Users(UserId), WorkDate DATE NOT NULL, Hours DECIMAL(8,2) NOT NULL, Remark NVARCHAR(200) NULL, CreatedAt DATETIME DEFAULT GETDATE() ); CREATE TABLE ProjectFiles ( FileId INT IDENTITY(1,1) PRIMARY KEY, ProjectId INT NOT NULL REFERENCES Projects(ProjectId), FileName NVARCHAR(200) NOT NULL, FilePath NVARCHAR(300) NOT NULL, UploadedBy INT NOT NULL REFERENCES Users(UserId), UploadedAt DATETIME DEFAULT GETDATE() );参数说明所有名称类字段都用NVARCHAR而不是VARCHAR因为NVARCHAR按Unicode存储中文、日语都不会乱码主键用IDENTITY自增简单可靠不适合分布式但内部系统够用状态字段用TINYINT存数字枚举比如任务状态0未开始、1进行中、2已完成、3挂起不要直接存中文否则后面写统计SQL时到处是LIKE匹配性能差还容易错工时字段用DECIMAL(8,2)可以记录半个小时的粒度。逻辑说明外键约束必须建否则业务代码里插入一条不存在的项目ID数据库不会报错等查数据时才发现关联不上。WorkLogs表是任务和用户的多对多关系表一个任务多条工时记录一个用户一个项目下也有多条。3.2 索引怎么加别一上来就给所有列建索引索引不是越多越好。我在这个系统里只对会出现在WHERE和JOIN里的列建索引CREATE INDEX IX_Tasks_ProjectId ON Tasks(ProjectId); CREATE INDEX IX_Tasks_AssigneeId ON Tasks(AssigneeId); CREATE INDEX IX_Tasks_Status ON Tasks(Status); CREATE INDEX IX_WorkLogs_TaskId ON WorkLogs(TaskId); CREATE INDEX IX_WorkLogs_UserId ON WorkLogs(UserId); CREATE INDEX IX_Projects_OwnerId ON Projects(OwnerId);逻辑说明索引加快查询但每次INSERT和UPDATE都要同步维护索引所以建得越多写入越慢。建议只给外键列、状态列、常用筛选列建索引。比如WorkLogs表按WorkDate查工时的场景多但如果你还没确定要用日期做统计可以先不建等报表SQL写出来看执行计划再补。3.3 视图与存储过程进度统计和批量分任务统计每个项目的任务完成率用视图最方便CREATE VIEW v_ProjectProgress AS SELECT p.ProjectId, p.ProjectName, COUNT(t.TaskId) AS TotalTasks, SUM(CASE WHEN t.Status 2 THEN 1 ELSE 0 END) AS DoneTasks, CAST(SUM(CASE WHEN t.Status 2 THEN 1 ELSE 0 END) AS DECIMAL(8,2)) / NULLIF(COUNT(t.TaskId), 0) * 100 AS ProgressPercent FROM Projects p LEFT JOIN Tasks t ON p.ProjectId t.ProjectId GROUP BY p.ProjectId, p.ProjectName;逻辑说明LEFT JOIN保证没有任务的空项目也出现在视图里NULLIF防止除数为零把完成数转成DECIMAL再相除否则整数除以整数结果还是整数进度永远等于0或100。批量分任务时我习惯用存储过程接收一个“1,2,3”格式的ID串SQL Server 2016以上可以用STRING_SPLIT拆开。新手经常在这里踩坑SQL Server 2014及以下没有STRING_SPLIT函数执行会报“invalid object name string_split”。低版本只能写循环拆分所以我前面才强调生产环境尽量上2019以上。CREATE PROCEDURE sp_AssignTaskBatch TaskIds NVARCHAR(500), AssigneeId INT AS BEGIN SET NOCOUNT ON; UPDATE t SET t.AssigneeId AssigneeId, t.Status CASE WHEN t.Status 0 THEN 1 ELSE t.Status END FROM Tasks t INNER JOIN STRING_SPLIT(TaskIds, ,) s ON t.TaskId CAST(s.value AS INT); END参数说明TaskIds是逗号分隔的任务ID串STRING_SPLIT返回value列是NVARCHAR类型要和INT列比较必须先CAST转换SET NOCOUNT ON减少网络回传的影响。注意如果ID串里混入了非数字字符CAST会直接报错所以业务层在调用前必须做合法性校验。3.4 在Visual Studio里管理数据库不用SSMS也能干活很多开发机没装SSMS其实Visual Studio自带SQL Server对象资源管理器。视图菜单里打开它连接上数据库实例后可以直接建库、建表、执行SQL脚本、看表数据。写复杂SQL时在VS里新建一个SQL文件选中片段执行查询结果直接显示在下方的网格里。调试连接字符串有个实用技巧在VS的服务器资源管理器里新建连接填好服务器名和账号点“测试连接”如果这里能通过但程序里报错问题多半出在连接字符串格式上如果这里都连不上就回去检查SQL Server配置管理器的TCP/IP和实例名。这个排查顺序能帮你省掉半天时间。4. 用Visual Studio把核心功能跑通登录、项目列表、CRUD与附件上传4.1 登录页与FormsAuthentication最小实现项目管理系统的权限不用做太复杂角色就三种管理员、项目经理、普通成员。用ASP.NET自带的FormsAuthentication做登录票据最小实现如下。Login.aspx.cs的核心代码protected void btnLogin_Click(object sender, EventArgs e) { string userName txtUserName.Text.Trim(); string password txtPassword.Text; DataTable dt UserDal.GetUserByNameAndPassword(userName, password); if (dt.Rows.Count 0) { FormsAuthentication.SetAuthCookie(userName, false); Response.Redirect(~/Default.aspx); } else { lblMsg.Text 用户名或密码错误; } }逻辑说明先从DAL层按用户名和密码查出用户查不到就提示错误查到了就调用FormsAuthentication.SetAuthCookie写入认证票据之后每个页面通过Page.User.Identity.IsAuthenticated判断是否登录。这里有个点必须注意密码不能明文比对DAL查询时应先对用户输入的密码做Hash后再传SQL。常见做法是SHA256加盐public static string ComputeHash(string password, string salt) { using (var sha System.Security.Cryptography.SHA256.Create()) { byte[] bytes sha.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password salt)); return Convert.ToBase64String(bytes); } }参数说明密码Hash再加一个随机盐同一密码不同盐值结果不同防止彩虹表爆破。盐存在Users表里注册时生成登录时取出来重新计算比对。4.2 项目列表页GridView绑定数据与分页排序项目列表页是管理系统的门面。我通常直接在aspx页面放GridView后台写绑定方法。Projects.aspx的GridView声明asp:GridView IDgvProjects runatserver AutoGenerateColumnsFalse AllowPagingTrue PageSize10 OnPageIndexChanginggvProjects_PageIndexChanging Columns asp:BoundField DataFieldProjectNo HeaderText项目编号 / asp:BoundField DataFieldProjectName HeaderText项目名称 / asp:BoundField DataFieldDisplayName HeaderText负责人 / asp:BoundField DataFieldStatus HeaderText状态 / /Columns /asp:GridViewProjects.aspx.cs的绑定代码private void BindProjects() { DataTable dt ProjectDal.GetAllProjects(); gvProjects.DataSource dt; gvProjects.DataBind(); } protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { BindProjects(); } } protected void gvProjects_PageIndexChanging(object sender, GridViewPageEventArgs e) { gvProjects.PageIndex e.NewPageIndex; BindProjects(); }逻辑说明分页事件尤其容易翻车。如果忘记处理OnPageIndexChanging事件点击页码时GridView会回到第一页或直接报错。Page_Load里必须用IsPostBack包裹绑定逻辑否则回发时数据会被二次绑定用户点一下分页按钮页面刚设置的PageIndex马上被Page_Load覆盖掉。状态列显示的是数字不直观。我的做法是在RowDataBound事件里把数字翻译成中文或者直接用TemplateField加Label。注意页面标题和列头的中文显示aspx页面顶部要加meta charset否则浏览器用默认编码解析中文必乱码% Page LanguageC# CodeBehindProjects.aspx.cs InheritsPMS.Web.Projects % !DOCTYPE html html head runatserver meta charsetutf-8 / title项目列表/title /head4.3 参数化SQL实现新增和编辑别拼字符串做项目管理系统最怕看到这样的代码直接在C#里拼SQL字符串再执行这是后期被脱库的根源。所有写操作我都用SqlParameter参数化DAL层一个标准的新增项目方法长这样public static bool InsertProject(ProjectModel model) { string sql INSERT INTO Projects(ProjectNo, ProjectName, OwnerId, Status, StartDate, EndDate, Description) VALUES(ProjectNo, ProjectName, OwnerId, Status, StartDate, EndDate, Description); SqlParameter[] parameters { new SqlParameter(ProjectNo, SqlDbType.NVarChar, 20) { Value model.ProjectNo }, new SqlParameter(ProjectName, SqlDbType.NVarChar, 100) { Value model.ProjectName }, new SqlParameter(OwnerId, SqlDbType.Int) { Value model.OwnerId }, new SqlParameter(Status, SqlDbType.TinyInt) { Value model.Status }, new SqlParameter(StartDate, SqlDbType.Date) { Value (object)model.StartDate ?? DBNull.Value }, new SqlParameter(EndDate, SqlDbType.Date) { Value (object)model.EndDate ?? DBNull.Value }, new SqlParameter(Description, SqlDbType.NVarChar, 500) { Value (object)model.Description ?? DBNull.Value } }; return SqlHelper.ExecuteNonQuery(sql, parameters) 0; }参数说明每个SqlParameter尽量显式指定DbType和长度给数据库明确类型信息避免隐式转换导致索引失效可空字段判断null后赋DBNull.Value不能直接传null否则会报“未处理的异常”或参数类型不匹配日期字段用SqlDbType.Date而不是DateTime避免把时分秒也写进表。逻辑说明这种写法让SQL Server把参数当作值处理而不是拼进SQL语句SQL注入的脚本只会被当成普通字符串存进数据库不会执行。隐患排查时可以写一个简单的检测搜索代码里所有包含“SELECT”“UPDATE”“DELETE”的字符串拼接凡是出现SqlParameter对比一下是不是每条拼接语句都配了参数。4.4 文件上传项目附件的存储与服务端校验项目管理中的附件比如立项文档、设计图纸存储上我一般用“服务端目录加数据库记录路径”的方案不把文件本身放进SQL Server。aspx页面放一个FileUpload控件asp:FileUpload IDfuAttachment runatserver AllowMultiplefalse / asp:Button IDbtnUpload runatserver Text上传 OnClickbtnUpload_Click /后台代码protected void btnUpload_Click(object sender, EventArgs e) { if (!fuAttachment.HasFile) return; if (fuAttachment.PostedFile.ContentLength 30 * 1024 * 1024) { lblMsg.Text 文件不能超过30MB; return; } string ext Path.GetExtension(fuAttachment.FileName).ToLower(); string[] allowed { .pdf, .doc, .docx, .xls, .xlsx, .zip }; if (!allowed.Contains(ext)) { lblMsg.Text 不允许的文件类型; return; } string dir Server.MapPath(~/Uploads/Projects/ projectId); if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } string newName Guid.NewGuid().ToString(N) ext; string fullPath Path.Combine(dir, newName); fuAttachment.SaveAs(fullPath); ProjectFileDal.Insert(projectId, fuAttachment.FileName, ~/Uploads/Projects/ projectId / newName, currentUserId); }逻辑说明文件大小和扩展名必须在服务端校验客户端限制很容易被绕过。重新命名用Guid避免上传同名的docx互相覆盖。IIS上部署时记得给网站物理目录的Uploads文件夹加写权限否则SaveAs会抛“对路径的访问被拒绝”。数据库里只存虚拟路径页面下载时直接拼URL访问。5. 必踩的五个坑连接失败、GridView翻页失灵、SQL注入与中文乱码5.1 现象连接字符串没问题却一直报“远程主机强迫关闭连接”这个报错在排查时最容易误导人。我见过一个系统开发环境跑得好好的发布到服务器上就报这个错查了半天防火墙最后发现是服务器上SQL Server的TCP/IP协议没启用。原因SQL Server默认可能只开了Shared Memory和Named PipesTCP/IP被禁用。本机用“.”连接时走了Shared Memory还能通但网页发布到IIS后从远程连接就必须走TCP/IP。解决步骤打开SQL Server配置管理器双击“SQL Server网络配置”下的实例右键TCP/IP选择启用再到“SQL Server服务”里重启SQL Server服务。改完用命令行验证一次sqlcmd -S 服务器IP,1433 -U sa -P 密码 -Q SELECT VERSION能查到版本号说明端口和协议都通了。如果sqlcmd也连不上再查Windows防火墙是否放行1433端口。这个坑的核心教训本机能连不代表远程能连发布前先把远程连接验证做完不要等部署后才排查。5.2 现象GridView点击页码后数据没变或者一直停在第一页这是Web Forms新手最常遇到的分页失灵。现象有两个版本点击第3页列表还是第1页的内容或者点击页码页面闪一下列表回到第1页。原因GridView本身只负责显示分页数据要后台重新绑。第一忘记处理OnPageIndexChanging事件GridView的PageIndex永远不会变第二Page_Load里没有用IsPostBack判断导致每次回发先把PageIndex重置成0再绑定数据。解决给GridView加上OnPageIndexChanging事件事件里设置PageIndex并重新调用绑定方法Page_Load里必须把绑定代码放进if (!IsPostBack)块。另外如果GridView启用了Sorting还要处理OnSorting事件否则排序列名会被当作参数传到回发里有时会引发异常。5.3 现象任务表被注入脚本清空整个系统数据丢失这是web安全领域老生常谈但永远有人中招的坑。现象是系统某个页面的查询框输入了“’; DELETE FROM Tasks; --”这类内容提交后任务表被清空。原因后台代码直接拼接字符串比如“SELECT * FROM Tasks WHERE TaskName LIKE % txtKeyword.Text %”用户输入被当成SQL执行。解决所有动态条件查询全部用SqlParameter拼接的只是参数占位符。比如上面这个查询改成string sql SELECT * FROM Tasks WHERE TaskName LIKE kw; SqlCommand cmd new SqlCommand(sql, conn); cmd.Parameters.AddWithValue(kw, % txtKeyword.Text.Trim() %);再给连接字符串加上“PoolingTrue”不影响但千万别图省事发数组拼接。SQL Server没有关闭动态SQL开关防范只能靠参数化。数据恢复的后悔药是提前做好备份第6章会放定时备份脚本。5.4 现象SQL Server导入数据时报“数据无效”或者字符串转数字失败用导入向导把Excel数据导进Tasks表经常报“无法导入数据 数据无效”。现象是向导走到“选择源表和视图”就中断日志提示第几行数据有问题。原因源Excel某列是文本格式目标表列是INT或DATE向导自动推断类型失败。比如“2024/1/5”这种日期字符串在Excel里显示正常但底层实际存的是数字序列导过去就成了奇怪的数字或直接报无效。解决先不要用向导硬导把Excel另存为CSV文件注意编码选UTF-8带BOM否则中文变乱码再用导入向导选CSV源并在“高级”里手动指定每列数据类型。如果只要处理少量数据直接写SQLSELECT TRY_CAST(value AS INT) FROM STRING_SPLIT(1,2,x, ,);TRY_CAST是SQL Server 2012以上提供的安全转换函数转不了返回NULL不会报错中断。用它查出脏数据行清洗后再批量导入。5.5 现象部署到服务器后中文全部变成问号界面乱码开发环境中文正常发布到服务器IIS后所有中文显示为“???”数据库里读出来的中文也全是问号。这个坑经常和数据库排序规则绑定在一起。原因有两层一是数据库本身的Collation不是中文字符集比如默认的SQL_Latin1_General_CP1_CI_AS二是页面响应编码没指定UTF-8浏览器按系统区域编码解析。解决数据库层面在建库时指定排序规则CREATE DATABASE ProjectManager COLLATE Chinese_PRC_CI_AS;生产库已经建好的可以改库级别排序规则但已存储的数据可能仍有问题最稳妥是建新库导数据。页面层面web.config里加强制编码globalization requestEncodingutf-8 responseEncodingutf-8 fileEncodingutf-8 /还有一个隐藏点aspx文件本身要用“UTF-8带签名”格式保存如果文件是ANSI编码即使meta声明UTF-8中文还是会乱。Visual Studio里打开文件文件菜单另存为点编码保存选“Unicode (UTF-8 带签名) - 代码页 65001”再改一次。6. 最后一步优化无刷新交互、导出Excel与发布备份的实用技巧6.1 用UpdatePanel把列表页改成无刷新操作GridView翻页每次都整页回发体验确实一般。常见做法是套一个UpdatePanel再配少量jQuery提示比为了找GridView的jQuery插件去引入整套前端框架靠谱得多。asp:ScriptManager IDsm runatserver/asp:ScriptManager asp:UpdatePanel IDupGrid runatserver ContentTemplate asp:GridView IDgvProjects runatserver AllowPagingTrue OnPageIndexChanginggvProjects_PageIndexChanging / /ContentTemplate /asp:UpdatePanel逻辑说明UpdatePanel拦截内部控件的回发用异步局部更新替代整页刷新。注意ScriptManager必须放在UpdatePanel之前。局部刷新模式下页面上其他静态内容不会闪烁但后台绑定代码不用改这是它比纯jQuery异步方案省事的地方。如果是数据量大的报表页异步回发期间用户反复点击会堆积请求可以在ScriptManager的AsyncPostBackTimeout里加超时时长控制。6.2 一键导出Excel与每日备份的落地脚本给项目列表加导出Excel按钮我用最简单的GridView直接输出法protected void btnExport_Click(object sender, EventArgs e) { BindProjects(); Response.Clear(); Response.Buffer true; Response.Charset utf-8; Response.ContentEncoding System.Text.Encoding.UTF8; Response.AddHeader(content-disposition, attachment;filenameProjects.xls); Response.ContentType application/vnd.ms-excel; StringWriter sw new StringWriter(); HtmlTextWriter hw new HtmlTextWriter(sw); gvProjects.RenderControl(hw); Response.Write(sw.ToString()); Response.End(); }逻辑说明这种方式把GridView渲染成表格写入Excel足够内部系统用。前提是要重写GridView的VerifyRenderingInServerForm方法否则会报“必须放在runatserver的表单标记中”同时导出的列头是中文需要确保页面编码是UTF-8不然Excel打开会乱。备份我放到SQL Server Agent里跑每日任务脚本就一条BACKUP DATABASE ProjectManager TO DISKD:\Backup\ProjectManager_ REPLACE(CONVERT(VARCHAR(10), GETDATE(), 120), -, ) .bak WITH FORMAT, COMPRESSION;6.3 收尾发布与维护Web Forms项目发布很简单右键项目选“发布”选文件系统或Web Deploy输出到服务器IIS的物理目录。但有一个高频坑——IIS应用程序池的.NET CLR版本必须选“v4.0”托管管道模式用“集成”。选错版本页面直接报500或“无法加载类型”。而且发布出来的web.config里的连接字符串要是正式库别把开发库密码带到线上。我给这类系统收尾时另一个保留项目是看一眼SQL Server的错误日志和事务日志大小日志增长到几十GB会导致备份变慢磁盘被吃满。检查一下恢复模式如果公司没做完整备份策略我一般会在作业里把数据库恢复模式设成简单模式配合每日差异备份能省出大量空间。老实说内部管理系统安全性和稳定性不用做到互联网级别但外键约束、参数化SQL、每日备份这三样缺一样后续都要拿血泪去填。我做过的第一个项目管理系统就是败在连接字符串上。开发库用Windows认证测试通过部署到服务器发现服务器是纯SQL认证环境web.config里那行配置文件改来改去最后线上用户全屏报连接错误半夜起来回滚。从那以后我养成了一个习惯任何系统提测前先写一个只读接口验证数据库连通性发布清单里逐项核对连接字符串、应用程序池版本和备份任务。这套流程虽然土但确实帮我避掉了后来绝大多数“上了线才发现”的翻车。希望帮到你。本文还有配套的精品资源点击获取
返回列表