使用XMLHttpRequest发布到ASP.Net Core WebAPI时出现错误415

bsi*_*zle 10 c# asp.net xmlhttprequest typescript asp.net-core

使用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
Run Code Online (Sandbox Code Playgroud)

来自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 
Run Code Online (Sandbox Code Playgroud)

我想发布以下JSON:

{
    UserDOB: "2016-12-18",
    UserFirstName: "asdf",
    UserLastName: "asasdf",
    UserName: "asdf",
    UserSecret: "asdf"
}
Run Code Online (Sandbox Code Playgroud)

使用此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));
    }
}
Run Code Online (Sandbox Code Playgroud)

用户的模型是

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; }
    }
Run Code Online (Sandbox Code Playgroud)

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

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

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

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();
        }
Run Code Online (Sandbox Code Playgroud)

moh*_*has 35

在我的情况下,问题是我FromBody在action参数之前放了一个属性.

从:

[HttpPost("Contact")]
public async Task<IActionResult> NewContact([FromBody]Contact contact)
Run Code Online (Sandbox Code Playgroud)

至:

[HttpPost("Contact")]
public async Task<IActionResult> NewContact(Contact contact)
Run Code Online (Sandbox Code Playgroud)

  • 它也为我解决了该问题,但仔细检查后,我的Web应用程序使用的内容类型为application / x-www-form-urlencoded。一旦我将POST的内容类型更改为application / json,[FromBody]就可以做到这一点。我还没有研究是否可以将`[FromBody]`与`application / x-www-form-urlencoded`的内容类型结合使用。 (2认同)
  • 出现问题是因为 [FromBody] 的 ContentType 必须是 Json。如果它不是 JSON,它将出现 415 错误。当你取出它时,它接受 ContentType 的分配,而不接受 ContentType。 (2认同)

nem*_*mec 7

正如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();
}
Run Code Online (Sandbox Code Playgroud)

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

例如:

app.UseCors(builder =>
    builder.WithOrigins("http://example.com")
           .AllowAnyHeader()
);
Run Code Online (Sandbox Code Playgroud)

邮差是一个应用程序,因此有能力免受跨源规则.