
简介这是一款基于ASP.NET的开源在线考试系统源代码面向需要完成课程设计、毕业设计或搭建轻量级考试平台的计算机学习者和开发者。系统内置分类验证登录模块能够按管理员、教师、学生三种身份自动区分操作入口保证角色权限隔离考试环节采用随机抽题方式考生提交试卷后立即显示得分流程简洁且客观公正。后台管理分为系统管理模块与试题管理模块前者由高级管理员负责全局配置和维护后者供教师管理自己任教科目的试题并可查看学生的考试成绩覆盖了从题库维护到成绩统计的完整闭环。资源包为rar压缩格式整体容量约282KB虽然体积很小但包含登录验证、随机组卷、在线答题、成绩判定等核心功能模块代码结构完整可直接导入Visual Studio进行学习或二次改造。目前已有1916人浏览学习对于寻求ASP.NET实战项目的读者而言这份代码提供了清晰的权限设计思路与典型业务实现可帮助你快速上手并扩展出自己的考试系统。1. 这套开源代码到底能干什么先想清楚你要的是毕设还是生产系统期末考试前两周教务老师把需求拍在桌上要能管题库、自动组卷学生在线答题交卷自动出分最好还能防作弊。外包报价一万八、工期三周这时候去 GitHub、Gitee 搜“ASP.NET 在线考试系统 源代码 开源”能翻出几十个现成项目。这些源码质量参差不齐但好消息是在线考试系统是 .NET 圈最经典的业务型项目之一结构就那几块——题库、试卷、考试、判分、成绩数据模型二十年内没大变过。只要仓库里有完整的数据库脚本、能正常编译、登录后能把“出题-答题-判分-查成绩”这条链路走通剩下的事就是改改样式、调调规则。这篇笔记就按我实际跑这类源码的顺序来讲先教你挑一个能用的版本再讲怎么把数据库和站点跑起来哪几块代码最值得改以及最容易翻车的地方都在哪。这个场景适合三类人做毕业设计想找现成框架再二次开发的学生企业内部要搭培训考核系统但预算有限的工程师还有想学 .NET 传统分层架构的新手。先说结论别指望下载下来就能上线但花一到两天把数据库理顺、把默认账号跑通这套代码能省你三周开发量代价是你要有面对老代码的心理准备。2. 挑一个能跑的开源版本先分清 Web Forms、MVC 与 ASP.NET Core2.1 三种 ASP.NET 形态选错等于给自己埋雷搜“ASP.NET 在线考试系统”你拿到的源码大概率是三种形态之一ASP.NET Web Forms、ASP.NET MVC以及这两年新写的 ASP.NET Core MVC。很多新手把项目拉下来才发现根本不是自己熟悉的那套这叫开场翻车。Web Forms 是 2000 年代到 2010 年代的主流特征是大量 .aspx 文件和服务端控件事件驱动模型拖控件就能做页面。老一代教育类开源项目很多是这个形态优点是开发快缺点是页面逻辑和业务逻辑缠在一起改起来像在拆毛线团。MVC 则是路由驱动Controller-Action-View 分层清晰适合二次开发2012 到 2018 年间的开源考试系统大多长这样。ASP.NET Core MVC 是跨平台的新一代但搜“在线考试系统开源”时真正用 Core 写完整考试链路的仓库反而不多很多是个人练手项目模块不全。判断方法很简单打开源码根目录看有没有 .aspx 文件有就是 Web Forms有没有 Controllers 文件夹有就是 MVC有没有 .csproj 里写 net8.0 / net6.0 这种目标框架有就是 Core。我的建议是优先选 ASP.NET MVC 或 ASP.NET Core MVC 版本因为你要改的是业务逻辑不是去跟 ViewState 搏斗。2.2 判断源码值不值得下的四个硬指标别看到 README 写得漂亮就直接下载。我一般先看四个东西全部通过才往本地拉。第一个硬指标是数据库脚本完不完整。项目里有没有 .sql 文件里面有没有建表语句和初始数据。题库、用户表、考试记录表这些核心表必须齐全。很多开源项目只给了代码数据库脚本丢在网盘里或者干脆没有这种直接跳过。第二个指标是有没有默认账号说明。README 里写了“管理员 admin / 密码 123456”这种种子数据你才能第一次登录进去。找不到账号信息的项目你得先去翻数据库脚本里的 INSERT 语句翻不到就只能自己造数据体验非常糟。第三个指标是能不能直接编译。打开 .sln 解决方案文件看项目引用有没有明显的缺包痕迹。老项目如果用了 NuGet 第三方库拉下来后 Visual Studio 不还原包是编译不过的。没有 package.config 或 PackageReference 声明的项目说明依赖可能被砍了一半慎用。第四个指标是技术栈跟你的部署环境匹配。如果线上服务器只有 Windows IIS那 .NET Framework 4.x 的 MVC 项目完全够用如果你想部署到 Linux 容器里就老老实实找 ASP.NET Core 版本。别为了追新技术强行上 Core很多老考试系统在 Framework 上跑了十年没出过事。3. 把源码跑起来数据库还原、连接字符串与 IIS 部署3.1 建库建表别直接附加 mdf用脚本重建最稳拿到源码后的第一步永远是把数据库搞出来。开源项目给的数据库交付方式无非两种一种给你 .mdf 数据库文件让你附加另一种给你 .sql 脚本让你执行。我的血泪经验是优先用 SQL 脚本重建不要碰 .mdf。原因是 mdf 文件的 SQL Server 版本兼容性问题能让人怀疑人生——你在 SQL Server 2012 上附加 2019 生成的库文件大概率报“数据库版本 904 不受支持”而脚本重建几乎没有版本门槛。常见做法是打开 SQL Server Management Studio新建一个数据库然后打开项目里的 .sql 脚本直接执行。脚本通常包含建库语句和建表语句但我建议你只执行建表部分单独手工建库这样能避免脚本里的 USE 语句把库建到你不想去的位置。核心表结构一般长这样CREATE TABLE [dbo].[Student]( [StudentId] INT IDENTITY(1,1) PRIMARY KEY, [StudentNo] NVARCHAR(50) NOT NULL, -- 学号 [StudentName] NVARCHAR(50) NOT NULL, -- 姓名 [Password] NVARCHAR(128) NOT NULL, -- 登录密码多数老项目存明文或MD5 [ClassName] NVARCHAR(100) NULL, -- 班级 [CreateTime] DATETIME DEFAULT GETDATE() ); CREATE TABLE [dbo].[Question]( [QuestionId] INT IDENTITY(1,1) PRIMARY KEY, [SubjectId] INT NOT NULL, -- 所属科目 [QuestionType] INT NOT NULL, -- 1单选 2多选 3判断 4简答 [Content] NVARCHAR(MAX) NOT NULL, -- 题干 [OptionA] NVARCHAR(500) NULL, [OptionB] NVARCHAR(500) NULL, [OptionC] NVARCHAR(500) NULL, [OptionD] NVARCHAR(500) NULL, [Answer] NVARCHAR(50) NOT NULL, -- 标准答案单选存A多选存ABD [Score] INT NOT NULL DEFAULT 2, -- 单题分值 [Difficulty] INT NULL DEFAULT 1 -- 难度系数用于组卷 );执行完脚本后检查两个东西一是表列表里有没有考试记录表ExamRecord 或 ExamResult二是脚本末尾有没有 INSERT 语句写入默认账号。很多老项目把默认账号写在注释里翻阅脚本时留意“admin”字样。执行完先手工跑一条查询确认账号表有数据再去启动 Web 项目否则到登录那一步又要折返。3.2 改连接字符串一个配置节点决定能不能连上库代码里的数据库连接串一般是写在 Web.config.NET Framework 项目或 appsettings.jsonASP.NET Core 项目里。90% 的项目跑不起来都是因为这一行没改对。Web.config 里的连接字符串长这样connectionStrings add nameConnectionString connectionStringServer.;DatabaseOnlineExam;User Idsa;Password123456; providerNameSystem.Data.SqlClient / /connectionStrings参数说明很简单Server 是数据库实例名本机用英文句点“.”或“localhost”都行命名实例要写成“你的机器名\实例名”Database 是刚才建的库名一定和脚本建出来的库名严格一致User Id 和 Password 是 SQL Server 登录账号我建议不要直接用 sa单独建一个只读业务账号但开源项目默认连 sa本地调试图省事可以先用 sa上线前再改。还有一类老源码用的连接串是“Data Source.;Initial CatalogOnlineExam;Integrated SecurityTrue”这是 Windows 认证模式不需要账号密码。如果你不确定用哪种先看 SQL Server 的登录模式设置用 SQL Server 认证就选第一种用 Windows 认证就选第二种。改完连接串后务必重编译一次因为 Web.config 的修改会触发应用程序域重启如果你用的 Web Forms 项目运行时动态修改可能不生效。3.3 用 IIS Express 或完整 IIS 把它跑起来本地调试时最简单的办法是用 Visual Studio 打开 .sln 直接 F5 跑默认用 IIS Express 启动它会自动处理虚拟目录和端口。注意看启动项目是不是你想要的 Web 层——有些解决方案里有多个项目启动一个类库项目是什么都不会发生的页面白屏半天才反应过来选错了启动项。要部署到真实 IIS 上流程是右键 Web 项目发布到本地文件夹然后在 IIS 里新建网站、物理路径指向发布目录、端口设一个不冲突的号应用程序池选“集成模式”.NET 版本根据源码情况选 v4.0 或 v4.5。ASP.NET Core 项目部署方式不一样需要安装 Windows Hosting Bundle 并用“无托管代码”的应用程序池这跟传统 .NET Framework 项目有本质区别别混着来。发布完成后浏览器访问本机 IP 加端口看到登录页说明 IIS 这块通了。4. 最常改的三块代码登录权限、组卷与自动判分4.1 登录与权限Session 判断放在哪一层比用什么技术更关键跑通登录是验证代码逻辑的第一步。老开源项目的登录逻辑基本长一个样拿页面输入的账号密码去数据库用户表里比对比对成功就写 Session然后跳转页面。这里最容易改错的是角色判断。一张用户表同时存学生、教师、管理员三种角色时登录代码通常长这样// 登录按钮事件以Web Forms为例 string account txtUserName.Text.Trim(); string pwd txtPassword.Text.Trim(); string sql SELECT UserId, Role FROM SysUser WHERE UserNameacc AND Passwordpwd; using (SqlConnection conn new SqlConnection(ConfigurationManager.ConnectionStrings[ConnectionString].ConnectionString)) { SqlCommand cmd new SqlCommand(sql, conn); cmd.Parameters.AddWithValue(acc, account); cmd.Parameters.AddWithValue(pwd, pwd); conn.Open(); SqlDataReader reader cmd.ExecuteReader(); if (reader.Read()) { Session[UserId] reader[UserId].ToString(); Session[Role] reader[Role].ToString(); // 角色admin / teacher / student // 根据角色跳转到不同首页 string role reader[Role].ToString(); if (role admin) Response.Redirect(/Admin/Index.aspx); else if (role teacher) Response.Redirect(/Teacher/ExamList.aspx); else Response.Redirect(/Student/ExamList.aspx); } else { lblMsg.Text 用户名或密码错误; } reader.Close(); // 不关闭 DataReader 后面会踩坑第五章细说 }这段代码的逻辑说明先拼 SQL 去 SysUser 表查账号密码查到了就按角色分流。注意我用的是参数化查询而不是字符串拼接这既是为了防注入也是因为老代码里常见的 SqlParameter 集合操作容易写错。密码这一栏很多仓库直接存明文本地跑没问题如果要在真实环境用建议改成 MD5 或 SHA256 哈希再比——但这属于二次开发范围后面讲。改这段代码最常踩的坑是你改了表名或字段名但忘了同步修改 SQL 语句。老项目的数据库表命名非常不规范有的叫 T_User有的叫 UsersInfo代码和数据库对不上是家常便饭。我一般拿到手第一步就是全局搜索“SELECT.*FROM”把登录相关的 SQL 全部捞出来跟表结构对照一遍能省下后面大量排错时间。4.2 自动组卷看懂随机抽题的三种常见策略组卷模块是考试系统的核心也是最容易让新手思路断掉的地方。主流开源项目有三种抽题策略随机抽题、按难度比例抽题、按知识点比例抽题。随机抽题最简单SQL 里 ORDER BY NEWID() 就是随机排序取前 N 条但这样抽出来的卷子难度可能全偏到简单题上考试没有区分度。按难度比例抽题是中型项目最常见的做法先配置好“简单 20% 中等 60% 较难 20%”然后分三次抽。按知识点比例抽题更接近正规考试但需要题库表里维护知识点字段很多开源项目压根没这个字段想改也改不了。实际操作里最常见的组卷代码长这样// 按难度比例抽取选择题生成一份试卷 public DataTable GeneratePaper(int subjectId, int totalScore) { DataTable paper new DataTable(); // 先取该科目的全部单选题 string sql SELECT QuestionId, Content, OptionA, OptionB, OptionC, OptionD, Answer, Score, Difficulty FROM Question WHERE SubjectIdsubjectId AND QuestionType1; DataTable allQuestions Query(sql, new { subjectId }); // 按难度分组Difficulty1简单2中等3较难 var easy allQuestions.Select(Difficulty 1); var medium allQuestions.Select(Difficulty 2); var hard allQuestions.Select(Difficulty 3); // 随机打乱后从每组取题比例按 2:5:3 Random rand new Random(); // 实际项目中这里会做更严谨的分组取题逻辑 return BuildPaperByRatio(easy, medium, hard, totalScore); }这段代码逻辑说明先一次性把某科目的所有单选题捞出来放到 DataTable用内存里的筛选按难度分组再按比例随机抽取这是一种避免多次访问数据库的常见做法。注意 Random 在 .NET Framework 里如果不加种子在高并发下可能生成相同序列但考试系统同时答题的规模通常不大这个坑可以暂时忽略真要严谨就改用 RNGCryptoServiceProvider。改组卷逻辑时新手最爱改错的是判分逻辑和组卷逻辑混在一起。题目里如果带选项抽题时必须把选项一起抽出来供页面渲染如果抽题只取了 QuestionId到答题页发现选项是空的那八成是 SQL 里漏了 OptionA~OptionD 字段或者存储过程只返回了部分列。这属于低级错误但出现频率极高。4.3 自动判分选择题判分很容易但答案比较要处理编码和空白自动判分模块在不同的开源项目里实现差别很大。选择题判分最简单学生提交的答案是“A”“B”这种单字符跟标准答案字符串比对就行。判断题是判定“对/错”或“T/F”也差不多。多选题麻烦一点因为答案顺序可能不一致标准答案是“ABD”学生可能填“DAB”直接字符串比较就误判了。这时候要先对字符串做排序再比较。下面这段是选择题判分的核心逻辑// 单选题判分比较答案忽略大小写并去掉首尾空格 public bool CheckSingleChoice(string studentAnswer, string correctAnswer) { if (string.IsNullOrEmpty(studentAnswer)) return false; return string.Equals(studentAnswer.Trim(), correctAnswer.Trim(), StringComparison.OrdinalIgnoreCase); } // 多选题判分把 “ABD” 拆成字符数组排序后再拼接比较 public bool CheckMultiChoice(string studentAnswer, string correctAnswer) { if (string.IsNullOrEmpty(studentAnswer)) return false; var sortedStudent string.Concat(studentAnswer.Trim().ToUpper().OrderBy(c c)); var sortedCorrect string.Concat(correctAnswer.Trim().ToUpper().OrderBy(c c)); return sortedStudent sortedCorrect; }参数说明和逻辑说明两个方法都先处理空值再比较避免传入 null 导致异常。单选用 OrdinalIgnoreCase 忽略大小写多选先排序再比这样不论学生填“abd”还是“DAB”都能正确判分。这两段代码可以直接复制到你的项目里替换原来用 直接比较的写法。判分过后把每题得分累加写入考试记录表这一步通常不会出问题容易出问题的是最后 Update 语句没带 where 条件导致整张表成绩被刷成同一个值第五章细讲。人工阅卷部分也一样——简答题需要老师手动给分开源项目一般是先让系统保存学生答案再在教师端按考试场次列出待批改列表由操作员打分提交。别指望开源系统自带完美的简答题自动批改绝大多数版本只有“保存答案人工打分”这个程度。5. 血泪避坑这五个问题能卡住九成新手5.1 附加 mdf 失败别跟数据库版本较劲重建库是最优解现象把老源码的 App_Data 目录里的 OnlineExam.mdf 附加到 SQL Server报错 “无法附加数据库版本 904 不受支持” 或提示文件不是有效的 SQL Server 数据库文件。原因mdf 文件是用高版本 SQL Server 生成的低版本实例无法读取文件头。开源项目没人保证文件版本跟你本机一致上一手用什么版本导出你是不知道的。解决扔掉 mdf直接用 .sql 脚本重建库。如果源码里真没有脚本就用“只读方式打开 mdf 文件”的思路——先装一个高版本 SQL Server 把数据导出来生成脚本再把脚本放到低版本机器上执行。别死磕附加一分钟搞定的事不值得耗半小时。5.2 登录之后立刻跳回登录页或 Session 老丢先查 IIS 应用程序池现象本地用 Visual Studio 调试一切正常发布到 IIS 后登录成功跳转又弹回登录页或者用一会就掉线。原因最典型的是 IIS 应用程序池默认“空闲超时设为 20 分钟”池被回收后内存中的 Session 全部清空。而很多老 ASP.NET 项目的登录状态就存在进程内 Session 里一回收就失忆。解决右键应用程序池 → 高级设置把“空闲超时”改成 0永不回收把“固定时间间隔”的回收周期调长或禁用。如果是多台服务器做负载均衡那还得换 Session 存储方式把 Session 改存 SQL Server 或 Redis老项目改起来略麻烦但小规模部署只调 IIS 就够了。5.3 中文注释和页面文字全乱码编码问题改保存格式现象打开 .aspx.cs 文件注释全是“锟斤拷”页面显示的问号替身。原因源码仓库里的文件当初是以 GB2312 或 GBK 编码保存的Visual Studio 默认按 UTF-8 打开字节序列解读错位。这种情况在 2015 年以前的老项目里极其普遍。解决用 Visual Studio 打开文件后文件 → 高级保存选项 → 将编码改为“简体中文(GB2312)”重新加载乱码就能还原。如果想彻底转成 UTF-8先按 GB2312 正确打开再高级保存选项改成“Unicode(UTF-8 带签名)”保存全项目操作完基本就干净了。别直接动文件先开一个文件试确认好再批量改。5.4 答题页打开后题目列表空白DataReader 没及时关闭现象点了“开始考试”进答题页页面框架在但题目列表区域完全空白也不报异常。刷新几次偶尔会出数据。原因这算 .NET 老项目经典黑匣子。答题页用到 SqlDataReader 逐行读取题目同一个数据库连接上还挂着另一个未关闭的 DataReader导致后面查询报“已有打开的与此连接关联的 DataReader必须首先将其关闭”。页面代码里 try-catch 吞掉了异常表现出来就是白屏。解决全局搜代码里的 SqlDataReader检查每个使用它的方法里是否在 finally 或 using 块中关闭连接与 DataReader。快速修法是把数据库连接串里加一句“MultipleActiveResultSetsTrue”让同一连接支持多个结果集治标但见效快根治要把读数据的代码改成读完即关或用 DataTable 一次性接收。直接复制数据到 DataTable 其实是最好用的办法代码量省一半连接也释放得快。5.5 成绩明明算对了却没写进库要么事务没提交要么主键写死现象交卷后分数在页面显示但去数据库查成绩表没有记录或者后一个学生把前一个学生的成绩覆盖了。原因第一种是代码里写了 SqlTransaction 却忘了 Commit异常路径直接回滚第二种是成绩表的主键不是自增列而是某个写死的常量每次插入都主键冲突被 catch 吞掉后页面照常显示。解决打开成绩写入那段代码检查有没有调用了 transaction.Commit()。关于主键检查成绩表的建表语句主键列必须是 IDENTITY(1,1)如果开源脚本建表时忘了写手工执行一句“ALTER TABLE ExamRecord ALTER COLUMN RecordId INT IDENTITY(1,1)”重建主键约束。改完记得跑一次完整交卷流程查库确认记录落进去了再继续改别的模块。6. 上线前的一小时验证三组账号走完一条考试链路不管你改了多少代码上线前务必做一次完整走查别嫌麻烦这一小时能拦住九成线上翻车。准备三组账号管理员、教师、学生各一个。流程按真实考试顺序来管理员登录进科目管理建一个科目进入题库管理录十道题——涵盖单选、多选、判断三种类型其中故意放一道答案带空格的题和一道多选选项顺序乱序的题用来验证判分逻辑。接着管理员或教师组一份试卷难度比例设简单 40%、中等 40%、较难 20%题型分布按你系统的配置走发布。然后切到学生账号登录进考试列表开始答题交卷后立刻查成绩。最后切到教师账号进入成绩管理确认判分结果和成绩单。这一圈走下来登录权限、组卷、判分、成绩落库四条链路全部验证到了。验证过程中重点看三个容易被忽略的细节一是学生交卷后再点一次交卷按钮系统会不会重复写成绩常见项目缺少防重复提交二是答案大小写不一样的题判分是否正常这验证第五章的多选判分排序逻辑改没改对三是教师能不能把成绩导出成 Excel很多开源系统的导出功能留着没做或用 HTML 表格代替导出时中文文件名乱码是老常客。如果想再往前走一步我建议你把 Session 存储换掉、给答题页加一道页面离开提醒以及把题库的难度字段利用起来做真正的组卷策略。这些是让这套代码从“课程设计”变成“能用系统”的分水岭。我自己跑过不下十套这类源码最大的体会不是代码写得不好而是数据库和部署环境占掉七成排错时间。你只要记住先跑通再改代码别一上来就动业务逻辑。希望帮到你。本文还有配套的精品资源点击获取