当 运行 我的测试(405 方法不允许)时,无法在 ASP.NET 核心中调用 API DELETE。但它大摇大摆地工作
Cannot call API DELETE in ASP.NET core when running my tests (405 Method Not Allowed) . BUT it works in swagger
也许我需要在测试虚拟主机中设置某种权限?测试的 Get 和 Post 工作正常。但是当它尝试调用控制器上的 DELETE 方法时出现 HTTP 405 错误。
[HttpDelete("{id:int}")]
public async Task<ActionResult<RfAttachmentModel>> DeleteByIdAsync(int id)
{
await _rfAttachmentService.DeleteByIdAsync(id);
return NoContent();
}
public class CustomWebApplicationFactory<TStartup> : WebApplicationFactory<Startup>
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.UseEnvironment("LocalTesting");
builder.ConfigureServices(services =>
{
services.AddEntityFrameworkInMemoryDatabase();
ServiceProvider provider = services
.AddEntityFrameworkInMemoryDatabase()
.BuildServiceProvider();
services.AddDbContext<PwdrsContext>(options =>
{
options.UseInMemoryDatabase("Pwdrs");
options.UseInternalServiceProvider(provider);
});
ServiceProvider sp = services.BuildServiceProvider();
using (IServiceScope scope = sp.CreateScope())
{
IServiceProvider scopedServices = scope.ServiceProvider;
PwdrsContext db = scopedServices.GetRequiredService<PwdrsContext>();
ILoggerFactory loggerFactory = scopedServices.GetRequiredService<ILoggerFactory>();
ILogger<CustomWebApplicationFactory<TStartup>> logger = scopedServices
.GetRequiredService<ILogger<CustomWebApplicationFactory<TStartup>>>();
db.Database.EnsureDeleted();
db.Database.EnsureCreated();
try
{
PwdrsContextSeed.SeedAsync(db, loggerFactory).Wait();
}
catch (Exception ex)
{
logger.LogError(ex, $"An error occurred seeding the " +
"database with test messages. Error: {ex.Message}");
}
}
});
}
}
EDIT1:这是测试项目中进行调用的方法
[Fact]
public async Task Delete_Item_By_Id()
{
HttpResponseMessage responseDelete = await Client.GetAsync("/api/RfAttachment/DeleteById/1");
responseDelete.EnsureSuccessStatusCode();
HttpResponseMessage responseGetAll = await Client.GetAsync("/api/RfAttachment/GetAll");
responseGetAll.EnsureSuccessStatusCode();
string stringResponse = await responseGetAll.Content.ReadAsStringAsync();
List<RfAttachment> result = JsonConvert
.DeserializeObject<IEnumerable<RfAttachment>>(stringResponse)
.ToList();
Assert.Single(result);
}
如果您的 IWebHost 在 IIS / IISExpress 下 运行,您可能需要在 IIS 上启用 PUT 和 DELETE。
必须设置以下项目才能启用:
- 网站应用程序池托管管道模式必须设置为集成
- IIS 必须支持 HTTP 动词
设置应用程序池管道模式
- 转到 IIS 管理器 > 应用程序池
- 找到目标的应用程序池:
- (网站)> 编辑(双击)> 托管管道模式:集成
HTTP 动词更新
应将以下代码片段添加到 web.config
以启用所有动词,并确保 WebDAV
不会拦截和拒绝 PUT
和 DELETE
。如果配置了默认的WebDAV
,WebDAV
会拦截PUT
和DELETE
动词,返回405错误(方法不允许)。
<system.webServer>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="WebDAV" />
<add name="dotless" path="*.less" verb="GET" type="dotless.Core.LessCssHttpHandler,dotless.AspNet" resourceType="File" preCondition="" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" resourceType="Unspecified" requireAccess="Script" preCondition="integratedMode,runtimeVersionv4.0" responseBufferLimit="0" />
</handlers>
<modules>
<remove name="WebDAVModule" />
</modules>
</system.webServer>
如果您更喜欢 GUI to add verbs,请转至 IIS 管理器 > 处理程序映射。找到 ExtensionlessUrlHandler-Integrated-4.0
,双击它。单击 Request Restrictions...
按钮并在 Verbs
选项卡上,添加 DELETE
和 PUT
。
HttpResponseMessage responseDelete = await Client.GetAsync("/api/RfAttachment/DeleteById/1");
responseDelete.EnsureSuccessStatusCode();
这是错误的,您正在调用 GetAsync
,您应该调用 DeleteAsync
,因为您用 [HttpDelete]
动词标记了您的方法。
HttpResponseMessage responseDelete = await Client.DeleteAsync("/api/RfAttachment/DeleteById/1");
responseDelete.EnsureSuccessStatusCode();
在此查看更多详细信息 post
在 Web.Config 文件中包含这一行
<configuration>
<system.webServer>
<modules>
<remove name="WebDAVModule" />
</modules>
</system.webServer>
</configuration>
也许我需要在测试虚拟主机中设置某种权限?测试的 Get 和 Post 工作正常。但是当它尝试调用控制器上的 DELETE 方法时出现 HTTP 405 错误。
[HttpDelete("{id:int}")]
public async Task<ActionResult<RfAttachmentModel>> DeleteByIdAsync(int id)
{
await _rfAttachmentService.DeleteByIdAsync(id);
return NoContent();
}
public class CustomWebApplicationFactory<TStartup> : WebApplicationFactory<Startup>
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.UseEnvironment("LocalTesting");
builder.ConfigureServices(services =>
{
services.AddEntityFrameworkInMemoryDatabase();
ServiceProvider provider = services
.AddEntityFrameworkInMemoryDatabase()
.BuildServiceProvider();
services.AddDbContext<PwdrsContext>(options =>
{
options.UseInMemoryDatabase("Pwdrs");
options.UseInternalServiceProvider(provider);
});
ServiceProvider sp = services.BuildServiceProvider();
using (IServiceScope scope = sp.CreateScope())
{
IServiceProvider scopedServices = scope.ServiceProvider;
PwdrsContext db = scopedServices.GetRequiredService<PwdrsContext>();
ILoggerFactory loggerFactory = scopedServices.GetRequiredService<ILoggerFactory>();
ILogger<CustomWebApplicationFactory<TStartup>> logger = scopedServices
.GetRequiredService<ILogger<CustomWebApplicationFactory<TStartup>>>();
db.Database.EnsureDeleted();
db.Database.EnsureCreated();
try
{
PwdrsContextSeed.SeedAsync(db, loggerFactory).Wait();
}
catch (Exception ex)
{
logger.LogError(ex, $"An error occurred seeding the " +
"database with test messages. Error: {ex.Message}");
}
}
});
}
}
EDIT1:这是测试项目中进行调用的方法
[Fact]
public async Task Delete_Item_By_Id()
{
HttpResponseMessage responseDelete = await Client.GetAsync("/api/RfAttachment/DeleteById/1");
responseDelete.EnsureSuccessStatusCode();
HttpResponseMessage responseGetAll = await Client.GetAsync("/api/RfAttachment/GetAll");
responseGetAll.EnsureSuccessStatusCode();
string stringResponse = await responseGetAll.Content.ReadAsStringAsync();
List<RfAttachment> result = JsonConvert
.DeserializeObject<IEnumerable<RfAttachment>>(stringResponse)
.ToList();
Assert.Single(result);
}
如果您的 IWebHost 在 IIS / IISExpress 下 运行,您可能需要在 IIS 上启用 PUT 和 DELETE。
必须设置以下项目才能启用:
- 网站应用程序池托管管道模式必须设置为集成
- IIS 必须支持 HTTP 动词
设置应用程序池管道模式
- 转到 IIS 管理器 > 应用程序池
- 找到目标的应用程序池:
- (网站)> 编辑(双击)> 托管管道模式:集成
HTTP 动词更新
应将以下代码片段添加到 web.config
以启用所有动词,并确保 WebDAV
不会拦截和拒绝 PUT
和 DELETE
。如果配置了默认的WebDAV
,WebDAV
会拦截PUT
和DELETE
动词,返回405错误(方法不允许)。
<system.webServer>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="WebDAV" />
<add name="dotless" path="*.less" verb="GET" type="dotless.Core.LessCssHttpHandler,dotless.AspNet" resourceType="File" preCondition="" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" resourceType="Unspecified" requireAccess="Script" preCondition="integratedMode,runtimeVersionv4.0" responseBufferLimit="0" />
</handlers>
<modules>
<remove name="WebDAVModule" />
</modules>
</system.webServer>
如果您更喜欢 GUI to add verbs,请转至 IIS 管理器 > 处理程序映射。找到 ExtensionlessUrlHandler-Integrated-4.0
,双击它。单击 Request Restrictions...
按钮并在 Verbs
选项卡上,添加 DELETE
和 PUT
。
HttpResponseMessage responseDelete = await Client.GetAsync("/api/RfAttachment/DeleteById/1");
responseDelete.EnsureSuccessStatusCode();
这是错误的,您正在调用 GetAsync
,您应该调用 DeleteAsync
,因为您用 [HttpDelete]
动词标记了您的方法。
HttpResponseMessage responseDelete = await Client.DeleteAsync("/api/RfAttachment/DeleteById/1");
responseDelete.EnsureSuccessStatusCode();
在此查看更多详细信息 post
在 Web.Config 文件中包含这一行
<configuration>
<system.webServer>
<modules>
<remove name="WebDAVModule" />
</modules>
</system.webServer>
</configuration>