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

OData 8/ASP.NET Core 7 MVC约定路由:Delete方法无法生成端点

OData 8 + ASP.NET Core 7 MVC 约定路由下Delete端点无法生成问题解决

问题描述

在使用OData 8与ASP.NET Core 7 MVC的约定路由时,仅Delete方法无法创建端点。调试时访问{host}/$odata能看到GET、POST、PATCH方法,但看不到DELETE方法。

已尝试的操作:

  • 添加/移除[HttpDelete]特性,其他方法无论是否添加对应特性都正常工作;
  • 用app.UseEndpoints(endpoints => endpoints.MapControllers())替换app.MapControllerRoute(...),使用MapControllerRoute时Delete方法会作为非OData方法出现在{host}/$odata结果中,否则直接被省略;
  • 为控制器和方法添加[ODataAttributeRouting]和[ODataRouteComponent]特性,无效果;
  • 参考官方教程,代码结构与示例一致,但问题仍存在。

控制器代码

public class HomeController : ODataController
{
    private readonly TestDbContext _context;
    private readonly ILogger<HomeController> _logger;

    public HomeController(ILogger<HomeController> logger, TestDbContext dbContext)
    {
        _logger = logger;
        _context = dbContext;
    }

    [EnableQuery]
    [HttpGet]
    public ActionResult<IEnumerable<Home>> Get()
    {
        var items = _context.Home.Include(o => o.Option).Take(50).ToList<Home>();
        return items;
    }

    [HttpPost]
    public IActionResult Post([FromBody] Home HttpBody)
    {
        if (ModelState.IsValid)
        {
            foreach (var option in HttpBody.Option)
            {
                var currentOptions = _context.Option.Local
                                             .FirstOrDefault(x => x.Id == option.Id); 
                if (currentOptions != null)
                {
                    option.Id = currentOptions.Id;
                }
                else 
                {
                    _context.Attach(option);
                }
            }

            _context.Home.Add(HttpBody);
            _context.SaveChanges();

            return Ok();
        }
        else
        { 
            return BadRequest(); 
        }
    }

    [HttpDelete]
    public ActionResult Delete([FromRoute] Guid id)
    {
            _context.Home.Remove(new Home()
            {
                Id = id,
            });
            _context.SaveChanges();
            return NoContent();
    }
}

Program.cs代码

var builder = WebApplication.CreateBuilder(args);
var modelBuilder = new ODataConventionModelBuilder();
modelBuilder.EntitySet<Home>("Home");

builder.Services.AddControllers().AddOData(options => 
    options.Select().EnableQueryFeatures().AddRouteComponents(
    routePrefix: "api",
    model: modelBuilder.GetEdmModel())

builder.Services.AddControllersWithViews();

var app = builder.Build();

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

app.Run();
);

问题根源与解决办法

1. 修正Delete方法路由配置

OData约定路由要求Delete方法明确指定包含主键的路由模板,将[HttpDelete]改为[HttpDelete("{id}")],让OData识别这是符合约定的实体删除端点:

[HttpDelete("{id}")]
public ActionResult Delete([FromRoute] Guid id)
{
    var home = _context.Home.Find(id);
    if (home == null)
    {
        return NotFound();
    }
    _context.Home.Remove(home);
    _context.SaveChanges();
    return NoContent();
}

(注:原代码直接创建空实体删除可能引发数据异常,建议先查询实体是否存在)

2. 修复Program.cs的语法错误

原代码存在括号不闭合、重复添加控制器服务的问题,正确写法如下:

var builder = WebApplication.CreateBuilder(args);
var modelBuilder = new ODataConventionModelBuilder();
modelBuilder.EntitySet<Home>("Home");

builder.Services.AddControllersWithViews()
    .AddOData(options => 
        options.Select().EnableQueryFeatures()
               .AddRouteComponents("api", modelBuilder.GetEdmModel()));

var app = builder.Build();

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

app.Run();

3. 确保实体主键配置正确

OData需要明确的主键才能生成Delete端点,检查Home实体是否标记了主键:

public class Home
{
    [Key]
    public Guid Id { get; set; }
    // 其他属性...
    public ICollection<Option> Option { get; set; }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 13:25:16