HTTP Error 406 after execting a restsharp request - c#

I'm trying to use RestSharp to connect to a server. but I get HTTP Error 406 Not acceptable.
Here is the web service response:
{"metaInfo":{"ErrorString":" ","ErrorCode":" ","Result":true},"userModel":
{"UserId":"123qwe","UserName":"aaa","FirstName":"ALi","LastName":"TbT"}}
The rest service is actually a simple php file that I created for test:
<?php
$a = array("metaInfo"=>array("ErrorString"=>" ","ErrorCode"=>" ","Result"=>true),"userModel"=>array("UserId"=>"123qwe","UserName"=>"aaa","FirstName"=>"ALi","LastName"=>"TbT"));
echo json_encode($a);
?>
And Here is the RegisterResult and MetaInfo classes:
public class RegisterResult
{
public MetaInfo metaInfo { get; set; }
}
public class MetaInfo
{
public string ErrorString { get; set; }
public string ErrorCode { get; set; }
public bool Result { get; set; }
}
The code that runs the rest request is as follows:
var client = new RestClient(Configuration.PortalUri);
var request = new RestRequest(requestUri, HttpMethod.Post);
var asyncHandle = await client.Execute<RegisterResult>(request);
Could you please tell me what the problem is? I think something is wrong with headers or encoding or something like that. Am I right?

This error is specific to the way the programmers have created the service you are calling. There's nothing wrong with your code from a C# perspective, but the way the service author has chosen to implement their service doesn't like something in the service call. You will have to refer to their documentation or ask one of their programmers.
Here's an explanation of http error 406
(taken from http://www.checkupdown.com/status/E406.html):
Fixing 406 errors - general
This error occurs very infrequently in Web browsers, because most
browsers will accept any data returned from the Web server.
If the client is not a Web browser, then anyone can only investigate
the problem by looking at the Accept headers generated by the client
system
Consider these headers to modify:
•Accept: The MIME types accepted by the client. For example, a browser
may only accept back types of data (HTML files, GIF files etc.) it
knows how to process.
•Accept-Charset: The character sets accepted by
the client.
•Accept-Encoding: The data encoding accepted by the
client e.g. the file formats it understands. •Accept-Language: The
natural languages (English, German etc.) accepted by the client.
•Accept-Ranges: Whether the client accepts ranges of bytes from the
resource i.e. a portion of the resource.
For example, you may need to add this to your request:
request.AddHeader("Accept", "application/json");

Related

C# API call from MarketStack and print values - Error 403

I would like to make a successful API call, then print the values in order to see if it works. My main goal is to analyze the data, after I can make a successful API call, and build a systematic strategy for trading.
System.Net.Http.HttpRequestException: "Response status code does not indicate success: 403 (Forbidden)
namespace marketstacktest
{
class Program
{
static async Task Main(string[] args)
{
Console.WriteLine("Hello World!");
var options = Options.Create(new MarketstackOptions() { ApiToken = "secretTokenHere" });
var marketstackService = new MarketstackService(options, NullLogger<MarketstackService>.Instance);
var appleSymbol = "AAPL";
var fromDate = DateTime.Now.AddDays(-200);
var toDate = DateTime.Now;
//error at the await System.Net.Http.HttpRequestException: "Response status code does not indicate success: 403 (Forbidden)."
List<Marketstack.Entities.Stocks.StockBar> stock = await marketstackService.GetStockEodBars(appleSymbol, fromDate, toDate);
foreach (var stock_i in stock)
{
Console.WriteLine($"close: {stock_i.Close}");
}
}
}
}
In the API manual, which is directly linked from the github, it gives information about all of the error codes. The relevant ones here are these two:
Code
Type
Description
403
https_access_restricted
HTTPS access is not supported on the current subscription plan.
403
function_access_restricted
The given API endpoint is not supported on the current subscription plan.
Their class library on github is just wrapping a json REST api. Every call to the API is just an http request, returning data as json objects. The 403 error indicates that your request was accepted as a valid request, but intentionally rejected by the server for some reason. And according to the docs, the error was because your account is not allowed access to either https or to the type of request.
Their free-tier subscription only includes end-of-day data, which is what you requested, so it wouldn't make sense for that not to be allowed. So, your app is almost certainly making an https call.
I went to the examples at the very beginning of their quick start guide, and chose the end-of-day example to match your app, and clicked on the link. It worked, and gave a bunch of json records. But, the request they made was using 'http' not 'https'.
Changing the requst to 'https' elicited a 403 response with this content (formatted for readability):
{
"error":
{
"code": "https_access_restricted",
"message": "Access Restricted - Your current Subscription Plan does not support HTTPS Encryption."
}
}
At this point we have enough to be almost certain that this is your issue. The final thing is to go look up how to turn https requests off in their class library. To avoid having to go through the code, I checked the help at the bottom of the page one more time, and found this (formatted for readability):
var options = Options.Create(new MarketstackOptions(){
ApiToken = apiKey,
MaxRequestsPerSecond = 3,
Https = true
});
Welp. This should probably be in their first example, since that's what people are most likely to try first, but it's not. So, to stop trying to make http requests, you just need to set the Https option to false in your code. You just need to add that to the options in your code, like so:
var options = Options.Create(new MarketstackOptions(){
ApiToken = "secretTokenHere",
Https = false
});
I will leave the testing to you, but from the browser test, we know that the request should work, unless there's a bug in their library. Given the information that was available, this is almost certainly the issue.

Internal Server Error when calling POST method

I am trying to create a console application that is able to push things into a database by calling a certain API. I have control over neither the database or the API. The API is working fine as I already created tested the GET method, but I guess there is something wrong with my POST.
So first, I create the Product object containing the values that I want to send to the API.
Product product = new Product
{
productId = "27795",
amount = 1,
customerid = 0,
returnbasketid = true
};
And this is the method which is supposed to call the API's POST method.
static async Task CreateProductAsync(HttpClient cons, Product product)
{
using (cons)
{
HttpResponseMessage res = cons.PostAsJsonAsync("", product).Result;
res.EnsureSuccessStatusCode();
Console.WriteLine(res.Content.ReadAsStringAsync().Result);
}
}
Upon running the code, line HttpResponseMessage res = cons.PostAsJsonAsync("", product).Result; has the following error:
System.AggregateException: 'One or more errors occurred. (Response status code does not indicate success: 500 (Internal Server Error).)'
HttpRequestException: Response status code does not indicate success: 500 (Internal Server Error).
I guess that the problem is how I send the values to the API and what the API expects. I have this data expected example:
{
"":[{
"productId":"27795",
"amount":2,
"customerid":0
},{
"productId":"27796",
"amount":1,
"customerid":0
}],
"returnbasketid":true
}
I already tested this using Postman and it is working fine, so the problem must be with my code.
https://pastebin.com/pZDehaaD This is a full example of my Program.cs. The API url has been removed, though.
EDIT: So this is the JSON that my console application is sending:
Whereas the JSON that works through Postman is this:
So the question is how should I write my code so the JSON that I am sending is properly configurated?
You're passing a Product to the API (that's the first Fiddler capture above).
But if we look at the required input (the second Fiddlel capture above), and also the "data expected example" (grey background), we see an object that contains an (unnamed) array of Products and field called "returnbasketid".
What we need to do if re-create this object. We can call this class a "Wrapper", or "MyRequestObject" or any other name. The name is not important. I would try code of this form.
public class Wrapper
{
[JsonProperty("")] // rename json property to empty string - don't know if this will work
public List<Product> Products { get; set; } = new List<Product>();
public bool returnbasketid { get; set; }
}
You then pass an instance of this Wrapper, instead of a Product, to the with cons.PostAsJsonAsync() call.
The problem with this is that our Wrapper's Product array has a name, and the server wants an array without a name. I'm trying to rename the array above. If that works great. Otherwise I think you'll be obliged to create the json yourself (easy with Newtonsoft) and then post with HttpClient's PostAsync(Uri, HttpContent).

How to verify Slack Events API Request Url in ASP.Net Core Mvc application?

I'm working on Slack integration in an ASP.Net Core MVC 2 application.
I have done it for Searching and Posting messages to Slack channels. Now I'm stuck at integrating Events API in this application. Basically, at the moment I'm not able to verify my Request Url as mentioned here Events API Subscription
Following is my action method that we have give to Slack where they will send the verification json object which will be mapped to request parameter of my action and is as follows:
{
"token": "Jhj5dZrVaK7ZwHHjRyZWjbDl",
"challenge": "3eZbrw1aBm2rZgRNFdxV2595E9CY3gmdALWMmHkvFXO7tYXAYM8P",
"type": "url_verification"
}
[HttpPost]
public IActionResult Event(EventsRequest request)
{
if (request != null)
{
if (request.type.Equals("url_verification"))
return Content(request.challenge);
else
ViewBag.Challenge = request.challenge;
}
return View();
}
Here is my EventsRequest class:
public class EventsRequest
{
public string token { get; set; }
public string challenge { get; set; }
public string type { get; set; }
}
I have deployed this application locally on IIS and have applied InBound rules to make it accessible publicly and it is accessible. But issues arise when I give the following URL to Slack for verification:
http://IP_Address/Slack/Event
Following is the screenshot of the response that Slack gives
Can someone tell what's wrong here? I tried to hit this URL with Postman and I was able to get the desired results.
You can try these:
As suggested in https://api.slack.com/events-api#subscriptions
Your Event Request URL must be confirmed before saving this form. If
your server takes some time to "wake up" and your initial attempt at
URL verification fails due to a timeout, use the retry button to
attempt verification again.
If it fails at first attempt make sure server is up & running and try next time.
After you've completed typing your URL, we'll dispatch a HTTP POST to
your request URL. We'll verify your SSL certificate and we'll send a
application/json POST body containing three fields:
{
"token": "Jhj5dZrVaK7ZwHHjRyZWjbDl",
"challenge": "3eZbrw1aBm2rZgRNFdxV2595E9CY3gmdALWMmHkvFXO7tYXAYM8P",
"type": "url_verification"
}
You need to replace example json with the real values generated for you url configuration and verification.
Make sure url for verification is set correctly before generating challenge and is not changed afterwards.
Make sure no mismatch in url scheme like http in one place and https at other.
Try adding from body in post request:
[HttpPost]
public IActionResult Event([FromBody]EventsRequest request)

How to remove #strin3http//schemas.microsoft.com/2003/10/Serialization/� received from service bus queue received in python script?

I have set the output of Azure stream analytics job to service bus queue which sends the data in JSON serialized format. When I receive the queue message in python script, along with the data in curly braces, I get #strin3http//schemas.microsoft.com/2003/10/Serialization/� appended in front. I am not able to trim it as the received message is not being recognized as either a string or a message. Because of this I cannot de-serialize the data.
This TechNet article suggests the following code:
// Get indices of actual message
var start = jsonString.IndexOf("{");
var end = jsonString.LastIndexOf("}") + 1;
var length = end - start;
// Get actual message
string cleandJsonString = jsonString.Substring(start, length);
Pretty primitive but whatever works I suppose...
The issue was similiar with the SO thread Interoperability Azure Service Bus Message Queue Messages.
Per my experience, the data from Azure Stream Analytics to Service Bus was sent via AMQP protocol, but the protocol of receiving the data in Python is HTTP. The excess content was generated by AMQP during transmission.
Assumption that receiving the message via the code below, please see https://azure.microsoft.com/en-us/documentation/articles/service-bus-python-how-to-use-queues/#receive-messages-from-a-queue. The function receive_queue_message with the False value of the argument peek_lock wrapped the REST API Receive and Delete Message (Destructive Read).
msg = bus_service.receive_queue_message('taskqueue', peek_lock=False)
print(msg.body)
According to the source code of Azure Service Bus SDK for Python include the functions receive_queue_message, read_delete_queue_message and _create_message, I think you can directly remove the excess content from the msg.body using the string common function lstrip or strip.
I ran into this issue as well. The previous answers are only workarounds and do not fix the root cause of this issue. The problem you are encountering is likely due to your Stream Analytics compatibility level. Compatibility level 1.0 uses an XML serializer producing the XML tag you are seeing. Compatibility level 1.1 "fixes" this issue.
See my previous answer here: https://stackoverflow.com/a/49307178/263139.
I had the same issue but in a .net solution. I was writing a service which sends data to a queue, and on the other hand, I was writing a service which gets that data from the queue. I've tried to send a JSON, like this:
var documentMessage = new DocumentMessage();
var json = JsonConvert.SerializeObject(documentMessage);
BrokeredMessage message = new BrokeredMessage(json);
await _client.SendAsync(message);
In this second service I was getting the JSON but with this prefix:
#strin3http//schemas.microsoft.com/2003/10/Serialization/�
I solved this problem by add DataContractJsonSerializer like that:
var documentMessage = new DocumentMessage();
var serializer = new DataContractJsonSerializer(typeof(DocumentMessage));
BrokeredMessage message = new BrokeredMessage(documentMessage , serializer);
await _client.SendAsync(message);
If you want to solve the problem in that way, you will have to add Data Attributes from System.Runtime.Serialization to the model:
[DataContract]
public class DocumentMessage
{
[DataMember]
public string Property1 { get; private set; }
[DataMember]
public string Property2 { get; private set; }
}
When using Microsoft.ServiceBus nuget package, replace
message.GetBody<Stream>();
with
message.GetBody<string>();

Posting data to asp.net Web API

I'm trying to figure out the new ASP.NET Web API.
So far I've been able to create this method signature and connect to it just fine and get a valid response...
[HttpPost]
public HttpResponseMessage CreateAccount()
I am able to send a request to this method with fiddler and have verified that it is receiving the request.
However, when I try to pass data is when I am running into a problem.
The first thing I tried was...
[HttpPost]
public HttpResponseMessage CreateAccount([FromBody]string email, [FromBody]string password)
And I type
email:xyz,password:abc
into the body of the request in fiddler. When I do this I get a 500 error stating
'Can't bind multiple parameters ('email' and 'password') to the request's content.'
I have also tried this as a method signature...
[HttpPost]
public HttpResponseMessage CreateAccount([FromBody]UserAccountRequestData data)
with the UserAccountRequestData being a simple POCO
public class UserAccountRequestData
{
public string Email { get; set; }
public string Password { get; set; }
}
And I put
{Email:xyz,Password:abc}
or
data:{Email:xyz,Password:abc}
into the body of the request. In both cases trying to populate the POCO I am able to reach the method while debugging, but the data object is always null.
I need to understand how to create API methods that accept both strongly typed POCOs and others that accept multiple primitive types like strings and ints.
Thanks
You need to set the Content-Type header to application/json and then provide valid JSON.
{"Email":"xyz","Password":"abc"}

Categories