C# HTTP post , how to post with List<XX> parameter? - c#

using (WebClient wc = new WebClient())
{
wc.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
string HtmlResult = wc.UploadString(url, "sign=fsadfasdf&charset=utf-8");
}
Server can get value of sign and charset.
But there is a third parameter LIST, which is a list of object (this object is an entity class).
How can I pass this parameter to the server?
I tried to use "sign=fsadfasdf&charset=hhh&list=" + Json(list) as postData (convert List to json string). But the server didn't get value of this list param.

I hate to post 1 line answers with links in them but this has been solved on here before ...
POSTing JsonObject With HttpClient From Web API
HttpClient class is designed to solve exactly this problem, i believe its found in the nuget package "Microsoft.AspNet.WebApi.Client", this should add the namespace "System.Net.Http" to your project.
It's also geared at being completely async which should be nicer to your server!
EDIT:
To post an array / collection you would do something like this ...
var myObject = (dynamic)new JsonObject();
myObject.List = new List<T>();
// add items to your list
httpClient.Post(
"",
new StringContent(
myObject.ToString(),
Encoding.UTF8,
"application/json"));

Related

What is the idiomatic way to make a get request using RestSharp?

I'm trying to make a GET request to a REST api which returns a JSON. This is what I have right now:
RestClient client = new RestClient(BASE_URL);
var request = new RestRequest(CONTROLLER_PATH);
var response = await client.GetAsync<MyDtoClass[]>(request);
When this code executes, response is an array of MyDtoClass but the fields in each element of the array are null. If instead, I run this code (I removed the generic):
RestClient client = new RestClient(BASE_URL);
var request = new RestRequest(CONTROLLER_PATH);
var response = await client.GetAsync(request);
then response is a string represintation of the JSON that BASE_URL + CONTROLLER_PATH returns (nothing is null).
What is the idiomatic way to make a request to this REST api and convert the response into an array of MyDtoClass. Also, if anyone has suggestions for a library you think is better then RestSharp, please share.
Thank you in advance.
The issue was that MyDtoClass had fields instead of properties.

UnityWebRequest POST not sending Body

As the title says, the code is as below. I have tried setting chunkedTransfer=false, Content-Type application/json, WWWForm, building the JSON object manually, and HttpClient. For Content-Type application/json, the API isn't even hit. For the rest, the body is an empty object. I have no idea what the issue is here looking through StackOverflow, YouTube, Unity documentation, and all the other resources.
As of this morning I am using Newtonsoft.Json to serialize the JSON body. I think the biggest issue right now is that when I set webRequest.SetRequestHeader("Content-Type", "application/json"); the API route doesn't even receive the request.
async Task<string> makeRequest()
{
string url = API_BASE + "/users";
Dictionary<string, string> body = new Dictionary<string, string>();
body.Add("username", username);
body.Add("password", password);
body.Add("email", email);
using (UnityWebRequest webRequest = UnityWebRequest.Post(url, JsonConvert.SerializeObject(body)))
{
await webRequest.SendWebRequest();
string result = Encoding.UTF8.GetString(webRequest.downloadHandler.data);
if (webRequest.result != UnityWebRequest.Result.Success)
{
JSONNode error = JSON.Parse(result);
registerAndLoginError.GetComponent<Text>().text = error["error"]["message"];
registerAndLoginError.SetActive(true);
return "";
}
}
BasicLogin();
return "";
}
So I had seen this solution elsewhere, but I continued ignoring it because it's hacky af and seems like something that should be addressed. However, I'm at the point of not caring right now.
Use UnityWebRequest.Put instead of UnityWebRequest.Post
Set webRequest.method = "POST";
Set webRequest.SetRequestHeader("Content-Type", "application/json");
This works, but it feels really bad and doesn't make any sense.
The builtin JsonUtility does NOT support Dictionary! It follows the same serialization rules as the Inspector, see Script Serialization.
=> The JsonUtility.ToJson(body) will just return "" or in best case "{}".
Try to rather create the JSON string "manually" like e.g.
var json = "{\"username\":\""+username+"\", \"password\":\""+password+"\", \"email\":\""+email+"\"}";
or use a different library like e.g. Newtonsoft .NET Json (available as Package via the PackageManager) which supports direct (de)serialization of collections and Dictionary.

POST json to another url

I've a problem as I need to send some json to a url. When I send all my json and token to the page.
Then there will be no content JSON value into the system.
I have checked up on whether there is some content and it is there, but it sends just do not like json values.
string apiKeyToken = model.reepaytoken; // TOKEN HERE.
string URLLink = APIClassPay.HelperPay.CreateCustomerURL;//URL to send it json to.
WebClient client = new WebClient();
//JSON coming here!
var JSONCustomer = APIClassPay.HelperPay.CreateCustomer(model.Brugernavn, model.Adresse, model.Byen, model.Postnr.ToString(), model.Mobil.ToString(), model.Fornavn, model.Efternavn);
client.Headers.Add("text/json", JSONCustomer);
client.Headers.Set("X-Auth-Token", apiKeyToken);
string reply = client.DownloadString(URLLink);
When I blow my json looks like this.
[HttpPost]
public ActionResult information(BuyMedlemskabViewModel model)
{
DataLinqDB db = new DataLinqDB();
var Pric = db.PriceValues.FirstOrDefault(i => i.id == model.HiddenIdMedlemskab);
if (Pric != null)
{
string _OrderValue = DateTime.Now.Year + Helper.Settings.PlanValue();
Session[HelperTextClass.HelperText.SessionName.OrderId] = _OrderValue;
Session[HelperTextClass.HelperText.SessionName.FakturaId] = model.HiddenIdMedlemskab;
Session[HelperTextClass.HelperText.SessionName.fornavn] = model.Fornavn;
Session[HelperTextClass.HelperText.SessionName.efternavn] = model.Efternavn;
Session[HelperTextClass.HelperText.SessionName.Adresse] = model.Adresse;
Session[HelperTextClass.HelperText.SessionName.Post] = model.Postnr;
Session[HelperTextClass.HelperText.SessionName.Byen] = model.Byen;
Session[HelperTextClass.HelperText.SessionName.Mobil] = model.Mobil;
string apiKeyToken = model.reepaytoken;.
string URLLink = APIClassPay.HelperPay.CreateCustomerURL;//URL to send it json to.
WebClient client = new WebClient();
//JSON coming here!
var JSONCustomer = APIClassPay.HelperPay.CreateCustomer(model.Brugernavn, model.Adresse, model.Byen, model.Postnr.ToString(), model.Mobil.ToString(), model.Fornavn, model.Efternavn);
client.Headers.Add("text/json", JSONCustomer);
client.Headers.Set("X-Auth-Token", apiKeyToken);
string reply = client.DownloadString(URLLink);
}
return RedirectToAction("information");
}
EDIT - Update (ERROR HERE):
ReePay API reference: https://docs.reepay.com/api/
I think there are a few things, you'll have to fix:
First of all you're obviously trying to create a ressource (usually a POST or PUT, speaking in REST-words but you're using WebClient's DownloadString-method which performs a GET. So I think you should probably use a POST or PUT instead but which one to chose exactly depends on the web service you're contacting.
Then you seem to have mistaken the Content-Type-header and tried to pack the payload in there. The payload - your customer JSON - will have to be put into the request's body.
Based on your previous questions I assume the service you're trying to contact is either PayPal or QuickPay. To further help you with this question, it'd be helpful if you could specify which one you use.
If it's QuickPay, please notice that there's an official .NET client which you could use instead of using WebClient on you own.
But anyway for making HTTP requests I'd suggest you to use HttpClient in favor of WebClient. You'd generally do it in a way like this:
using (var httpClient = new HttpClient())
{
var request = new HttpRequestMessage(HttpMethod.Post,
APIClassPay.HelperPay.CreateCustomerURL);
request.Headers.Add("X-Auth-Token", apiKeyToken);
request.Headers.Add("Content-Type", "application/json");
request.Content = new StringContent(JSONCustomer);
var response = await httpClient.SendAsync(request);
}
EDIT:
As you clarified in a comment, the service you're using is Reepay. If you take a look at the documentation of the create customer method, you can see, that the necessary HTTP method is POST. So the code snippet above should generally fit.
Regarding the compilation error you faced, I updated the code-snipped above. There was a mistake in the variable names I chose. Please note, that you dropped the keyword await as I can see from your screenshot. Please re-enter it. If the compiler complains about it, it's very likely that the .NET framework version of your project is less than 4.5 which is necessary to use async/await.
So you should update your project's .NET framework version at best to version 4.6.1 as Microsoft recently announced that support for 4.5 and others is discontinued. Have a look here on how to do that.

Post complex type formatted as form-url-encoded using ASP.Net HttpClient

I need to HTTP POST a complex type to a web service (which I don't controll). I believe the web service was built using an older version of ASP.NET MVC. It model binds payloads formatted as form-url-encoded.
If I fire the following at it, it works perfectly. As you can see, I've manually created a collection of key/value pairs.
var values = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("Username", "some-username"),
new KeyValuePair<string, string>("Password", "some-password"),
new KeyValuePair<string, string>("Product", "some-product")
};
var content = new FormUrlEncodedContent(values);
var response = new HttpClient().PostAsync(url, content).Result;
But I don't want to have to do this, I just want to send complex types if I can.
var content = new ComplexType("some-username", "some-password", "some-product");
var response = new HttpClient().PostAsync(url, content).Result;
I believe there used to be a HttpRequestMessage<T> but that's been dropped in favour of
HttpClient.PostAsJsonAsync<T>(T value) sends “application/json”
HttpClient.PostAsXmlAsync<T>(T value) sends “application/xml”
But I don't want to send Json or XML I want to send form-url-ecncoded without the hassle of converting complex types to collections of key/value pairs.
Essentially I'd also like to know the answer to this question that Jaans poses (His is the second comment to the second answer).
Can anyone advise please.
Flurl [disclosure: I'm the author] provides a method that seems to be exactly what you're looking for:
using Flurl.Http;
var resp = await url.PostUrlEncodedAsync(new {
Username = "some-username",
Password = "some-password",
Product = "some-product",
});
Flurl is small and portable, and uses HttpClient under the hood. It is available via NuGet:
PM> Install-Package Flurl.Http
Since you've almost got a solution that does work, I'd say just go with it. Organize your code inside an extension method so that you can post using that, something like:
public static async Task<HttpResponseMessage> PostAsFormUrlEncodedAsync<T>(
this HttpClient httpClient, T value)
{
// Implementation
}
Your implementation just needs to serialize your object into form-encoded values, which you should be able to do easily with reflection.
Then you can call the code exactly as you would for JSON or XML.
You can do this:
var content = new ComplexType("some-username", "some-password", "some-product");
var response = new HttpClient().PostAsync<ComplexType>(url, content, new FormUrlEncodedMediaTypeFormatter()).Result;

Consuming web services in C#

I just started playing around with some API's in C#. In my form I had added a service reference http://wsf.cdyne.com/WeatherWS/Weather.asmx. Everything works great and I am able to utilize its library. Now I am trying to use for example http://free.worldweatheronline.com/feed/apiusage.ashx?key=(key goes in here)&format=xml. [I have a key] Now when I try to use it as service reference I am not able to use.
Do I have to call it in my form instead of referencing it? or do some sort of conversion? Also does it matter if its xml or json type?
ASMX is old technology and uses SOAP under the hood. SOAP doesn't tend to work with query string parameters, it takes parameters as part of the message.
ASHX is something different (it could be anything, it's one way to write a raw HTML/XML page in .NET), so you can't transfer the method for calling one to the other. It also won't have a service reference, it's likely you request it via a raw HTTP request. You'll need to consuly the service documentation to discover how to use it.
worldweatheronline doesn't return a SOAP-XML that is consumable by a WebService client. Therefore you should download the response and parse it as done with many REST services.
string url = "http://free.worldweatheronline.com/feed/apiusage.ashx?key=" + apikey;
using (WebClient wc = new WebClient())
{
string xml = wc.DownloadString(url);
var xDoc = XDocument.Parse(xml);
var result = xDoc.Descendants("usage")
.Select(u => new
{
Date = u.Element("date").Value,
DailyRequest = u.Element("daily_request").Value,
RequestPerHour = u.Element("request_per_hour").Value,
})
.ToList();
}
Also does it matter if its xml or json type?
No, at the end you have to parse the response by yourself.
string url = "http://free.worldweatheronline.com/feed/apiusage.ashx?format=json&key=" + apikey;
using (WebClient wc = new WebClient())
{
string json = wc.DownloadString(url);
dynamic dynObj = JsonConvert.DeserializeObject(json);
var jArr = (JArray)dynObj.data.api_usage[0].usage;
var result = jArr.Select(u => new
{
Date = (string)u["date"],
DailyRequest = (string)u["daily_request"],
RequestPerHour = (string)u["request_per_hour"]
})
.ToList();
}
PS: I used Json.Net to parse the json string

Categories

Resources