使用 XMLHttpRequest 发布到 ASP.Net Core WebAPI 时出现错误 415
Posted
技术标签:
【中文标题】使用 XMLHttpRequest 发布到 ASP.Net Core WebAPI 时出现错误 415【英文标题】:Error 415 when posting to ASP.Net Core WebAPI using XMLHttpRequest 【发布时间】: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();
【问题讨论】:
请参阅 ***.com/questions/8153832/… 了解为什么您看到的是OPTIONS
请求而不是 POST
。
【参考方案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)
【讨论】:
以上是关于使用 XMLHttpRequest 发布到 ASP.Net Core WebAPI 时出现错误 415的主要内容,如果未能解决你的问题,请参考以下文章
用于 XmlHttpRequest 的带有 WebAPI 的 CORS
带有 Vue JS 的 ASP.NET Core 5 从源访问 XMLHttpRequest 已被 CORS 策略阻止
是否可以在XMLHttpRequest标头中包含antiforgerytoken?