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
相关产品推荐
相关产品推荐

