【问题标题】:Error 415 when posting to ASP.Net Core WebAPI using XMLHttpRequest使用 XMLHttpRequest 发布到 ASP.Net Core WebAPI 时出现错误 415
【发布时间】:2017-05-03 16:05:13
【问题描述】:

使用 WebAPI 后端服务器处理一个新项目,我在从实际网站向控制器发布时遇到问题,尽管 Postman 向控制器发布没有问题。我收到错误 415,浏览器控制台日志记录:

HTTP415: UNSUPPORTED MEDIA TYPE - The server is refusing to service the request because the entity of the request is in a format not supported by the requested resource for the requested method.
(XHR)OPTIONS - http://localhost:5000/api/Users

虽然来自 Kestrel 的日志是

info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 OPTIONS http://localhost:5000/api/Users  0
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 OPTIONS http://localhost:5000/api/Users  0
info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
      Executing HttpStatusCodeResult, setting HTTP status code 415
Microsoft.AspNetCore.Mvc.StatusCodeResult:Information: Executing HttpStatusCodeResult, setting HTTP status code 415
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
      Executed action SchoolsChat.Controllers.UserContoller.Post (SchoolsChat) in 2.5323ms
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action SchoolsChat.Controllers.UserContoller.Post (SchoolsChat) in 2.5323ms
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 6.6615ms 415 
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 6.6615ms 415 

我正在尝试发布以下 JSON:

{
    UserDOB: "2016-12-18",
    UserFirstName: "asdf",
    UserLastName: "asasdf",
    UserName: "asdf",
    UserSecret: "asdf"
}

使用这个 TypeScript 类

/**
 * JsonPost
 */
class JsonPost {
    private _response: number;
    public get Reponse(): number {
        return this._response;
    }
    constructor(link: string, data: Object) {
        let request = new XMLHttpRequest();
        request.withCredentials = true;

        request.open("POST", APIUri + link, true);
        request.setRequestHeader("content-type", "application/json");
        request.setRequestHeader("cache-control", "no-cache");
        request.onreadystatechange = () => this._response = request.status;
        console.log(request);
        request.send(JSON.stringify(data));
    }
}

User的模型是

public class User
    {
        [KeyAttribute]
        public int UserId { get; set; }
        [RequiredAttribute]
        public int SchoolId { get; set; }
        [RequiredAttribute]
        public string UserName { get; set; }
        [RequiredAttribute]
        [DataTypeAttribute(DataType.Password)]
        public string UserSecret { get; set; } // Unnecessary due to school linking?
        [RequiredAttribute]
        public virtual School UserSchool { get; set; }
    }

虽然发布的控制器很简单,只是输出名字

[HttpPost]
    public IActionResult Post([FromBody]User user)
    {
        Console.WriteLine(user.UserName);
        return StatusCode(200);
    }

编辑 虽然 nemec 的回答有助于解决问题,但我发现对于 WebAPI,最好的解决方案是仅使用 app.UseCors 作为服务配置 cors。在许多情况下,AddCors 实际上并没有在响应中包含必要的标头。

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            app.UseCors(options => options.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod().AllowCredentials());
            loggerFactory.AddConsole(Configuration.GetSection("Logging"));
            loggerFactory.AddDebug();
            app.UseMvc();
        }

【问题讨论】:

标签: c# asp.net typescript asp.net-core xmlhttprequest


【解决方案1】:

就我而言,问题在于我在操作参数之前放置了一个FromBody 属性。

发件人:

[HttpPost("Contact")]
public async Task<IActionResult> NewContact([FromBody]Contact contact)

收件人:

[HttpPost("Contact")]
public async Task<IActionResult> NewContact(Contact contact)

【讨论】:

  • 它也为我解决了这个问题,但仔细检查后,我的网络应用使用application/x-www-form-urlencoded 的内容类型发布。一旦我将POST 的内容类型更改为application/json [FromBody] 就可以做到这一点。我还没有深入研究是否可以将[FromBody]application/x-www-form-urlencoded 的内容类型结合使用。
  • 出现问题是因为[FromBody]的ContentType必须是Json。如果它不是 JSON,它将执行 415 错误。取出时,接受分配的ContentType,不接受ContentType。
  • 我同意@mohas。对我来说,ASP.Net Core 415 错误的常见原因是缺少绑定属性或请求与声明的绑定([FromBody]、[FromForm]、[FromQuery] 等)不匹配。旧版本的 MVC 通常可以在没有绑定属性的情况下正常工作。
【解决方案2】:

正如 Evan 在他的评论中提到的,当您发出跨域 ajax 请求时,您的 POST 正在变成 OPTIONS。由于浏览器的跨域安全策略,您的 web api 需要告诉浏览器/js,您的网站允许对其进行 ajax 请求。

https://docs.microsoft.com/en-us/aspnet/core/security/cors

要为您的应用程序设置 CORS,请将 Microsoft.AspNetCore.Cors 包添加到您的项目中。

在 Startup.cs 中添加 CORS 服务:

public void ConfigureServices(IServiceCollection services)
{
    services.AddCors();
}

如果您按照链接的说明进行操作,您甚至可以使用IApplicationBuilder.UseCors 进一步自定义允许哪些网站。

例如:

app.UseCors(builder =>
    builder.WithOrigins("http://example.com")
           .AllowAnyHeader()
);

Postman 是一款应用程序,因此可以免除跨域规则的约束。

【讨论】:

    【解决方案3】:

    还不知道为什么,我对 .Net Core Web API 还是很陌生。我删除了控制器属性 [ApiController],一切都到位了。

    在我的情况下,我在同一个项目上有一个 MVC 接口和 WebApi。 希望这对某人有所帮助。

    【讨论】:

      【解决方案4】:

      我们升级到 .NET core 3.0,当您从查询参数构建对象时需要使用 [FromQuery],例如使用 GET 请求。

      例子:

      [HttpGet("Hierarchy")]
      public virtual async Task<IActionResult> GetHierarchy([FromServices] IDeviceHierarchyService service, [FromQuery] HierarchyStructureRequest structureLoad)
      

      【讨论】:

        猜你喜欢
        • 2017-01-07
        • 2020-10-08
        • 2016-07-27
        • 2017-05-26
        • 1970-01-01
        • 1970-01-01
        • 2017-08-26
        • 1970-01-01
        • 2018-12-26
        相关资源
        最近更新 更多