WebApi 2.1 PUT throw error 415 - asp.net-web-api

I'm trying to update data using WebApi PUT method. My code working fine before, but suddenly I start to get this error.
"Message":"The request contains an entity body but no Content-Type header. The inferred media type 'application/octet-stream' is not supported for this resource.","ExceptionMessage":"No MediaTypeFormatter is available to read an object of type 'xEmployee' from content with media type 'application/octet-stream'.","ExceptionType":"System.Net.Http.UnsupportedMediaTypeException".
This is headers:
Response Header.
HTTP/1.1 415 Unsupported Media Type
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/7.5
Set-Cookie: Role=D65520F37D105E39C1A92C15CD482E378F32A769592AC7D8305285A5B9B90362F7F2F13F14E6DC220E44D26940B06B52E7460EF13184F245805AF9523D1072464F4BD06AFB4F8AEB8B7D8BF607A8922C6041A3A4C636BF3B26388E606A94FE43; expires=Tue, 07-Oct-2014 09:49:56 GMT; path=/
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Tue, 07 Oct 2014 09:19:56 GMT
Content-Length: 809
Request Header:
PUT /api/xemployees/2110481232 HTTP/1.1
Host: guideonline.ilvestour.office
Connection: keep-alive
Content-Length: 229
Accept: application/json, text/javascript, */*; q=0.01
Origin: http://guideonline.ilvestour.office
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36
Content-Type: application/json; charset=UTF-8"
Referer: http://guideonline.ilvestour.office/account
Accept-Encoding: gzip,deflate,sdch
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4
Cookie: .ASPXAUTH=215C424A0A023F5B42775B7A73B08FEC8CB36E7200FBA430EADF2F300A84500571F8B5EE980C3EF2913FE160978973CDBC50BDD216E16FC342EF0B566D0944ECFD901DF471DEF9F6E5D272B52F2450CC0A1FB96BCC6B3B6E7A7C07343D4DFBD66; Role=DE678EE89D7089B8CD74B202E00C53CA9AE9E4C40B506C5C4EEF56E7962F38ED86F6BFD34E5FD3A6DD6ECCCF61AF768CAB0C1D7C5F15A8638F9454B24DF3208F021EB638235420574C6420CA5A19F0B6BD07BAC303FF79612D6C1AF246563A7
Request Payloadview source
{"Kod":2110481232, "Сотрудник": "Lena", "Telephon": "088-6734227", "Password":"rimosa57", "email":"samoylova-elena#mail.ru", "CrWho":"OMEGA.Administrator", "CrWhen":"2014-10-07T09:20:05.735Z"}
Nothing special in Controller code:
[Authorize(Roles = "Admin, User")]
public async Task<IHttpActionResult> PutxEmployee(int id, xEmployee xEmployee)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (id != xEmployee.Kod)
{
return BadRequest();
}
try
{
var user = db.xEmployee.Find(id);
user.Сотрудник = xEmployee.Сотрудник;
user.Telephon = xEmployee.Telephon;
user.Password = xEmployee.Password;
user.email = xEmployee.email;
await db.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!xEmployeeExists(id))
{
return NotFound();
}
else
{
throw;
}
}
catch (DbEntityValidationException e)
{
foreach (var eve in e.EntityValidationErrors)
{
var path = "C:/error.txt";
using (StreamWriter sw = File.CreateText(path))
{
sw.WriteLine("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:",
eve.Entry.Entity.GetType().Name, eve.Entry.State);
}
using (StreamWriter sw1 = File.CreateText("C:/error1.txt"))
foreach (var ve in eve.ValidationErrors)
{
sw1.WriteLine("- Property: \"{0}\", Error: \"{1}\"",
ve.PropertyName, ve.ErrorMessage);
}
}
throw;
}
return StatusCode(HttpStatusCode.NoContent);
}
Same as WebApiConfig:
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
var json = config.Formatters.JsonFormatter;
json.SerializerSettings.Culture = new CultureInfo("ru-RU");
config.Formatters.Remove(config.Formatters.XmlFormatter);
}

There seems to be a typo (last ") in the request's Content-Type header:
Content-Type: application/json; charset=UTF-8"
When this header is missing or malformed, the server will automatically use application/octet-stream by default, as described by this post.

I were facing similar problem. Though i have a Content-Type declare it was still sending same error.
What I did is added Accept Header and it started working.
Accept: application/json
Content-Type: application/json

Also, make sure there's only one header Content-Type. In my case, my rest client was implicitly sending the empty Content-Type which got overridden by Content-Type: application/json hence the error.

Related

Wrong response from the server - It seems my FrontEnd is getting Options response instead of Post

I have read a lot about CORS, preflight etc, I know the problem is related to it, but couldn't figure out, what's going on here.
I'm using VueJs and SpringBoot with Spring Security and jsonwebtoken.
When I make a POST request /login on Postman:
{
"username":"admin",
"password":"password"
}
I got the right response with the expected token:
http 200 with headers:
{
Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhZG1pbiIsImV4cCI6MTYwODI5OTIxMn0.9oXFpm9DivR3DNPcBaoc_KgsqNdBJbkFq_oA4pBJbXF2iUwx7_XfBwv-Xcn-da9LS9M5zxd8oRslr_wdVyoQkA,
X-Content-Type-Options:nosniff
X-XSS-Protection:1; mode=block
Cache-Control:no-cache, no-store, max-age=0, must-revalidate
Pragma:no-cache
Expires:0
X-Frame-Options:DENY
Content-Length:0
}
However, when the front-End calls the service I got the following answer with the wrong header, there is no token:
http 200 with headers
{
cache-control: "no-cache, no-store, max-age=0, must-revalidate",
content-length: "0", expires: "0", pragma: "no-cache"
}
When I open the browser with security disabled it works fine as well, I got the expected token on the header...
"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --user-data-dir="C://Chrome dev session" --disable-web-security
So it seems to be related to Cors indeed, but I don't get any Cors error message!
I used fiddler to track the requests and responses and I notice that the option method is happening, So my first question is, should the options response go up to the front-end? as far as I know the options stay within the browser boundary and then the browser makes the post request (if the server allowed).
Options Request:
OPTIONS http://ec2-52-4-252-232.compute-1.amazonaws.com:9090/login HTTP/1.1
Host: ec2-52-4-252-232.compute-1.amazonaws.com:9090
Connection: keep-alive
Accept: */*
Access-Control-Request-Method: POST
Access-Control-Request-Headers: authorization
Origin: http://s3-sa-east-1.amazonaws.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36
Sec-Fetch-Mode: cors
Referer: http://s3-sa-east-1.amazonaws.com/
Accept-Encoding: gzip, deflate
Accept-Language: pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7,es;q=0.6
Options Response:
HTTP/1.1 200
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Access-Control-Allow-Origin: http://s3-sa-east-1.amazonaws.com
Access-Control-Allow-Methods: POST
Access-Control-Allow-Headers: authorization
Access-Control-Allow-Credentials: true
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Length: 0
Date: Tue, 08 Dec 2020 14:58:56 GMT
Post Request:
POST http://ec2-52-4-252-232.compute-1.amazonaws.com:9090/login HTTP/1.1
Host: ec2-52-4-252-232.compute-1.amazonaws.com:9090
Connection: keep-alive
Content-Length: 42
Accept: application/json, text/plain, */*
Authorization: undefined
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Origin: http://s3-sa-east-1.amazonaws.com
Referer: http://s3-sa-east-1.amazonaws.com/
Accept-Encoding: gzip, deflate
Accept-Language: pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7,es;q=0.6
{
"username":"admin",
"password":"password"
}
Post Response:
HTTP/1.1 200
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Access-Control-Allow-Origin: http://s3-sa-east-1.amazonaws.com
Access-Control-Allow-Credentials: true
Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhZG1pbiIsImV4cCI6MTYwODI5OTUzNn0.0UgsNHd9Aw9Ei5aq-k0y74BlxJ92-j7w-FrryZaDAwzLC1a2OpSH3rXhRWGIul3wqpWLbqJ7icNlM3d590UFWw
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Length: 0
Date: Tue, 08 Dec 2020 14:58:56 GMT
Part of My front-end Code:
login({ commit }, user) {
const cors = require('cors')({
origin: true
});
const qs = require('querystring')
return new Promise((resolve, reject) => {
commit('auth_request')
axios({
url: process.env.VUE_APP_BACKEND_ENDPOINT + '/login', data: user, method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded'}
})
.then(resp => {
console.log(resp.headers)
const token = resp.headers["authorization"]
localStorage.setItem('token', token)
axios.defaults.headers.common['Authorization'] = token
commit('auth_success', token, user.username)
resolve(resp)
})
.catch(err => {
commit('auth_error')
localStorage.removeItem('token')
reject(err)
})
})
Part of my Back-End Code:
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.cors().configurationSource(corsConfigurationSource()).and()
.csrf().disable().authorizeRequests()
.antMatchers("/home").permitAll()
.antMatchers(HttpMethod.POST, "/login").permitAll()
.anyRequest().authenticated()
.and()
// filtra requisições de login
.addFilterBefore(new JWTLoginFilter("/login", authenticationManager()),
UsernamePasswordAuthenticationFilter.class)
// filtra outras requisições para verificar a presença do JWT no header
.addFilterBefore(new JWTAuthenticationFilter(),
UsernamePasswordAuthenticationFilter.class);
}
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
List<String> allowOrigins = Arrays.asList("*");
configuration.setAllowedOrigins(allowOrigins);
configuration.setAllowedMethods(singletonList("*"));
configuration.setAllowedHeaders(singletonList("*"));
//in case authentication is enabled this flag MUST be set, otherwise CORS requests will fail
//configuration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// cria uma conta default
auth.inMemoryAuthentication()
.withUser("admin")
.password("{noop}password")
.roles("ADMIN");
}
}```
Anyone knows what's going on here ? Why the Post response isn't coming to the front-end ?
I spend many hours but couldn't solve it, so I appreciate any help.
I can reproduce your Postman request with curl:
curl -vv -H "Content-Type: application/x-www-form-urlencoded" http://ec2-52-4-252-232.compute-1.amazonaws.com:9090/login -d '{"username":"admin", "password":"password"}'
Returns a 200 with the Authorization header filled in.
Can you run the frontend code with the Network tab in Developer Tools open and see how the POST request looks?
And possibly right-click and "copy as cURL" and then compare it to the curl request above.
Actually my problem wasn't related to options method as I thought, the problem was that I was missing the Access-Control-Expose-Headers which should also be presented in the headers of server response.
I just set it on my springboot app and it worked fine !
List<String> exposedHeaders = Arrays.asList("Authorization");
configuration.setExposedHeaders(exposedHeaders);
I got the answer from this one: axios response headers missing data when running in vuejs app

issue posting multipart/form-data via html5 FormData to c# Api

My issue is that my c# api controller is kicking back theFormData Post request when I check for multi-part data here: IsMimeMultipartContent(), which then throws the message back to the UI:
415 (Unsupported Media Type)
[HttpPost]
[Route("MediaUpload")]
public async Task<HttpResponseMessage> MediaUpload([FromUri]string sessionId, [FromUri]string patientId)
{
if (!Request.Content.IsMimeMultipartContent())
{ // *** ALWAYS THROWS ERROR ***
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
//access form data
var provider = await Request.Content.ReadAsMultipartAsync(new InMemoryMultipartFormDataStreamProvider());
NameValueCollection formData = provider.FormData;
//... additional code omitted
var response = Request.CreateResponse(HttpStatusCode.OK);
response.Headers.Add("UploadPath", fullPath);
response.Headers.Add("Access-Control-Allow-Origin", "*");
return response;
}
My front end payload looks like this:
REQUEST HEADERS
POST /api/import/MediaUpload?sessionID=c83f9589-742e-40e3-8cf5-7ffff141c3d7&patientId=5981 HTTP/1.1
Host: localhost:56703
Connection: keep-alive
Content-Length: 6545
Accept: application/json, text/plain, */*
Origin: http://localhost:4200
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36
Content-Type: multipart/form-data
Referer: http://localhost:4200/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
REQUEST PAYLOAD
------WebKitFormBoundaryVrKSHPqdT9c6JkKv
Content-Disposition: form-data; name="enctype"
multipart/form-data
------WebKitFormBoundaryVrKSHPqdT9c6JkKv
Content-Disposition: form-data; name="MediaInfo"
[{"PatientID":5981,"PatientLastName":"Hobo","PatientFirstName":"John","DeviceID":"123","InstanceID":89,"PatientDOB":"1/3/1970","FileName":"image2.jpg","FileSize":5880,"ExamDate":"5/30/2018","PatientID":66665981,"SessionID":"sessionID=9999141c3d7"}]
------WebKitFormBoundaryVrKSHPqdT9c6JkKv
Content-Disposition: form-data; name="files[]"; filename="image2.jpg"
Content-Type: image/jpeg
ÿØÿàJFIFÿÛC
------WebKitFormBoundaryVrKSHPqdT9c6JkKv--
My front end is sending in FormData, generated in the following TypeScript method, then calling the importService further below:
save() {
let params = { patientID: ''};
let exDate = new Date(this.defaultDate).toLocaleDateString();
// Populate MediaInfo object
let minfo = this.SetMediaArray();
params.pID = minfo[0].PID;
const formData = new FormData();
formData.set("enctype", "multipart/form-data" ); // doesn't make a difference..
formData.append("MedInfo", JSON.stringify(minfo));
for(var i=0; i<this.importImages.length; i++){
// append images to the files[] array, then send formData object to impService
formData.append("files[]", this.dataURItoBlob(this.importImages[i].TnUrl), this.importImages[i].name);
}
let endpoint = this.selectedObj.Url;
this.importService.saveImportObjects(formData, params, endpoint).subscribe(
data=> {
console.log(data);
},
err => {
console.log(err);
}
);
}
So basically I would like to know exactly what http option I'm missing for this to work.
thank you.
I removed the multipart/boundary header attribute, and let the browser take care of it for you. The upload worked.

No Authorization Header sending POST from Angular to Spring

I have:
a backend server written with Spring
and a client written in Angular
I am trying to send a POST request...
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders } from '#angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
#Injectable()
export class AuthenticationService {
constructor(private http: HttpClient) { }
login(username: string, password: string) {
const httpOptions = {
headers: new HttpHeaders({
'Content-Type' : 'application/x-www-form-urlencoded',
'Accept' : 'application/json',
'Authorization' : 'Basic blablabla_base64_encoded'
})
};
const body = 'username=' + username + '&password=' + password + '&grant_type=password';
console.log(body);
console.log(httpOptions.headers);
console.log(this.http.post<any>('http://localhost:8080/oauth/token', body, httpOptions));
return this.http.post<any>('http://localhost:8080/oauth/token', body, httpOptions)
.map(
user => {
// login successful if there's a jwt token in the response
if (user && user.token) {
// store user details and jwt token in local storage to keep user logged in between page refreshes
localStorage.setItem('currentUser', JSON.stringify(user));
}
return user;
});
}
logout() {
// remove user from local storage to log user out
localStorage.removeItem('currentUser');
}
}
Filtering the request with Wireshark I got:
OPTIONS /oauth/token HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Access-Control-Request-Method: POST
Origin: http://localhost:4200
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML,
like Gecko) Chrome/67.0.3396.79 Safari/537.36
DNT: 1
Access-Control-Request-Headers: authorization
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
HTTP/1.1 401 Unauthorized
Server: Apache-Coyote/1.1
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
WWW-Authenticate: Basic realm="oauth2/client"
Access-Control-Allow-Origin: http://localhost:4200
Vary: Origin
Access-Control-Allow-Methods: POST
Access-Control-Allow-Headers: authorization
Access-Control-Allow-Credentials: true
Allow: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH
Content-Length: 0
Date: Sat, 09 Jun 2018 14:19:36 GMT
For some reason I have no Authorization header and my request from POST become OPTIONS. I searched for some hour other solutions over the web but none of them helped me.
Some advice?
Found the answer to this question.
The Spring server has to manage also pre-flighted requests according to the paradigm explained in the documentation here:
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Preflighted_requests
To add the CORS management is possible to add a CORSFilter before all other filters implemented in the Spring Boot App, with a good code example here:
https://gist.github.com/malike/f8a98b498368932e6d7511886a167848

Preflight request is ok, then, after auth, response does not contain allow cors header

Asp MVC 5 app deployed on IIS 8.5.
Need to enable ajax request from a number of clients.
Server-side I have In WebApiConfig.cs
config.EnableCors();
In controller:
[EnableCors(origins: "http://localhost:59901", headers: "*", methods: "*", SupportsCredentials = true)]
public class ItemController : Controller
Client side
$("#getItem").on("click", function (e) {
var myurl = "http://servername/item/details/1"
$.ajax({
url: myurl,
type: "GET",
dataType: "JSON",
xhrFields: {
withCredentials: true
},
contentType: "application/json; charset=utf-8",
error: function (jqXHR, textStatus, errorThrown) {
$('#result').text(jqXHR.responseText || textStatus);
},
success: function (result) {
$('#result').text(result);
}
});
});
Running client from VisualStudio Origin is http://localhost:59901.
Running the ajax request I get the following in fiddler:
1. Preflight request/response
OPTIONS http://vrtsrv01.webdev.local/item/details/1 HTTP/1.1
Host: vrtsrv01.webdev.local
Connection: keep-alive
Access-Control-Request-Method: GET
Origin: http://localhost:59901
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
Access-Control-Request-Headers: content-type
Accept: */*
Referer: http://localhost:59901/Home/Index
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8,it;q=0.6,it-IT;q=0.4
HTTP/1.1 200 OK
Server: Microsoft-IIS/8.5
Access-Control-Allow-Origin: http://localhost:59901
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, MaxDataServiceVersion
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Credentials: true
X-Powered-By: ASP.NET
Date: Sat, 13 May 2017 15:34:54 GMT
Content-Length: 0
2. GET request without credentials/ 401 error response
GET http://vrtsrv01.webdev.local/item/details/1 HTTP/1.1
Host: vrtsrv01.webdev.local
Connection: keep-alive
Accept: application/json, text/javascript, */*; q=0.01
Origin: http://localhost:59901
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
Content-Type: application/json; charset=utf-8
Referer: http://localhost:59901/Home/Index
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8,it;q=0.6,it-IT;q=0.4
HTTP/1.1 401 Unauthorized
Cache-Control: private
Content-Type: text/html
Server: Microsoft-IIS/8.5
X-AspNet-Version: 4.0.30319
WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM
X-Powered-By: ASP.NET
Date: Sat, 13 May 2017 15:34:54 GMT
Content-Length: 1352
Proxy-Support: Session-Based-Authentication
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"/>
<title>401 - Autorizzazione negata: accesso negato a causa di credenziali non valide.</title>
....
</head>
<body>
<div id="header"><h1>Errore del server</h1></div>
....
</body>
</html>
3. GET request with NTLM token for auth / response without Allow CORS header
GET http://vrtsrv01.webdev.local/item/details/1 HTTP/1.1
Host: vrtsrv01.webdev.local
Connection: keep-alive
Authorization: Negotiate <...NTLM TOKEN HERE ...>
Accept: application/json, text/javascript, */*; q=0.01
Origin: http://localhost:59901
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
Content-Type: application/json; charset=utf-8
Referer: http://localhost:59901/Home/Index
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8,it;q=0.6,it-IT;q=0.4
HTTP/1.1 200 OK
Cache-Control: private
Content-Type: application/json; charset=utf-8
Server: Microsoft-IIS/8.5
X-AspNetMvc-Version: 5.2
X-AspNet-Version: 4.0.30319
Persistent-Auth: true
X-Powered-By: ASP.NET
Date: Sat, 13 May 2017 15:34:58 GMT
Content-Length: 8557
{"id":1, .....}
QUESTION
Why after enabling MVC app for CORS and seeing the right response to preflight request, the response obtained after NTLM authentication does not contain the expected Access-Control-Allow-Origin header?
I'm not sure that it will help you, but it might help someone else looking to have both NTLM and CORS enabled.
CORS enabling
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
var corsAttr = new EnableCorsAttribute("*", "*", "*") { SupportsCredentials = true };
//SupportsCredentials = true means that we will add Access-Control-Allow-Credentials to the response.
config.EnableCors(corsAttr);
}
}
SupportsCredentials = true means that we will add Access-Control-Allow-Credentials to the response.
Other solutions,
global.asax.cs - properly reply with headers that allow caller from another domain to receive data
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
if (Context.Request.HttpMethod == "OPTIONS")
{
Context.Response.AddHeader("Access-Control-Allow-Origin", Context.Request.Headers["Origin"]);
Context.Response.AddHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept,MaxDataServiceVersion");
Context.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
Context.Response.AddHeader("Access-Control-Allow-Credentials", "true");
Context.Response.End();
}
}
SOLVED (...for now...)
The invoked action was a controller action returning Json. This does not work with CORS. I need to create an API controller, cannot use the existing controller. This leads to code duplication, but I have no time now to refactor the whole application to use a single controller both for MVC and API

WebApi HttpPost not working with parameters

I have a Web Api project with this route config
var config = GlobalConfiguration.Configuration;
config.Routes.MapHttpRoute(
"DefaultApiRoute",
"api/v1/{controller}/{action}");
I have two post method
[HttpPost]
public IHttpActionResult RetrieveTestNoParam()
{
return new JsonResult<string>("This is a test", new JsonSerializerSettings(), Encoding.UTF8, this);
}
[HttpPost]
public IHttpActionResult RetrieveTest(string input)
{
return new JsonResult<string>(input, new JsonSerializerSettings(), Encoding.UTF8, this);
}
The first one is working but the second one gives this respone
{
"Message": "No HTTP resource was found that matches the request URI 'http://test.dev.local/api/v1/NewsApi/RetrieveTest'.",
"MessageDetail": "No action was found on the controller 'NewsApiController' that matches the request."
}
This is what I see in fiddler
POST http://test.dev.local/api/v1/NewsApi/RetrieveTest HTTP/1.1
Host: test.dev.local
Connection: keep-alive
Content-Length: 261
Cache-Control: no-cache
Origin: chrome-extension://fhbjgbiflinjbdggehcddcbncdddomop
Content-Type: application/javascript
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.84 Safari/537.36
Postman-Token: c2ba631b-4bfd-9379-bf40-0ca1a6a8a3bc
Accept: */*
DNT: 1
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8,nl;q=0.6
Cookie: ASP.NET_SessionId=4kgfwd2u3pwusfdvdsrkt2vt; SC_ANALYTICS_GLOBAL_COOKIE=ddd9185a3e8940c9823e81b7d38cdf20|False; sc_expview=0
------WebKitFormBoundaryxdYhzJ7A8WnI8qaa
Content-Disposition: form-data; name="input"
Dit is de input
------WebKitFormBoundaryxdYhzJ7A8WnI8qaa
Content-Disposition: form-data; name="czczcsdcsdf"
sdfsfsdfsdff
------WebKitFormBoundaryxdYhzJ7A8WnI8qaa--
Any ideas?
Other questions I have about Web Api:
Can a controller contain multiple get or post methods?
Do I need the actionname attribute and what does this attribute do?
Regards
Danny

Resources