HttpResponseMessage content is not getting serialized for BadRequest responses - c#

I have ASP.NET application, with some MVC and WebAPI controllers in there. MVC 5.1 and WebAPI 2.1. There is no tricky configuration at all, the only thing is getting configured is removed XML formatter:
public static class WebApi
{
public static void Configure(HttpConfiguration config)
{
var formatters = config.Formatters;
formatters.Remove(formatters.XmlFormatter);
}
}
There is simple DTO to put data returned from controller action together:
public class TokenResponse
{
public string token { get; set; }
public string token_type { get; set; }
public int expires_in { get; set; }
public string error { get; set; }
}
And the following code:
[NoHttpResponseCaching]
public class TokenController : ApiController
{
public async Task<HttpResponseMessage> PostAsync(HttpRequestMessage request, TokenRequest tokenRequest)
{
try
{
// do some stuff
var response = new TokenResponse { ... };
return request.CreateResponse(HttpStatusCode.OK, response);
}
catch (TokenRequestValidationException ex)
{
_logger.WriteError(ex);
var response = new TokenResponse { error = ex.ErrorToDisplay };
return request.CreateResponse(HttpStatusCode.BadRequest, response);
}
}
}
The problem is that if everything fine, I have my TokenResponse serialized to JSON, as expected, but if there is exception occurring, execution flow is coming into catch block and response body is equal to "Bad Request", this is the RAW dump of response from Fiddler:
HTTP/1.1 400 Bad Request
Cache-Control: no-store
Pragma: no-cache
Content-Type: text/html
Server: Microsoft-IIS/8.5
X-Powered-By: ASP.NET
Date: Wed, 18 Jun 2014 08:25:53 GMT
Content-Length: 11
Bad Request
Tried to return anonymous object having some random named properties instead of using TokenResponse, getting same response:
return request.CreateResponse(HttpStatusCode.BadRequest, new {klhjaoiubf = "kjhaflkjh"});
And I'm stuck at this point trying to understand why I'm not getting my object serialized in response body and how to change it. Anyone, any ideas, why my object is getting ignored when response code is BadRequest?

Related

400 Bad Request in MVC C# Web App but not Postman

I have the following method that I've been working on for hours now and am not able to PUT my updates to an external Ellucian Ethos API.
public async Task<string> UpdatePersonH11()
{
var token = await GetAccessTokenAsync("TokenApi", "value");
var guid = await GetPersonGUID(token);
Uri personsURI = new Uri(string.Format("https://URLtoAPI" + guid));
H11Model h11Data = new H11Model
{
h11 = new h11
{
extendedPersonUser2 = "2021/FA",
extendedPersonUser3 = "OUT",
extendedPersonUser4 = DateTime.Now.ToShortDateString()
}
};
using (var client = new HttpClient())
{
client.BaseAddress = personsURI;
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Add("Accept", "application/vnd.hedtech.integration.v12+json");
client.DefaultRequestHeaders.Add("Accept-Encoding", "gzip, deflate, br");
client.DefaultRequestHeaders.Add("Connection", "keep-alive");
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {token}");
var responseString = "";
var content = JsonSerializer.Serialize(h11Data);
**using (HttpResponseMessage response = await client.PutAsJsonAsync(personsURI, content))** Debugger stops here and gives me a 400 Bad Request
{
if (response.IsSuccessStatusCode)
{
responseString = await response.Content.ReadAsStringAsync();
}
else
{
log.Debug("Error in response." + response);
return "";
}
return responseString;
}
}
}
This is the json that Json is serializing for the variable content to send through PutAsJsonAsync.
{
"h11":
{
"extendedPersonUser2":"2021/FA",
"extendedPersonUser3":"OUT",
"extendedPersonUser4":"8/5/2021",
}
}
H11 Model
public class H11Model
{
[JsonProperty("h11")]
public h11 h11 { get; set; }
}
public class h11
{
[JsonProperty("extendedPersonUser2")]
public string extendedPersonUser2 { get; set; }
[JsonProperty("extendedPersonUser3")]
public string extendedPersonUser3 { get; set; }
[JsonProperty("extendedPersonUser4")]
public string extendedPersonUser4 { get; set; }
[JsonProperty("extendedPersonUser5")]
public string extendedPersonUser5 { get; set; }
[JsonProperty("extendedPersonUser6")]
public string extendedPersonUser6 { get; set; }
[JsonProperty("extendedPersonUser7")]
public string extendedPersonUser7 { get; set; }
[JsonProperty("extendedPersonUser8")]
public string extendedPersonUser8 { get; set; }
[JsonProperty("extendedPersonUser9")]
public string extendedPersonUser9 { get; set; }
[JsonProperty("extendedPersonUser10")]
public string extendedPersonUser10 { get; set; }
}
I've read that PutAsJsonAsync does not need the content serialized first, but when I comment out var content = JsonSerializer.Serialize(h11Data); I get a 406 Not Acceptable error, that leads me to believe that I do need to serialize the content first.
This is the request message I get back from the debugger:
{
Method: PUT,
RequestUri: 'API URI',
Version: 1.1,
Content: System.Net.Http.ObjectContent`1[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=token]],
Headers:
{
Authorization: Bearer 'token is here'
Accept: application/vnd.hedtech.integration.v12+json
Content-Type: application/json; charset=utf-8
Content-Length: 293
}
}
This is the response message:
{
StatusCode: 400, ReasonPhrase: 'Bad Request', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
Connection: keep-alive
pragma: no-cache
hedtech-ethos-integration-application-id: GUID
hedtech-ethos-integration-application-name: Colleague
vary: origin
access-control-expose-headers: x-max-page-size,x-media-type,x-total-count,x-content-restricted,hedtech-ethos-integration-application-id,hedtech-ethos-integration-application-name,hedtech-ethos-integration-proxy-generated
Cache-Control: no-cache
Date: Fri, 06 Aug 2021 13:41:56 GMT
Server: Microsoft-IIS/10.0
Content-Length: 447
Content-Type: text/plain; charset=utf-8
Expires: -1
}
}
If anyone can help point me in the right direction, I would really appreciate it. I haven't used APIs this way before, so this is new territory for me and I am stumped on this.
EDIT: Final code (snippet) that works:
H11Model h11Data = new H11Model
{
h11 = new h11
{
extendedPersonUser5 = "OUT", // fall term
extendedPersonUser6 = DateTime.Now.ToShortDateString()
}
};
using (var client = new HttpClient())
{
client.BaseAddress = personsURI;
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Add("Accept", "application/vnd.hedtech.integration.v12+json");
client.DefaultRequestHeaders.Add("Accept-Encoding", "gzip, deflate, br");
client.DefaultRequestHeaders.Add("Connection", "keep-alive");
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {token}");
var responseString = "";
//var content = JsonSerializer.Serialize(h11Data);
using (HttpResponseMessage response = await client.PutAsJsonAsync(personsURI, h11Data))
{
if (response.IsSuccessStatusCode)
{
try
{
responseString = await response.Content.ReadAsStringAsync();
}
catch (NotSupportedException ex) // When content type is not valid
{
log.Debug("The content type is not supported.", ex);
}
catch (JsonException ex) // Invalid JSON
{
log.Debug("Invalid JSON.", ex);
}
}
else
{
log.Debug("Error in response." + response);
return "";
}
return responseString;
}
}
If the service does not override the meaning of the HTTP codes and uses them as described in RFC then
406 Not Acceptable
The 406 (Not Acceptable) status code indicates that the target resource does not have a current representation that would be acceptable to the user agent, according to the proactive negotiation header fields received in the request (Section 5.3), and the server is unwilling to supply a default representation.
Simply put, the value of Accept, Accept-Encoding, Accept-Charset or Accept-Language HTTP header is invalid or not defined as service expects.
In the described case, there are at least two such headers set through HttpClient.DefaultRequestHeaders collection. Their values need to be compared with the service documentation. And it is important to note that in the general case the Accept-Encoding header should be set via HttpClientHandler.AutomaticDecompression property instead of DefaultRequestHeaders collection, otherwise it will be ignored.
400 Bad Request
The 400 (Bad Request) status code indicates that the server cannot or
will not process the request due to something that is perceived to be
a client error (e.g., malformed request syntax, invalid request
message framing, or deceptive request routing).
For example, service expects { "h11": { "extendedPersonUser2": ... JSON object; but instead of it, service receives "{ \"h11\": { \"extendedPersonUser2\": ... and cannot deserialize it.
As it was already mentioned in comments, there is a difference between PutAsJsonAsync extension method and HttpClient.PutAsync method with StringContent. The first one sends a PUT request to the specified Uri containing the value serialized as JSON in the request body. The PutAsync method sends raw content as it is defined by content argument.
So, the code from example
string content = JsonSerializer.Serialize(h11Data);
... = await client.PutAsJsonAsync(personsURI, content);
uses PutAsJsonAsync and sends JSON string additionally serialized to JSON. As result service receives the following content "{ \"h11\": { \"extendedPersonUser2\": ....
Usually, when PutAsJsonAsync extension method is used, the additional JSON serialization is not needed. Content object can be passed directly to PutAsJsonAsync extension method.
... = await client.PutAsJsonAsync(personsURI, h11Data);
In such case the request will be sent as { "h11": { "extendedPersonUser2": ....
There are multiple PutAsJsonAsync extension method overloads that also accept JsonSerializerOptions to customize JSON serialization. And it's important to note that PutAsJsonAsync internally use HttpClient.PutAsync method with StringContent to send the request.

ServiceStack: Custom login method and create manual IAuthSession for use with [Authenticate] attribute?

I'm trying to manually create an IAuthSession and saving it, so I can use the attribute [Authenticate] on my methods, but doesn't seem to work.
So, I have my LoginHandler : Service where I do some custom code to login a user, and then I do:
namespace RequestHandlers
{
public class LoginHandler : Service
{
public object Post(Login request)
{
// do magic login code
if (loginSuccess)
{
IAuthSession session = GetSession();
session.FirstName = "My First name"
session.IsAuthenticated = true;
base.Request.SaveSession(session); // save the session??
}
else
{
throw new UnauthorizedAccessException(pc.GetFaultString());
}
return new LoginResponse() { Result = "OK" };
}
}
}
I was then my hope that the base.Request.SaveSession(session); would save the Session so that ServiceStack would later detect it and see that "aha, a protected method is allowed, since the user is logged in".
The response for the Login call is (in Fiddler):
HTTP/1.1 200 OK
Transfer-Encoding: chunked
Content-Type: application/json; charset=utf-8
Vary: Accept
Server: Microsoft-HTTPAPI/2.0
Set-Cookie: ss-id=TwOJExNFhBuVuDna1aDO;path=/;HttpOnly
Set-Cookie: ss-pid=O4bJqgiLWRTFTOgcf2DD;path=/;expires=Mon, 08 Feb 2038 12:39:30 GMT;HttpOnly
X-Powered-By: ServiceStack/5,02 NET45 Win32NT/.NET
Date: Thu, 08 Feb 2018 12:39:31 GMT
f
{"Result":"OK"}
0
So, I get some cookie with a pid, I take that as the session id?
Now, I have the Test method that I after running the Login above, should be available, right? =)
namespace tWorks.Alfa.Modules.ModuleRestApiService.Services.AlfaConnectService.Requests
{
[Authenticate]
[Route("/test")]
public class Test : IReturn<TestResponse>
{
public string Message { get; set; }
}
public class TestResponse
{
public string Result { get; set; }
}
}
But its not, I get a 401 error:
HTTP/1.1 401 Unauthorized
Transfer-Encoding: chunked
Vary: Accept
Server: Microsoft-HTTPAPI/2.0
X-Powered-By: ServiceStack/5,02 NET45 Win32NT/.NET
WWW-Authenticate: basic realm="/auth/basic"
Date: Thu, 08 Feb 2018 12:40:12 GMT
0
The call from Fiddler for Test is this:
POST http://192.168.0.147:8080/alfaconnect/test HTTP/1.1
Host: 192.168.0.147:8080
Accept: application/json
Content-Type: application/json
Content-Length: 18
DeviceUUID: 123asd123
Domain: AlfaOnline
Cookie: ss-id=TwOJExNFhBuVuDna1aDO
Cookie: ss-pid=O4bJqgiLWRTFTOgcf2DD
{"Message": "Hej"}
As you can see, I copied the ss-id and ss-pid from the Login response to the Test call.
What am I missing?
Here is my AppHost:
public class AppHost : AppSelfHostBase
{
public AppHost(IModuleController moduleController, IContactModule contactModule) : base("HttpListener Self-Host", typeof(Services.AlfaProService.AlfaProService).Assembly)
{
}
public override void Configure(Funq.Container container)
{
Plugins.Add(new AuthFeature(() => new AuthUserSession(),
new IAuthProvider[] {
new BasicAuthProvider(), //Sign-in with HTTP Basic Auth
new CredentialsAuthProvider(), //HTML Form post of UserName/Password credentials
}));
container.Register<ICacheClient>(new MemoryCacheClient());
var userRep = new InMemoryAuthRepository();
container.Register<IUserAuthRepository>(userRep);
}
public override RouteAttribute[] GetRouteAttributes(Type requestType)
{
var routes = base.GetRouteAttributes(requestType);
if (requestType.FullName.Contains("AlfaConnectService"))
{
routes.Each(x => x.Path = "/alfaconnect" + x.Path);
}
else if (requestType.FullName.Contains("AlfaProService"))
{
routes.Each(x => x.Path = "/alfapro" + x.Path);
}
return routes;
}
}
}
ServiceStack also requires the session.UserAuthName to be set to the Username.
All ServiceStack's constructs are designed to work together, if you're not going to use ServiceStack's AuthProvider model just ignore it and implement your own Authentication. i.e. ignore all of ServiceStack's built-in Auth/Session features and use your own filters/validation instead.

JAVAScriptSerilized JSON String displays invalid message on fiddler

I'm building an WEB API that is supposed to retrieve a list of events from a SQL Server database and create a response of those objects in JSON to the client
Event object:
public class OCEvents
{
public long event_id { get; set; }
public string event_date {get; set;}
public string event_time { get; set;}
public string event_location { get; set;}
public string event_name { get; set; }
public string event_image { get; set; }
public string event_description { get; set; }
}
Simple Web API Controller to retrieve event JSON DATA
public class EventsController : ApiController
{
private string JSONResponse = "";
public string getEvents()
{
//Create class the haandles all DB related data
DBConnect db = new DBConnect();
//Creates List of Event Objects
List<OCEvents> events = new List<OCEvents>();
//get latest events posted
db.getOCEvents(events);
//Serialize event objects to JSON
JSONResponse = new JavaScriptSerializer().Serialize(events);
//return JSON Response
return JSONResponse;
}
}
This the raw post back(response) from the event controller
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?QzpcVXNlcnNcREFOT05FXERvY3VtZW50c1xCaXpcTW9iaWxlIEFwcGxpY2F0aW9uIERldmVsb3BtZW50IERvY3VtZW50c1xQcm9qZWN0c1xPdXJDaHVyY2hBUElcT3VyQ2h1cmNoQVBJXGFwaVxldmVudHM=?=
X-Powered-By: ASP.NET
Date: Mon, 18 Apr 2016 08:58:41 GMT
Content-Length: 1061
"[{\"event_id\":5,\"event_date\":\"13 January 2016\",\"event_time\":\"12:00\",\"event_location\":\"South Africa,North West,Rustenburg,Church\",\"event_name\":\"Imposition of Ashes\",\"event_image\":\"\",\"event_description\":\"Come anytime from 12:00 noon to 1:00 p.m for quiet meditation and prayer. Clergy will be available for the imposition of ashes.\"},{\"event_id\":7,\"event_date\":\"13 January 2016\",\"event_time\":\"19:00\",\"event_location\":\"South Africa,North West,Rustenburg,Church\",\"event_name\":\"Ash Wednesday Service\",\"event_image\":\"\",\"event_description\":\"Join us as we mark the begining of the season off Lent with a traditional Ash Wednesday service ,including imposition of ashes.\"},{\"event_id\":1,\"event_date\":\"08 January 2016\",\"event_time\":\"14:00\",\"event_location\":\"South Africa,North West,Rustenburg,Church\",\"event_name\":\"Special Worship Service\",\"event_image\":\"\",\"event_description\":\"Rev. Dr Amy Bulter, preaching Sermon--\\u0027Shine, Jesus,Shine\\u0027hebrew Scripture Lesson--Exodus 34:29-35.\"}]"
My issue is this error when I open the JSON tab
Fiddler screenshot with inspector & json tab open
I finally figured it out. The problem was that the getEvents method was returning a string instead of an HTTP Response object. So instead of returning a JSON string I used this.
public HttpResponseMessage getEvents()
{
//Create class the haandles all DB related data
DBConnect db = new DBConnect();
//Creates List of Event Objects
List<OCEvents> events = new List<OCEvents>();
//get latest events posted
db.getOCEvents(events);
//Serialize event objects to JSON
JSONResponse = new JavaScriptSerializer().Serialize(events);
var response = new HttpResponseMessage()
{
Content = new StringContent(JSONResponse)
};
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
//return JSON Response
return response;
}
You can let the system do the JSON or XML creation depending on what the accept header is in the users original request.
public HttpResponseMessage getEvents()
{
//Create class the haandles all DB related data
DBConnect db = new DBConnect();
//Creates List of Event Objects
List<OCEvents> events = new List<OCEvents>();
//get latest events posted
db.getOCEvents(events);
return Request.CreateResponse(HttpStatusCode.OK, events);
}
If you want to force JSON then in your WepApiConfig remove the XML formatter.
//Remove XML so only JSON is returned
GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);

aspnet webapi 2 response payload not displayed for HttpStatusCode.Unauthorized

I have an ActionFilterAttribute that overrides the OnActionExecuting. If the user isn't authenticated I want to return and 401 Unauthorized status and a JSON object of type Response with a custom message and other properties
public class Response
{
public Boolean Error { get; set; }
public IList<string> Messages { get; set; }
public object Data { get; set; }
}
That's what I did:
public override void OnActionExecuting(HttpActionContext actionContext)
{
//some code here
var response = new Response();
response.AddMessage(true, Util.Localization.Authentication.Validation_UserNotAuthenticated);
actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized)
{
Content = new ObjectContent(typeof(Response), response, new JsonMediaTypeFormatter())
};
}
When the client makes a request, that's the Response Header (from google chrome developer tools - network):
HTTP/1.1 401 Unauthorized
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.5
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Thu, 18 Dec 2014 13:19:12 GMT
Content-Length: 83
Well, the JSON with the Response object isn't displayed to the client.
If I only change theHttpStatusCode to OK, the JSON is displayed:
actionContext.Response = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new ObjectContent(typeof(Response), response, new JsonMediaTypeFormatter())
};
Also, if I keep theHttpStatusCode as Unauthorized, but change the Type to string, the text is displayed normally to the client:
actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized)
{
Content = new ObjectContent(typeof(string), "test string", new JsonMediaTypeFormatter())
};
How can I send a custom JSON object when I get a Unauthorized Http status?
Thnaks
I assume you are using the built-in AuthorizeAttribute on your controller to secure your api. I think the reason it's not working is because the AuthorizationFilters (like AuthorizeAttribute) happen earlier in the WebApi pipeline than ActionFilters. See here for details:
https://damienbod.wordpress.com/2014/01/04/web-api-2-using-actionfilterattribute-overrideactionfiltersattribute-and-ioc-injection/
So your code never executes because the AuthorizeAttribute already failed and returned its default response (401 message with no body).
The easiest way to do what you want is to inherit a custom authorization attribute, ex MyAuthorizeAttribute, inheriting from AuthorizeAttribute and changing the way it handles errors. Then just decorate your controllers with [MyAuthorize] instead of [Authorize].
public class MyAuthorizeAttribute : AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(HttpActionContext actionContext)
{
var jsonFormatter = new JsonMediaTypeFormatter();
var response = new Response();
response.AddMessage(true, Util.Localization.Authentication.Validation_UserNotAuthenticated);
actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized)
{
ReasonPhrase = "Unauthorized",
Content = new ObjectContent(typeof(Response), response, new JsonMediaTypeFormatter())
};
}
}

ASP.NET WEB API not binding to dynamic object on POST

If have the following Api Controller ... using StrutureMap for the DI ...
using System;
using System.Dynamic;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using IdentityService.Domain;
using IdentityService.Domain.Contracts;
using IdentityService.Domain.Models;
namespace IdentityService.Controllers
{
public class AccountController : ApiController
{
private readonly IRepository<Client> _clientRepository;
private readonly IRepository<RelyingParty> _relyingPartyRepository;
private readonly IRepository<Token> _tokenRepository;
public AccountController(
IRepository<Client> clientRepository,
IRepository<RelyingParty> relyingPartyRepository,
IRepository<Token> tokenRepository)
{
_clientRepository = clientRepository;
_relyingPartyRepository = relyingPartyRepository;
_tokenRepository = tokenRepository;
}
public HttpResponseMessage Post(
[FromBody] dynamic data)
{
dynamic result = new ExpandoObject();
try
{
var clientAuthenticator = new ClientAuthenticator(
_clientRepository,
_relyingPartyRepository,
_tokenRepository);
Token token;
clientAuthenticator.Authenticate(
data.Key,
data.ChecksumValue,
data.Checksum,
data.Name,
data.Password,
out token);
result.Token = token;
}
catch (Exception ex)
{
result.ErrorCode = ex.GetType().ToString();
result.ErrorMessage = ex.GetBaseException().Message;
}
return this.Request.CreateResponse(HttpStatusCode.OK, (ExpandoObject)result);
}
}
}
Using Fiddler, I am make the following post:
POST http://localhost:54029/api/account HTTP/1.1
User-Agent: Fiddler
Host: localhost:54029
Content-Type: "application/json"
Content-Length: 218
{
"Key": "7d42276d3c3954716c672543385b575836472f5d543d7776205627413a",
"ChecksumValue": "127.0.0.1",
"Checksum": "ao4Ei77BaX1/iMZMTAJxWzt4fxc=",
"Name": "USER_NAME",
"Password": "PASSWORD"
}
Any idea why my data would be null? I have tried switching to JObject, with no success. All the examples I have found makes me think this should work.
Here is the complete response:
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?QzpcY29kZS1tYXR0cnVtYVx0YWxrLWF1dGhlbnRpY2F0aW9uLXNlcnZlclxJZGVudGl0eVNlcnZpY2VcYXBpXGFjY291bnQ=?=
X-Powered-By: ASP.NET
Date: Mon, 27 May 2013 13:59:45 GMT
Content-Length: 137
{"ErrorCode":"Microsoft.CSharp.RuntimeBinder.RuntimeBinderException","ErrorMessage":"Cannot perform runtime binding on a null reference"}
Any help would be much appreciated!
Update
I tried just a simple example, like:
public async Task<dynamic> Post(dynamic data)
{
var body = await Request.Content.ReadAsStringAsync();
return data;
}
The parameter data is still null, but I can see the values in body.
Remove the quotes from "application/json".
Content-Type: application/json
In an MVC 6 controller (which extends from Controller and not ApiController) the following does work (with report being JSON) :
[HttpPost("[action]")]
public void RunReport([FromBody]dynamic report)
{
....
}
Updated: For MVC 5 this is what I use
[HttpPost]
public async Task<HttpResponseMessage> FBLogin(Newtonsoft.Json.Linq.JObject jObject)
{
dynamic data = (dynamic)jObject;
string accessToken = data.accessToken;
...
}
Where the JSON payload is :
'{accessToken: "EAAJF9eVIKOsBABdKVNOLJyfyCnnkrl8mlW2crgZC1NYsDqgq9ZBIZC......" }'
if you make the param from [FromBody] to dynamic, and if its a JSON object (made with JSON.stringify) then you can just use .ToString() to get the string value and you should be OK
public void Post(string token, [FromBody]dynamic value)
{
int userID = db.GetUserIdByToken(token);
db.InsertJson(userID, value.ToString());
}
other definitions is headers: {'Content-Type': 'application/json'},
remove [FromBody] attribute and it should work

Categories