Error 415 when submitting to ASP.Net Core WebAPI using XMLHttpRequest

Working on a new project using the WebAPI backend server, and I had problems sending to the controller from the actual website, despite the fact that Postman has no problems sending to the controller. I get error 415, browser console logging:

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 

Bye magazine from 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 

I am trying to post the following JSON:

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

using this TypeScript class

 /** * 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 model

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

While the controller for wiring is simple, just print the first name

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

Edit Although the answer from nemec was useful in solving the problem, I found that for WebAPI, in particular, the best solution was to configure cors using app.UseCors as services.AddCors in many cases did not actually include the necessary headers in the header.

 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(); } 
+10
source share
4 answers

As Evan mentioned in his comment, your POST turns into OPTIONS when you make an ajax request with cross origin. Due to the cross-starting browser security policy, your web api should tell the / js browser that your website is allowed to make ajax requests against it.

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

To configure CORS for your application, add the Microsoft.AspNetCore.Cors package to your project.

Add CORS services to Startup.cs:

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

If you follow the related instructions, you can even use IApplicationBuilder.UseCors to further configure which sites are allowed.

For instance:

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

A postman is an application and therefore has the ability to break free from cross-origin rules.

+7
source

In my case, the problem was that I placed the FromBody attribute in front of my action parameter.

From:

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

To:

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

I don't know why yet, I'm still pretty new to the .Net Core Web API. I deleted the controller attribute [ApiController] and everything fell into place.

In my situation, I have the MVC & WebApi interface for the same project. Hope this helps someone.

0
source

We upgraded to .NET core 3.0, and for this it was necessary to use [FromQuery] when creating an object from request parameters, for example, with a GET request.

Example:

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

Source: https://habr.com/ru/post/1261455/


All Articles