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

.NET Core中解决‘路由模板中SubjectId参数重复’错误

路由参数重复异常问题分析

错误信息

System.ArgumentException: The route parameter name 'SubjectId' appears more than one time in the route template. (Parameter 'routeTemplate')

控制器代码

using System;
using System.Threading;
using System.Threading.Tasks;
using Contracts;
using Microsoft.AspNetCore.Mvc;
using Services.Abstractions;

namespace Presentation.Controllers
{
    [ApiController]
    [Route("api/[controller]/[action]")]
    public class SubjectController : ControllerBase
    {
        private readonly IServiceManager _serviceManager;

        public SubjectController(IServiceManager serviceManager) => _serviceManager = serviceManager;

        [HttpGet]
        public async Task<IActionResult> GetSubjects(Guid id, CancellationToken cancellationToken)
        {
            var accountsDto = await _serviceManager.SubjectService.GetByIdAsync(id, cancellationToken);

            return Ok(accountsDto);
        }

        [HttpGet("{id:guid}")]
        public async Task<IActionResult> GetSubjectById(Guid id, CancellationToken cancellationToken)
        {
            var accountDto = await _serviceManager.SubjectService.GetByIdAsync(id,  cancellationToken);

            return Ok(accountDto);
        }

        [HttpPost]
        public async Task<IActionResult> CreateAccount(Guid id,  SubjectForCreationDto subjectForCreationDto, CancellationToken cancellationToken)
        {
            var subject = await _serviceManager.SubjectService.CreateAsync(subjectForCreationDto, id, cancellationToken);

            return CreatedAtAction(nameof(GetSubjectById), new { ownerId = subject.SubjectId}, subject);
        }

        [HttpDelete("{id:guid}")]
        public async Task<IActionResult> DeleteAccount(Guid id, CancellationToken cancellationToken)
        {
            await _serviceManager.SubjectService.DeleteAsync(id, cancellationToken);

            return NoContent();
        }
        
        [HttpPut("{id:guid}")]
        public async Task<IActionResult> UpdateSubject(Guid id, SubjectForUpdateDto subjectForUpdate, CancellationToken cancellationToken)
        {
            await _serviceManager.SubjectService.UpdateAsync(id, subjectForUpdate, cancellationToken);

            return NoContent();
        }
    }
}

端点配置(Startup.cs)

app.UseEndpoints(endpoints => endpoints.MapControllers());

Program.cs代码

public class Program
{
        public static async Task Main(string[] args)
        {
            var webHost = CreateHostBuilder(args).Build();
            await webHost.RunAsync();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup<Startup>());
}

问题根源与修复方案

核心错误原因

异常的根源在CreateAccount方法的CreatedAtAction调用中:你传递的路由参数是ownerId = subject.SubjectId,但目标方法GetSubjectById的路由定义为[HttpGet("{id:guid}")],需要的参数名为id。ASP.NET Core在生成路由时,无法匹配到对应参数,进而触发了路由参数重复的异常。

修复步骤

  1. 修改CreatedAtAction的路由参数,将ownerId替换为id,确保与目标方法的参数名一致:
return CreatedAtAction(nameof(GetSubjectById), new { id = subject.SubjectId}, subject);
  1. 额外代码规范优化(非错误根源,但提升代码可读性与一致性):
    • GetSubjects方法名与逻辑不符:方法内调用GetByIdAsync获取单个对象,但方法名是复数GetSubjects,建议调整:如果是获取所有Subject,删除Guid id参数并调用对应的GetAllAsync方法;如果是获取单个,重命名方法并调整路由避免冲突。
    • 方法命名与控制器主题不匹配:CreateAccount、DeleteAccount应改为CreateSubject、DeleteSubject,符合SubjectController的职责定位。

修复后的CreateSubject方法示例

[HttpPost]
public async Task<IActionResult> CreateSubject(Guid id, SubjectForCreationDto subjectForCreationDto, CancellationToken cancellationToken)
{
    var subject = await _serviceManager.SubjectService.CreateAsync(subjectForCreationDto, id, cancellationToken);

    return CreatedAtAction(nameof(GetSubjectById), new { id = subject.SubjectId}, subject);
}

内容的提问来源于stack exchange,提问作者Turing

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 00:45:55