I am working on an android application which uses push notification service by GCM. Currently I am stuck at creating a server. The guides provided by the GCM documentation is in java which I have no idea how to implement. After researching for awhile, I found GCMSharp on github which uses C#
PushSharp - https://github.com/Redth/PushSharp
But as of now, I am new to creating a server and have no idea how to get started. Is the server actually a web service that keeps listening to request and upon getting a request directs it to the GCM which pushes notification to the client phone?
And if yes, do I implement it in a webservice such as WCF?
You could follow this tutorial.
Is the server actually a web service that keeps listening to request
and upon getting a request directs it to the GCM which pushes
notification to the client phone?
You don't need to listen to requests. GCM Push directly pushes any message to the device without any request. For more details, Read this documentation.
I have answered to this on another thread and here i am repeating. Code looks bit longer but it works. I just sent a push notification to my phone after struggling 2 days by implementing the following code in C# project. I referred a link regarding this implementation, But couldn't find it to post here. So will share my code with you. If you want to test the Notification online you may visit to this link.
note : I have hardcorded apiKey, deviceId and postData, please pass
the apiKey,deviceId and postData in your request and remove them from
the method body. If you want pass message string also
public string SendGCMNotification(string apiKey, string deviceId, string postData)
{
string postDataContentType = "application/json";
apiKey = "AIzaSyC13...PhtPvBj1Blihv_J4"; // hardcorded
deviceId = "da5azdfZ0hc:APA91bGM...t8uH"; // hardcorded
string message = "Your text";
string tickerText = "example test GCM";
string contentTitle = "content title GCM";
postData =
"{ \"registration_ids\": [ \"" + deviceId + "\" ], " +
"\"data\": {\"tickerText\":\"" + tickerText + "\", " +
"\"contentTitle\":\"" + contentTitle + "\", " +
"\"message\": \"" + message + "\"}}";
ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(ValidateServerCertificate);
//
// MESSAGE CONTENT
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
//
// CREATE REQUEST
HttpWebRequest Request = (HttpWebRequest)WebRequest.Create("https://android.googleapis.com/gcm/send");
Request.Method = "POST";
Request.KeepAlive = false;
Request.ContentType = postDataContentType;
Request.Headers.Add(string.Format("Authorization: key={0}", apiKey));
Request.ContentLength = byteArray.Length;
Stream dataStream = Request.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
//
// SEND MESSAGE
try
{
WebResponse Response = Request.GetResponse();
HttpStatusCode ResponseCode = ((HttpWebResponse)Response).StatusCode;
if (ResponseCode.Equals(HttpStatusCode.Unauthorized) || ResponseCode.Equals(HttpStatusCode.Forbidden))
{
var text = "Unauthorized - need new token";
}
else if (!ResponseCode.Equals(HttpStatusCode.OK))
{
var text = "Response from web service isn't OK";
}
StreamReader Reader = new StreamReader(Response.GetResponseStream());
string responseLine = Reader.ReadToEnd();
Reader.Close();
return responseLine;
}
catch (Exception e)
{
}
return "error";
}
public static bool ValidateServerCertificate(
object sender,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors sslPolicyErrors)
{
return true;
}
You may not familiar with words like apiKey, deviceId. Dont worry i will explain what are they and how to create those.
apiKey What & why :This a key that will be used when sending requests to GCM server. How to create : Refer this post
deviceId What & why : This id also known as RegistrationId. This is a unique id to identify the device. When you want to send a
notification to a specific device you need this id. How to
create: This depends on how you implement the application. For cordova
i used a simple pushNotification Plugin You can simply create a
deviceId/RegistrationId using this plugin. To do that you need to have
a senderId. Google how to create a senderId it is really simple =)
If anyone needs some help leave a comment.
Happy Coding.
-Charitha-
Related
I have written a WPF application that sends a POST WebHTTPRequest to a WCF service. The service required windows credentials to perform operations on the server. When the service receives the HTTP request, it is unable to parse the Authorization header.
The POST request begins like this.
HttpWebRequest req = WebRequest.CreateHttp(url);
req.ContentType = "application/json;charset=UTF-8";
req.Accept = "application/json";
req.Headers.Add("Authorization", Base64Encode(Details.username + ":" + Details.password + ":" + Details.domain));
req.Method = "POST";
byte[] reqBytes = Encoding.ASCII.GetBytes(body.ToString());
And is received on the service like this
IncomingWebRequestContext request = WebOperationContext.Current.IncomingRequest;
WebHeaderCollection headers = request.Headers;
if (headers["Authorization"] != null)
{
cred = headers["Authorization"];
} else
{
HttpContext.Current.Response.Write(result);
return;
}
I print the "cred" variable to a log file and what I get begins something like this "敎潧楴瑡䥙䝉䅺䝙" which, quite clearly, is wrong. Can anybody tell me why I'm getting this output as opposed to the input consisting of the English characters I sent the request with?
The problem is that you encoded a UTF-8 encoded string into Base64.
You specified that the charset type for your JSON file is UTF-8 here:
req.ContentType = "application/json;charset=UTF-8";
So when you tried to encode your Authentication into Base64 it would have ruined your string.
req.Headers.Add("Authorization", Base64Encode(Details.username + ":" + Details.password + ":" + Details.domain));
Try a different way of encoding the string
I am working on a simple Windows Forms program that take a username and password from a "Textbox" then it show my linked-in name in a "Messagebox".
I want to accomplish the code with the using of "HttpWebRequest" or using any method to send my POST request to Linked-in then i can get the response and find my name to shown it in a "Messagebox".
I am familiar with creating a "GET" Request and also i made some "POST" Requests but in this case i didn't know how can i send my "txt_UserName.Text" and "txt_Password" with the POST Request and how can i receives the Response.
I tried to using Fiddler to capture POST request (=POST) from linkedin when i try to login but it captures more than 4 requests when i see the header of them it seem like a GET Request this is an example of one:
GET /nhome/?trk= HTTP/1.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
and all of them have a multiple cookies values.
This is my POST request code:
public void SubmitData()
{
try
{
string postData = "This is a test that posts this string to a Web server.";
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
// Create a request using a URL that can receive a post.
WebRequest request = WebRequest.Create("http://www.linkedin.com");
// Set the Method property of the request to POST.
request.Method = "POST";
// Set the ContentLength property of the WebRequest.
request.ContentLength = byteArray.Length;
//Content Length
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();
dataStream = response.GetResponseStream();
StreamReader sr = new StreamReader(dataStream);
MessageBox.Show(sr.ReadToEnd());
sr.Close();
dataStream.Close();
}
catch (Exception ex)
{
MessageBox.Show("Error: " + ex.Message);
}
}
Now the only thing i wish to know, how can i send my username and password as a values to login to linked-in?
Edit:
Below is my second try, it's ok, i can now send the User and Password in postData and i can store the Cookies and retrive it. but there are two issues:
1- how can i make sure that the login is accomplished and not failed
2- if the login is accomplished i want to know what is the second step to get my name from profile, is it made another request or what ?
private void button1_Click(object sender, EventArgs e)
{
PostMessage();
}
private void PostMessage()
{
try {
// POST Data and the POST uri
string postData = "isJsEnabled=true&source_app=&session_key=" + textBox1.Text + "&session_password=" + textBox2.Text + "&signin=Sign+In&session_redirect=";
string uri = "https://www.linkedin.com/uas/login-submit";
// Encoding the POST Data
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
// Create the POST Request
HttpWebRequest WebReq = (HttpWebRequest)WebRequest.Create(uri);
//POST Parameters (Method and etc.)
WebReq.Method = "POST";
WebReq.ContentType = "application/x-www-form-urlencoded";
WebReq.ContentLength = byteArray.Length;
// Set the POST Request Cookies
var cookieContainer = new CookieContainer();
WebReq.CookieContainer = cookieContainer;
// Get the request stream.
Stream dataStream = WebReq.GetRequestStream();
// Write the data to the request stream.
dataStream.Write(byteArray, 0, byteArray.Length);
// Close the Stream object.
dataStream.Close();
// Get the response.
HttpWebResponse response = (HttpWebResponse)WebReq.GetResponse();
dataStream = response.GetResponseStream();
StreamReader sr = new StreamReader(dataStream);
//MessageBox.Show(sr.ReadToEnd());
sr.Close();
dataStream.Close();
if (response.StatusCode != HttpStatusCode.OK)
{
MessageBox.Show(" Error: " + response.StatusDescription);
response.Close();
}
foreach (Cookie cook in response.Cookies)
{
MessageBox.Show(cook.Name + " " + cook.Value);
}
}
catch (Exception ex)
{
MessageBox.Show("POST Message Error: " + ex.Message);
}
}
I used Fiddler while I was logging in and found a request to https://www.linkedin.com/uas/login-submit containing the username and password. Found it? Now, if you want to look at it completely from an HTTP Request perspective, you will have to figure out how to generate the other data in the post data/cookie header using the other requests and responses that your browser sent and received to and from the site before this particular request (the information should be there). I think this will lead you to what you need to do, but there's some work to be done!
You're going to need more than you think to log in there is good documentation on how to do this just here, you are going to need an auth token etc, This is because like other services, for example google, they are using oauth2 to secure applications etc.
oauth works by issuing tokens and refreshing tokens and there's a bit of a learning curve but its not especially difficult.
Essentially the following happens
You register your application with linked in and they give you a
client secret.
You pass this code to linked in in your application
and they will generate an auth screen saying that the application is
requesting permission.
you then approve this and it will give you an access token
You then log in with the access token (access tokens on linkedin are valid for 60 days, you must refresh them by this time).
On the plus side the linked in api is pretty straight forward and once authorised you will be able to get stuff pretty easily. All of this is detailed in the link provided in nice step by step stages.
By the way there is also a nuget package that gives you access to profile information.
Try Install-Package LinkedIn
I should point out that the nuget package above gives you a login provider to help authenticate if you don't want to roll your own.
Added after your comments below.
If all you want to do is know how to send a post request here's a generic bit of code that does just that:
string url = "www.foo.bar.com";
using (var webClient= new WebClient())
{
var data = new NameValueCollection();
data["username"] = "<yourusername>";
data["password"] = "<yourPassword>";
var response = webClient.UploadValues(url, "POST", data);
}
note: because its a web uri you should use POST in the method argument here.
The problem you up against is that Linkedin uses a redirect within the login session and is differcult to catch.
So somehow within the login session you need to code that it redirects to the https://www.linkedin.com/nhome/?trk= this provides the user page access.
I am also testing with this, however did not manage to figure this part out, normally
httpWebRequest.AllowAutoRedirect = true;
should do the trick but not in this case it does not work.
So if you find the solution let me know, if I find will post it also.
I am building a WCF that encapsulates Google OAuth 2.0.
The plan: Client calls WCF endpoint which then redirects to the Google Sign In page for user authentication. On successful authentication, Google kicks back to the redirect URI and returns the Access Token in the response.
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
public class AdWordsOAuthService : IOAuthService
{
public string AuthenticateAndGetRefreshToken()
{
string refreshToken = string.Empty;
try
{
AuthenticateUser();
}
catch (Exception ex)
{
throw;
}
return refreshToken;
}
private void AuthenticateUser()
{
// build the SOAP header here...
string authUrl = "https://accounts.google.com/o/oauth2/auth"; //redirect to this url
string postData = "response_type=code"
+ "&client_id=" + HttpUtility.UrlEncode("9999999999999.apps.googleusercontent.com")
//+ "&client_secret=" + HttpUtility.UrlEncode("dsflkdfsljkdfskjldskjlfds")
+ "&redirect_uri=" + HttpUtility.UrlEncode("http://localhost:50306/NextOAuthService/AdWordsOAuthService/AuthenticateAndGetRefreshToken")
+ "&scope=" + HttpUtility.UrlEncode("https://adwords.google.com/api/adwords")
+ "&access_type=offline";
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
//handle webrequest stuff...
var request = (HttpWebRequest)WebRequest.Create(authUrl);// + postData);
if (request != null)
{
request.Method = "POST";
request.Timeout = 20000;
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = byteArray.Length; // byteArray.Length;
Stream dataStream = request.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
//attempt to redirect to the Adwords OAuth URL: https://adwords.google.com/api/adwords&?response.....blah blah
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.RedirectKeepVerb;
WebOperationContext.Current.OutgoingResponse.Location = response.ResponseUri.AbsoluteUri;
return;
}
}
}
What's Actually Happening: When the code attempts the redirect, I get following exception:
The content type text/html; charset=UTF-8 of the response message does not match the content type of the binding (application/soap+xml;> charset=utf-8)
When I examine the response (using fiddler), the response contains the actual HTML code for the Google OAuth Sign In page. So, instead of redirecting the WCF to the url, I am instead receiving an html response containing the page source.
How do I get around this and force the redirect?
I think you are miss understanding the calls a bit. The First URL that you are building there is the one that you should be displaying to the user asking if they want to let you access there data.
You need to wait for them to except. You need to deal with the Authentication Code. Google 3 Legged OAuth2 Flow
You should consider using Googles dot net client lib. It will handle all this for you.
Can any one guide me how to tackle with Linkedin Invitation API in c# asp.net. I want to send invitation to particular user from my app via this api, but don't find any sufficient information to start it. Can any one give me some example to start with. I have already get list of users from linkedin search api. Now i want to send invitation to those users.
Thanks in advanced. Hope best answer will come out.
Thanks
Finally, it's done. I have successfully implement linkedin invitation api with asp.net c#.
I am posting sample code here, for other users who want to implement it.
try
{
string uid=uniqueid of user,to whom you want to send request.
// if you get this user bysearch api or 1st connection, then from http-header response, you will find value field. split this value by ':' and store in two variable
string name=splitvalue1;
string namevalue=splitvalue2;
string xml = "<?xml version='1.0' encoding='UTF-8'?><mailbox-item><recipients><recipient><person path=\"/people/id=" + uid + "\" /></recipient></recipients>";
xml += "<subject>Invitation to Connect</subject>";
xml += "<body>Please join my professional network on LinkedIn.</body>";
xml += "<item-content><invitation-request><connect-type>friend</connect-type><authorization><name>" + name + "</name><value>" + namevalue + "</value></authorization></invitation-request></item-content></mailbox-item>";
string accessCodeUri = "https://api.linkedin.com/v1/people/~/mailbox?oauth2_access_token=" + Session["accessCode"]; // this is session value which you get on authorization success return by linkedin
WebRequest request = WebRequest.Create(accessCodeUri);
request.Method = "POST";
request.ContentType = "application/xml";
request.ContentLength = xml.Length;
StreamWriter requestWriter = new StreamWriter(request.GetRequestStream(), System.Text.Encoding.ASCII);
requestWriter.Write(xml);
requestWriter.Close();
WebResponse webResponse = request.GetResponse();
//success
}
catch(WebException exc)
{
}
Hope it helps other.
i have to implement push notification in my project.
It has sender(windows phone window application),wcf service and client(windows phone applcation).
How can i replace the sender and use my url to send and recieve notification from client?
i want sender to be some application in emulator itself that run parallely with the client and push data continously to the client.
how to develop such application
can anyone tell the way.
It sounds as though you are looking to use two WP7 apps to send messages back and forth to one another using the push notification functionality. Is that correct?
My understanding it that you will still require a each device to subscribe to a push notification service (MS hosted) using the unique URI sent back when the subscription is successful. It appears that SL3/4 can create HttpWebRequest objects and therefore should be able to formulate a correct package to send, however, the difficulty as I see it will be how to obtain the URI of the device you want to send the post to. Normally the post is sent to the subscriber, which knows its on URI as it was returned during the subscribing phase.
My WCF hosted code only works if the WCF knows the URI of the device, which is sent when the WCF method is called:
public bool sendTileUpdate(string tileText, string url, string image)
{
string TilePushXML = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
"<wp:Notification xmlns:wp=\"WPNotification\">" +
"<wp:Tile>" +
"<wp:BackgroundImage>{2}</wp:BackgroundImage>" +
"<wp:Count>{0}</wp:Count>" +
"<wp:Title>{1}</wp:Title>" +
"</wp:Tile>" +
"</wp:Notification>";
try
{
HttpWebRequest sendNotificationRequest = (HttpWebRequest)WebRequest.Create(url);
sendNotificationRequest.Method = "POST";
sendNotificationRequest.Headers = new WebHeaderCollection();
sendNotificationRequest.ContentType = "text/xml";
// Tile
sendNotificationRequest.Headers.Add("X-WindowsPhone-Target", "token");
sendNotificationRequest.Headers.Add("X-NotificationClass", "1");
string str = string.Format(TilePushXML, "", tileText, image);
byte[] strBytes = new UTF8Encoding().GetBytes(str);
sendNotificationRequest.ContentLength = strBytes.Length;
using (Stream requestStream = sendNotificationRequest.GetRequestStream())
{
requestStream.Write(strBytes, 0, strBytes.Length);
}
HttpWebResponse response = (HttpWebResponse)sendNotificationRequest.GetResponse();
string notificationStatus = response.Headers["X-NotificationStatus"];
string deviceConnectionStatus = response.Headers["X-DeviceConnectionStatus"];
return true;
}
catch (Exception e)
{
return false;
}
}
I know this is a TileNotification, but the principles are the same.
I understand that Mango (WP7.1 & SL4) will support sockets and this might be a more appropriate way for your devices to communicate!
Good luck,
Jason.