Posting JSON to WebAPI2 function - json

I have the following code in an MVC app controller to send some data to be stored in an Archive table using EF6 via a WebAPI2 call.
I'm getting a "Cannot send a content-body with this verb-type" even though I'm setting to POST and the api call is defined to accept only POST.
What in the world am I doing wrong and how can I fix it?
ArchiveUploadModel.ArchiveUpload obj = new ArchiveUploadModel.ArchiveUpload();
obj.LT = LT;
obj.PID = PID.ToString();
obj.Title = "Ex Review";
obj.HTML = message.Body; // the HTML is a rendered HTML email message
if (!string.IsNullOrEmpty(obj.HTML))
{
HttpWebRequest req = HttpWebRequest.Create("http://example.com/MyApp/api/UploadToArchive") as HttpWebRequest;
request.ContentType = "application/json";
request.Method = "POST";
string json = JsonConvert.SerializeObject(obj);
using (var streamWriter = new StreamWriter(request.GetRequestStream()))
{
streamWriter.Write(json);
streamWriter.Flush();
streamWriter.Close();
}
}
using (HttpWebResponse webresponse = request.GetResponse() as HttpWebResponse)
{
using (StreamReader reader = new StreamReader(webresponse.GetResponseStream()))
{
string response = reader.ReadToEnd();
}
}
This is the code for my WebAPI call:
[HttpPost]
[Route("api/UploadToArchive")]
[EnableCors("http://example.com", // Origin
"Accept, Origin, Content-Type, Options", // Request headers
"POST", // HTTP methods
PreflightMaxAge = 600 // Preflight cache duration
)]
public IHttpActionResult UploadToArchive(ArchiveUpload upload)
{
string HTML = upload.HTML;
string Title = upload.Title;
string LT = upload.LT;
string lt = getLT(upload.PID); // essentially secure checking to see if it matches passed LT.
if (lt == LT)
{
// Upload the file to the archive using the ArchiveRepository's UpdateArchive() function:
_ArchiveRepository.UpdateArchive(HTML, System.Web.HttpUtility.HtmlDecode(Title), "", upload.PID);
return Ok(PID);
}
else
{
return BadRequest("Invalid LT");
}
}
ArchiveUpload model definition in both applications:
public class ArchiveUpload
{
public string LT { get; set; }
public string PID { get; set; }
public string Title { get; set; }
public string HTML { get; set; }
}

Better try to use the Microsoft Http Client Libraries. You can install it from nuget and here you find examples calling Web API using different HTTP verbs

Related

How to generate refresh and access token for Windows phone app

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

Why are PostAsJsonAsync's parameters not included in the post as JSON content?

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.

How to perform POST operation on Windows Phone 8.1

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.

http client in windows 8 app

i made an app in windows phone successfully & now i want to make it for windows 8 store app but i stuck on a point where i want to my web service in store app.
I use webclient in WP but i don't know anything about how to access web service in Windows 8 store app. My web service return data in json format i deserialize & store in a variable in WP & i use post method . but how it would be done in Windows 8 store app.
what would i use for windows 8 in place of Webclient.
i post my windows phone code
private void PostData()
{
Uri uri = new Uri(my web service url);
string data = "device_id=" + val + "&quiz_type=all";
WebClient wc = new WebClient();
wc.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
wc.UploadStringAsync(uri, data);
wc.UploadStringCompleted += wc_UploadComplete;
}
public void wc_UploadComplete(object sender, UploadStringCompletedEventArgs e)
{
var rootObject = JsonConvert.DeserializeObject<RootObject>(e.Result);
}
You see that i store all the data in rootObject.
How these thing can be done in windows 8 app?
1st Method: Parsing and Reusing JSON Objects
Step1: Go to Json2Csharp site and paste either your entire JSON string or URL to the JSON and click on Generate button. This creates all the required classes for your JSON response.
For example, this JSON dataset:
{"MyBlogList":[{"ID":9,"TYPE":"WindowsPhone","TITLE":"XYZ","PRICE":"0","IMAGE":"Post1.jpg"}],"success":3}
The generated class object is:
public class MyBlogList
{
public int ID { get; set; }
public string TYPE { get; set; }
public string TITLE { get; set; }
public string PRICE { get; set; }
public string IMAGE { get; set; }
}
public class RootObject
{
public List<MyBlogList> MyBlogList { get; set; }
public int success { get; set; }
}
Now place this class somewhere in your project, so that it will be available in the required locations.
Step 2: (i.e. assuming that you get your JSON from a web service), Make a web request to get the JSON response
You will have to use the WebClient class as well as enabling the DownloadStringCompleted Event handler which returns the response to be manipulated.
WebClient webClient = new WebClient();
webClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(webClient_DownloadStringCompleted);
webClient.DownloadStringAsync(new Uri(http://somedomain.com/xyz/myjson.aspx));
And then in the response handler, use the following code to parse the data and convert into classes:
void webClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
var rootObject = JsonConvert.DeserializeObject<RootObject>(e.Result);
foreach (var blog in rootObject.MyBlogList)
{
Console.WriteLine(blog.TITLE);
}
}
2nd Method: One Time JSON Parse
Here as your requirement is one time parsing and one time usage, instead of storing them in unnecessary classes, we just wisely parse the data and get the task done.
Consider the exact same sample JSON dataset provided above, and we want to get the blog title so here is the code snippet for that:
JObject obj = JObject.Parse(jsonData);
JArray jarr = (JArray)obj["MyBlogList"];
string blogTitle = (string)jarr[0]["TITLE"]; //To get the title of the blog
or
foreach(var item in jarr)
Console.WriteLine(item["TITLE"]); //Gets the title of each book in the list
There you go, you can play with the response and bind the data with the UI elements.
You have to use HttpClient.
private async Task UploadData()
{
HttpClient httpClient = new HttpClient();
httpClient.MaxResponseContentBufferSize = 256000;
httpClient.DefaultRequestHeaders.Add("user-agent", "Mozilla/5.0 (compatible; MSIE 10.0; WIndows NT 6.2; WOW64; Trident/6.0)");
httpClient.DefaultRequestHeaders.Add("Content-Type", "application/x-www-form-urlencoded");
string data = "device_id=" + val + "&quiz_type=all";
HttpContent content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("payloadData", data)
});
HttpResponseMessage response = await httpClient.PostAsync(new Uri(my web service url), content);
response.EnsureSuccessStatusCode();
if (!response.IsSuccessStatusCode)
{
throw new Exception(response.StatusCode.ToString());
}
// This is your responce data.
string result = await response.Content.ReadAsStringAsync();
var rootObject = JsonConvert.DeserializeObject<RootObject>(result);
}

How can I read this json on windows phone 8?

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.