I need to pass one of parameters to HttpRequest (POST).
Lets say we have 'someParam' parameter and we need to pass 'some+value' value.
When using request.AddParameter("someParam", "some+value"); - value is automatically converted to 'some%2Bvalue' and in request it looks like 'someparam=some%2Bvalue'. But the application only understands +.
Is there any way how to add parameter to request but don't encode it???
On server side should be 'some%2Bvalue' decoded to "some+value". If it is not, better solution for you is to separate values to:
request.AddParameter("someParam", "some");
request.AddParameter("someParamValue", "value");
And on server side just parse parameters to some+value as you wanted.
Another workaround would be to replace string "%2" with "+". But still it is better approach to separate values.
Possible workaround for GET:
string resource = "something";
var client = new RestClient(baseurl+ resource +"?"+"someParam"+"="+"some+value");
var request = new RestRequest(resource, method);
IRestResponse<T> response = client.Execute<T>(request);
return response.Data;
So you have to compose url by yourself and provide it whole to request.
You can use:
System.Web.HttpUtility.UrlDecode
for example:
var url = getUrlFromConfig();
var params = HttpUtility.UrlDecode("$foo/bar?someParam={some}&someParamValue={value}");
var client = new RestClient(apiUrl + params);
This will generate a valid url without your problem.
Related
I'm building a http request in my c# client and and want to append an If-Match header. To get that If-Match header, I'm using this object which comes from System.Net:
var headerkey = HttpRequestHeader.IfMatch.ToString();
I would expect calling toString on this to output: If-Match however, instead I'm getting IfMatch which is not a valid http header. Is there a way I can get the correct value without hardcoding a string in my code that looks like this:
const string ifMatch = "If-Match";
You can use the code below, and it will generate the headers that you need based on those enums, instead of performing a ToString on an enum
var request = (HttpWebRequest)WebRequest.Create("http://www.google.com");
var headers = request.Headers;
headers.Add(HttpRequestHeader.IfMatch, "NameHere")
I am struggling with Rest call. Here is my code and it is working for basic authentication.
public async Task RunAsync(string name, string value)
{
using (var handler = new HttpClientHandler { UseDefaultCredentials = true })
using (var client = new HttpClient(handler))
{
var byteArray = Encoding.ASCII.GetBytes("username:password");
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
var urlRestGet = HomeController.url;
client.BaseAddress = new Uri(urlRestGet + "?name=" + name + "&value=" + value + "");
client.DefaultRequestHeaders.Accept.Clear();
**1. if(HomeController.contentType.ToLower()=="xml"){
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));
}**
else if (HomeController.contentType.ToLower() == "json")
{
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
}
HttpResponseMessage response = await client.GetAsync(urlRestGet + "?name=" + name + "&value=" + value + "");
if (response.IsSuccessStatusCode)
{
//Get the response
loginJsonString = await response.Content.ReadAsStringAsync();
//Converting to xml
using (var stream = new MemoryStream(Encoding.ASCII.GetBytes(loginJsonString)))
{
var output = new XmlDictionaryReaderQuotas();
xmlResult = XDocument.Load(JsonReaderWriterFactory.CreateJsonReader(stream, output)).ToString();
}
}
}
}
1) If the content type is application/xml am I correct to use line 1 part in the code.
2) How can I make this code more generic. (when the authentication type is different eg: tokenized or cookiebased how can I change this.)
There are a couple of things about your code I do not understand.
What is HomeController.contentType all about? The name "HomeController" suggests you're writing an ASP.NET MVC Controller (serverside). Though you seem to be writing something intended to be used as a HTTP client. But I could be mistaken or mislead here.
You are reading a Json response, then loading it as a Xml document?
I'll try to answer anyway.
1) If the content type is application/xml am I correct to use line 1 part in the code.
The Accept header sent by the client (you) tells the server that you accept the given content type. If you send Accept application/xml you tell the server you prefer if the response is Xml.
Your code seem to assume the response's content type is always Json.
You could include both application/xml and application/json as Accept headers in your request. The server should honor that request and pick the first supported content type for it's response.
When processing the response you should check the actual content type and handle the response content appropriately.
Remember that Accept only tells the server that you prefer those content types. The server may decide not to honor your whishes and can return any content type it desires.
2) How can I make this code more generic. (when the authentication type is different eg: tokenized or cookiebased how can I change this.)
If you mean tokenized as in a query parameter you should probably handle your query parameters as a collection rather than a hardcoded formatted string.
Check out the NameValueCollection class and this SO question on NameValueCollection to query string.
To handle cookies, you basically need to copy/re-use the cookie collection returned in a response in the next request.
See this SO question on how to inject cookies when you create a new HttpClient.
... but it's much easier to use a library
As you already discovered, making a robust REST/HTTP client is not a easy task.
And as #Mafii and #Fildor already pointed out in comments there are already numerous libraries available. RestSharp (https://restsharp.org) being one very popular.
I need to be able to append an encoded object to a URI to pass it to a Web API endpoint.
In this post, the author is creating an object:
var request = new Object();
request.SearchWindowStart = start.toISOString();
request.SearchWindowEnd = end.toISOString();
request.ServiceId = "5f3b6e7f-48c0-e511-80d7-d89d67631c44";
request.Direction = '0';
request.NumberOfResults = 10;
request.UserTimeZoneCode = 1;
Then they are appending it to a URL:
var req = new XMLHttpRequest()
req.open("GET", clientUrl + "/api/data/v8.0/Search(AppointmentRequest=#request)?#request=" + JSON.stringify(request) , true);
I actually cannot modify the C sharp code however I have two options. The first option is to add the parameters into the URL I actually cannot modify the c# code however I have two options. The first option is to add the parameters into the URL and the other option would be to add a body to the request with my intended object.
If I know the structure of the object ahead of time how do I include it with my request?
You can do it in a two ways.
Just add every propery of the object with the value to the url eg. /search?property1=value1&property2=value2
Of course each value should be url encoded.
Serialize the whole object into json and send it via post or get. Look at the https://www.newtonsoft.com/json how to do it. Sending request could be done by simple WebClient class.
Based on the code snippet you need to serialize the object to JSON. You can use Json.Net as already linked in the other answer.
Using OP as an example...
var request = new {
SearchWindowStart = "some_start_value",
SearchWindowEnd = "some_end_value",
ServiceId = "5f3b6e7f-48c0-e511-80d7-d89d67631c44",
Direction = '0',
NumberOfResults = 10,
UserTimeZoneCode = 1
};
//JSON.stringify(request)
var json = JsonConvert.SerializeObject(request);
var url = clientUrl + "/api/data/v8.0/Search(AppointmentRequest=#request)?#request=" + json;
From there you should be able to use the URL as desired.
let encodedObj = encodeURIComponent(JSON.stringify(yourObject))
Then you could just.
req.open("GET", clientUrl +
"/api/data/v8.0/Search(AppointmentRequest=#request)?#request=" + encodedObj, true);
Although according to: https://javascript.info/url
The encode functions are based on the obsolete version RFC2396, and advises you to use these classes instead:
URL and URLSearchParams to build a URL.
I am building a small Web API for syncing data and pulling down the objects works great, but pushing my objects up doesn't work no matter what I have tried.
Edited to reflect some changes:
Here is my Controller:
[System.Web.Mvc.HttpPost]
public void UpdateTasks([FromBody] string s)
{
Console.WriteLine(s);
}
Here is my Client code:
HttpContent c = new StringContent("1234");
HttpClient client = new HttpClient();
c.Headers.ContentType = new MediaTypeHeaderValue("application/json");
client.BaseAddress = new Uri("http://localhost/QAQC_SyncWebService/Tasks/UpdateTasks/");
var resp = client.PostAsync(client.BaseAddress, c).Result;
I can get a value though if I put it in the URI, but the string content alone doesn't seem to work.
Try
[HttpPut]
public void UpdateTasks([FromBody]string s)
{
Console.WriteLine(s);
}
Please also note:
[FromBody] parameters must be encoded as =value
The final hurdle remaining is that Web API requires you to pass [FromBody] parameters in a particular format. That’s the reason why our value parameter was null in the previous example even after we decorated the method’s parameter with [FromBody].
Instead of the fairly standard key=value encoding that most client- and server-side frameworks expect, Web API’s model binder expects to find the [FromBody] values in the POST body without a key name at all. In other words, instead of key=value, it’s looking for =value.
This part is, by far, the most confusing part of sending primitive types into a Web API POST method. Not too bad once you understand it, but terribly unintuitive and not discoverable.
from http://encosia.com/using-jquery-to-post-frombody-parameters-to-web-api/
The line you are initializing client.BaseAddress looks a bit off.
HttpContent c = new StringContent("1234");
HttpClient client = new HttpClient();
c.Headers.ContentType = new MediaTypeHeaderValue("application/json");
client.BaseAddress = new Uri("http://localhost/QAQC_SyncWebService/Tasks/UpdateTasks");
var resp = client.PutAsync(client.BaseAddress, c).Result;
The PutAsync method is expecting the full URI, not just a method. Read more here: https://msdn.microsoft.com/en-us/library/hh138168(v=vs.118).aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-1
I'm building a simple server that uses HttpListener to process requests. The query string parameters I send to it are url encoded if necessary. For example, to send the Kanji string "尺八", the encoding is "%E5%B0%BA%E5%85%AB".
My sample url, then is "/?q=%E5%B0%BA%E5%85%AB".
In my context callback, I have:
HttpListenerContext context = Listener.EndGetContext();
string rawUrl = context.Request.RawUrl;
string query = context.Request.QueryString["q"];
Checking the results, I get:
rawUrl = "/?q=%E5%B0%BA%E5%85%AB"
query = "尺八"
But if I look at context.Request.Url, I get {http://localhost:8080/?q=尺八}.
It looks like the query string in context.Request.QueryString is being decoded using some encoding other than UTF-8.
My workaround is to ignore context.Request.QueryString and create my own by doing this:
var queryString = HttpUtility.ParseQueryString(context.Request.Url.Query);
That gives me the correct value, but it seems like something of a hack.
Is there any way to tell the HttpListener (or the context, or the request) to interpret the query string as UTF-8, which I think is the standard anyway? Or should I just live with this workaround?
By looking at the code, it relies on ContentEncoding being set to UTF8. Here is the snipit from the QueryString property of HttpListenerRequest:
public NameValueCollection QueryString
{
get
{
NameValueCollection nvc = new NameValueCollection();
Helpers.FillFromString(nvc, this.Url.Query, true, this.ContentEncoding);
return nvc;
}
}
Since there is no way to modify the ContentEncoding property your stuck with your 'hack'. Anyway, I think your use of HttpUtility.ParseQueryString is likely going to serve you the best.
Try System.Web.HttpUtility
string query = "d=bla bla bla";
string encoded = System.Web.HttpUtility.UrlEncode( query, System.Text.Encoding.UTF8 );
Learn more https://msdn.microsoft.com/en-us/library/system.web.httputility(v=vs.110).aspx