创建BaseController供其他控制器继承后Swagger出现内部服务器错误
问题描述
我创建了一个BaseController,将通用的GetId方法放入其中,让所有业务控制器(如TaskController)继承该基类实现方法复用,但运行后Swagger UI出现以下错误:
Fetch error
Internal Server Error https://localhost:7032/swagger/v1/swagger.json
日志显示:
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1] An unhandled exception has occurred while executing the request.
相关代码
BaseController代码
using System; using System.Collections.Generic; using System.Linq; using System.Security.Claims; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; namespace TodoList.Api.Controllers { public class BaseController : ControllerBase { public string GetId() { if (HttpContext.User.Identity is ClaimsIdentity identity) { if (identity != null) { var IdUser = identity?.FindFirst(ClaimTypes.SerialNumber).Value; return IdUser!; } } return null!; } } }
TaskController代码
using System; using System.Collections.Generic; using System.IdentityModel.Tokens.Jwt; using System.Linq; using System.Security.Claims; using System.Text; using System.Threading.Tasks; using AutoMapper; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.IdentityModel.Tokens; using TodoList.Api.DbContextFolder; using TodoList.Api.Entity; using TodoList.Api.Model; namespace TodoList.Api.Controllers { [ApiController] [Route("api/TaskManage")] [Authorize] public class TaskController : BaseController { private readonly TaskDbContext taskDbContext; private readonly IMapper _mapper; public TaskController(TaskDbContext taskDbContext,IMapper mapper) { this.taskDbContext = taskDbContext; this._mapper = mapper; } // GET: api/values [HttpGet("All")] public async Task<ActionResult<ICollection< TaskEntity>>> GetAllTask() { var result = await taskDbContext.TaskDb.ToListAsync(); if (HttpContext.User.Identity is ClaimsIdentity identity) { var IdUser = identity?.FindFirst(ClaimTypes.SerialNumber).Value; } return Ok(result); } // GET api/id [HttpGet("{id}")] public async Task<ActionResult<TaskEntity>> GetBuyId(int id) { var result = await taskDbContext.TaskDb.FirstOrDefaultAsync(c => c.Id == id); if (result == null) { return NotFound(result); } return Ok(result); } // POST api/Create [HttpPost("Create")] public async Task<ActionResult<TaskEntity>> CreateToDo(TaskSendDTO T) { if (T != null) { var IdUser = GetId(); //var IdUser = User.Claims.First(x => x.Type == "Id").Value; var DataMapper = _mapper.Map<TaskEntity>(T); DataMapper.createById = Convert.ToInt32(IdUser); //DataMapper.createBy = taskDbContext.UsersAccounts.FirstOrDefault(x => x.UserId == Convert.ToInt32(IdUser)); await taskDbContext.TaskDb.AddAsync(DataMapper); taskDbContext.SaveChanges(); return Ok(DataMapper); } return BadRequest("Something went wrong"); } // PUT api/NameUpdate/id [HttpPut("NameUpdate/{id}")] public async Task<ActionResult<TaskUpdateTitle>> UpdateNameToDo(int id,string value) { var FindId = taskDbContext.TaskDb.Find(id); if (FindId == null) { return NotFound(FindId); } var DataNew = await taskDbContext.TaskDb.Select(e => e.Title).FirstOrDefaultAsync(); FindId.Title = value; if (FindId.Title is not null) { //taskDbContext.Update(FindId); taskDbContext.SaveChanges(); return Ok(FindId.Title); } return NotFound(); } //put api/IsDoneUpdate/Id [HttpPut("IsDoneUpdate")] public async Task<ActionResult<TaskUpdateIsDoneDTO>> UpdateIsDone(int[] ids) { var tasks = await taskDbContext .TaskDb .Where(t=> ids.Contains(t.Id)).ToListAsync(); if (ids.Length != tasks.Count) { return NotFound(tasks); } foreach (var task in tasks) { task.IsDone = true; } taskDbContext.SaveChanges(); return Ok(); } //DELETE api/TaskId [HttpDelete("{TaskId}")] public async Task<ActionResult<TaskEntity>> DeleteBuyId(int TaskId) { var result = await taskDbContext.TaskDb.FindAsync(TaskId); if (result == null) { return NotFound(result); } taskDbContext.Remove(result); taskDbContext.SaveChanges(); return NoContent(); } } }
解决方法
Swagger生成文档时会扫描控制器的所有公共方法并尝试生成API定义,你的BaseController中的GetId是公共方法但未标注任何HTTP特性或排除标记,导致Swagger无法识别它的类型,进而抛出异常。
步骤1:标记非API方法
给BaseController的GetId方法添加[NonAction]特性,明确告诉Swagger这不是一个API接口方法:
using System; using System.Collections.Generic; using System.Linq; using System.Security.Claims; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; namespace TodoList.Api.Controllers { public class BaseController : ControllerBase { [NonAction] // 添加此特性排除Swagger扫描 public string GetId() { if (HttpContext.User.Identity is ClaimsIdentity identity) { if (identity != null) { var IdUser = identity?.FindFirst(ClaimTypes.SerialNumber).Value; return IdUser!; } } return null!; } } }
步骤2:优化空引用风险
GetId中强制解空IdUser!可能引发NullReferenceException,可以优化代码避免该问题:
[NonAction] public string? GetId() { var identity = HttpContext.User.Identity as ClaimsIdentity; return identity?.FindFirst(ClaimTypes.SerialNumber)?.Value; }
修改后重新运行项目,Swagger即可正常生成文档。
内容的提问来源于stack exchange,提问作者Ali Garivani
相关产品推荐
相关产品推荐

