核心2控制器 - HTTP动词不允许
问题描述:
我有一个控制器,我在一个Restful API中使用作为.NET Core 2 MVC应用程序的一部分。下面我粘贴了控制器的代码。核心2控制器 - HTTP动词不允许
除了最后一种方法之外,一切都很好。 [HttpDelete("Race/{raceid}")]
。当我尝试从Postman或Swagger发出DELETE时,我得到“用于访问此页面的HTTP动词是不允许的”
我不明白为什么。我的标准删除方法工作正常。这只是第二个删除方法。我有GET方法遵循类似的模式,他们工作正常。
任何想法?
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
using System.Linq;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using System;
using TechsportiseOnline.Data;
using Microsoft.AspNetCore.Identity;
using TechsportiseOnline.Models;
// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
namespace Techsportise.Controllers
{
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
[Route("api/[controller]")]
public class TimingController : Controller
{
private readonly ApplicationDbContext _context;
private readonly UserManager<ApplicationUser> _userManager;
private readonly IAuthorizationService _authorizationService;
public TimingController(ApplicationDbContext context, IAuthorizationService authorizationService,
UserManager<ApplicationUser> userManager)
{
_context = context;
_userManager = userManager;
_authorizationService = authorizationService;
}
/// <summary>
/// Get all Race Timings by Race ID
/// </summary>
/// <remarks>
/// Gets all Race Timings which have been recorded by the user for the passed race
/// </remarks>s
/// <param name="raceid">Race ID</param>
/// <returns>All created Race Timings</returns>
[HttpGet("Race/{raceid}", Name = "GetTimingsByRaceID")]
public IEnumerable<Timing> GetAllByRaceID(long raceid)
{
//Get only records where the OwnerID is not the logged in User.
var alltimings = _context.Timings.Where(p => p.OwnerId == _userManager.GetUserId(User))
.Where(p => p.RaceId == raceid);
return alltimings.ToList();
}
/// <summary>
/// Get Count of Timings by Race ID
/// </summary>
/// <remarks>
/// Gets a count of all Race Timings which have been recorded by the user for the passed race
/// </remarks>s
/// <param name="raceid">Race ID</param>
/// <returns>All created Race Timings</returns>
[HttpGet("Race/{raceid}/count", Name = "GetTimingsCountByRaceID")]
public IActionResult GetCountByRaceID(long raceid)
{
//Get only records where the OwnerID is not the logged in User.
var count = _context.Timings.Where(p => p.OwnerId == _userManager.GetUserId(User))
.Where(p => p.RaceId == raceid)
.Count();
var response = new TimingCount()
{
RaceId = raceid,
TimingsCount = count
};
return new ObjectResult(response);
}
/// <summary>
/// Get a single Race Timing
/// </summary>
/// <remarks>
/// Gets the details from a single Race Timing from it's ID
/// </remarks>
/// <param name="id">Timing ID</param>
/// <returns>Single Race Timing</returns>
[HttpGet("{id}", Name = "GetTiming")]
public IActionResult GetById(long id)
{
var item = _context.Timings .Where(t => t.OwnerId == _userManager.GetUserId(User))
.FirstOrDefault(t => t.Id == id);
if (item == null)
{
return NotFound();
}
return new ObjectResult(item);
}
/// <summary>
/// Create a new Race Timing
/// </summary>
/// <remarks>
/// Creates a new Race Timing
/// </remarks>
/// <returns>The JSON for the created Race Timing</returns>
[HttpPost]
public IActionResult Create([FromBody] TimingPost item)
{
if (item == null)
{
return BadRequest();
}
//Validate that the race ID exists
var race = _context.Races.Where(p => p.OwnerID == _userManager.GetUserId(User)).FirstOrDefault(t => t.ID == item.RaceId);
if (race == null)
{
return BadRequest("The RaceID you have sent does not exist");
}
var timingitem = new Timing();
timingitem.EndTime = item.EndTime;
timingitem.RaceId = item.RaceId;
timingitem.OwnerId = _userManager.GetUserId(User);
timingitem.Position = item.Position;
timingitem.StartTime = item.StartTime;
timingitem.LastUpdated = DateTime.Now;
_context.Timings.Add(timingitem);
_context.SaveChanges();
return CreatedAtRoute("GetTiming", new { id = timingitem.Id }, timingitem);
}
/// <summary>
/// Update a Race Timing
/// </summary>
/// <remarks>
/// Update's a Race Timing's details
/// </remarks>
/// <param name="id">Timing ID</param>
/// <returns>The JSON for the updated Race Timing</returns>
[HttpPut("{id}")]
public IActionResult Update(long id, [FromBody] Timing item)
{
if (item == null)
{
return BadRequest();
}
//Validate that the race ID exists
var race = _context.Races.Where(p => p.OwnerID == _userManager.GetUserId(User)).FirstOrDefault(t => t.ID == item.RaceId);
if (race == null)
{
return BadRequest("The RaceID you have sent does not exist");
}
var timing = _context.Timings .Where(t => t.OwnerId == _userManager.GetUserId(User))
.FirstOrDefault(t => t.Id == id);
if (timing == null)
{
return NotFound();
}
timing.RaceId = item.RaceId;
timing.StartTime = item.StartTime;
timing.EndTime = item.EndTime;
timing.Position = item.Position;
timing.OwnerId = _userManager.GetUserId(User);
timing.LastUpdated = DateTime.Now;
_context.Timings.Update(timing);
_context.SaveChanges();
return new NoContentResult();
}
/// <summary>
/// Delete a Race Timing
/// </summary>
/// <remarks>
/// Deletes a Race Timing. Note: This will orphan any related result data and is not recommended!
/// </remarks>
/// <param name="id">Race Entry ID</param>
/// <returns></returns>
[HttpDelete("{id}")]
public IActionResult Delete(long id)
{
var timing = _context.Timings .Where(t => t.OwnerId == _userManager.GetUserId(User))
.FirstOrDefault(t => t.Id == id);
if (timing == null)
{
return NotFound();
}
_context.Timings.Remove(timing);
_context.SaveChanges();
return new NoContentResult();
}
/// <summary>
/// Delete all timings for a Race
/// </summary>
/// <remarks>
/// Deletes all timings for the race passed
/// </remarks>
/// <param name="raceid">Race ID</param>
/// <returns></returns>
[HttpDelete("Race/{raceid}")]
public IActionResult DeleteAllTimingsForRace(long raceid)
{
var race = _context.Races.Where(t => t.OwnerID == _userManager.GetUserId(User))
.FirstOrDefault(t => t.ID == raceid);
if (race == null)
{
return NotFound();
}
if ((race.ResultStatus == "Published") || (race.ResultStatus == "Provisional"))
{
return BadRequest("You cannot delete scans for a race which is already published");
}
foreach (var timing in _context.Timings.Where(p => p.OwnerId == _userManager.GetUserId(User))
.Where(p => p.RaceId == raceid))
{
_context.Timings.Remove(timing);
}
_context.SaveChanges();
return new NoContentResult();
}
}
}
答
这实际上最终成为与WebDAV相关的服务器配置。
我最终在3个本地环境上进行了测试,没有发现任何问题,因此将其与服务器隔离开来,然后进行了一些更多的取证搜索,将其缩小到在我的Web服务器上的Web.Config中禁用WebDAV。
<modules runAllManagedModulesForAllRequests="false">
<remove name="WebDAVModule" />
</modules>
请求的外观如何? 'DELETE/api/Timing/Race/1234'? –
是的,这是正确的。这里是一个示例卷曲curl -X DELETE - 标头授权:承载' - 标头'接受:text/html''https://www.techsportise.com/api/Timing/Race/1'--header'接受:text/html''https://www.techsportise.com/api/Timing/Race/1' –
尝试将'Race/{raceid}'删除放在{id}删除之上。首先有特殊的端点总是更好。我最好的猜测是'Race/1'与{id}匹配,然后不能绑定。我总是喜欢在我的端点上使用{id:int},只要我知道它总是一个整数。 – NathanS