How to read a value in WebAPI sent via WebClient.UploadString? - c#

I want to POST data to WebAPI. Ideally I would just do:
http:www.myawesomesite.com?foo=bar
As a POST. But to my specific question, I am trying to use:
using(var webClient = new WebClient())
{
client.uploadString("http:www.myawesomesite.com", "POST", "foo=bar");
}
But that converts "foo=bar" to a bye array. Okay fine, I'm just trying to get it to work at this point.
My Web API controller looks like this:
[HttpPost]
public void MashPotatos(string foo)
{
potatoMasher.Mash(foo);
}
But I get The remote server returned an error: (404) Not Found. First off, I thought WebAPI would automatically grock that data for me even if it was in the body of the request. But more importantly, I just want to be able to get it to work.
Ideally, I'd like to leave the WebAPI method in a form such that you can still invoke it by using a query string with a POST verb.

you need to configure your web API route to accept a foo parameter.May be this will solve your issue
config.Routes.MapHttpRoute(name: "newont",
routeTemplate: "api/{controller}/{foo}",
defaults: new { controller = "Controllername", foo= "foo"}
);

Well here is a post that might be helpful to some. For me I just had to do:
using(var webClient = new WebClient())
{
client.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
client.uploadString("http:www.myawesomesite.com", "POST", "foo=bar");
}
and
[HttpPost]
public void MashPotatos([FromBody]string foo)
{
potatoMasher.Mash(foo);
}
I decided against doing a POST with a query string as it seems to go against convention but there is also a [FromUri] attribute

public string GetData(){
string jsonResponse = string.Empty;using (WebClient client = new WebClient()){client.Headers[HttpRequestHeader.ContentType] = "application/json";
jsonResponse = client.UploadString(baseuri, "POST", #"{personId:""1"", startDate:""2018-05-21T14:32:00"",endDate:""2018-05-25T18:32:00""}");
return JsonConvert.DeserializeObject<Model>(jsonResponse);}}
#"{personId:""1"",
startDate:""2018-05-21T14:32:00"",endDate:""2018-05-25T18:32:00""}
It's a JSON custom string, or you can serialize the object here on the API side
HttpPost
public string Metod(Something data)
{
DateTimeOffset sDate = DateTimeOffset.Parse(data.date1);
DateTimeOffset eDate = DateTimeOffset.Parse(data.date2);
return _someService.GetService(data.Id, sDate, eDate);
}
Then we go to the service and get data from DB

Related

How to pass Xml file using RestClient in Post - C#?

I'm trying to pass xml file to api using RestSharp, but I'm receiving the file at the Post method as null.
Here is my code:
public void SendXmlToApi()
{
var client = new RestClient(_uri);
var request = new RestRequest(Method.POST);
request.AddFile("Xml",XmlPath);
request.RequestFormat = DataFormat.Xml;
request.AddHeader("content-type", "application/xml");
var response = client.Execute(request);
bool res = (response.StatusCode == HttpStatusCode.OK);
}
And my Post Func:
[HttpPost]
[Route("Test")]
public void UpdateResult(XDocument a)
{
}
Any idea whats the problem?
I don't use XML, so this deviates a little from your example, but it is a viable option for posting XML into a [HttpPost] API endpoint. I used your SendXmlToApi() example untouched (just supplied my own _uri and XmpPath variables) and was successful (Core 3.1).
I modified your receiving code to be:
[HttpPost]
[Route("test")]
public async Task UpdateResult()
{
string body = await new StreamReader(HttpContext.Request.Body).ReadToEndAsync();
XDocument xdoc = XDocument.Parse(body);
}
Of course, you'll want to put guard rails on this and have proper error handling and validation, but it should get you over the hump.

IGDB V3 Request

Does anyone know how to properly search for games using the Internet Game Database API as of version 3? I'm trying to use IGDB to do a simple game search. For each game that matches the search terms, I'd like to retrieve the game's name, genres, developers and publishers, it's initial release date, and the URL of the cover. Through some Googling I'd gotten it working through the old URL parameters, but something seems to have changed on their end, and those no longer work. The version 3 documentation says to use Apicalypse to send the fields you want back in the body of the web request, but I can't for the life of me figure out how to do that. I'm using AJAX to send the search terms to the controller, and sending the results back via a JSON object. I'm getting a 400 Bad Request error every time, no matter the syntax I use for the fields. The documentation says that using URL parameters should still work, but they do not. Here's my controller code.
[HttpPost]
[WebMethod]
public JsonResult LookUpGames(string search)
{
string url = "https://api-v3.igdb.com/games/?search=" + search
+ "&fields=name,genres,involved_companies,first_release_date,cover";
HttpWebRequest gameRequest = (HttpWebRequest)WebRequest.Create(url);
gameRequest.Accept = "application/json";
gameRequest.Headers.Add("user-key", "[MYUSERKEY]");
WebResponse gameResponse = (HttpWebResponse)gameRequest.GetResponse();
string responseString = new StreamReader(gameResponse.GetResponseStream()).ReadToEnd();
return Json(new { result = responseString });
}
UPDATE: Thanks for the pointer, Jake. I'm now hitting the servers with the following code.
HttpResponse<JsonResult> jsonResponse = Unirest.post("https://api-v3.igdb.com/games")
.header("user-key", "[MYUSERKEY]")
.header("Accept", "application/json")
.body("fields name,genres,platforms,involved_companies,cover").asJson<JsonResult>();
JsonResult jsonResult = Json(new { result = jsonResponse });
return jsonResult;
There is no JsonNode in C# apparently, so I tried JsonResult, and the .asJson() seems to be .asJson(). I just fiddled with it until it worked. But I'm still not getting back a list. I'm getting a 400 Bad Request error. So even in this new format, it's still not liking the fields I'm giving it. According to the structure in the documentation, the fields I'm giving it are in fact there in the Game endpoint. So I don't know what could be wrong. Any other ideas anyone?
I decided to try the query approach again, and somehow it now works. Here's my controller method that works. Not sure which tweaks made it work again, but it does.
[HttpPost]
[WebMethod]
public JsonResult LookUpGames(string search)
{
string url = "https://api-v3.igdb.com/games?search=" + search +
"&fields=name,genres.name,platforms.name,involved_companies.*, involved_companies.company.*,first_release_date,cover.url";
HttpWebRequest gameRequest = (HttpWebRequest)WebRequest.Create(url);
gameRequest.Accept = "application/json";
gameRequest.Headers.Add("user-key", "[MYUSERKEY]");
WebResponse gameResponse = gameRequest.GetResponse();
StreamReader sr = new StreamReader(gameResponse.GetResponseStream());
string responseString = sr.ReadToEnd();
sr.Close();
JsonResult jsonResult = Json(new { result = responseString });
return jsonResult;
}

Receiving XML in HttpPost Using C#

I thought this would be pretty easy, but it's just not - at least for me. I am trying to send an XML string to a REST endpoint. At this time, the only thing the endpoint has to do is log the XML to a file or database. The XML itself is unknown, it could be literally any length and have any number of nodes. So it really needs to be treated as a string.
My problem is that I cannot determine how to receive the XML/string in the Post method. I am using the RestSharp library.
Here is the Post method I am using; very simple. I removed logging code and try/catch code to keep it simple.
[HttpPost]
public IHttpActionResult Post([FromBody] string status)
{
// Log the post into the DB
LogPost(status);
}
The code to perform the post:
public void TestPost()
{
IRestResponse response;
try
{
// Get the base url for
var url = #"http://blahblah/status";
// Create the XML content
object xmlContent = "<XML><test><name>Mark</name></test></XML>";
var client = new RestClient(url);
var request = new RestRequest(Method.POST);
// Add required headers
request.AddHeader("Content-Type", "text/plain");
request.AddHeader("cache-control", "no-cache");
request.AddJsonBody(xmlContent);
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
response = client.Execute(request);
}
catch (Exception ex)
{
...
}
}
The problem: the status parameter received by the post is, simply, "Mark". The full XML is missing! I need the entire XML string.
I have tried a few different variations of this. Changing the content-type to "application/xml", "application/json", etc. Nothing is working.
I have tried using request.AddXmlBody(statusObject), and request.AddBody(statusObject). Both were unsuccessful.
I have even tried sending the XML using request.AddHeader() with no luck. What am I missing. There must be something obvious that I'm not getting.
a) you must configure Web API to use XmlSerializer in your WebApiConfig.Register. Otherwise Web API uses the DataContractSerializer by default.
File: App_Start\WebApiConfig.cs
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Formatters.XmlFormatter.UseXmlSerializer = true; //HERE!
...
}
b) you need to define a class for your xml
public class test { public string name { get; set; } } //BASED ON YOUR XML NODE
[HttpPost]
public IHttpActionResult Post([FromBody] string status)
{
}
c) if you need to work with a simple string, change POST method
public void Post(HttpRequestMessage request)
{
string body = request.Content.ReadAsStringAsync().Result;
}
d) invoke from restsharp client
string xmlContent = "<test><name>Mark</name></test>";
var client = new RestClient(url);
var request = new RestRequest(Method.POST);
request.AddParameter("application/xml", xmlContent, ParameterType.RequestBody);
var response = client.Execute(request);
For "some" reason request.AddParameter takes the first param as ContentType(not the Name)
https://github.com/restsharp/RestSharp/issues/901
Did you tried to send the request with
Content-Type: application/xml; charset="utf-8"
instead of text\plain?

string parameter in controller is null when using webclient

When I use WebClient to call a function in a controller
using (WebClient client = new WebClient())
{
client.BaseAddress = "http://localhost/";
client.Headers.Add("Content-Type", "application/json");
client.UploadString("api/test", HttpMethod.Put.ToString(), stringParameter);
}
I called the function in controller successfully but the "stringParameter" in controller is empty like the following code:
[Route("api/test")]
[HttpPut]
public async Task<IHttpActionResult> Test([FromBody] string stringParameter)
{
if (!ModelState.IsValid)
{
// the flow goes here
return BadRequest(ModelState);
}
// ...
}
I would like to know where is the mistake(s) I made and how to fix the problem(s). Thank you very much.
Remark: "stringParameter" is fine if it is numeric such as "123" but not work if it is "A123" or "B123".
As you're setting content type to "application/json" you should be sending a valid JSON value rather then raw string. A number is JSON and in plain text is the same, so that's why it works.
Try serializing the text to JSON before sending:
JsonConvert.ToString(stringParameter);
(I'm using Newtonsoft.Json nuget package here)
Alternatively you can try to use content type text/plain, but I'm not sure if your web api is configured to handle that by default.

How to pass classic asp dictionary to .NET RESTful Web Api

I am having issues passing data parameters from a classic asp application to a .NET Web API. It seems that no matter what I do I cannot access the parameter inside the .NET web API. I have included the code I am using below:
The Classic ASP code:
Public Function GetResponse (HTTPMethod, ReqURL, QueryParamsOrArgs)
Set XMLHTTP = Server.CreateObject("MSXML2.ServerXMLHTTP")
If HTTPMethod = "GET" Then
ReqURL = ReqURL & "?" & QueryParamsOrArgs
QueryParamsOrArgs = ""
End If
XMLHTTP.open HTTPMethod , ReqURL, false
XMLHTTP.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
XMLHTTP.setRequestHeader "AuthToken", ServiceUrl_AuthToken
XMLHTTP.send(QueryParamsOrArgs)
If XMLHTTP.Status = 200 Then
GetResponse = XMLHTTP.responseText
Else
GetResponse = ""
End If
End Function
Public Function TestPOST(url)
mydata = "value1=1&value2=2&value3=3"
TestPOST = GetResponse("POST", url, mydata)
End Function
In the calling ASP page:
dim oDataUtils : Set oDataUtils = (New DataUtils)
myResponse = oDataUtils.TestPost(ServiceUrl_Base & "EventData/Post")
The .NET Web API Action Method:
[HttpPost]
public HttpResponseMessage Post([FromBody]string value)
{
StringContent sc = new StringContent(value);
sc.Headers.ContentType = new MediaTypeHeaderValue("application/json");
HttpResponseMessage resp = new HttpResponseMessage();
resp.Content = sc;
return resp;
}
No matter what I send, the value of the parameter "value" inside the api method is always null. Ultimately I would love to be able to send an entire dictionary or parameters to this method, but cannot even get the most simple component (a string) to pass in. What am I missing here?
My ultimate goal would be for something like this to work:
[HttpPost]
public HttpResponseMessage Post(Dictionary<string, object> data)
{
// Do something with the dictionary and then return a response...
StringContent sc = new StringContent("test");
sc.Headers.ContentType = new MediaTypeHeaderValue("application/json");
HttpResponseMessage resp = new HttpResponseMessage();
resp.Content = sc;
return resp;
}
but I will take either option at this point...
The "issue" is: [FromBody]
public HttpResponseMessage Post([FromBody]string value)
It is for "simple" type, and translated means, just one value. Additionally, the format the API expects using FromBody is =value (notice the missing "key").
e.g.
foo=bar //this will fail "null"
=bar //this is good (no key)
This will explain it in detail even if the topic is about jquery, it will give you insight to the behavior of FromBody.
Use FormDataCollection...
Hth....
It might work if you pass proper json instead of just string ,
form you json like
mydata="{'value':'value1=1&value2=2&value3=3'}"
You can also pass dictionary of like
var data={};
data.Value1="1";
data.Value2="2";
data.Value3="3";
Remember the name of param in action method and name of json key must be same,here 'values
mydata={values:data};
[HttpPost]
public HttpResponseMessage Post(Dictionary<string, string> values)

Categories