FromBody value get null in web api - asp.net

this is my post method in apiController
[HttpPost]
public String Post([FromBody]String key)
{
Users ws;
try
{
ws = JsonConvert.DeserializeObject<Users>(key);
// return "success "+ key;
return db.InsertFineInfo(ws);
}
catch (Exception ex)
{
return "ERROR Testing Purposes: " + ex;
}
}
This is part of my model calss.(Users class)there are many attributes but here i have mentioned only few of em with getters and setters
{
private String UserID;
private String UserName;
private String UserHeight;
private String UserWeight;
private String UserBMI;
private String RequiredNeutrition;
public string UserID1
{
get
{
return UserID;
}
set
{
UserID = value;
}
}
i tried to call this post method using postmen .in every attempt i get a null value for key .
this is how i tried the post method with one header parameter application/json
what went wrong ? something wrong with method or the way i try to call it?

OK a couple points...
Firstly the JSON your method would be expecting would look like
{
"key": "your string....."
}
Secondly the code you have supplied is a bit counter intuitive... Why not simply have
[HttpPost]
public String Post([FromBody]Users ws)
{
... // Done ?
}
You need to publish more code for me to be able to give you a correct answer as to what the JSON would look like that would be accepted by the above method.
In Web API when the parameter comes through as null you can be pretty sure that the JSON sent to the method does not match the JSON generated when you serialize the parameter to a JSON string.

You have to model your input as a C# class, and then take that type as an input.
Assuming that you already have a "User" class, with the same properties as the JSON, that you send in the request body:
[HttpPost]
public String Post([FromBody]User user)
{
try
{
return db.InsertFineInfo(user);
}
catch (Exception ex)
{
return "ERROR Testing Purposes: " + ex;
}
}

Related

Slack-Integration in ASP.NET Web-Api 2

I want to know exactly why this is not working:
[HttpPost]
public IHttpActionResult Post(Slack_Webhook json)
{
return Ok(json.challenge);
}
public class Slack_Webhook
{
public string type { get; set; }
public string token { get; set; }
public string challenge { get; set; }
}
The Official Documentation says:
We’ll send HTTP POST requests to this URL when events occur. As soon
as you enter a URL, we’ll send a request with a challenge parameter,
and your endpoint must respond with the challenge value.
This is an example object (JSON) sent by Slack:
{
"token": "Jhj5dZrVaK7ZwHHjRyZWjbDl",
"challenge": "3eZbrw1aBm2rZgRNFdxV2595E9CY3gmdALWMmHkvFXO7tYXAYM8P",
"type": "url_verification"
}
EDIT:
I could write a book on code that does not work in this issue... here's another example that did not work - still no idea what is wrong:
[HttpPost]
public IHttpActionResult Post()
{
var pairs = Request.GetQueryNameValuePairs();
bool isValidToken = false;
string c = "This does not work.";
foreach(var pair in pairs)
{
if (pair.Key == "token")
{
if (pair.Value == "<UNIQUETOKEN>")
{
isValidToken = true;
}
}
if (pair.Key == "challenge")
{
c = pair.Value;
}
}
if (isValidToken == true)
{
return Json(new {challenge = c });
}
else
{
return BadRequest();
}
}
EDIT2:
Very interesting that I get NULL as a response from below code - that means the body of the received POST is empty.. Could anyone with a working Slack-Integration try that out? So their site is wrong, stating the challenge is sent in the body - where else could it be?
// POST: api/Slack
[HttpPost]
public IHttpActionResult Post([FromBody]string json)
{
return Json(json);
}
EDIT3:
This function is used to get the raw request, but there is nothing inside the body - I am out of solutions.. the support of Slack said, they have no idea about ASP.NET and I should ask here on SO for a solution. Here we are again! ;-)
[HttpPost]
public async Task<IHttpActionResult> ReceivePostAsync()
{
string rawpostdata = await RawContentReader.Read(this.Request);
return Json(new StringContent( rawpostdata));
}
public class RawContentReader
{
public static async Task<string> Read(HttpRequestMessage req)
{
using (var contentStream = await req.Content.ReadAsStreamAsync())
{
contentStream.Seek(0, SeekOrigin.Begin);
using (var sr = new StreamReader(contentStream))
{
return sr.ReadToEnd();
}
}
}
}
The result ( as expected ) looks like this:
Our Request:
POST
"body": {
"type": "url_verification",
"token": "<token>",
"challenge": "<challenge>"
}
Your Response:
"code": 200
"error": "challenge_failed"
"body": {
{"Headers":[{"Key":"Content-Type","Value":["text/plain; charset=utf-8"]}]}
}
I think I'm missing something - is there another way to get the body of the POST-Request? I mean, I can get everything else - except the body ( or it says it is empty).
EDIT4:
I tried to read the body with another function I found - without success, returns empty string - but to let you know what I already tried, here it is:
[HttpPost]
public IHttpActionResult ReceivePost()
{
var bodyStream = new
StreamReader(HttpContext.Current.Request.InputStream);
bodyStream.BaseStream.Seek(0, SeekOrigin.Begin);
var bodyText = bodyStream.ReadToEnd();
return Json(bodyText);
}
While trying to solve this I learnt a lot - but this one seems to be so impossible, that I think I will never solve it alone. Thousands of tries with thousands of different functions - I have tried hundreds of parameters and functions in all of WebApi / ASP.NET / MVC / whatever - why is there no BODY? Does it exist? What's his/her name? Where does it live? I really wanna hang out with that parameter if I ever find it, must be hidden at the end of the rainbow under a pot of gold.
If you can use ASP.NET Core 2, this will do the trick:
public async Task<ActionResult> HandleEvent([FromBody] dynamic data)
=> new ContentResult {Content = data.challenge};
According to the official documentation linked to in the OP you have to format your response depending on the content type you return.
It is possible you are not returning the value (challenge) in one of the expected formats.
Once you receive the event, respond in plaintext with the challenge
attribute value. In this example, that might be:
HTTP 200 OK
Content-type: text/plain
3eZbrw1aBm2rZgRNFdxV2595E9CY3gmdALWMmHkvFXO7tYXAYM8P
To do the above you would have needed to return your request differently
[HttpPost]
public IHttpActionResult Post([FromBody]Slack_Webhook json) {
//Please verify that the token value found in the payload
//matches your application's configured Slack token.
if (ModelState.IsValid && json != null && ValidToken(json.token)) {
var response = Request.CreateResponse(HttpStatusCode.OK, json.challenge, "text/plain");
return ResponseMessage(response);
}
return BadRequest();
}
Documentation also shows
Or even JSON:
HTTP 200 OK
Content-type: application/json
{"challenge":"3eZbrw1aBm2rZgRNFdxV2595E9CY3gmdALWMmHkvFXO7tYXAYM8P"}
Which again would have to be formatted a little differently
[HttpPost]
public IHttpActionResult Post([FromBody]Slack_Webhook json) {
//Please verify that the token value found in the payload
//matches your application's configured Slack token.
if (ModelState.IsValid && json != null && ValidToken(json.token)) {
var model = new { challenge = json.challenge };
return Ok(model);
}
return BadRequest();
}
Here's how you can access the data:
[HttpPost]
[Route("something")]
public JsonResult DoSomething()
{
var token = HttpContext.Request.Form["token"];
// Is the same as:
// var token = Request.Form["token"];
return new JsonResult(token);
}
I suggest using a Request Bin for further debugging.

WEB.API returning string property as json

We have a fun situation where we are storing json as a string in SQL Server. We don't not care what is in this object its pretty much a passthrough property. Passthrough meaning we just save it for clients and return it as is. We never read it in C#. I'm storing it as a nvarchar in the database but I'm trying to figure out how i can automagically serialize that string into a json object to return to the client. I dont want to have to in javascript call fromJson.
We are using Newtonsoft as our Json Serializer. Here is the highlevel setup:
DTO:
public class MyDto{
public dynamic SessionBag { get;set;}
}
Entity Framework Entity:
public class My{
public string SessionBag { get;set;}
}
A client would post/put us:
{"SessionBag":{"Name":"test"}}
We would then save it in the db as a string:
"{"Name":"test"}"
How can I serialize this so when it returns from Web.API it looks like:
{
SessionBag:{
Name: "test"
}
}
I'm currently messing around trying to get it to save using dynamic / object. But i can't figure how how to return it as a json object. I would love to figure out how to do this with just annotations.
Here is how I convert it to a string to save:
if (dto.SessionBag != null){
var serializer = JsonSerializer.Create(new JsonSerializerSettings(){
NullValueHandling = NullValueHandling.Ignore
});
using (var writer = new StringWriter()){
serializer.Serialize(writer, dto.SessionBag);
entity.SessionData = writer.ToString();
}
}
In case its helpful our WebApiControllers are pretty simple and just return an IHttpActionResult with the dto. All feedback is welcome.
So I think i figured it out. In my dto:
[JsonIgnore]
public string SessionBagString { get; set; }
public JObject SessionBag
{
get
{
if (!string.IsNullOrEmpty(SessionBagString))
{
return JObject.Parse(SessionBagString);
}
return null;
}
set
{
if(value != null)
{
SessionBagString = value.ToString();
}
}
}
In my repo code I now have:
if (dto.SessionBag != null)
{
entity.SessionBagString = dto.SessionBagString;
}
That pretty much worked for me. Let me know if there is a better way to do it.

How to use IUserIdProvider

My code:
public string GetUserId(IRequest request) {
var token = request.QueryString.Get("token");
// what is it? request.User.Identity.Name;
if (string.IsNullOrWhiteSpace(token)) {
return token;
}
else {
return JsonConvert.SerializeObject(new UserAbility().GetUserByToken(token));
}
}
I need to map the connection with the user using a different identifier.
So i want to get the custom token from the QueryString in this method, but GetUserId doesn't trigger in every reqeust.
And i always get the request.User.Identity.Name is string empty?
This article explains what you need to do.
http://www.asp.net/signalr/overview/guide-to-the-api/mapping-users-to-connections#IUserIdProvider

Add additional json structure to all WebApi's responses?

We are integrating with mobile software company to do our application in a mobile device.
Our controller has ( simplification) methods like :
api/users/1
–GetUserById(...)
api/users/changePassword
–ChangePassword(Person p)
Ok.
The ChangePassword can return several applicative error codes ( password has already used , password too short , password bla bla...)
So if ,for example, password has already been used , then the HttpCode should be 200 returned with additional info
We agreed on this convention for every response :( additional to the response data)
{
"Success":0,
"ErrorCode": 6,
"ErrorMessage":"already used"
}
But this structure , as I said - should be in every response.
So till now - for example : api/users/1 returned :
{
"userId":1,
"name":"John"
}
But now - the response should be :
{
"data":
{
"userId":1,
"name":"John"
}
,
"result": //no errors
{
"Success":0,
"ErrorCode": 0,
"ErrorMessage":""
}
}
They always looking for the "result" object to see the applicative response.
Question
I assume that the place which I should do it is in message handler after base.SendAsync ( response part)
But how should I wrap the regular response which I send via Request.CreateResponseMessage with the format + values of :
NB , of course at the Request.CreateResponseMessage phase I already have result object with the appropriate result codes.
By the time message handlers run in Web API pipeline, the result your action method has produced would have been serialized. An action filter would be a better option, since you can deal with objects, and you can do something like this.
public class MyActionFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuted(HttpActionExecutedContext context)
{
var content = context.Response.Content as ObjectContent;
if (content != null)
{
content.Value =
new MyResponse()
{
Result = new Result() { Success = 0, ErrorCode = 6 },
Data = content.Value
};
}
}
}
public class Result
{
public int Success { get; set; }
public int ErrorCode { get; set; }
}
public class MyResponse
{
public Result Result { get; set; }
public object Data { get; set; }
}
Note: The above code will work only for JSON and not XML.
You can create an ActionFilterAttribute, and on the OnActionExecuted Method you will get HttpActionExecutedContext where you can check the response message.
you can decorate your controlleror action by this attribute and return and create you own ResponseMessage.
Hope that helps.

Call a WCF Data service boolean method

I'm trying to receive an answer from a WCF method from the client. When I try to execute void methods, they are working fine. For example:
Uri u = new Uri(string.Format(LogIn.ctx.BaseUri + "/CreateRole?name='{0}'",
TextBox1.Text), UriKind.RelativeOrAbsolute);
LogIn.ctx.Execute(u, "GET");
Now I want to call a method which returns a boolean, and this value will be used. Here's the method I want to call and receive its returned value:
[WebGet]
public bool Controler(string role, string user)
{
if (Roles.IsUserInRole(user, role))
{
return true;
}
else
{
return false;
}
}
Instead of LogIn.ctx.Execute(u, "GET"), try this:
IEnumerable<bool> result = LogIn.ctx.Execute<bool>(u);
bool answer = result.Single();

Resources