Postman Testing send string to Web Api accepting string is null - c#

I have been testing all the Get,Create,Update methods with Postman in which the Get passes in nothing. The Create and Update passes in raw json with Activity object with several properties that do match up with the C# class
So this signature for Create and Update works fine
[HttpPost]
public IHttpActionResult UpdateActivity(Activity activity)
Above works with Postman passing in JSON content type with all the properties. I have done this on OTHER projects.
HOWEVER
I'm trying to simply pass in a string and it is null no matter what
public IHttpActionResult DeleteActivity([FromBody]string Id)
{
// delete
var del = ActivityService.DeleteActivity(Id);
return Ok(del);
}
Postman I tried MANY ways
http://localhost:49810/api/activityapi/deleteactivity
I have tried MANY many ways based on blogs and google search one such example
{ "Id" = "5808786fa3e9ec79546b3c71" }

I know this is an older question but I wanted to help those who might have a similar problem as I was able to get this working.
In WebAPI Controller my method is setup as
[HttpPost]
public IHttpActionResult Create([FromBody] int eventId)
{
....
}
In order to get this to test properly in Postman you have to: In body, set to raw, make sure JSON (application/json) is set and then just add value like 2 that's it.. not like { "eventId":2 } which is proper JSON just the value and then it will work.
So in original poster's case, in Postman, if you set Body to raw, JSON (application/json) then "5808786fa3e9ec79546b3c71" as value it will work.

In Postman ensure the body is set to raw and select json and in the body just write "your string" in quotes. Do not use {} to surround it because that is to make a complex object

Try the following in the body, with the content-type as application/json
{ "5808786fa3e9ec79546b3c71" }
As when you specify it like so, it will attempt to de-serialize into a complex type with a property of Id
{ "Id" : "5808786fa3e9ec79546b3c71" }

Old question, but for those still wondering, I would recommend sending your string as a query parameter. Take a method like this for example:
[AllowAnonymous]
[HttpGet("resendEmailConfirmtionLink")]
public async Task<IActionResult> ResendEmailConfirmationLink(string email)
{
var user = await _userManager.FindByEmailAsync(email);
if (user == null) return Unauthorized();
var origin = Request.Headers["origin"];
var token = await _userManager.GenerateEmailConfirmationTokenAsync(user);
token = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(token));
var verifyUrl = $"{origin}/verifyEmail?token={token}&email={user.Email}";
var message = $"<p>Please click the below link to verify your email address:</p><p><a href='{verifyUrl}'>Click to verify email</a></p>";
await _emailSender.SendEmailAsync(user.Email, "Please verify email", message);
return Ok("Email verification link resent");
}
This method expects a key value pair of a string called email. You can send your request like "http://localhost:5000/api/account/verifyEmail?email=myemail#test.com" or, in Postman, add it as a parameter like this:
postman query params

Your payload is not valid.
Change-->
{ "Id" = "5808786fa3e9ec79546b3c71" }
To-->
{ "Id" : "5808786fa3e9ec79546b3c71" }

[HttpPost]
public IHttpActionResult Create(int eventId)
{
....
}
Use form-data instead of raw-json
Key - eventId
Value - "5808786fa3e9ec79546b3c71"
This worked for me.

Related

How can I make a return with parameters in a View c# asp .net mvc?

Sorry for the title, but don't know how to explain it. (.NET ASP MVC)
So what I'm trying is to create a payment request via TripleA API(redirect on their page), if the payment is successful, they will redirect on my success page with some parameters, how can I handle those parameters?
What I've tried:
public IActionResult ErrorPage(string payment_reference, string status)
{
return View(payment_reference,status);
}
https://developers.triple-a.io/docs/triplea-api-doc/dd286311a5afc-make-a-payment-request
(scroll down to success_url for more info)
To expand on Steve's comment, create a record (less code than a class) as follows...
public record ErrorViewModel(string PaymentReference, string Status);
...then use this when you send data to the view...
public IActionResult ErrorPage(string payment_reference, string status)
{
return View(new ErrorViewModel(payment_reference,status));
}
You'll need to update your view to have the following line at the top...
#model ErrorViewModel
That should be all you need.
Based on the documentation, you expect a request like this,
https://www.myshop.com/payment-success?status=paid&payment_reference=ASDDF...&order_currency=USD&order_amount=10
And you translate that into a controller method,
[HttpGet("payment-success")]
public IActionResult ResultPage(string payment_reference, string status, string order_currency, decimal order_amount)
{
var result = new ResultViewModel(payment_reference,status, order_currency, order_amount);
return View(result);
}
I also noticed that the doc says,
Note: This field is required if integrating using External URL Payment Form. For other integrations, either insert the field with a url, or remove the field completely.
So if you use External URL Payment Form integration, then I don't think you will be able to get the status and reference.
The same applies for cancel_url.

ASP.NET Web API object parameter not being filled on post request

I am trying to set up a small ASP.NET Web API projects so I can post data to the database from a small React.JS project. I tried alot of sollutions but the results made no sense and I have no idea how to fix it anymore.
I have this very simple model:
public class Hour
{
public int WeekID { get; set; }
}
And this is my controller
[HttpPost]
public IHttpActionResult AddHour(Hour hour)
{
return Ok();
}
This is the method that I use to POST my data
export const SaveWeek = weekData=> {
const headers = new Headers();
headers.append("Content-Type", "application/json");
const Week= {
method: "POST",
headers,
mode: "cors",
body: weekData
};
console.log("Hours:");
// Returns {"WeekID": 1}
console.log(Hours.body);
return axios.post("http://localhost:52350/api/REST/AddHour", {
Week
});
};
The way I call this SaveWeek method in React is:
// The JSON parameter is for testing hard coded to: {"WeekID": 1}
handleSave = async json => {
const data = await SaveWeek(json);
console.log(data);
this.closeModal();
};
I know that the axios POST request works, the way I tested that is by changing the method to not use any parameters and looking at the result that where received:
[HttpPost]
public IHttpActionResult AddHour(Hour hour)
{
// This returns a string in which the data that I sent
// can be found.
string body = Request.Content.ReadAsStringAsync().Result;
return Ok();
}
The weird thing is that the body will be filled with data when the method does not contain any parameters, but when I provide the method with the Hour object parameter the body will be an empty string (""). And also the Hour object parameter wont be filled with the values that I provide it.
What am I doing wrong here?
According to https://github.com/axios/axios#axiosposturl-data-config axios.post has following signature
axios.post(url[, data[, config]])
So you just need to change your request to
export const SaveWeek = weekData => {
//headers should be simple object, not Headers
const headers = {
"Content-Type": "application/json"
};
//removed body, because we pass data as second parameter
//removed method, because 'axios.post' implies using "post" method
const Config = {
headers,
mode: "cors"
};
const url = "http://localhost:52350/api/REST/AddHour";
return axios.post(url, weekData, Config);
}
An incoming request to the ASP.Net Web API pipeline is read as a forward-only stream for super speed. Once it has been read it cannot be read again.
[HttpPost]
public IHttpActionResult AddHour(Hour hour)
{
// With model binding
// use hour.WeekID
}
In this first example model binding is already done and once it has been read it cannot be read again. Hence, Request.Content will be empty after that.
[HttpPost]
public IHttpActionResult AddHour()
{
// Without model binding
// use Request.Content
}
In second example it does not use model binding therefore still has the Request.Content property populated.
Use one or the other, not both, do not mix with MVC model binding which works differently.
A better explanation is available in this blog post
http://www.hackered.co.uk/articles/asp-net-web-api-why-is-the-request-Content-empty-when-the-model-is-populated

How to register Redirect URL to webhook

Hi i've been strugling to register redirect url to Kaizal webhook (its chat app from microsoft like a whatsapp), I've create asp.net API Controller to register it in my Kaizala webhook. What i want to do is whenever there is a messege or Job created on Kaizala Group, my redirect url will capture the data and save the data to my database. I think i already meet all the requirement from here https://learn.microsoft.com/en-us/kaizala/connectors/webhookvalidaton, my Get method is already returning validationToken from Header. But it always return this error when i try to register my redirect url "message": "Callback URL couldn't be validated. StatusCode = InternalServerError",.
https://kaizala007.blog/2017/12/30/exploring-kaizala-webhooks/comment-page-1/#comment-3776
From this documentation he said i need support both get and post method, already add both but my post method still doesn't do anything just return statuscode.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web;
using System.Web.Http;
namespace KaizalaTestApi.Controllers
{
public class KaizalaCallbackController : ApiController
{
// GET: KaizalaCallback
[HttpGet]
public string Get()
{
string x = Request.Headers.GetValues("validationToken").FirstOrDefault().ToString();
return x;
}
[HttpPost]
public HttpResponseMessage Post()
{
//string validationToken = Request.Headers.GetValues("validationToken").FirstOrDefault().ToString();
//string data = new StreamReader(Request.Content).ReadToEnd();
string str = Request.Content.ReadAsStringAsync().Result;
return Request.CreateResponse(HttpStatusCode.OK);
}
}
}
Why im getting that error ? do i need to do any specific thing in my post method to able make it works ?
It is not the fact that you are returning int that it worked.
The first attempt failed because of an error when invoking
Request.Headers.GetValues("validationToken").FirstOrDefault().ToString();
Most likely a null reference exception, because you tried to access the token in the header, while linked documentation states
Kaizala will generate a validation token and send a GET request to your webhook with a query parameter “validationToken”.
emphasis mine
which was avoided in the updated used of
HttpContext.Request.Query["validationToken"]
I would suggest updating the syntax to
[HttpGet]
public IActionResult Get() {
var validationToken = Request.Query["validationToken"];
return Content(validationToken);
}
Of course you can refactor to add validation code for the expected query string parameter.
I suggest the above because there is no guarantee that the token will be a valid int based on the documentation. And even if it is, this approach would be more flexible if they ever do change away from using integers as tokens.
The requirements simply states
Your service is supposed to return the validation token (received in request) in the response body as a plain-text
With that, only return exactly what was sent. Do not try to make any changes to it.
Already found how to make it works, it seem we need to return int in our get method that we get from query paramstring instead of string, i using asp net core 2.2 to make my callback url. Here take a look at my sample code to save in the database too
[HttpGet]
public int Get()
{
int validationToken = Convert.ToInt32(HttpContext.Request.Query["validationToken"]);
return validationToken;
}
[HttpPost]
public void Post([FromBody]JObject rawBody)
{
using (TheoDBContext db = new TheoDBContext())
{
var jsonData = rawBody["data"];
string name = rawBody["fromUserName"].ToString();
string title = jsonData["title"].ToString();
Kaizala newKaizala = new Kaizala();
newKaizala.Name = name;
newKaizala.Question = title;
newKaizala.Answer = "yes";
db.Kaizala.Add(newKaizala);
db.SaveChanges();
}
}

Getting POST data from WebAPI

We're working on developing an application that uses Plivo for sending and receiving SMS messages. For every request that Plivo sends, they also send a signature in the HTTP header so that we can verify the request came from Plivo and not from a random user.
https://www.plivo.com/docs/xml/request/#validation
To do this validation, we require the POST content as a query string (eg: To=15555555555&From=11234567890&TotalRate=0&Units=1&Text=Text!&TotalAmount=0&Type=sms&MessageUUID=2be622bc-79f8-11e6-8dc0-06435fceaad7).
Current solution
This is what we have so far:
private bool VerifyPlivo(object thing, HttpRequestMessage Request)
{
if (Request.Headers.Contains("X-Plivo-Signature"))
{
Dictionary<string, string> reqParams = (from x in thing.GetType().GetProperties() select x).ToDictionary(x => x.Name, x => (x.GetGetMethod().Invoke(thing, null) == null ? "" : x.GetGetMethod().Invoke(thing, null).ToString()));
IEnumerable<string> headerValues = Request.Headers.GetValues("X-Plivo-Signature");
string signature = headerValues.FirstOrDefault();
return XPlivoSignature.Verify(Request.RequestUri.ToString(), reqParams, signature, plivoToken);
}
else
{
return false;
}
}
[Route("RecieveSMS")]
[HttpPost]
public HttpResponseMessage RecieveSMS(PlivoRecieveSMS req)
{
if (!VerifyPlivo(req, Request))
{
return new HttpResponseMessage(HttpStatusCode.Forbidden);
}
... // do actual work here
}
This works by using the object that it maps to PlivoRecieveSMS and doing some reflection to get the properties and values, and sticking them in a Dictionary. This works well especially given our lack of the preferred solution...
Preferred solution
Right now, we require a model (PlivoRecieveSMS) to map the data, and then do introspection to find the key/values. We would like to move the logic to an extension of System.Web.Http.AuthorizeAttribute, so that we can do something as simple as:
[AuthorizedPlivoApi]
[Route("RecieveSMS")]
[HttpPost]
public HttpResponseMessage RecieveSMS(PlivoRecieveSMS req)
{
... // do actual work here
}
The actual authorization is done in AuthorizedPlivoApi - if it's not valid, the request never reaches the controller. But we cannot do this at the moment because we can't map it to a specific object inside of AuthorizedPlivoApi.
I would like to access the POST key's / values directly, or perhaps map it to a dynamic object that isn't pre-defined before hand. If I can do that, we can then achieve our preferred solution.
tl;dr: is there any way to push application/x-www-form-urlencoded data from a POST request into a Dictionary<string,string>() without using a specific model?

MVC5 app doesn't hit my WebAPI2 POST method for creating new records

I have an MVC5 application, ASP.NET, that, when creating a new record and clicking submit, it calls my WebAPI (version 2 - the new one) to insert the record into the database. Problem is, it's not hitting the POST method in my WebAPI. Anyways, here's my MVC5, front end application code for "Create":
[HttpPost]
public ActionResult Create(BulletinBoard bulletinBoard)
{
bulletinBoard.CreatedDate = DateTime.Now;
bulletinBoard.CreatedBy = HttpContext.User.Identity.Name;
response = client.PostAsJsonAsync("api/bulletinboard", bulletinBoard).Result;
if (response.IsSuccessStatusCode)
{
return View("Index");
}
else
{
LoggerHelper.GetLogger().InsertError(new Exception(string.Format(
"Cannot create a new feedback record due to HTTP Response Status Code not being successful: {0}", response.StatusCode)));
return View("Problem");
}
}
I already defined "client" in my constructor and gave it the base URL for my WebAPI - keep in mind that GET works - so it's not a problem with my URL. I can also manually go to my WebAPI URL and get data back in my browser.
Here's my WebAPI code:
// POST api/bulletinboard
public HttpResponseMessage PostBulletinBoard(BulletinBoard bulletinBoard)
{
if (ModelState.IsValid)
{
db.BulletinBoards.Add(bulletinBoard);
db.SaveChanges();
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, bulletinBoard);
return response;
}
else
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
}
}
This worked when I was using WebAPI version 1 which had a different naming convention for the GET and POST and PUT methods.
So, when the URL for the POST request is called (the line that's response = client.PostAsJsonAsync...), the request never hits my POST method in my WebAPI and consequently, no records are inserted into my database. What am I doing wrong?
According to the comments it appears that you have POSTed invalid data (according to the validation rules you defined in your BulletinBoard model) and this validation simply fails. So to fix the issue make sure you are sending valid data.
I think there might be a few reasons why it doesn't hit your post method. Here is my example of Post method. The things you should note is method name and FromBody attribute
public async Task<HttpResponseMessage> Post([FromBody]FoodProduct foodProduct)
{
UnitOfWork.FoodRepository.Edit(foodProduct);
await UnitOfWork.SaveAsync();
return Request.CreateResponse(HttpStatusCode.OK);
}
I also like to use this new RoutePrefix Attribute on my controller, it works perfectly and looks good.
[RoutePrefix("api/Food")]
public class FoodController : BaseApiController
{
///some code here
}

Categories

Resources