WebApi not accepting RestSharp AddJsonBody - asp.net-web-api

I have a WebApi endpoint I can call with curl ok :
curl -X POST "https://endpoint/SendPin?email=john#smith.com" -H "accept: application/json"
WebAPI looks like this:
[HttpPost]
[Route("SendPin")]
public async Task<bool> SendPin([Required] [EmailAddress] string email)
{
....
}
Problem: The server returns a BadRequest message "Email is required" when I call it with RestSharp???
var request = new RestRequest("SendCode");
request.AddJsonBody(new { Email = "john#smith.com"});
RestClient client = new RestClient(TheUrl);
var response = await client .ExecutePostTaskAsync<bool>(request );
It appears RestSharp is not sending to the url as a param??

You are adding the email to the request body with the request.AddJsonBody() method.
Instead, add it to the request url as a querystring like you have done in the curl request
var request = new RestRequest("SendPin"+ "?email=john#smith.com");
RestClient client = new RestClient(TheUrl);
var response = await client.ExecutePostTaskAsync<bool>(request);

Because the parameter is a simple type, I need to call it like his:
request.AddParameter("email", credential.Email, ParameterType.QueryString);

Related

Getting 502 BadGateway response when posting using HttpClient (.NET) but not when using Postman

I have an API end-point that I need to post to.
Using Postman I do the following:
Set the method to be POST
Add the URL
In the Headers I set: Content-Type to be application/json
In the Body I add my json string
I hit [Send] and get a 200 response with the expected response.
However, in C# .Net Framework 4.8 (LinqPad 5) I do
var c = new HttpClient(); // Disposed of later
c.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
string data = #"{ ""a"": ""b"", ""c"": ""d"" }"; // copied from Postman.
HttpContent payload = new StringContent(data, Encoding.UTF8, "application/json");
var msg = new HttpRequestMessage(HttpMethod.Post, new Uri("https://the.url"), UriKind.Absolute)
{
Content = payload,
};
var response = c.SendAsync(msg).GetAwaiter().GetResult(); // It's a synchronous flow
And this responds with a 502 Bad Gateway.
What am I missing...?
I should point out that I need to use the HttpClient and not RestSharp.

How to correctly pass body to spring rest template?

SOLUTION: The API endpoint to get this specific information is the only one different from all the other ones. Thus I was trying to contact an outdated one.
Everything described in the post works like a charm.
Using kotlin and spring, I want to send a POST request to an API.
This is a curl, generated via postman, that works correctly:
curl --location --request POST 'URL' \
--header 'Content-Type: application/json' \
--data-raw '{
"username":"username",
"password":"password"
}'
However, with spring + rest template using the following code, it seems that the body is not parsed correctly, as the API I am contacting sends me back a 401, that occurs when password/username provided are incorrect/missing.
val body = JwtQuery(getUsername(), getPassword())
return restTemplate.postForObject(url, body, Jwt::class.java)!!
This is the JwtQuery class:
data class JwtQuery (
val username: String,
val password: String
)
Note that getUsername() and getPassword() return the expected value.
What am I doing wrong ?
Edit 1: setting headers
Using:
val body = JwtQuery(getUsername(), getPassword())
val headers = HttpHeaders()
headers.contentType = MediaType.APPLICATION_JSON
val bodyEntity = HttpEntity(body, headers)
return restTemplate.postForObject(url, bodyEntity, Jwt::class.java)!!
Still returns the same error (401)
edit 2: marshaled JwtQuery
val body = JwtQuery(mesProperties.getUsername(), mesProperties.getPassword())
val marshaled = ObjectMapper().writeValueAsString(body)
println(marshaled)
Output:
{"username":"username","password":"password"}

Google RECAPTCHA always returning error missing-input-response in the response

Google RECAPTCHA always returning error missing-input-response in the response when I try to check the correctness. How does the call to the service go, to the URL https://www.google.com/recaptcha/api/siteverify ?
The format is:
https://…/api/siteverify?secret=[…]&response=[…]&remote_ip=[…]
Make sure that Content-Type is set to application/x-www-form-urlencoded
.Net example
using (HttpClient httpClient = new HttpClient())
{
var response = await httpClient.PostAsync(GoogleVerificationUrl + "?secret=" + ReCaptchaSecretKey + "&response=" + ReCaptchaResponse, new StringContent("", Encoding.UTF8, "application/x-www-form-urlencoded"));
}

How to parameterize Bearer token authorization in Jmeter

I have a jmeter login script where user logs in and logs out. The detailed screenshots are attached below.
Request data is as attached:
In the response date , the authorization token is generated:
And the regular expression for the same is as below:
I am passing the value as parameter in 55/users:
When I'm running the script it is failing:
Here is the response data:
Use Header Manager to pass the Token as a Header so you would have:
See for more details:
https://stackoverflow.com/a/43283700/460802
If you're looking to learn jmeter correctly, this book will help you.
A bit easier JMeter setup (login/get):
Thread Group
HTTP Request, Body Data: { "Login":"some", "Password":"credentials" }
HTTP Header Manager: content-type application/json
JSON Extractor - Names of created variables: Token; JSON Path expression: tokenName (root level in my case)
HTTP Request
HTTP Header Manager: content-type -> application/json; Authorization -> Bearer ${Token}
Response Assertion: Fields to Test = Response Code; Pattern Matching Rules = Equals, Not; Pattern to Test 401
View Results Tree to check results
Local IE Ajax version in case...
<SCRIPT>
var baseUri = 'https://localhost:port';
var tokenUri = '/something';
var getUri = '/restrictedData';
var token;
var form = { "Login":"some", "Password":"credentials" };
postRequest(baseUri + tokenUri, form, gotToken)
function gotToken(progress) {
var response = progress.srcElement;
if (response.status != 200) {
document.body.innerText = "Error:\n" + response.response;
return;
}
token = JSON.parse(response.response);
console.log(JSON.stringify(token));
var restricted = getRequest(baseUri + getUri, token.tokenName, gotRestricted);
}
function gotRestricted(progress) {
var jsonStr = progress.srcElement.response;
var jsonObj = JSON.parse(jsonStr);
document.body.innerText = JSON.stringify(token,null,2) + '\n\n' + JSON.stringify(jsonObj,null,2);
}
function getRequest(url, token, callback) {
var xhr = new XMLHttpRequest();
xhr.onloadend = callback;
xhr.open('GET', url);
xhr.setRequestHeader('contentType', 'application/json')
if (token) xhr.setRequestHeader("Authorization", "Bearer " + token);
xhr.send();
return xhr;
}
function postRequest(url, body, callback) {
var xhr = new XMLHttpRequest();
xhr.onloadend = callback;
xhr.open('POST', url);
xhr.setRequestHeader('Content-Type', 'application/json')
xhr.send(JSON.stringify(body));
return xhr;
}
</SCRIPT>
Add Bearer ${token} in HTTP Header Manager available under failing HTTP Request.
If you already have the bearer token and just want to use in in header manager then,
in HTTP HEADER MANAGER tab, put these values under NAME and VALUE column respectively.
Name: Authorization
Value: Bearer "add your actual token without quotes"
Once you've extracted the token from the token API request, use this token in the HTTP Authorization Header manager for subsequent API's. Example below:
Header Name: Header Value Authorization: Bearer ${generated_token}
Where "generated_token" is a variable containing the extracted token.
I got cUrl from my API and then I imported it.
use Authorization as parameter name and value should be
Bearer ${variable_name}

WebAPI OData v4 custom action without parameters can't be routed with error "No routing convention was found..."

I have very simple OData controller that successfully process standard actions (at least GET, POST, PUT and DELETE methods are working). I have followed this tutorial and added simple bound action. The method has parameters argument, but actually it does not required the parameters:
[HttpPost]
public IHttpActionResult Close([FromODataUri] int key, ODataActionParameters parameters) {
return Ok();
}
I have defined this action in OData EDM configuration as following:
builder.EntitySet<Ticket>("tickets");
builder.EntityType<Ticket>().Action("Close");
I am trying to call action from Postman:
POST /odata/tickets(2)/Default.Close HTTP/1.1
Host: localhost:50477
Accept: application/json
Content-Type: application/json
Cache-Control: no-cache
Postman-Token: eef4c1f6-8c7f-f5eb-c22d-4397f3bda170
But receives the error message:
{
"error": {
"code": "",
"message": "No HTTP resource was found that matches the request URI 'http://localhost:50477/odata/tickets(2)/default.close'.",
"innererror": {
"message": "No routing convention was found to select an action for the OData path with template '~/entityset/key/unresolved'.",
"type": "",
"stacktrace": ""
}
}
}
I have read the whole internet and all related articles on SO but can't fix this issue. Please help me because I have no any fresh idea how to fight this.
My controller:
public class TicketsController : ODataController
{
[HttpPost]
public IHttpActionResult Close([FromODataUri] int key, ODataActionParameters parameters)
{
return Ok();
}
}
My request:
string requestUri = "http://localhost/odata/tickets(2)/Default.Close";
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, requestUri);
request.Content = new StringContent("",
Encoding.UTF8,
"application/json");
HttpResponseMessage response = _client.SendAsync(request).Result;
Or remove the ODataActionParameters parameters in the close method and call with:
string requestUri = "http://localhost/odata/tickets(2)/Default.Close";
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, requestUri);
HttpResponseMessage response = _client.SendAsync(request).Result;
My EdmModel is use your model.

Resources