I am struggling to successfully implement a POST operation within Windows Phone 8.1.
PostMessage method executes without any exceptions being caught.
However, the POST method within MessagesController never gets invoked.
How do I perform a POST for Windows Phone 8.1?
The code is below:
internal async Task PostMessage(string text)
{
Globals.MemberId = 1;
int memberId = 2;
// server to POST to
string url = #"http://localhost:17634/api/messages";
try
{
// HTTP web request
var httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
httpWebRequest.ContentType = "text/plain; charset=utf-8";
httpWebRequest.Method = "POST";
// Write the request Asynchronously
using (var stream = await Task.Factory.FromAsync<Stream>(httpWebRequest.BeginGetRequestStream,
httpWebRequest.EndGetRequestStream, null))
{
//create some json string
var message = new Message() { FromId = Globals.MemberId, ToId = memberId, Content = text, Timestamp = DateTime.Now };
var json = string.Format("{0}{1}", "action=", JsonConvert.SerializeObject(message));
// convert json to byte array
byte[] jsonAsBytes = Encoding.UTF8.GetBytes(json);
// Write the bytes to the stream
await stream.WriteAsync(jsonAsBytes, 0, jsonAsBytes.Length);
}
}
catch(Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
public class MessagesController : ApiController
{
public HttpResponseMessage Post(Message message)
{
throw new NotImplementedException();
}
}
public class Message
{
public int MessageId { get; set; }
public int FromId { get; set; }
public int ToId { get; set; }
public DateTime Timestamp { get; set; }
public string Content { get; set; }
}
The following link resolved my issue.
The updated client is as follows:
using (var client = new System.Net.Http.HttpClient())
{
// New code:
client.BaseAddress = new Uri(Globals.URL_PREFIX);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var message = new Message() { MessageId = 0, FromId = Globals.MemberId, ToId = memberId, Content = text, Timestamp = DateTime.Now };
var json_object = JsonConvert.SerializeObject(message);
var response = await client.PostAsync("api/messages", new StringContent(json_object.ToString(), Encoding.UTF8, "application/json"));
Debug.Assert(response.StatusCode == System.Net.HttpStatusCode.Accepted);
}
This works fine for me. The function accepts an payload of type T. The server accepts a JSON object and returns a JSON response.
public async static Task SendRequestPacket<T>(object payload)
{
Uri theUri = new Uri("the_uri");
//Create an Http client and set the headers we want
HttpClient aClient = new HttpClient();
aClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
aClient.DefaultRequestHeaders.Host = theUri.Host;
//Create a Json Serializer for our type
DataContractJsonSerializer jsonSer = new DataContractJsonSerializer(typeof(T));
// use the serializer to write the object to a MemoryStream
MemoryStream ms = new MemoryStream();
jsonSer.WriteObject(ms, payload);
ms.Position = 0;
//use a Stream reader to construct the StringContent (Json)
StreamReader sr = new StreamReader(ms);
StringContent theContent = new StringContent(sr.ReadToEnd(), Encoding.UTF8, "application/json");
//Post the data
HttpResponseMessage aResponse = await aClient.PostAsync(theUri, theContent);
if (aResponse.IsSuccessStatusCode)
{
string content = await aResponse.Content.ReadAsStringAsync();
System.Diagnostics.Debug.WriteLine(content);
}
else
{
// show the response status code
}
}
Just dont use HttpWebRequest if you are not forced to in any way.
This example is using HttpClient() and it is good to always have the client created once and not every time you make a request.
So in your class add:
private static HttpClient _client;
public static Uri ServerBaseUri
{
get { return new Uri("http://localhost:17634/api"); }
}
public ClassConstructor()
{
_client = new HttpClient();
}
internal async Task<ResponseType> PostMessage(string text)
{
Globals.MemberId = 1;
int memberId = 2;
try
{
var js = "{ JSON_OBJECT }";
var json = new StringContent(js);
json.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
var response = await Client.PostAsync(new Uri(ServerBaseUri, "/messages"), json);
var reply = await response.Content.ReadAsStringAsync();
} catch (Exception)
{
return null;
}
}
More on HttpClient.
Related
return await request.Content.ReadAsStringAsync();
This line of code returns me a response from API which is fine but I want a specific object only, how can i do that
using (var _client = new HttpClient())
{
try
{
var gettokenasyn = await GetTokenAsync();
//_client.DefaultRequestHeaders.Clear();
//_client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(gettokenasyn);
_client.DefaultRequestHeaders.Add("token", gettokenasyn);
var body = new StringContent(JsonConvert
.SerializeObject(payproModels), Encoding.UTF8, "application/json");
var request = await _client.PostAsync(endPointForOrder, body);
return await request.Content.ReadAsStringAsync();
}
catch (Exception exp)
{
return exp.Message;
}
}
You can parse the json string to a JsonDocument and then access the json properties.
Let's say you have this sample json response and you want to take the speed value:
{
"speed": 4,
"deg": 95,
"gust": 3.27
}
Then you can do:
var response = await _client.PostAsync(endPointForOrder, body);
var stream = await response.Content.ReadAsStreamAsync();
using (var jsonDocument = await JsonDocument.ParseAsync(stream))
{
JsonElement speed = jsonDocument.RootElement.GetProperty("speed");
return speed.GetDouble();
}
Alternative you can create a class and deserialize the json to an instance of that class:
public class Wind
{
public double Speed { get; set; }
public int Deg { get; set; }
public double Gust { get; set; }
}
.
var response = await _client.PostAsync(endPointForOrder, body);
var stream = await response.Content.ReadAsStreamAsync();
var wind = await JsonSerializer.DeserializeAsync<Wind>(stream);
return wind.Speed;
You also need to import System.Text.Json namespace:
using System.Text.Json;
https://learn.microsoft.com/en-us/dotnet/api/system.text.json?view=net-6.0
I have a windows phone 8 app and I'm trying to do Google Auth.
I get to the sign-in page and after signing in it takes me to the consent page.
After Clicking on Allow access, I am not getting the access token and refresh token in response.
Response that I am getting is as below:
{
"error" : "invalid_request",
"error_description" : "Missing header: Content-Type"
}
StatusCode is Bad Request.
Here is my Code:
private void webBrowserGooglePlusLogin_Navigating(object sender, NavigatingEventArgs e)
{
if (e.Uri.Host.Equals("localhost"))
{
webBrowserGooglePlusLogin.Visibility = Visibility.Collapsed;
e.Cancel = true;
int pos = e.Uri.Query.IndexOf("=");
code = pos > -1 ? e.Uri.Query.Substring(pos + 1) : null;
}
if (string.IsNullOrEmpty(code))
{
// OnAuthenticationFailed();
}
else
{
var request = new RestRequest(this.TokenEndPoint, Method.POST);
request.AddParameter("code", code);
request.AddParameter("client_id", this.ClientId);
request.AddParameter("client_secret", this.Secret);
request.AddParameter("redirect_uri", "http://localhost");
request.AddParameter("grant_type", "authorization_code");
//request.AddHeader("Content-type", "json");
client.ExecuteAsync<AuthResult>(request, GetAccessToken);
}
}
void GetAccessToken(IRestResponse<AuthResult> response)
{
if (response == null || response.StatusCode != HttpStatusCode.OK
|| response.Data == null || string.IsNullOrEmpty(response.Data.access_token))
{
// OnAuthenticationFailed();
}
else
{
}
}
Any help is appreciated.
The content type needs to be set
request.ContentType = "application/x-www-form-urlencoded";
This is my .net sample not sure if it all works on windows-phone but it might help
class TokenResponse
{
public string access_token { get; set; }
public string token_type { get; set; }
public string expires_in { get; set; }
public string refresh_token { get; set; }
}
/// <summary>
/// exchanges the authetncation code for the refreshtoken and access token
/// </summary>
/// <param name="code"></param>
/// <returns></returns>
public static string exchangeCode(string code)
{
string url = "https://accounts.google.com/o/oauth2/token";
string postData = string.Format("code={0}&client_id={1}&client_secret={2}&redirect_uri=urn:ietf:wg:oauth:2.0:oob&grant_type=authorization_code", code, Properties.Resources.clientId, Properties.Resources.secret);
// Create a request using a URL that can receive a post.
WebRequest request = WebRequest.Create(url);
// Set the Method property of the request to POST.
request.Method = "POST";
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
// Set the ContentType property of the WebRequest.
request.ContentType = "application/x-www-form-urlencoded";
// Set the ContentLength property of the WebRequest.
request.ContentLength = byteArray.Length;
// Get the request stream.
Stream dataStream = request.GetRequestStream();
// Write the data to the request stream.
dataStream.Write(byteArray, 0, byteArray.Length);
// Close the Stream object.
dataStream.Close();
// Get the response.
WebResponse response = request.GetResponse();
// Display the status.
Console.WriteLine(((HttpWebResponse)response).StatusDescription);
// Get the stream containing content returned by the server.
dataStream = response.GetResponseStream();
// Open the stream using a StreamReader for easy access.
StreamReader reader = new StreamReader(dataStream);
// Read the content.
string responseFromServer = reader.ReadToEnd();
TokenResponse tmp = JsonConvert.DeserializeObject<TokenResponse>(responseFromServer);
// Display the content.
Console.WriteLine(responseFromServer);
// Clean up the streams.
reader.Close();
dataStream.Close();
response.Close();
return tmp.refresh_token;
}
Oauth simple
I am trying to POST some JSON data to a remote server and read JSON response back from the remote server. My code is jumping in to the catch exception block with the error ex = {"The remote server returned an error: (500) Internal Server Error."} when it gets to this line near the bottom:
var httpResponse = (HttpWebResponse)request.GetResponse();
I have read a few posts on this forum and tried the code other suggest but I don't understand/can't get it to work.
Please can you help me understand what I am doing wrong? You can see my previous attempt which is commented out near the bottom of the code block.
using System;
using System.Text;
using System.Net;
// include
using System.IO;
using System.Web.UI.WebControls;
using HobbsDPDJSONLibrary;
using System.Web;
using Newtonsoft.Json;
namespace DPDAPILibrary
{
public class DPD_API
{
#region public class variables
private static string dpdapiun = "xxx";
private static string dpdapipw = "xxx";
private static string dpdAccountNumber = "xxx";
private static string dpdapihost = "api.dpd.co.uk";
private static string dpdapiinserttestshipment = "https://api.dpd.co.uk/shipping/shipment?test=true";
private static string dpdapiinsertshipment = "https://api.dpd.co.uk/shipping/shipment";
#endregion
/// <summary>
/// Send consignment data to the DPD API to create a shipment and return a consignment number (if successful).
/// </summary>
/// <param name="geoClientData"></param>
/// <param name="JSONData"></param>
/// <returns></returns>
public Boolean insertShipment(string geoSession, bool test, out string JSONdata)
{
try
{
// default output values
JSONdata = "";
bool returnValue = false;
#region create new insert shipment object
// a large block of code here that serialises a class into JSON, this bit works so I have omitted it to reduce the code I post on the forum
#endregion
string InsertShipmentData = JsonConvert.SerializeObject(NewShipmentObject);
// convert the 'insert shipment' JSON data to byte array for posting
//byte[] postBytes = Encoding.UTF8.GetBytes(InsertShipmentData);
// set the target uri for the insert shipment request (defaults to test, or switch to live as per input parameter)
Uri targetURI = new Uri(dpdapiinserttestshipment);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(dpdapiinserttestshipment);
if(!test)
{
targetURI = new Uri(dpdapiinsertshipment);
request = (HttpWebRequest)WebRequest.Create(dpdapiinsertshipment);
}
// add headers to the web request for inserting a new shipment
request.Host = dpdapihost;
request.ContentType = "application/json";
request.Accept = "application/json";
request.Method = "POST";
request.Timeout = 30000;
request.KeepAlive = true;
request.AllowAutoRedirect = false;
request.Headers["GEOClient"] = "thirdparty/" + dpdAccountNumber;
request.Headers["GeoSession"] = geoSession;
using (var streamWriter = new StreamWriter(request.GetRequestStream()))
{
streamWriter.Write(InsertShipmentData);
}
var httpResponse = (HttpWebResponse)request.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
}
//// run the request and read the response header
//using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
//{
// using (var sr = new StreamReader(response.GetResponseStream()))
// {
// JSONdata = Convert.ToString(sr.ReadToEnd());
// }
// // check if OK (status 200) returned
// if (response.StatusCode.ToString() == "OK")
// {
// returnValue = true;
// }
// else
// {
// returnValue = false;
// }
// return returnValue;
//}
return returnValue;
}
catch (Exception ex)
{
JSONdata = Convert.ToString(ex);
return false;
}
}
}
}
IT is very disapointing that after one week i cannot solve a simple problem of posting a JSON content to a Web Server's API. I think I will quit this attempt to use Xamarin.
I am trying to post the JSON parameters below using PostAsJsonAsync in a Xamarin app. The program does post the site but the parameters are not encoded as JSON content. Does anyone know why?
public async void Login()
{
var formcontent = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string,string>("email","marcio#netopen.com.br"),
new KeyValuePair<string, string>("password","Xy345")
});
var FlyVIPAPI = new HttpClient();
var request = await FlyVIPAPI.PostAsJsonAsync("http://www.ik.com.br/app/api/LoginUser.php", formcontent);
var response = await request.Content.ReadAsStringAsync();
//var res = JsonConvert.DeserializeObject(response);
var RepostaJson = Newtonsoft.Json.Linq.JObject.Parse(response);
System.Diagnostics.Debug.WriteLine(RepostaJson["success"]);
System.Diagnostics.Debug.WriteLine(RepostaJson["error"]);
return;
}
public class LoginRequest
{
public string email { get; set; }
public string password { get; set; }
}
public async void Login()
{
using (var FlyVIPAPI = new HttpClient())
{
// Create Request object
var requestObj = new LoginRequest { email = "marcio#netopen.com.br", password = "Xy345" };
// Serialize to JSON string
var formcontent = JsonConvert.SerializeObject(requestObj);
// Create HTTP content
var content = new StringContent(formcontent, Encoding.UTF8, "application/json");
// POST Request
var request = await FlyVIPAPI.PostAsync("http://www.ik.com.br/app/api/LoginUser.php", content);
// Read Response
var response = await request.Content.ReadAsStringAsync();
....
}
}
Additionally, I would suggest wrapping your HttpClient in a using statement so that is will be disposed of once your code block is done. Freeing up resources.
I'm trying to read the following json in a windows phone app using newtonsoft.json
I can't read anything. the also looks pretty strange to me.
{"type": "Menu","menu":
[{"0":"antipasto","tipo_piatto":"antipasto","1":"porchetta","nome_piatto":"porchetta","2":"1","prezzo":"1"},
{"0":"primo","tipo_piatto":"primo","1":"matriciana","nome_piatto":"matriciana","2":"5","prezzo":"5"},
{"0":"secondo","tipo_piatto":"secondo","1":"salsicce","nome_piatto":"salsicce","2":"4","prezzo":"4"},
{"0":"contorno","tipo_piatto":"contorno","1":"patate","nome_piatto":"patate","2":"2","prezzo":"2"},
{"0":"dolce","tipo_piatto":"dolce","1":"gelato","nome_piatto":"gelato","2":"6","prezzo":"6"}]}
this is my c# code for now
public class piatto_menu_giorno
{
public string tipo_piatto { get; set; }
public string nome_piatto { get; set; }
public string prezzo { get; set; }
}
public menu()
{
InitializeComponent();
WebClient webClient = new WebClient();
Uri uri = new Uri("http://www.stepapp.it/areacli/extDevice/getMenuOdierno_101.php");
webClient.OpenReadCompleted += new OpenReadCompletedEventHandler(fine_lettura_web);
webClient.OpenReadAsync(uri);
}
private void fine_lettura_web(object sender, OpenReadCompletedEventArgs e)
{
DataContractJsonSerializer json = null;
json = new DataContractJsonSerializer(typeof(ObservableCollection<piatto_menu_giorno>));
ObservableCollection<piatto_menu_giorno> menu = json.ReadObject(e.Result) as ObservableCollection<piatto_menu_giorno>;
if(menu==null)
menu_giorno.Text = "null";
else
foreach (piatto_menu_giorno piatto in menu)
{
menu_giorno.Text += piatto.nome_piatto + "\n";
}
}
sorry for all the variables name that are in italian
I am writing a code for you it will help you to deserialize the object from json to yourClassCustomObject.
private async Task<List<piatto_menu_giorno>> MyDeserializerFunAsync()
{
List<piatto_menu_giorno> book = new List<piatto_menu_giorno>();
try
{
//I am taking my url from appsettings. myKey is my appsetting key. You can write direct your url.
string url = (string)appSettings["mykey"];
var request = HttpWebRequest.Create(url) as HttpWebRequest;
request.Accept = "application/json;odata=verbose";
var factory = new TaskFactory();
var task = factory.FromAsync<WebResponse>(request.BeginGetResponse,request.EndGetResponse, null);
var response = await task;
Stream responseStream = response.GetResponseStream();
string data;
using (var reader = new System.IO.StreamReader(responseStream))
{
data = reader.ReadToEnd();
}
responseStream.Close();
DataContractJsonSerializer json = new DataContractJsonSerializer(typeof(List<piatto_menu_giorno>));
MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(data));
book = (List<piatto_menu_giorno>)json.ReadObject(ms);
return book;
}
}
Above code is working in my wp8 application it is faster you can try, it will help you. I am performing asynchronous operation but you can create your simple method with piatto_menu_giorno return type.