【问题标题】:Why sending a PUT request as plain/text is not accepted by ASP.NET Core?为什么 ASP.NET Core 不接受以纯文本/文本形式发送 PUT 请求?
【发布时间】:2019-04-27 09:38:08
【问题描述】:

我正在尝试发送一个包含字符串的 PUT 请求。

请求从 Angular 中的客户端发送到作为 ASP.NET Core 控制器的服务器。请求头是text/plain

要让 ASP.NET Core 接受 text/plain,我必须遵循 this 教程,该教程只有在我使用 Postman 发送请求时才有效:
当我尝试从客户端向服务器发送相同的请求时它不起作用,请求不是事件触发来自RawRequestBodyFormatter 类的制动点。

角度服务:

export class LendedBookService {
  private baseUrl: string;

  constructor(private httpClient: HttpClient) {
    this.baseUrl = 'http://localhost:55152/';
  }

  public sendReminder(lendedBookId: string): Observable<any> {
    var headers = new HttpHeaders({'Content-Type': 'text/plain; charset=utf-8'});
    return this.httpClient.put<string>(this.baseUrl + 'api/lendedBook/sendReminder', lendedBookId, {
      headers: headers
    });
  }
}

ASP.NET Core 控制器:

[Route("api/[controller]/[action]")]
[ApiController]
public class LendedBookController : ControllerBase
{
    private readonly Libranian libranian;

    public LendedBookController(Libranian libranian)
    {
        this.libranian = libranian;
    }

    [HttpPut]
    public async Task<IAsyncResult> SendReminder([FromBody]string lendedBookId)
    {
        using (var unitOfWork = UnitOfWorkLocator.GetUnitOfWork())
        {
            if (await libranian.NotifyToReturnLend(new Guid(lendedBookId)))
            {
                return Task.Run(() => NoContent());
            }

            return Task.Run(() => StatusCode(500));
        }
    }
}

在这种情况下,我应该怎么做或者我做错了什么发送text/plain 请求?
谢谢!

【问题讨论】:

  • 控制台有错误吗? API调用后
  • @PrashantPimpale 不。 Fiddler 也没有找到请求。
  • 网络标签中的任何内容?
  • 我建议将其设为 JSON 而不是纯文本,这样在维护和更改方面会更好
  • ASP.NET 字符串中的@PrashantPimpale 不能作为application/JSON 发送。

标签: angular asp.net-core httprequest


【解决方案1】:

一个原因可能是:

跨源资源共享 (CORS) 是一种机制,它使用额外的 HTTP 标头告诉浏览器让在一个源(域)运行的 Web 应用程序有权访问来自不同源的服务器的选定资源。当 Web 应用程序请求的资源与自己的来源不同(域、协议和端口)时,它会执行跨域 HTTP 请求。

跨域请求示例:从http://domain-a.com 提供服务的 Web 应用程序的前端 JavaScript 代码使用 XMLHttpRequest 向http://api.domain-b.com/data.json 发出请求。

出于安全原因,浏览器会限制从脚本中发起的跨域 HTTP 请求。例如,XMLHttpRequest 和 Fetch API 遵循同源策略。这意味着使用这些 API 的 Web 应用程序只能从加载应用程序的同一源请求 HTTP 资源,除非来自其他源的响应包含正确的 CORS 标头。

ref

加入 .NET Core:.NET Core 是否支持 CORS? 是的,确实如此。

将 CORS 与 .NET Core 一起使用非常简单明了。

您只需按照以下步骤操作:

  • 安装 Microsoft.AspNetCore.Cors Nuget 包。
  • 在 ConfigureService 方法中配置 CORS。
  • 在 Configure 方法中使用中间件启用 CORS。
  • 通过在控制器或操作中启用 CORS 在 .NET Core MVC 中启用它 或全球。 ref

更新

没有 JSON - 没有 Workey 如果你想发送一个 RAW 字符串或二进制数据,并且你想把它作为你请求的一部分,事情会变得更加复杂。 ASP.NET Core 只处理它知道的内容,默认情况下是 JSON 和 Form 数据。默认情况下,原始数据不能直接映射到控制器参数。

我基本上在做与第一个请求相同的事情,除了我发送的不是 JSON 内容类型而是纯文本。端点存在,但 MVC 不知道如何处理文本/纯内容或如何映射它,因此它失败并显示 404 Not Found。

这不是很明显,而且我知道这可能会让那些希望映射原始内容的毫无戒心的新手绊倒。但是,如果您考虑一下,这是有道理的:MVC 具有特定内容类型的映射,如果您传递不适合这些内容类型的数据,它就无法转换数据,因此它假定没有匹配的端点可以处理请求。

那么我们如何获取原始数据呢?

读取原始数据的 Request.Body 不幸的是,ASP.NET Core 不允许您仅通过方法参数以任何有意义的方式捕获“原始”数据。您需要以一种或另一种方式对 Request.Body 进行一些自定义处理以获取原始数据,然后对其进行反序列化。

您可以捕获原始 Request.Body 并从中读取原始缓冲区,这非常简单。

最简单、侵入性最小但不那么明显的方法是使用一种方法,接受不带参数的 POST 或 PUT 数据,然后从 Request.Body 中读取原始数据:

[HttpPost]
[Route("api/BodyTypes/ReadStringDataManual")]
public async Task<string> ReadStringDataManual()
{
    using (StreamReader reader = new StreamReader(Request.Body, Encoding.UTF8))
    {  
        return await reader.ReadToEndAsync();
    }
}

Check this post

【讨论】:

  • 感谢您的回答,服务器允许 CORS,因为以 application/json 发送的其他请求工作正常。
  • 检查更新部分@EduardStefanescu
  • 感谢您的更新,在我的帖子中我说我遵循了该教程。因为有了 Postman,我可以发送请求。
  • 所以在帖子中说,内容来自 [FromBody] 视为 json 而不是原始
  • 用Request.Body读取body,顺便说一下json更好
猜你喜欢
  • 2016-03-07
  • 2015-03-09
  • 1970-01-01
  • 2015-09-19
  • 1970-01-01
  • 1970-01-01
  • 2011-08-20
  • 2016-09-27
  • 1970-01-01
相关资源
最近更新 更多