繁体   English   中英

ASP.NET 5 Web API CreatedAtAction:POST 返回 500

[英]ASP.NET 5 Web API CreatedAtAction: POST returns 500

我有一个简单的 ASP.NET 5 Web API,带有一个用于上传/下载文件的控制器,例如:

[Authorize(Roles = "admin,browser,writer")]
[HttpPost("api/contents/{id}")]
public IActionResult UploadContent(IFormFile file,
    [FromForm] string mimeType,
    [FromForm] string id)
{
  // store...
  return CreatedAtAction(nameof(DownloadContent), new
  {
      id = id
  });
}

[Authorize]
[HttpGet("api/contents/{id}")]
public FileResult DownloadContent([FromRoute] string id)
{
    // fetch into item...
    return File(item.Content, item.MimeType);
}

上传操作正常工作,直到该方法返回:此时,当框架处理 201 返回对象的序列化(应将其位置设置为相应的下载操作)时,我得到一个InvalidOperationException告诉我No route matches the supplied values .

我发现 这个问题是关于一个类似的问题,但提到的解决方案似乎都不起作用。 我试过了:

  1. 使用[ActionName("DownloadContent")]显式命名下载操作,即使这应该没有任何区别; 这似乎仅在操作名称以Async结尾时才相关(请参阅此帖子和官方问题)。
  2. 使用CreatedAtRoute代替,通过加入相应的Name="DownloadContent"中的属性HTTPGET DownloadContent
  3. 使用CreatedAtActionResult像:
return new CreatedAtActionResult(nameof(DownloadContent),
    nameof(ItemContentController), new { id = id }, null);
  1. 直接创建 URL 并返回一个CreatedResult对象:
string url = Url.Action(new UrlActionContext
{
    Protocol = Request.Scheme,
    Host = Request.Host.Value,
    Action = nameof(DownloadContent)
});
return new CreatedResult(url, null);

现在,这就是重点:上面的代码为url返回null ,然后这使CreatedResult抛出,因为 201 标头的Locationurl为 null。 如果我通过选择不同的操作来更改此代码,例如Action = nameof(UploadContent) ,它会起作用,并且我会获得该操作的 URL。

为了完整Startup.cs ,我的Startup.cs Configure方法是这样的:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseForwardedHeaders(new ForwardedHeadersOptions
    {
        ForwardedHeaders = ForwardedHeaders.XForwardedFor
            | ForwardedHeaders.XForwardedProto
    });
    if (env.IsDevelopment()) app.UseDeveloperExceptionPage();
    else
    {
        app.UseExceptionHandler("/Error");
        if (Configuration.GetValue<bool>("Server:UseHSTS")) app.UseHsts();
    }
    app.UseHttpsRedirection();
    app.UseRouting();
    app.UseCors("CorsPolicy");
    app.UseAuthentication();
    app.UseAuthorization();
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
    // ... Swagger stuff ...
}

使用重载CreatedAtAction(string, object) ,param object不是您假设的路由参数,而是正文内容。 因此,代码正在寻找一条不存在的 GET api/contents路线。

您需要使用重载CreatedAtAction(string, object, object)其中 param #2 包含路由参数,而 param #3 包含正文内容。 所以在你的情况下, return CreatedAtAction(nameof(DownloadContent), new { id = id }, null); 将工作。

我能够使用此控制器和邮递员重现您的问题:

public class MyContentController : ControllerBase
{
    [HttpGet("api/contents/{id}")]
    public IActionResult DownloadContent(int id)
    {
        return Ok(1);
    }
    
    [HttpPost("api/contents/{id}")]
    public IActionResult UploadContent(int id)
    {
        return CreatedAtAction(nameof(DownloadContent), new { id = id });
    }
}

更换时我得到了预期的响应

return CreatedAtAction(nameof(DownloadContent), new { id = id });

return CreatedAtAction(nameof(DownloadContent), new { id = id }, null);

文档: https : //docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.controllerbase.createdataction? view = aspnetcore-5.0# Microsoft_AspNetCore_Mvc_ControllerBase_CreatedAtAction_System_String_System_Object _

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM