C# Post XML file using RestSharp - c#

I have written a method to post messages to an uri.
public string RestClientPost(string uri, string message = null)
{
var client = new RestClient(uri);
var request = new RestRequest(Method.POST);
request.AddHeader("Accept", "text/xml");
if (!string.IsNullOrEmpty(message))
request.AddParameter(message, ParameterType.RequestBody);
var result = "";
var response = client.Execute(request);
if (response.StatusCode == HttpStatusCode.OK)
{
result = response.Content;
Console.WriteLine(result);
}
else
{
result = response.StatusCode.ToString();
}
return result;
}
and below code is used above method to post.
public void test123()
{
string uri = "myuri"; //private uri, cannot expose.
var file= System.IO.File.ReadAllText(Path.Combine(Settings.EnvValPath, "RestClientXML", "test.XML"));
var content = new RestClientServices().RestClientPost(uri, file);
}
however, it returns "Unsupported Media type".
my test.XML's content is
<customer>
<customerName>test</customerName >
<customerStatus>OK</customerStatus >
</customer>
And using Advanced Rest Client Plugin for Google Chrome, I'm able to post it and return with string that I wanted. Is there something wrong?? I set "content-type" to "text/xml" in Advanced Rest Client.
The return message is id of the customer. e.g: 2132

im using postman,
if you can call any xml web services with this tools , then you can click on code and select restsharp and copy paste it to your code

This happened because the header "Accept" is to specify a type of return object. In this case a value of a variable content, not the type of content to send. Specify a type of content to send with: "Content-Type: application/xml".
If a return type of POST request is a media file, you can use 'image/png' or 'image/jpeg'. You can use multiple accept header values like: "application/xml, application/xhtml+xml, and image/png".
For example, you can use Fiddler to debug HTTP(s) traffic - it's a good tool for web developers.

Related

Adding Comment to Fortify Issue via REST API results in Content Encoding Error

I'm trying to add a comment to an issue inside Fortify. When I POST what I think is the correct JSON, I receive the response "{"message":"Content was incorrectly formatted (expected application/json; charset=utf-8).","responseCode":400,"errorCode":-20209}"
However, if I use Fiddler to examine the message I'm POSTing and receiving the appropriate headers appear to be in place. What secondary issue could be causing this exception to be thrown?
Fortify v18.10.0187
.NET v4.6.2
Newtonsoft.Json v9.0.0
public static string PostCommentIssue(FortifyComment fc)
{
var content = JsonConvert.SerializeObject(fc);
var postUri = String.Format(Configuration.FortifyCommentsUri, fc.data.issueId);
return WebServiceHelper.PostMessage(postUri, content);
}
public static string PostMessage(string url, string content)
{
HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Post, url);
requestMessage.Headers.Add("Authorization", Configuration.FortifyAuthorization.ToHeader());
requestMessage.Content = new StringContent(content, Encoding.UTF8, JsonMediaTypeFormatter.DefaultMediaType.MediaType);
HttpResponseMessage hrm = HttpClient.SendAsync(requestMessage).Result;
hrm.EnsureSuccessStatusCode();
HttpContent hc = hrm.Content;
return hc.ReadAsStringAsync().Result;
}
FortifyComment is just an object with the basic elements of a comment in it. It's based on the Fortify response given on a query (thus the inner data element).
Using
FortifyComment fc = new FortifyComment();
fc.data.issueId = defect.id;
fc.data.comment = String.Format("TFS #{0}.", tfsNumber);
FortifyHelper.PostCommentIssue(fc);
I receive the 400 error. Screenshot of Fiddler intercept:

RestSharp "Error getting response stream (ReadAsync): ReceiveFailure Value cannot be null. Parameter name: src"

Hello all am trying to do a login to my xamarin api using RestSharp, the API ought to return status code 200 OK if the authentication works and status code 415 if the authentication fails(wrong password) and other codes depending on what the case scenario, but instead i get a status code 0 on all other case asides when the authentication pass(status code 200 ok), the source code below is how i implement
//payload am sending to the api
RequestPayload res = new RequestPayload();
res.appid = appid;
res.data = data;
res.method = "Login";
//convert to json object
var MySerializedObject = JsonConvert.SerializeObject(res);
string APIUrl = ""http://142.168.20.15:8021/RouteTask";
//create client
RestClient client = new RestClient(APIUrl);
//create request
RestRequest request = new RestRequest(Method.POST);
// set request headeer
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
//request.AddJsonBody(MySerializedObject); --i have also tried this
request.AddParameter("application/json", MySerializedObject, ParameterType.RequestBody);
request.JsonSerializer.ContentType = "application/json; charset=utf-8";
request.AddParameter("RequestSource", "Web", "application/json", ParameterType.QueryString);
client.Timeout = 2000000;
var response = client.Execute(request); // where the issue appears
//RestResponse response = client.Execute(request); // i have tried this
//IRestResponse response = client.Execute(request); // i have tried this
if (response.IsSuccessful)
{
//use response data
}
on all scenerio it comes back with a StatusCode: 0, Content-Type: , Content-Length: 0) and errorMessage
"Error getting response stream (ReadAsync): ReceiveFailure Value
cannot be null. Parameter name: src"
screenshot below indicate when the api call fails
Response receieved when the authentication is valid
I was finally able to find a workaround for this. Bear with the long-winded response.
The tags mention Xamarin, which is what I am working in as well - specifically with iOS. I think it may actually be a bug with Mono, but I didn't take it that far to confirm.
The problem lies with the default way of copying the response buffer. In the RestSharp code, this is done by an extension method in MiscExtensions.cs called ReadAsBytes. It appears that with certain response buffers, the call to the Stream.Read method is failing. When this happens, the exception causes RestSharp to "shortcut" the rest of the processing on the response, hence the status code never gets filled in since it happens after the call to ReadAsBytes.
The good news is RestSharp does give a way to replace this call to ReadAsBytes with one of your own. This is done via the ResponseWriter property on the IRestRequest object. If it has a function defined, it will bypass the ReadAsBytes call and call the function you gave it instead. The problem is, this is defined as an Action and you don't get a copy of the full response object, so it's somewhat useless. Instead you have to use the AdvancedResponseWriter property. This one includes both the response object and the response stream. But you still have to set the ResponseWriter property or it won't bypass the default handler and you'll still get the error.
Ok, so how do you make this work? I ended up implementing it as a wrapper to RestClient so I wouldn't have to implement the code all over the place. Here's the basic setup:
public class MyRestClient : RestClient
{
public MyRestClient(string baseUrl) : base(baseUrl)
{ }
public override IRestResponse Execute(IRestRequest request)
{
request.ResponseWriter = s => { };
request.AdvancedResponseWriter = (input, response) => response.RawBytes = ReadAsBytes(input);
return base.Execute(request);
}
private static byte[] ReadAsBytes(Stream input)
{
var buffer = new byte[16 * 1024];
using (var ms = new MemoryStream())
{
int read;
try
{
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{ ms.Write(buffer, 0, read); }
return ms.ToArray();
}
catch (WebException ex)
{ return Encoding.UTF8.GetBytes(ex.Message); }
};
}
}
The ReadAsBytes method is actually just a copy/paste of the RestSharp ReadAsBytes method with the addition of a try/catch. If it fails, it returns the exception reason in to the response buffer. This may or may not be what you want, so modify as needed. You may also need to override other methods for Execute, but in my case this is the only one we're using so it was enough.
So far this seems to be doing the trick for me. Perhaps if someone got ambitious they could trace it all the way in to Mono to try and see what it doesn't like about the stream, but I don't have the time for it at the moment.
Good luck!
OK so after toying around with RestSharp for a bit, i realize just as #steve_In_Co mentioned earlier there were compatibility issues with MONO (we presume this is a bug) so i did it in a basic way using the .Net HTTP library and it works for me, so in case someone is still looking for a way out, find the working .net http implementation code below.
//payload am sending to the api
RequestPayload res = new RequestPayload();
res.appid = appid;
res.data = data;
res.method = "Login";
//convert to json object
var MySerializedObject = JsonConvert.SerializeObject(res);
string APIUrl = ""http://142.168.20.15:8021/RouteTask";
//create basic .net http client
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(APIUrl);
// this was required in the header of my request,
// you may not need this, or you may need to adjust parameter
//("RequestSource","Web") or you own custom headers
client.DefaultRequestHeaders.Add("RequestSource", "Web");
// this class is custom, you can leave it out
connectionService = new ConnectionService();
//check for internet connection on users device before making the call
if (connectionService.IsConnected)
{
//make the call to the api
HttpResponseMessage response = await
client.PostAsJsonAsync(ApiConstants.APIDefault, res);
if (response.IsSuccessStatusCode)
{
string o = response.Content.ReadAsStringAsync().Result;
dynamic payload = JsonConvert.DeserializeObject(o);
string msg = payload["valMessage"];
resp.a = true;
resp.msg = payload["responseDescription"];
}
else
{
string o = response.Content.ReadAsStringAsync().Result;
dynamic payload = JsonConvert.DeserializeObject(o);
resp.a = false;
resp.msg = payload["response"];
}
}

unable to send json data in c#

I am sending my JSON string to this url http://myipaddress/WindowsApp/Registration?data=
I am using the following code which is as follows :
internal static async Task<String> getHttpResponse(HttpWebRequest request,string postData)
{
String received = null;
byte[] requestBody = Encoding.UTF8.GetBytes(postData);
using(var postStream=await request.GetRequestStreamAsync())
{
await postStream.WriteAsync(requestBody, 0, requestBody.Length);
}
try
{
var response = (HttpWebResponse)await request.GetResponseAsync();
if(response != null)
{
var reader = new StreamReader(response.GetResponseStream());
received = await reader.ReadToEndAsync();
}
}
catch(WebException ae)
{
var reader = new StreamReader(ae.Response.GetResponseStream());
string responseString = reader.ToString();
Debug.WriteLine("################ EXCEPTIONAL RESPONSE STRING ################");
Debug.WriteLine(responseString);
return responseString;
}
return received;
}
and I am calling this method when I click on one of my buttons in XAML as follows :
HttpWebRequest request = HttpWebRequest.Create(Classes.Constants.SERVER_URL) as HttpWebRequest;
request.Method = "POST";
request.ContentType = "application/json";
postData = JsonConvert.SerializeObject(user);
string receivedString = await getHttpResponse(request, postData);
Debug.WriteLine("############# RECEIVED STRING #############");
Debug.WriteLine(receivedString);
So, the problem I am facing is that I am unable to get the string on the server.
Note : I am able to get the json string when my server implements its method with a url : http://myipaddress/WindowsApp/Registration
(without parameter "?data=") and also sends me response string. But fails when the term "?data=" is implemented and used in the server url.
So what am I going wrong in my code? Please help.
So, from what I see in the code you posted, from client side perspective(since we don't see the server side code)you are sending a request to the server in the body of the request.
There are two ways to POST: one way in the body of the request, the other one in the query string.
Seems to me that you are mixing the two.
When you do a POST request to your server to the address without the ?data=
then you send the request in the body.
Solutions:
If you want to POST in the body of the request, POST to the address without the ?data= parameter in the query string
If you want to send it trough the query string, you need to add the value after the ?data=
something like:
http://myipaddress/WindowsApp/Registration?data=MyValue
If I have understood everything correctly, you are trying to send a POST request to the server and to get a response from the server?
The POST request methods documentation says, that POST request must be used to submit data, not to get a response.
Note that query strings (name/value pairs) is sent in the HTTP message body of a POST request like this:
POST /test/demo_form.asp HTTP/1.1
Host: w3schools.com
name1=value1&name2=value2
Your Url should be http://myipaddress/WindowsApp/Registration since you are posting your data in the payload.

How to get response data from RestSharp to download for user?

I am using RestSharp to call an HTTP service via a Querystring. The service generates a Word document.
When I call this service, it looks like a Word document is being returned in the "Content" property, but I struggling to work out how to return this content to the user via the traditional download window as a word document for saving.
public ActionResult DocGen(string strReportId)
{
var client = new RestClient("http://localhost:88");
var request = new RestRequest("DocGen/{id}", Method.GET);
request.AddUrlSegment("id", "1060"); // replaces matching token in request.Resource
// execute the request
//RestResponse response = (RestResponse) client.Execute(request);
IRestResponse response = client.Execute(request);
if (response.ErrorException != null)
{
const string message = "Error retrieving response. Check inner details for more info.";
var myException = new ApplicationException(message, response.ErrorException);
throw myException;
}
// Important and simple line. response.rawbytes was what I was missing.
return File(response.RawBytes,response.ContentType,"sample.doc");
}
Should this be an action?
The content type seems correct ie Word.11
So how do I code get this Response.Content back to the user?
Many thanks in advance.
EDIT
I was closer to the solution than I thought. Power to RestSharp I guess !! See above. Now there might be a better way, and I am all ears for any suggestions, but this is where I am at at present.
return File(response.RawBytes,response.ContentType,"sample.doc");
In case anyone may benefit.

Can't access Web of Trust (WoT) API w/ JSON.Net

I'm new to JSON & am using VS 2013/C#. Here's the code for the request & response. Pretty straightforward, no?
Request request = new Request();
//request.hosts = ListOfURLs();
request.hosts = "www.cnn.com/www.cisco.com/www.microsoft.com/";
request.callback = "process";
request.key = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
string output = JsonConvert.SerializeObject(request);
//string test = "hosts=www.cnn.com/www.cisco.com/www.microsoft.com/&callback=process&key=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
try
{
var httpWebRequest = (HttpWebRequest) WebRequest.Create("http://api.mywot.com/0.4/public_link_json2?);
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "POST";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
string json = output;
streamWriter.Write(json);
}
var httpResponse = (HttpWebResponse) httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var responseText = streamReader.ReadToEnd();
}
}
catch (WebException e)
{
MessageBox.Show(e.ToString());
}
//response = true.
//no response = false
return true;
}
When I run this, I get a 405 error indicating method not allowed.
It seems to me that there are at least two possible problems here: (1) The WoT API (www.mywot.com/wiki/API) requires a GET request w/ a body, & httpWebRequest doesn't allow a GET in the httpWebRequest.Method; or (2) the serialized string isn't serialized properly.
NOTE: In the following I've had to remove the leading "http://" since I don't have enough rep to post more than 2 links.
It should look like:
api.mywot.com/0.4/public_link_json2?hosts=www.cnn.com/www.cisco.com/www.microsoft.com/&callback=process&key=xxxxxxxxxxxxxx
but instead looks like:
api.mywot.com/0.4/public_link_json2?{"hosts":"www.cnn.com/www.cisco.com/www.microsoft.com/","callback":"process","key":"xxxxxxxxxxxxxxxxxxx"}.
If I browse to:api.mywot.com/0.4/public_link_json2?hosts=www.cnn.com/www.cisco.com/www.microsoft.com/&callback=process&key=xxxxxxxxxxxxxx; I get the expected response.
If I browse to: api.mywot.com/0.4/public_link_json2?{"hosts":"www.cnn.com/www.cisco.com/www.microsoft.com/","callback":"process","key":"xxxxxxxxxxxxxxxxxxx"}; I get a 403 denied error.
If I hardcode the request & send as a GET like below:
var httpWebRequest = (HttpWebRequest) WebRequest.Create("api.mywot.com/0.4/public_link_json2? + "test"); it also works as expected.
I'd appreciate any help w/ this & hope I've made the problem clear. Thx.
Looks to me like the problem is that you are sending JSON in the URL. According to the API doc that you referenced, the API is expecting regular URL encoded parameters (not JSON), and it will return JSON to you in the body of the response:
Requests
The API consists of a number of interfaces, all of which are called using normal HTTP GET requests to api.mywot.com and return a response in XML or JSON format if successful. HTTP status codes are used for returning error information and parameters are passed using standard URL conventions. The request format is as follows:
http://api.mywot.com/version/interface?param1=value1&param2=value2
You should not be serializing your request; you should be deserializing the response. All of your tests above bear this out.

Categories

Resources