C# 使用XMLHttpRequest发布到ASP.Net核心WebAPI时出现错误415

C# 使用XMLHttpRequest发布到ASP.Net核心WebAPI时出现错误415,c#,asp.net,typescript,asp.net-core,xmlhttprequest,C#,Asp.net,Typescript,Asp.net Core,Xmlhttprequest,在使用WebAPI后端服务器进行一个新项目时,尽管邮递员在向控制器发送邮件时没有遇到问题,但我在从实际网站向控制器发送邮件时遇到了问题。我得到一个错误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 r

在使用WebAPI后端服务器进行一个新项目时,尽管邮递员在向控制器发送邮件时没有遇到问题,但我在从实际网站向控制器发送邮件时遇到了问题。我得到一个错误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
而红隼的原木是

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"
}
使用这个类型脚本类

/**
 * 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));
    }
}
用户模型是

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();
        }

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

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

在Startup.cs中添加CORS服务:

public void ConfigureServices(IServiceCollection services)
{
    services.AddCors();
}
如果按照链接的说明操作,您甚至可以使用
iaapplicationbuilder.UseCors
进一步自定义允许的站点

例如:

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

Postman是一个应用程序,因此有能力免除自己的跨来源规则。

在我的例子中,问题是我在操作参数之前放置了一个
FromBody
属性

发件人:

[HttpPost(“联系人”)]
公共异步任务NewContact([FromBody]联系人)
致:

[HttpPost(“联系人”)]
公共异步任务NewContact(联系人联系人)

我还不知道为什么,我对.Net核心Web API还是相当陌生的。我删除了controller属性[ApiController],一切都正常了

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

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

例如:

[HttpGet("Hierarchy")]
public virtual async Task<IActionResult> GetHierarchy([FromServices] IDeviceHierarchyService service, [FromQuery] HierarchyStructureRequest structureLoad)
[HttpGet(“层次结构”)]
公共虚拟异步任务GetHierarchy([FromServices]IDeviceHierarchyService服务,[FromQuery]HierarchyStructureRequestStructureLoad)

请参阅,了解为什么您看到的是
选项
请求而不是
帖子
。这也解决了我的问题,但仔细检查后,我的web应用程序使用的内容类型是
应用程序/x-www-form-urlencoded
。一旦我将
POST
的内容类型更改为
application/json
[FromBody]
就可以了。我还没有深入研究是否可以将
[FromBody]
应用程序/x-www-form-urlencoded
的内容类型结合使用。出现问题的原因是[FromBody]的内容类型必须是Json。如果不是JSON,它将执行415错误。当你取出它时,它接受ContentType的分配,而不接受ContentType。我同意@mohas。对我来说,ASP.Net Core出现415个错误的常见原因是缺少绑定属性或请求与声明的绑定不匹配([FromBody]、[FromForm]、[FromQuery]等)。旧版本的MVC通常可以在没有绑定属性的情况下正常工作。
[HttpPost("Contact")]
public async Task<IActionResult> NewContact(Contact contact)
[HttpGet("Hierarchy")]
public virtual async Task<IActionResult> GetHierarchy([FromServices] IDeviceHierarchyService service, [FromQuery] HierarchyStructureRequest structureLoad)