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

ASP.NET中Post请求同时使用路由与Body参数的实现问题

前言

我最近接到一个大学项目,使用ASP.NET Core 6 Web API和Entity Framework开发。课程要求实现API时无需考虑其结构与路由规范,特此强调:我无法选择或修改路由规则,哪怕是微小调整也不行。

实际问题

我有3个模型类,分别为Application、Module和Data。一个Application包含多个子Module,每个Module又包含多个子Data。

问题在于,创建Module或Data实例时,要求同时从URL路由和请求Body中获取数据。

以下是创建Module的示例:

POST: https://ip:port/api/OurProjectName/{application}/
POSTBODY:

<?xml version="1.0"?>
<Module><!--根节点名称可灵活设置,无需担心DTO问题-->
   <id>99999</id>
   <name>some name</name>
   <creation_dt>{the current timestamp}</creation_dt>
</Module>

正确的逻辑应该是:控制器获取路由中的application字符串和Body中的Module/ModuleDTO,从数据库中查询名称匹配的Application实例,再将Body中的模块与路由参数指定的父应用关联,通过EF完成数据持久化。

失败的尝试

Data的处理逻辑与Module类似,但仅支持创建和删除操作。创建Data的路由为:

POST: https://ip:port/api/OurProjectName/{application}/{module}

其中application仅用于校验数据库结构相关的历史错误。

我首先尝试如下实现:

[HttpPost("{application}/{module}")]
[Produces("application/xml")]
[Consumes("application/xml")]
public IActionResult Post(string application, string module, [FromBody] Data data) 
{
    var mod = _context.Modules.SingleOrDefault(m => m.name == module);
        
    if (mod == null)
    {
        return NotFound();
    }
        
    if (mod.parent.name != application)
    {
        //... 此处逻辑暂不关注
    }
        
    data.parent = mod;

    // TODO: 后续处理解引用问题
    mod.datas.Add(data);

    _context.Add(data);
    _context.SaveChanges();

    return Ok(data);
}

但返回了常见的415错误。由于Data包含导航属性,Swagger生成的XML请求体层级极深,类似配置文件。

随后我尝试为路由参数添加[FromRoute]特性,仍返回“unsupported media format”错误。

接着我尝试自定义路由(移除控制器上的特性),相关Startup配置如下:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment()) 
    {
        app.UseDeveloperExceptionPage();
        app.UseSwagger();
        app.UseSwaggerUI();
    }

    var option = new RewriteOptions();
    option.AddRedirect("^$", "swagger");
    app.UseRewriter(option);

    app.UseCors("AllowAll");
    app.UseRouting();
        
    app.UseAuthorization();

    app.UseEndpoints(endpoints => {
        endpoints.MapControllers();
        endpoints.MapControllerRoute(
                name: "postDataCustom",
                pattern: "api/OurProjectName/{application}/{module}", new {controller = "DataController", action = "Post"});
        });
}

但Swagger中看不到该端点,Postman测试也显示端点不存在。

之后我尝试使用DTO,为字段添加特性:

public IActionResult Post(DataDTO data)
{
    var mod = _context.Modules.SingleOrDefault(m => m.name == data.module);
            
    if (mod == null)
    {
        return NotFound();
    }

    Console.WriteLine(mod.name);

    // ...(若能打印则可继续推进)
            
    return Ok();
}
    
public class DataDTO
{
        [FromRoute]
        public string application { get; set; }
        [FromRoute]
        public string module { get; set; }
        [FromBody]
        public Data data { get; set; }
        
        public DataDTO(string application, string module, Data data)
        {
            this.application = application;
            this.module = module;
            this.data = data;
        }
}

仍返回错误。于是我简化DTO测试:

[HttpPost("{module}")]
public IActionResult Post(testeDTO data)
{
    Console.WriteLine(data.module);
    Console.WriteLine(data.bb);
    return Ok();
}

public class testeDTO
{
    [FromRoute]
    public string? module { get; set; }

    [FromBody]
    public string bb { get; set; }

    public testeDTO(string bb)
    {
        this.bb = bb;
    }
}

请求能返回200,但[FromRoute]修饰的module始终未赋值,似乎Body内容覆盖了路由参数。

目前我已无其他思路,老旧文档也增加了排查难度。我也曾考虑使用x-www-urlencode,但不确定是否符合要求。

简而言之:我无法成功实现同时携带路由参数的Post请求。

2022年12月26日更新

调试发现如下代码能正常运行(Swagger测试无错误),检查Git发现仅修改了以下内容:

[HttpPost("{module}")]
public IActionResult Post([FromRoute]string module, [FromBody]testeDTO data){
    Console.WriteLine(module);
    Console.WriteLine(data.bb);
    return Ok();
}
...
public class testeDTO{
    
    [FromBody]
    public string bb{get;set;}

    public testeDTO(string bb){
        
        this.bb = bb;
    }

}

我将继续调试以找到完整解决方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 06:25:23