Accessing query string variables sent as POST in HttpActionContext - c#

I'm trying to access a query string parameter that was sent using the POST method (WebClient) to the Web API in ASP.NET MVC 5 (in an overridden AuthorizationFilterAttribute).
For Get, I've used the following trick:
var param= actionContext.Request.GetQueryNameValuePairs().SingleOrDefault(x => x.Key.Equals("param")).Value;
However, once I use POST, this does work and the variable paran is set to null. I think that's because the query string method only applies to the url, not the body. Is there any way to get the query string (using one method preferably) for both GET and POST requests?
EDIT: WebClient Code
using (WebClient client = new WebClient())
{
NameValueCollection reqparm = new NameValueCollection();
reqparm.Add("param", param);
byte[] responsebytes = client.UploadValues("https://localhost:44300/api/method/", "POST", reqparm);
string responsebody = Encoding.UTF8.GetString(responsebytes);
return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(responsebody);
}
}

Using the code you show, you upload the param=value in the request body using the application/x-www-form-urlencoded content-type.
If you also want to utilize the query string, you need to set it separately using the WebClient.QueryString property:
// Query string parameters
NameValueCollection queryStringParameters = new NameValueCollection();
queryStringParameters.Add("someOtherParam", "foo");
client.QueryString = queryStringParameters;
// Request body parameters
NameValueCollection requestParameters = new NameValueCollection();
requestParameters.Add("param", param);
client.UploadValues(uri, method, requestParameters);
This will make the request go to uri?someOtherParam=foo, enabling you to read the query string parameters serverside through actionContext.Request.GetQueryNameValuePairs().

Related

How to make HttpClient.PostAsync work the same way as post from Postman?

When I post to my API (written in .NET core and hosted on Linux) from Postman, everything works as expected. When I do the same from code (using HttpClient), the parameters do not get sent. Below my code:
var content = new FormUrlEncodedContent(new []
{
new KeyValuePair<string, string>(nameof(userName), userName),
new KeyValuePair<string, string>(nameof(serialNumber), serialNumber)
});
var result = await _httpClient.PostAsync(_uri, content).ConfigureAwait(false);
var json = await result.Content.ReadAsStringAsync().ConfigureAwait(false);
return JsonConvert.DeserializeObject<Response>(json);
In my opinion content should get sent and everything should be alright. I see significant differences between the calls in Wireshark.
Working POST from Postman:
POST from HttpClient that does not work:
.
What can I do to make sure that my HttpClient.PostAsync sends the data correctly?
The Postman version doesn't have a body, but it has userName and serialNumber encoded into the url as query parameters.
In order to achieve the same using HttpClient, you need to add those parameters to the url.
var uriBuilder = new UriBuilder(_uri);
// If you already have query parameters, this code will preserve them.
// Otherwise you can just create a new NameValueCollection instance.
var parameters = HttpUtility.ParseQueryString(uriBuilder.Query);
parameters[nameof(userName)] = userName;
parameters[nameof(serialNumber)] = serialNumber;
uriBuilder.Query = parameters.ToString();
// Pass null as HttpContent to make HttpClient send an empty body
var result = await _httpClient.PostAsync(uriBuilder.ToString(), null).ConfigureAwait(false);

How to use sended post data on server side

I have a simple script to upload a file. Actually everything is working fine.
private void UploadCSV()
{
Uri address = new Uri("https://www.mydomain.xy/inc.upload.php");
string fileName = #"C:\test.csv";
using (WebClient client = new WebClient())
{
var parameters = new NameValueCollection();
parameters.Add("test", "aaaa");
client.QueryString = parameters;
client.UploadProgressChanged += WebClientUploadProgressChanged;
client.UploadFileCompleted += WebClientUploadCompleted;
client.UploadFileAsync(address, "POST", fileName);
}
}
Now as you can see, I try so send some data via POST test what contains aaaa. But now matter how I try to select the data serverside... there is nothing....
I tried $_POST['test'], $_POST['data']['test'].... but no results.
How can I access the extra Data ?
client.QueryString = parameters;
This will append a query string to the URL that you send the data to.
Even though the request method is POST, PHP always provides the query string parameters in $_GET.

Get raw querystring of WebClient in C#

I'm using a WebClient to make a POST request with a query string but I can't see the raw string. This is what I have:
WebClient TheWebClient = new WebClient();
TheWebClient.QueryString.Add("Param1", "1234");
TheWebClient.QueryString.Add("Param2", "4567");
TheWebClient.QueryString.Add("Param3", "4539");
var TheResponse = TheWebClient.UploadValues("https://www.example.com/posturl", "POST", TheWebClient.QueryString);
string TheResponseString = TheWebClient.Encoding.GetString(TheResponse);
//problem is that this only shows the keys
var RawQueryString = TheWebClient.QueryString;
How can I see the actual raw query string?
WebClient.UploadValues doesn't save the request "raw query string" simply because you provided it with them, and it's not gonna change, thus is redundant.
Furthermore, HttpPost requests doesn't use query string for the request payload, it has a url, a message payload; which is appended after the headers, maybe query string. Thus there is nothing new the client class should let you know, so it won't save it.

How to send multiple parameters to a Web API call using WebClient

I want to send via POST request two parameters to a Web API service. I am currently receiving 404 not found when I try in the following way, as from msdn:
public static void PostString (string address)
{
string data = "param1 = 5 param2 = " + json;
string method = "POST";
WebClient client = new WebClient ();
string reply = client.UploadString (address, method, data);
Console.WriteLine (reply);
}
where json is a json representation of an object. This did not worked, I have tried with query parameters as in this post but the same 404 not found was returned.
Can somebody provide me an example of WebClient which sends two parameters to a POST request?
Note: I am trying to avoid wrapping both parameters in the same class only to send to the service (as I found the suggestion here)
I would suggest sending your parameters as a NameValueCollection.
Your code would look something like this when sending the parameters with a NameValueCollection:
using(WebClient client = new WebClient())
{
NameValueCollection requestParameters = new NameValueCollection();
requestParameters.Add("param1", "5");
requestParameters.Add("param2", json);
byte[] response = client.UploadValues("your url here", requestParameters);
string responseBody = Encoding.UTF8.GetString(response);
}
Using UploadValues will make it easier for you, since the framework will construct the body of the request and you won't have to worry about concatenating parameters or escaping characters.
I have managed to send both a json object and a simple value parameter by sending the simple parameter in the address link and the json as body data:
public static void PostString (string address)
{
string method = "POST";
WebClient client = new WebClient ();
string reply = client.UploadString (address + param1, method, json);
Console.WriteLine (reply);
}
Where address needs to expect the value parameter.

How do I get posted data in MVC Action?

I am trying to post some data to a ASP.NET MVC Controller Action. Current I am trying to use WebClient.UploadData() to post several parameters to my action.
The following will hit the action but all the parameters are null. How can get the posted data from the http request?
string postFormat = "hwid={0}&label={1}&interchange={2}localization={3}";
var hwid = interchangeDocument.DocumentKey.Hwid;
var interchange = HttpUtility.UrlEncode(sw.ToString());
var label = ConfigurationManager.AppSettings["PreviewLabel"];
var localization = interchangeDocument.DocumentKey.Localization.ToString();
string postData = string.Format(postFormat, hwid, interchange, label, localization);
using(WebClient client = new WebClient())
{
client.Encoding = Encoding.UTF8;
client.Credentials = CredentialCache.DefaultNetworkCredentials;
byte[] postArray = Encoding.ASCII.GetBytes(postData);
client.Headers.Add("Content-Type", "pplication/x-www-form-urlencoded");
byte[] reponseArray = client.UploadData("http://localhost:6355/SymptomTopics/BuildPreview",postArray);
var result = Encoding.ASCII.GetString(reponseArray);
return result;
}
Here is the Action I am calling
public ActionResult
BuildPreview(string hwid, string
label, string interchange, string
localization) {
... }
When this Action is reached all the parameters are null.
I have tried using the WebClient.UploadValue() and passing the data as a NameValueCollection. This method always returns a status of 500 and because I am making this http request from within the MVC application I cannot find a way to bebug this.
Any help getting this resolved would be super helpful.
-Nick
I corrected the Header to read:
client.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
Now UploadData just errors immediately with with server error 500.
Just for laughs have a look in Request.Form and the RouteData in your controller to see if something ended up there.
I was able to get the post xml data from the Request objects InputStream property.
public ActionResult BuildPreview(string hwid, string label, string localization)
{
StreamReader streamReader = new StreamReader(Request.InputStream);
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.LoadXml(streamReader.ReadToEnd());
...
}
As a stop-gap measure, you can always change your controller action to accept a FormCollection parameter and then reach in and access the form parameters by name directly.
To get the raw posted bytes from WebClient.UploadData("http://somewhere/BuildPreview", bytes)
public ActionResult BuildPreview()
{
byte[] b;
using (MemoryStream ms = new MemoryStream())
{
Request.InputStream.CopyTo(ms);
b = ms.ToArray();
}
...
}

Categories

Resources