Some help posting to ASP.NET Web API with C# - c#

I have been playing with ASP.NET Web API. I am looking to see can I post to a method I have built which simply returns back the object I have POSTED:
On The Accounts Controller:
// POST /api/accounts
public Account Post(Account account)
{
return account;
}
Code Used To Post:
public void PostAccount()
{
// http://local_ip/api/accounts
var uri = string.Format("{0}", webServiceRoot);
var acc = new Account();
acc.AccountID = "8";
acc.AccountName = "Mitchel Cars";
acc.AccountNumber = "600123801";
acc.SubscriptionKey = "2535-8254-8568-1192";
acc.ValidUntil = DateTime.Now;
var request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = "POST";
request.ContentType = "application/xml";
request.ContentLength = 800;
XmlSerializer xmlSerializer = new XmlSerializer(typeof(Account));
xmlSerializer.Serialize(request.GetRequestStream(), acc);
var response = (HttpWebResponse)request.GetResponse();
XmlSerializer serializer = new XmlSerializer(typeof(Account));
var newAcc = (Account)serializer.Deserialize(response.GetResponseStream());
}
I have removed any error checking or any boiler plate code to make it easier to read. This is strictly a spike just to under stand to to actually POST. My understanding is that you should write to the GetRequestStream(). All the reading and such seems to work ok but I never here back from the request.GetResponse();
If I do a simple get it works fine. I did see you can use a class called HTTPClient for doing this stuff but I can't use it as I need to get this working for WinForms, Silverlight and Windows Phone all based on .Net 3.5
Any help pushing POCO's to the server would be a great help, cheers!
ADDITIONAL INFO:
Currently I get no error, the test app just hangs.
If I turn off the WebAPI project I get a server not found response.
I have not changed any routes or any of that.
Gets to the same controller work.

You will need to close the response stream. Most examples I see also show setting the content length. You may be better to serialize to a memory stream and then use the length of that stream as the Content-Length. Unfortunately in .net 3.5 there is no CopyStream so you may have to write that yourself.

If you want to use the HttpClient, you can install the download the REST starter Kit. and use the DLLs as external DLLs
http://forums.asp.net/t/1680252.aspx/1

Related

Issues with posting JSON

So on my client (windows phone 8.1 app) I have posted a JSON just for testing, here is the code for this:
public async void SendJSON()
{
try
{
string url = "http://posttestserver.com/post.php?dir=karim";
var httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
httpWebRequest.ContentType = "text/plain; charset=utf-8";
httpWebRequest.Method = "POST";
using (var stream = await Task.Factory.FromAsync<Stream>(httpWebRequest.BeginGetRequestStream,
httpWebRequest.EndGetRequestStream, null))
{
//create some json string
string json = "{ \"my\" : \"json\" }";
// 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)
{
}
}
Now I'm trying to figure out, from the www.myurl.com how would I retrieve what has been posted from the mobile app using a Web Service?
UPDATE
When I debug these lines, it runs perfectly without breaking nor falling within the catch. However when looking at where it should post to (the results are here http://www.posttestserver.com/data/2015/12/14/karim/) it doesn't post anything.
Does anyone know what I'm doing wrong?
BTW: it already has results there because I have done this directly from my desktop.
Not sure what you are trying to do but if you want to inspect your http requests fiddler is a good choice. Since your are using windows phone apps you can configure the windows phone emulator to proxy through fiddler.
Here is a blog post how to set this up: http://blogs.msdn.com/b/wsdevsol/archive/2013/06/05/configure-the-windows-phone-8-emulator-to-work-with-fiddler.aspx - Configure the Windows Phone 8 Emulator to work with Fiddler
// Edit: Have you considered to use HttpClient
var httpClient = new HttpClient();
string resourceAddress = "http://posttestserver.com/post.php?dir=karim";
string postBody = "{ \"my\" : \"json\" }"
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = await httpClient.PostAsync(resourceAddress, new StringContent(postBody, Encoding.UTF8, "application/json"));
Code is from the top of my head so you might have to tweak it... and of course you need to handle error cases and/or retry, etc
HTH
If you just want to see, what have you send, you can use this http://posttestserver.com
Otherwise there is not easy way how to force some endpoint to retrieve data. There must but set up server, which is allowing it, proccessing it, storing it etc.
If you POST anything to http://posttestserver.com/post.php it will return you this message
Successfully dumped 0 post variables. View it at
http://www.posttestserver.com/data/2015/12/15/00.19.29177030164 Post
body was 134 chars long.
So just print somewhere your response and you will get the exact url
You should use fiddler to see the outputted content:
http://www.telerik.com/fiddler
Windows Phone 8.1 Emulator not proxying through Fiddler

Making a post request in Unity on Windows Phone 8

I'm trying to do a post request on windows phone 8 from the Unity Platform. I do not want to use the unity WWW method as this blocks rendering (and is not thread safe).
The following code works in the editor and on Android, but when building it for WP8 I get the following error.
System.Byte[] System.Net.WebClient::UploadData(System.String,System.String,System.Byte[])` doesn't exist in target framework.
The reason for this error is explained here
It’s because Windows Phone 8 uses a different flavor of .NET called .NET for Windows Phone which is missing some of the types available on other platforms. You’ll have to either replace these types with different ones or implement them yourself.
- http://docs.unity3d.com/Manual/wp8-faq.html
This is my code
using (WebClient client = new WebClient())
{
client.Encoding = System.Text.Encoding.UTF8;
client.Headers[HttpRequestHeader.ContentType] = "application/json";
byte[] requestData = new byte[0];
string jsonRequest = "{}";
if (data != null)
{
string tempRequest = Converter.SerializeToString (data);
jsonRequest = "{\"Data\": \"" + tempRequest + "\"}";
requestData = System.Text.Encoding.UTF8.GetBytes(jsonRequest);
}
// below line of code is the culprit
byte[] returnedData = client.UploadData(url, "POST", requestData);
if(returnedData.Length > 0)
{
// do stuff
}
}
I've also tried WebRequests, but GetResponse() breaks it, and HttpClient does not exist.
So, how do I post data in Unity, without using WWW, on windows phone 8?
UPDATE AS PER COMMENT REQUEST - WebRequests
This code, using HttpWebRequest works in the editor and on Android, but on windows phone throws the errors listed below the code.
var request = (System.Net.HttpWebRequest) System.Net.WebRequest.Create(url);
request.ContentType = "application/json";
request.Method = "POST";
var sw = new System.IO.StreamWriter(request.GetRequestStream(), System.Text.Encoding.UTF8);
sw.Write(jsonRequest); // jsonRequest is same variable as in above code, string with json object.
sw.Close();
var re = request.GetResponse();
string resultString = "";
using (var outputStream = new System.IO.StreamReader(re.GetResponseStream(), System.Text.Encoding.UTF8))
{
resultString = outputStream.ReadToEnd();
}
if(resultString.Length > 0)
{}
Error 1:
Error: method System.IO.Stream System.Net.HttpWebRequest::GetRequestStream() doesn't exist in target framework.
Error 2:
System.Net.WebResponse System.Net.HttpWebRequest::GetResponse() doesn't exist in target framework.
UPDATE WITH MORE DETAILS - UploadStringAsync
Using this code to make an async request it again works great in the editor, errors are thrown on the WP8.
bool isCompleted = false;
byte[] returnedData = null;
client.UploadDataCompleted +=
new UploadDataCompletedEventHandler((object sender, UploadDataCompletedEventArgs e) =>
{
Debug.Log("return event");
returnedData = e.Result;
isCompleted =true;
});
Debug.Log("async call start");
client.UploadDataAsync(new Uri(url), requestData);
while(isCompleted == false){
Thread.Sleep(100);
}
if(returnedData.Length > 0)
{}
Error 1
method System.Void System.Net.WebClient::add_UploadDataCompleted(System.Net.UploadDataCompletedEventHandler) doesn't exist in target framework.
Error 2
Error: method System.Void System.Net.WebClient::UploadDataAsync(System.Uri,System.Byte[]) doesn't exist in target framework.
Error 3
Error: type System.Net.UploadDataCompletedEventArgs doesn't exist in target framework.
Error 4
Error: method System.Byte[] System.Net.UploadDataCompletedEventArgs::get_Result() doesn't exist in target framework.
I don't know about any potential restrictions placed on you by Unity, but Windows Phone 8 has the WebClient.UploadStringAsync method and the WebClient.UploadStringCompleted event for doing just this.
HttpWebRequest should also work (again, I don't know about any Unity limitations - see comment above asking for clarification).
Go it to work on the windows phone using the code below. Compiles and runs in the editor, on Android and on WP8 (yay!). Haven't tried it on iOS yet.
Also wrote a post about it here: Create Web requests for unity that work on all platforms, even WP8
/// <summary>
/// Make post request to url with given paramaters
/// </summary>
/// <param name="url">URL to post data to http://server.com/method </param>
/// <param name="data">{ Data: data }</param>
/// <returns>string server response</returns>
public string PostData(string url, string data)
{
// json request, hard coded right now but use "data" paramater to set this value.
string jsonRequest = "{\"Data\": \"data\"}"; // the json request
var request = System.Net.WebRequest.Create(url) as System.Net.HttpWebRequest;
// this could be different for your server
request.ContentType = "application/json";
// i want to do post and not get
request.Method = "POST";
// used to check if async call is complete
bool isRequestCallComplete = false;
// store the response in this
string responseString = string.Empty;
request.BeginGetRequestStream(ar =>
{
var requestStream = request.EndGetRequestStream(ar);
using (var sw = new System.IO.StreamWriter(requestStream))
{
// write the request data to the server
sw.Write(jsonRequest);
// force write of all content
sw.Flush();
}
request.BeginGetResponse(a =>
{
var response = request.EndGetResponse(a);
var responseStream = response.GetResponseStream();
using (var sr = new System.IO.StreamReader(responseStream))
{
// read in the servers response right here.
responseString = sr.ReadToEnd();
}
// set this to true so the while loop at the end stops looping.
isRequestCallComplete = true;
}, null);
}, null);
// wait for request to complete before continuing
// probably want to add some sort of time out to this
// so that the request is stopped after X seconds.
while (isRequestCallComplete == false) { Thread.Sleep(50); }
return responseString;
}
You cannot use these frameworks from unity because they are threaded / async / use another version of .Net
In short :
Unity runs on a version of mono which accepts only .Net 3.5
Unity does not allow you to start threads, tasks or anything close to real asynchronicity
You can implement those though.
To do that on windows phone you will need to create a class library (two in fact) what unity calls a plugin
So why two dlls?
Because the editor needs a mockup dll (or the actual one if you want to implement it for desktop as well) that implements the same interface as the dll which is compatible on windows phone.
To be clear :
The dll for the editor (in Assets/Plugins) needs to be compatible .Net 3.5 and desktop
The dll placed in Assets/plugins/WP8 needs to be compatible windows phone .Net subset (as i remember you can be .Net 4.5 with no pb)
So you should implement that functionality in a dll, then reference that in unity, and finally call it directly.
All is explained here : http://docs.unity3d.com/Manual/wp8-plugins-guide-csharp.html
It is simpler than it looks like.
I know you said you don't want to use the WWW class, but the reasons you gave to dont make sense IMO.
If you use a Coroutine to check the ".isDone" flag and not check it by using the Thread.Sleep() it wont block rendering and is thread safe (since unity only gives you access to its info on a single thread).
If you want to access the return data on another thread you just need to read that data in the main unity thread and then pass it along to whatever thread you want to use it on.
Unity by design is all runs on a single thread to make life easier for less experienced programmers. Though you should be able to create multiple threads using .NET threading, you will not be able to communicate directly with any Unity components, but you can pass the data back to Unity and wait until Update or another call by Unity to use the data. I know this doesnt answer your question exactly but if you cant solve it I think it would be worthwhile to look again at the WWW class and the best practices in using it.

Pass complex object via http

I’ve got 2 projects that run on different servers but both have a reference to a common dll that contains a complex type called LeadVM. LeadVM contains sub-objects, like Employer which contains properties. Ex:
LeadVM.FirstName
LeadVM.LastName
LeadVM.Employer.Name
LeadVM.Employer.Phone
So, project 1 can create a LeadVM type of object, and populate it. I need to then, via an HTTP call, POST in the data to a controller/action in the 2nd project. The 2nd project knows what a LeadVM object is.
How can I...serialize(?) LeadVM and pass it to the accepting Action in the 2nd project?
EDIT: Thanks to #Unicorno Marley, I ended up using the Newtonsoft JSON stuff.
Now I just create my object in project 1, then do the following code (I'm sure it's clunky but it works).
LeadVM NewCustomer = new LeadVM();
NewCustomer.set stuff here....
var js = Newtonsoft.Json.JsonSerializer.Create();
var tx = new StringWriter();
js.Serialize(tx, NewCustomer);
string leadJSON = tx.ToString();
And then I can use HttpWebRequest to send a web request to my project 2.
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://localhost:1234/Lead/Create");
request.Method = "POST";
StreamWriter streamOut = new StreamWriter(request.GetRequestStream(), System.Text.Encoding.ASCII);
streamOut.Write(System.Web.HttpUtility.UrlEncode(leadJSON));
streamOut.Close();
HttpWebResponse resp = null;
resp = (HttpWebResponse)request.GetResponse();
StreamReader responseReader = new StreamReader(resp.GetResponseStream(), Encoding.UTF8);
sResponse = responseReader.ReadToEnd();
resp.Close();
In project 2, I can catch the json sent like this and my NewCustomer object in project 2 is already populated, ready for use.
var buffer = new byte[Request.InputStream.Length];
Request.InputStream.Read(buffer, 0, buffer.Length);
string json = System.Text.Encoding.Default.GetString(buffer);
json = System.Web.HttpUtility.UrlDecode(json);
LeadVM NewCustomer = Newtonsoft.Json.JsonConvert.DeserializeObject<PhoenixLead.LeadVM>(json);
I'm sure I'm doing things very awkwardly. I'll clean it up, but wanted to post the answer that I was led to.
Json is probably the most common option, there is a good json library for c# that can be found here:
http://james.newtonking.com/json
Alternatively, since youre just doing an HTTP post and you only have one object, the fastest option would just be to write out the data line by line and have the recipient machine parse it. Since they both know what a LeadVM is, and both presumably have the same definition, it would be trivial to read a text string into the proper variables. This quickly becomes the slower option if you decide to add more object types to this process though.

Google+ API plus.me

The question: How to use people.get with the "me" parameter?
I know how to get the json object when using https://www.googleapis.com/plus/v1/people/{id}?key={key}
but what parameters should I include when Im using "me" as id?
(I use response_type=code in the auth)
Edit: (fixed)
I am using ASP.NET, and I found this link, but the POST request for the access token json throws an error. Sending the request works but, but when I use GetResponse(), I get error(400). And also Im not sure if the uri that I use is correct: https://accounts.google.com/o/oauth2/token
Edit 2:
Problem solved. The request was bad because I used UTF32Encoding instead of UTF8Encoding when converting the parameter string to byte[] before writing to Stream. With UTF8Encoding works good. :)
Code that I wrote after this question:
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
webRequest.ContentType = "application/x-www-form-urlencoded";
webRequest.Method = "POST";
UTF8Encoding utfenc = new UTF8Encoding();
byte[] bytes = utfenc.GetBytes(parameters);
Stream os = null;
try // send the post
{
webRequest.ContentLength = bytes.Length; // Count bytes to send
os = webRequest.GetRequestStream();
os.Write(bytes, 0, bytes.Length); // Send it
}
// error handling...
try // get the response
{
HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse();
if (webResponse == null)
{ return null; }
StreamReader sr = new StreamReader(webResponse.GetResponseStream());
return sr.ReadToEnd().Trim();
}
// error handling...
he called this with the parameters from here, and the returned string(json) contains my access_token.
We have developed a .NET client library for Google+ APIs. This library makes it very easy to use Google+ APIs from any .NET programming languages like C#, VB.NET or ASP.NET
You can find more details about the .NET library for Google+ here: http://www.googleplustips.com/resources/3332-NET-Library-Google-APIs-released.aspx
The current version supports all Google+ APIs version 1, and works with API Key. Calling any Google APIs require only a single method call.
You can use me ID as long as you access the app with the access token of an (OAuth) authenticated user. To quote from the G+ API documentation:
If using the userId value "me", this method requires authentication using a token that has been granted the OAuth scope https://www.googleapis.com/auth/plus.me. Read more about using OAuth.
Example: when using the PHP API client, before issuing e.g.
$plus_api = new apiPlusService($client); // $client is the apiClient() object
$plus_api->activities->listActivities('me', ...);
you have to set the access token of the authenticated user first by executing:
$client->setAccessToken($access_token);
With that set, the me ID will be recognized without a problem.
I sent a POST request (info here) to get the Oauth2 access_token and used:
https://www.googleapis.com/plus/v1/people/me?key={key}&access_token={token}
GetActivity and ListComments are getting all the data, or it has some method(using nextPageToken) to get all the items?
Each method call returns the resultset page by page. The returned object has a property called NextPageToken which can be passed with the next call to retrieve the next page of the result set.

RPC to java based Google App Engine from C# Client

I'm having a lot of problems calling a Java based Google App Engine server from a C# client
This is how my client code looks like:
// C# Client
static void Main(string[] args)
{
const string URL = "http://localhost:8888/googlewebapptest7/greet";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);
request.Method = "POST";
request.ContentType = "text/x-gwt-rpc; charset=utf-8";
string content = "<?xml version='1.0'?><methodCall><methodName>greetServlet.GetName</methodName><params></params></methodCall>";
byte[] contentBytes = UTF8Encoding.UTF8.GetBytes(content);
request.ContentLength = contentBytes.Length;
using (Stream stream = request.GetRequestStream())
{
stream.Write(contentBytes, 0, contentBytes.Length);
}
// get response
WebResponse response = request.GetResponse();
using (Stream responseStream = response.GetResponseStream())
{
string res = new StreamReader(responseStream).ReadToEnd();
Console.WriteLine("response from server:");
Console.WriteLine(res);
Console.ReadKey();
}
The server is basically the Google default web project with an additional method:
public String GetName()
{
return "HI!";
}
added to GreetingServiceImpl.
Everytime I run my client, I get the following exception from the server:
An IncompatibleRemoteServiceException was thrown while processing this call.
com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException: This application is out of date, please click the refresh button on your browser. ( Malformed or old RPC message received - expecting version 5 )
I would like to keep it in plain HTTP requests.
Any idea what's going on?
As Nick pointed out you're trying to emulate GWT's RPC format. I tried that too :)
Then I took different approach. I used Google Protocol Buffers as encoder/decoder over HTTP(S).
One of my projects is desktop application written in C#. Server-side is also C#.Net. Naturally we use WCF as transport.
You can plug-in Protocol Buffers into WCF transport. You'll have same interface configuration both for C# client and Java server. It's very convenient.
I'll update this answer with code-samples when I'm less busy with work.
I never found a good way to use XML based RPC on the Google App Engine. Instead i found this excellent JSON library with tutorial:
http://werxltd.com/wp/portfolio/json-rpc/simple-java-json-rpc/
it works very well!

Categories

Resources