You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

创建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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 14:39:57