
简介这是一份基于.NET平台、使用C#语言开发的试卷生成系统源码适用于需要快速搭建在线题库与自动组卷功能的教育类项目或课程设计场景。系统支持人工选题与随机选题两种组卷模式人工模式下可按题型勾选已有试题并设定分值随机模式下可配置各题型数量与分值后自动生成试卷生成结果支持导出为Word文档便于线下打印使用。资源包共278个文件大小仅1.06MB核心包括48个C#源码文件、30个aspx页面及对应后台逻辑同时附带176个gif动图可直观展示页面操作流程另有css、js、数据库文件等支撑完整运行环境。目前已有159人学习下载适合.NET初学者学习分层架构与基本业务逻辑也可作为毕业设计或小型教务系统的参考实现。1. 我的技术选型思路为什么用.NET做试卷生成系统先聊个实际场景。学校或培训机构要组织一场考试最头疼的事情是什么出题。出题要考虑知识点覆盖、难度分布、重复率控制还要防止泄题。手动出题不仅耗时而且很难做到每次考试的难度一致。我做的这套试卷生成系统就是把出题这个过程自动化老师维护好题库系统按规则自动抽题、排版、生成试卷文档还可以配套生成答案卷和答题卡。关于技术栈的选择我最终选了.NET而不是Python或Java有几个实际考量。首先题库管理和试卷生成这种业务逻辑密集、事务性强的系统.NET的EF Core配合SQL Server或MySQL开发效率非常高。其次如果单位本来就用Windows环境.NET部署和维护成本最低——装个IIS或者直接用Kestrel跑起来就行不需要额外折腾Linux服务器。第三也是很多人忽略的一点.NET在Office文档生成方面有天然优势服务端直接引用OpenXML SDK就能操作Word文档格式如果走其他技术栈生成docx还得额外调第三方库或者让服务器装Office麻烦且不稳定。这个系统的核心使用场景很明确教师维护题库、设置组卷规则、生成试卷教务管理人员审核、导出、归档学生或考生使用在线考试端答题。其中组卷是整个系统的灵魂后面我会详细拆解。2. 核心功能模块与代码架构拆解2.1 题库管理模块一切组卷的前提题库是整个系统的数据底座设计得好不好直接决定组卷算法能不能跑起来。我采用的是题库-题型-知识点三级分类结构。数据库层面最核心的是QuestionBank题库表字段设计包括Id主键SubjectId科目IDQuestionType题型单选/多选/判断/填空/简答KnowledgePointId知识点ID用于难度和内容分布控制DifficultyLevel难度系数1-5Stem题干OptionsJson选项JSON格式存储方便扩展Answer参考答案Analysis解析CreateTime、UpdateTime选项用JSON存而不是单独建表是我从实际开发中总结出来的技巧。如果按范式建选项表查询要Join插入要事务而且不同题型的选项数量不一样——单选题4个多选题5个判断题就2个用关系表反而别扭。JSON存进去读取的时候反序列化就行性能更好代码也简洁。还有个容易踩的坑题型字段不要用字符串用枚举映射成int存。因为程序里到处要判断题型字符串拼SQL或者做条件判断都容易出错。我习惯用QuestionTypeEnum取值从1到6查的时候直接Where(q q.QuestionType (int)QuestionTypeEnum.SingleChoice)。2.2 组卷引擎系统的灵魂组卷的核心是抽题算法。最粗糙的做法是ORDER BY NEWID()随机抽但实际考试不可能这么干——你要保证每张试卷的难度系数接近要覆盖所有章节还要避免同一道题在一份试卷里重复出现。我把组卷拆成四个环节。知识点覆盖控制试卷里每个知识点的题目数量要有上限防止所有题都从一个章节里出。实现方式是在抽题前先对题库按知识点分组然后从每个组里按比例抽取。难度分布控制比如设定整卷难度0.75其中简单题占30%、中等题占50%、难题占20%抽题时要分别按难度筛选。这里有个细节难度系数不是单纯的平均值建议用加权平均总难度 Σ(题型分数占比 × 该题型平均难度)。排除重复题如果有人连续生成多套试卷要保证卷与卷之间重复率不超过某个阈值。我的方案是给每道题加一个UsedCount字段抽题时优先选UsedCount小的题这样能自然地把题目使用频率拉平。抽题算法选型我用的是改进的遗传算法。第一版直接用随机算法加重量约束效果不稳定经常出现某一章题目过多、另一章空缺的情况。后来改成遗传算法基本流程是初始化一批试卷方案作为种群每个方案是一个题目ID列表用知识点覆盖率难度偏差重复率总分偏差作为适应度函数迭代做选择、交叉、变异达到迭代次数后输出最优解。实际测试下来50道题、题库2000题、迭代100次耗时约2-3秒完全可接受。2.3 试卷导出模块Word格式是关键题目抽好了接下来是生成试卷文档。最开始我试过在服务端用Html转Word效果很差排版经常乱。后来改用OpenXML SDK直接操作docx文件结构彻底解决了这个问题。具体做法是先用Word手工做一套试卷模板.docx设置好字体、字号、页边距、标题样式然后服务端打开这个模板往里面填充内容。用OpenXML的好处是模板里只要定义了样式名比如试卷标题、大题标题、题干、选项代码里就只管往这些命名样式对应的段落里写入内容样式问题完全不用关心。填空和横线处理填空题的横线不是下划线而是连续短横线这个在OpenXML里是Run的属性设置要单独处理。公式支持简单的上下标可以用OpenXML的RunProperties处理但真正的数学公式根号、分式docx原生支持有限我采用了折中方案——用LaTeX公式转图片插入虽然会增加一些处理时间但效果很专业。2.4 在线考试与权限控制这一块按标准的角色访问控制RBAC来做管理员、教师、学生三种角色教师角色里再细分出题教师和审核教师。JWT做身份验证刷新Token到期时间设为2小时配合Redis存储会话。在线考试端比较关键的是防作弊逻辑。我的方案有三层考试开始前校验IP和白名单考试中前端定时上报鼠标失焦事件如果检测到切换到其他应用后端记录异常日志考试结束时自动提交未答完的题按空题处理。不搞太复杂的摄像头监控因为实际部署时很多机房摄像头条件不满足反而容易出问题。3. 实操过程中的关键细节与踩坑记录3.1 选择题选项的随机排序问题这是考试系统一个容易被忽略的细节同一份试卷打印出来后不能让所有考生的选择题选项顺序都一样否则相邻考生容易互相抄袭。代码实现不复杂就是在组卷完成后对每道选择题的选项做一次洗牌Fisher-Yates算法同时把正确答案的下标同步更新。但要注意两点第一必须在选项洗牌后再写入试卷文档顺序不能反第二洗牌要基于Random的种子值保证同一套试卷重新生成时选项顺序不变否则教师审核时发现每次生成的选项顺序都不一样会以为程序出bug了。3.2 OpenXML操作docx时的大坑用OpenXML往模板里填内容最常见的坑是段落复制和替换。如果你用Paragraph.InsertAfter插入新段落新段落的样式可能不会继承模板里的段落样式结果就是字体、字号突然变了。我的解决思路是不要在模板的中间插入段落而是在模板末尾留一个内容锚点段落所有动态内容统一在锚点位置追加追加时复制锚点段落的ParagraphProperties。这样字体样式完全可控。另一个坑是表格的合并单元格。有段时间系统生成的试卷页脚总有一条多余的分隔线排查了很久才发现是模板里表格的GridSpan设置问题模板里复制粘贴的小动作导致列宽定义错乱。后来我把模板的XML直接打开检查tblGrid定义和代码里实际操作到哪几列对齐问题才解决。3.3 .NET版本兼容性与部署问题参考热词里很多人问.NET Framework 4.8不支持Windows 7、电脑需要安装.NET Framework 3.5这类问题我在实际开发中也遇到过。如果目标环境是老旧机房服务器还是Server 2008或者Windows 7选择**.NET Framework 4.7.2**比4.8更稳妥4.8在部分精简版系统上装不上会莫名报错。如果是从零开始的新项目我建议直接上**.NET 8Core毕竟微软官方已经明确.NET Framework不会再有大版本更新.NET 8的长期支持要到2026年11月性能比Framework好很多特别是字符串处理和JSON序列化这块。但要注意.NET 8部署服务器需要安装ASP.NET Core Runtime 8.0**不像Framework版自带IIS集成那么简单。3.4 Web API启动后打不开网页的排查热词里提到c# .net 8 core web api 运行后没打开网页这个问题我遇到过。原因是.NET 8 Web API项目默认的launchSettings.json里启用的是HTTPS端口本地跑的时候浏览器弹出404。解决方案是检查Properties/launchSettings.json里的applicationUrl确保HTTP和HTTPS两个地址都配置了或者直接设置为仅HTTP先调试。还有一类情况是Swagger打不开热词里也提到了.net swagger ui。这个大概率是环境问题——Swagger中间件注册了但开发环境下UseSwagger没生效。检查Program.cs里是否if (app.Environment.IsDevelopment())包裹了Swagger的启用代码。4. 常见问题与排查速查表问题现象可能原因解决方法生成的试卷选项排列顺序总是变每次生成时Random种子不同组卷模式下用试卷编号作Random种子Word导出后公式显示为方块OpenXML不支持复杂公式图片插入失败检查公式图片的数据流是否被GC回收用using块包裹Web API部署后502 Bad Gateway反向代理未配置或Kestrel未监听正确端口检查appsettings.json中的Urls配置IIS部署时启用AspNetCoreModuleV2Swagger页面一直没有响应Swagger中间件被开发环境判断拦截确认UseSwagger是否在环境判断之外题库导入Excel大量数据时超时循环逐条插入数据库改用EF Core的AddRange批量插入或SqlBulkCopy在线答题提交时偶尔报错数据丢失前端JSON序列化时把答题字符串截断检查MaxRequestBodySize配置增大到10MB5. 后端增强功能与后续扩展方向这套系统上线运行后我陆续加了不少增强功能这里挑几个最实用的分享一下。随机抽题的缓存优化题库规模如果到几万题每次组卷都去数据库全量查题速度会慢。我给题库加了一层内存缓存启动时预加载常用科目的题目到ConcurrentDictionary组卷算法直接操作内存数据响应时间从3秒降到200毫秒。但要注意缓存失效策略教师在后台更新题目时要主动清掉对应科目的缓存。Word转PDF的免费方案热词里有人提到aspose.pdf for .net授权很贵其实可以先用Word模板OpenXML生成docx然后调用Office COM组件转换成PDF。这个方法不需要额外授权费用前提是服务器装了Office且配置了适当的DCOM权限。如果服务器不方便装Office可以试试DocX库配合WPS的转换接口但稳定性会差一些。多语言试卷的支持部分国际学校有双语试卷需求我给题干和选项加了StemEn、OptionsJsonEn两个字段导出时根据试卷设置里的语言字段读取不同内容。这个需求虽然不常见但加上之后系统能覆盖更多场景而且实现成本并不高。知识点薄弱项分析这是从试卷生成延伸到学情分析的增值功能。考试结束后根据答题记录反推每个学生每个知识点的得分率用雷达图展示。这一块的价值甚至比自动组卷更高——因为老师和家长最关心的往往不是卷面分数而是这孩子到底哪里不会。6. 个人实操经验与总结试卷生成系统这个项目我从需求分析到第一版上线大概用了三周时间期间砍掉不少需求也有几个功能返工过两三次。这里分享几条比较有价值的心得。第一业务规则一定先于代码理清楚。比如抽题时是否允许同一份试卷出现两道完全相同的题、判断题的正确答案True/False在显示时能不能随机变换位置这些规则如果不提前和老师确认代码写完后改起来特别痛苦。我在第一个版本里就没考虑判断题True/False位置随机后来老师提出建议我只能回填所有历史试卷重新洗牌浪费了不少时间。第二试卷生成系统最核心的价值是可追溯。系统能自动生成试卷但如果学生或家长对某道题提出质疑要能快速查出来这张卷子是什么时候、由谁、按什么规则生成的。所以每次组卷的规则参数、抽题结果、操作人、操作时间我都会记录到一张PaperGenerateLog表里。这个细节在演示的时候非常加分也体现系统的专业性。第三别过度设计。我最初想做成完全自动化的智能组卷系统后来发现实际需求中老师更多是手动选题——从题库里挑出若干道题微调后生成试卷。自动化组卷只是辅助真正的刚需是高效地手动组卷和灵活的题目编辑。花了一周的精力实现全自动算法结果老师们更常用的反而是手动模式。建议在开发前多听听真实用户的流程别一上来就追求高大上的算法。这个系统的后续方向我计划加上AI自动改分和智能推荐相似题的功能。前者用来处理简答题后者是为了给做错题的学生推荐同知识点的练习。如果你也在做类似的项目欢迎交流。本文还有配套的精品资源点击获取