I need to upload files from client machine to a remote server and for that i have created a windows application which will work as client. It will select the required file and call the Web API.
Please find my client code as below :
//...other code removed for brevity
private void UploadFile(string filename)
{
Stream ms = new MemoryStream();
using (FileStream file = new FileStream(filename, FileMode.Open, FileAccess.Read))
{
var fileInfo = new FileInfo(filename);
byte[] bytes = new byte[file.Length];
file.Read(bytes, 0, (int)file.Length);
ms.Write(bytes, 0, (int)file.Length);
MultiPartFormUpload multiPartFormUpload = new MultiPartFormUpload();
List<FileInfo> files = new List<FileInfo>() { fileInfo };
try
{
MultiPartFormUpload.UploadResponse response = multiPartFormUpload.Upload("http://localhost:10458/api/Upload", files);
}
catch (Exception ex)
{
throw ex;
}
}
}
public class MultiPartFormUpload
{
public class MimePart
{
NameValueCollection _headers = new NameValueCollection();
byte[] _header;
public NameValueCollection Headers
{
get { return _headers; }
}
public byte[] Header
{
get { return _header; }
}
public long GenerateHeaderFooterData(string boundary)
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append("--");
stringBuilder.Append(boundary);
stringBuilder.AppendLine();
foreach (string key in _headers.AllKeys)
{
stringBuilder.Append(key);
stringBuilder.Append(": ");
stringBuilder.AppendLine(_headers[key]);
}
stringBuilder.AppendLine();
_header = Encoding.UTF8.GetBytes(stringBuilder.ToString());
return _header.Length + Data.Length + 2;
}
public Stream Data { get; set; }
}
public class UploadResponse
{
public UploadResponse(HttpStatusCode httpStatusCode, string responseBody)
{
HttpStatusCode = httpStatusCode;
ResponseBody = responseBody;
}
public HttpStatusCode HttpStatusCode { get; set; }
public string ResponseBody { get; set; }
}
public UploadResponse Upload(string url, List<FileInfo> files)
{
using (WebClient client = new WebClient())
{
List<MimePart> mimeParts = new List<MimePart>();
try
{
foreach (FileInfo file in files)
{
MimePart part = new MimePart();
string name = file.Extension.Substring(1);
string fileName = file.Name;
part.Headers["Content-Disposition"] = "form-data; name=\"" + name + "\"; filename=\"" + fileName + "\"";
part.Headers["Content-Type"] = "application/octet-stream";
part.Data = new MemoryStream(File.ReadAllBytes(file.FullName));
mimeParts.Add(part);
}
string boundary = "----------" + DateTime.Now.Ticks.ToString("x");
client.Headers.Add(HttpRequestHeader.ContentType, "multipart/form-data; boundary=" + boundary);
long contentLength = 0;
byte[] _footer = Encoding.UTF8.GetBytes("--" + boundary + "--\r\n");
foreach (MimePart mimePart in mimeParts)
{
contentLength += mimePart.GenerateHeaderFooterData(boundary);
}
byte[] buffer = new byte[8192];
byte[] afterFile = Encoding.UTF8.GetBytes("\r\n");
int read;
using (MemoryStream memoryStream = new MemoryStream())
{
foreach (MimePart mimePart in mimeParts)
{
memoryStream.Write(mimePart.Header, 0, mimePart.Header.Length);
while ((read = mimePart.Data.Read(buffer, 0, buffer.Length)) > 0)
memoryStream.Write(buffer, 0, read);
mimePart.Data.Dispose();
memoryStream.Write(afterFile, 0, afterFile.Length);
}
memoryStream.Write(_footer, 0, _footer.Length);
byte[] responseBytes = client.UploadData(url, memoryStream.ToArray());
string responseString = Encoding.UTF8.GetString(responseBytes);
return new UploadResponse(HttpStatusCode.OK, responseString);
}
}
catch (Exception ex)
{
foreach (MimePart part in mimeParts)
if (part.Data != null)
part.Data.Dispose();
if (ex.GetType().Name == "WebException")
{
WebException webException = (WebException)ex;
HttpWebResponse response = (HttpWebResponse)webException.Response;
string responseString;
using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8))
{
responseString = reader.ReadToEnd();
}
return new UploadResponse(response.StatusCode, responseString);
}
else
{
throw;
}
}
}
}
}
Please find Web API code as below :
public async Task<HttpResponseMessage> Post()
{
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
string fileSaveLocation = HttpContext.Current.Server.MapPath("~/upload/files");
CustomMultipartFormDataStreamProvider provider = new CustomMultipartFormDataStreamProvider(fileSaveLocation);
List<string> files = new List<string>();
try
{
await Request.Content.ReadAsMultipartAsync(provider);
foreach (MultipartFileData file in provider.FileData)
{
files.Add(Path.GetFileName(file.LocalFileName));
}
// Send OK Response along with saved file names to the client.
return Request.CreateResponse(HttpStatusCode.OK, files);
}
catch (System.Exception e)
{
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e);
}
}
public class CustomMultipartFormDataStreamProvider : MultipartFormDataStreamProvider
{
public CustomMultipartFormDataStreamProvider(string path) : base(path) { }
public override string GetLocalFileName(HttpContentHeaders headers)
{
return headers.ContentDisposition.FileName.Replace("\"", string.Empty);
}
}
I am able to hit the Web API with the client code but fileInfo.Length is coming 0.
Please let me know what i am missing in Client or Web API code. Thanks !
I have an OpenIdConnect Server I'm connecting to an I would like to forward token data the first time logging in to be stored on the server. Currently I'm doing this to forward the access token
var xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.onload = function () {
log(xhr.status, JSON.parse(xhr.responseText));
}
xhr.setRequestHeader("Authorization", "Bearer " + user.access_token);
xhr.send();
I want to send the Profile Data as well but I don't know the proper header.
How can I do something like this:
xhr.setRequestHeader("Authorization-Profile", "Bearer " + user.profile);
Does anyone know the proper header so I can add these claims to the access token.
Here is an example of what we did in one of our project:
Created a common API response class as below:
public class ApiCommonResponse
{
public object Object { get; set; }
public int httpStatus { get; set; }
public string httpErrorMessage { get; set; }
}
And a generic method to call GET and POST API endpoints. This method will map the response to the supplied data model and will return you the object.
public static ApiCommonResponse GetApiData<T>(string token, T dataModel, string apiEndPoint = null)
{
var responseText = "";
var apiCommonResponse = new ApiCommonResponse();
if (apiEndPoint != null)
{
var request = (HttpWebRequest)WebRequest.Create(apiEndPoint);
request.Method = "GET";
request.ContentType = "application/json";
request.Headers.Add("Authorization", "Bearer " + token);
request.Headers.Add("X-Api-Version", "");
try
{
var httpResponse = (HttpWebResponse)request.GetResponse();
var stream = httpResponse.GetResponseStream();
if (stream != null)
{
using (var streamReader = new StreamReader(stream))
{
responseText = streamReader.ReadToEnd();
}
}
}
catch (WebException we)
{
var stream = we.Response.GetResponseStream();
if (stream != null)
{
var resp = new StreamReader(stream).ReadToEnd();
dynamic obj = JsonConvert.DeserializeObject(resp);
throw new Exception(obj.ToString());
}
}
}
var jsonSettings = new JsonSerializerSettings { MissingMemberHandling = MissingMemberHandling.Ignore };
apiCommonResponse.Object = JsonConvert.DeserializeObject<T>(responseText, jsonSettings);
apiCommonResponse.httpStatus = 0;
return apiCommonResponse;
}
public static ApiCommonResponse PostApiData<T>(string username, string token, T dataModel, string apiEndPoint = null)
{
var apiCommonResponse = new ApiCommonResponse();
if (apiEndPoint == null) return null;
var webRequest = WebRequest.Create(apiEndPoint);
webRequest.Method = "POST";
webRequest.Timeout = 20000;
webRequest.ContentType = "application/json";
request.Headers.Add("Authorization", "Bearer " + token);
webRequest.Headers.Add("X-Api-Version", "");
using (var requeststreams = webRequest.GetRequestStream())
{
using (var sw = new StreamWriter(requeststreams))
{
sw.Write(JsonConvert.SerializeObject(dataModel));
}
}
try
{
var httpStatus = (((HttpWebResponse)webRequest.GetResponse()).StatusCode);
var httpMessage = (((HttpWebResponse)webRequest.GetResponse()).StatusDescription);
using (var s = webRequest.GetResponse().GetResponseStream())
{
if (s == null) return null;
using (var sr = new StreamReader(s))
{
var responseObj = sr.ReadToEnd();
if (!string.IsNullOrEmpty(responseObj))
{
apiCommonResponse = JsonConvert.DeserializeObject<ApiCommonResponse>(responseObj);
}
}
apiCommonResponse.httpStatus = (int)httpStatus;
apiCommonResponse.httpErrorMessage = httpMessage;
apiCommonResponse.Object = apiCommonResponse.Object;
}
}
catch (WebException we)
{
var stream = we.Response.GetResponseStream();
if (stream != null)
{
var resp = new StreamReader(stream).ReadToEnd();
dynamic obj = JsonConvert.DeserializeObject(resp);
throw new Exception(obj.ToString());
}
}
return apiCommonResponse;
}
Failed to get response for large file HTTP put create file using c#
I am using file watcher service service monitor, when user created file or folder we are uploading to cloud
if file size more than 512 MB it is taking too much time to get the response
here I am confusing here the issue with my code or server
and reason for this error
if any changes on my code suggest me.
{
var fileFolderObj1 = new FileFolder();
var postURL = apiBaseUri + "/filefolder/create/file/user/" + userId; // +"?type=file";
code = HttpStatusCode.OK;
HttpWebResponse response = null;
FileInfo f = new FileInfo(filePath);
long filesizeF = f.Length;
try
{
string selectedFile = null;
selectedFile = filePath;
var fi = System.IO.Path.GetFileName(filePath);
////commented for some reason
var postParameters = new Dictionary<string, object>();
postParameters.Add("file", new FileParameter(filePath, ""));
postParameters.Add("parentId", parentId);
postParameters.Add("newName", fi);
postParameters.Add("cloudId", cloudId);
postParameters.Add("isSecure", isSecure);
//postParameters.Add("fileSize", fi.Length);
postParameters.Add("fileSize", filesizeF);
var userAgent = "Desktop";
var formDataBoundary = "----WebKitFormBoundary" + DateTime.Now.Ticks.ToString("x");
var uri = new Uri(postURL);
var createFileRequest = WebRequest.Create(uri) as HttpWebRequest;
this.SetBasicAuthHeader(createFileRequest, userId, password);
createFileRequest.ContentType = "multipart/form-data";
createFileRequest.Method = "PUT";
createFileRequest.Timeout = System.Threading.Timeout.Infinite;
createFileRequest.KeepAlive = false;/*true;*/
createFileRequest.UserAgent = userAgent;
createFileRequest.CookieContainer = new CookieContainer();
try
{
using (var requestStream = createFileRequest.GetRequestStream())
{
}
using (response = (HttpWebResponse)createFileRequest.GetResponse())
{
StreamReader(response.GetResponseStream()).ReadToEnd();
fileFolderObj1 = JsonConvert.DeserializeObject<FileFolder>(reslut);
}
}
catch (Exception exc)
{
if (response != null)
{
code = response.StatusCode;
}
}
}
catch (Exception exc)
{
}
}
}
private static readonly Encoding encoding = Encoding.UTF8;
private void WriteMultipartFormData(Dictionary<string, object> postParameters, string boundary, Stream requestStream, ILogService logService = null)
{
var needsCLRF = false;
foreach (var param in postParameters)
{
// Skip it on the first parameter, add it to subsequent parameters.
if (needsCLRF)
{
requestStream.Write(encoding.GetBytes("\r\n"), 0, encoding.GetByteCount("\r\n"));
}
needsCLRF = true;
if (param.Value is FileParameter)
{
var fileToUpload = (FileParameter)param.Value;
// Add just the first part of this param, since we will write the file data directly to the Stream
var header = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{2}\"\r\nContent-Type: {3}\r\n\r\n",
boundary,
param.Key,
fileToUpload.FileName ?? param.Key,
fileToUpload.ContentType ?? "application/octet-stream");
requestStream.Write(encoding.GetBytes(header), 0, encoding.GetByteCount(header));
// Write the file data directly to the Stream, rather than serializing it to a string.
FileStream fileStream = new FileStream(fileToUpload.FileName, FileMode.Open, FileAccess.Read);
byte[] buffer = new byte[4096];
int bytesRead = 0;
while ((bytesRead = fileStream.Read(buffer, 0,buffer.Length)) != 0)
{
requestStream.Write(buffer, 0, bytesRead);
logService.Debug("WRITEMULTIPART FORM DATA Bufferlent Running :{0}", bytesRead);
}
fileStream.Close();
}
else
{
var postData = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"\r\n\r\n{2}",
boundary,
param.Key,
param.Value);
requestStream.Write(encoding.GetBytes(postData), 0, encoding.GetByteCount(postData));
}
}
// Add the end of the request. Start with a newline
var footer = "\r\n--" + boundary + "--\r\n";
requestStream.Write(encoding.GetBytes(footer), 0, encoding.GetByteCount(footer));
}
}
I am using this code to send notification message by C# with GCM, using Winforms, Webforms, whatever. Now I want to send to FCM (Firebase Cloud Messaging). Should I update my code? :
public class AndroidGCMPushNotification
{
public AndroidGCMPushNotification()
{
//
// TODO: Add constructor logic here
//
}
public string SendNotification(string deviceId, string message)
{
string SERVER_API_KEY = "server api key";
var SENDER_ID = "application number";
var value = message;
WebRequest tRequest;
tRequest = WebRequest.Create("https://android.googleapis.com/gcm/send");
tRequest.Method = "post";
tRequest.ContentType = " application/x-www-form-urlencoded;charset=UTF-8";
tRequest.Headers.Add(string.Format("Authorization: key={0}", SERVER_API_KEY));
tRequest.Headers.Add(string.Format("Sender: id={0}", SENDER_ID));
string postData = "collapse_key=score_update&time_to_live=108&delay_while_idle=1&data.message=" + value + "&data.time=" + System.DateTime.Now.ToString() + "®istration_id=" + deviceId + "";
Console.WriteLine(postData);
Byte[] byteArray = Encoding.UTF8.GetBytes(postData);
tRequest.ContentLength = byteArray.Length;
Stream dataStream = tRequest.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
WebResponse tResponse = tRequest.GetResponse();
dataStream = tResponse.GetResponseStream();
StreamReader tReader = new StreamReader(dataStream);
String sResponseFromServer = tReader.ReadToEnd();
tReader.Close();
dataStream.Close();
tResponse.Close();
return sResponseFromServer;
}
}
but the GCM was changed to FCM. Is this same code to send the notification?
Where can I find the SERVER_API_KEY? Is the same solution?
firebase cloud messaging with c#:
working all .net platform (asp.net, .netmvc, .netcore)
WebRequest tRequest = WebRequest.Create("https://fcm.googleapis.com/fcm/send");
tRequest.Method = "post";
//serverKey - Key from Firebase cloud messaging server
tRequest.Headers.Add(string.Format("Authorization: key={0}", "AIXXXXXX...."));
//Sender Id - From firebase project setting
tRequest.Headers.Add(string.Format("Sender: id={0}", "XXXXX.."));
tRequest.ContentType = "application/json";
var payload = new
{
to = "e8EHtMwqsZY:APA91bFUktufXdsDLdXXXXXX..........XXXXXXXXXXXXXX",
priority = "high",
content_available = true,
notification = new
{
body = "Test",
title = "Test",
badge = 1
},
data = new
{
key1 = "value1",
key2 = "value2"
}
};
string postbody = JsonConvert.SerializeObject(payload).ToString();
Byte[] byteArray = Encoding.UTF8.GetBytes(postbody);
tRequest.ContentLength = byteArray.Length;
using (Stream dataStream = tRequest.GetRequestStream())
{
dataStream.Write(byteArray, 0, byteArray.Length);
using (WebResponse tResponse = tRequest.GetResponse())
{
using (Stream dataStreamResponse = tResponse.GetResponseStream())
{
if (dataStreamResponse != null) using (StreamReader tReader = new StreamReader(dataStreamResponse))
{
String sResponseFromServer = tReader.ReadToEnd();
//result.Response = sResponseFromServer;
}
}
}
}
Here is another approach of writing Notification Service inside ASP.Net REST API.
public async Task<bool> NotifyAsync(string to, string title, string body)
{
try
{
// Get the server key from FCM console
var serverKey = string.Format("key={0}", "Your server key - use app config");
// Get the sender id from FCM console
var senderId = string.Format("id={0}", "Your sender id - use app config");
var data = new
{
to, // Recipient device token
notification = new { title, body }
};
// Using Newtonsoft.Json
var jsonBody = JsonConvert.SerializeObject(data);
using (var httpRequest = new HttpRequestMessage(HttpMethod.Post, "https://fcm.googleapis.com/fcm/send"))
{
httpRequest.Headers.TryAddWithoutValidation("Authorization", serverKey);
httpRequest.Headers.TryAddWithoutValidation("Sender", senderId);
httpRequest.Content = new StringContent(jsonBody, Encoding.UTF8, "application/json");
using (var httpClient = new HttpClient())
{
var result = await httpClient.SendAsync(httpRequest);
if (result.IsSuccessStatusCode)
{
return true;
}
else
{
// Use result.StatusCode to handle failure
// Your custom error handler here
_logger.LogError($"Error sending notification. Status Code: {result.StatusCode}");
}
}
}
}
catch (Exception ex)
{
_logger.LogError($"Exception thrown in Notify Service: {ex}");
}
return false;
}
References:
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
I have posted this answer as this question was viewed most and this server side code was written in VS 2015 in C# for sending push notification either single device based on device id or subscribed topic to Xamarin Android app
public class FCMPushNotification
{
public FCMPushNotification()
{
// TODO: Add constructor logic here
}
public bool Successful
{
get;
set;
}
public string Response
{
get;
set;
}
public Exception Error
{
get;
set;
}
public FCMPushNotification SendNotification(string _title, string _message, string _topic)
{
FCMPushNotification result = new FCMPushNotification();
try
{
result.Successful = true;
result.Error = null;
// var value = message;
var requestUri = "https://fcm.googleapis.com/fcm/send";
WebRequest webRequest = WebRequest.Create(requestUri);
webRequest.Method = "POST";
webRequest.Headers.Add(string.Format("Authorization: key={0}", YOUR_FCM_SERVER_API_KEY));
webRequest.Headers.Add(string.Format("Sender: id={0}", YOUR_FCM_SENDER_ID));
webRequest.ContentType = "application/json";
var data = new
{
// to = YOUR_FCM_DEVICE_ID, // Uncoment this if you want to test for single device
to="/topics/"+_topic, // this is for topic
notification=new
{
title=_title,
body=_message,
//icon="myicon"
}
};
var serializer = new JavaScriptSerializer();
var json = serializer.Serialize(data);
Byte[] byteArray = Encoding.UTF8.GetBytes(json);
webRequest.ContentLength = byteArray.Length;
using (Stream dataStream = webRequest.GetRequestStream())
{
dataStream.Write(byteArray, 0, byteArray.Length);
using (WebResponse webResponse = webRequest.GetResponse())
{
using (Stream dataStreamResponse = webResponse.GetResponseStream())
{
using (StreamReader tReader = new StreamReader(dataStreamResponse))
{
String sResponseFromServer = tReader.ReadToEnd();
result.Response = sResponseFromServer;
}
}
}
}
}
catch(Exception ex)
{
result.Successful = false;
result.Response = null;
result.Error = ex;
}
return result;
}
}
and its uses
// start sending push notification to apps
FCMPushNotification fcmPush = new FCMPushNotification();
fcmPush.SendNotification("your notificatin title", "Your body message","news");
// end push notification
Yes, you should update your code to use Firebase Messaging interface.
There's a GitHub Project for that here.
using Stimulsoft.Base.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;
namespace _WEBAPP
{
public class FireBasePush
{
private string FireBase_URL = "https://fcm.googleapis.com/fcm/send";
private string key_server;
public FireBasePush(String Key_Server)
{
this.key_server = Key_Server;
}
public dynamic SendPush(PushMessage message)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(FireBase_URL);
request.Method = "POST";
request.Headers.Add("Authorization", "key=" + this.key_server);
request.ContentType = "application/json";
string json = JsonConvert.SerializeObject(message);
//json = json.Replace("content_available", "content-available");
byte[] byteArray = Encoding.UTF8.GetBytes(json);
request.ContentLength = byteArray.Length;
Stream dataStream = request.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
HttpWebResponse respuesta = (HttpWebResponse)request.GetResponse();
if (respuesta.StatusCode == HttpStatusCode.Accepted || respuesta.StatusCode == HttpStatusCode.OK || respuesta.StatusCode == HttpStatusCode.Created)
{
StreamReader read = new StreamReader(respuesta.GetResponseStream());
String result = read.ReadToEnd();
read.Close();
respuesta.Close();
dynamic stuff = JsonConvert.DeserializeObject(result);
return stuff;
}
else
{
throw new Exception("Ocurrio un error al obtener la respuesta del servidor: " + respuesta.StatusCode);
}
}
}
public class PushMessage
{
private string _to;
private PushMessageData _notification;
private dynamic _data;
private dynamic _click_action;
public dynamic data
{
get { return _data; }
set { _data = value; }
}
public string to
{
get { return _to; }
set { _to = value; }
}
public PushMessageData notification
{
get { return _notification; }
set { _notification = value; }
}
public dynamic click_action
{
get
{
return _click_action;
}
set
{
_click_action = value;
}
}
}
public class PushMessageData
{
private string _title;
private string _text;
private string _sound = "default";
//private dynamic _content_available;
private string _click_action;
public string sound
{
get { return _sound; }
set { _sound = value; }
}
public string title
{
get { return _title; }
set { _title = value; }
}
public string text
{
get { return _text; }
set { _text = value; }
}
public string click_action
{
get
{
return _click_action;
}
set
{
_click_action = value;
}
}
}
}
Based on Teste's code .. I can confirm the following works. I can't say whether or not this is "good" code, but it certainly works and could get you back up and running quickly if you ended up with GCM to FCM server problems!
public AndroidFCMPushNotificationStatus SendNotification(string serverApiKey, string senderId, string deviceId, string message)
{
AndroidFCMPushNotificationStatus result = new AndroidFCMPushNotificationStatus();
try
{
result.Successful = false;
result.Error = null;
var value = message;
WebRequest tRequest = WebRequest.Create("https://fcm.googleapis.com/fcm/send");
tRequest.Method = "post";
tRequest.ContentType = "application/x-www-form-urlencoded;charset=UTF-8";
tRequest.Headers.Add(string.Format("Authorization: key={0}", serverApiKey));
tRequest.Headers.Add(string.Format("Sender: id={0}", senderId));
string postData = "collapse_key=score_update&time_to_live=108&delay_while_idle=1&data.message=" + value + "&data.time=" + System.DateTime.Now.ToString() + "®istration_id=" + deviceId + "";
Byte[] byteArray = Encoding.UTF8.GetBytes(postData);
tRequest.ContentLength = byteArray.Length;
using (Stream dataStream = tRequest.GetRequestStream())
{
dataStream.Write(byteArray, 0, byteArray.Length);
using (WebResponse tResponse = tRequest.GetResponse())
{
using (Stream dataStreamResponse = tResponse.GetResponseStream())
{
using (StreamReader tReader = new StreamReader(dataStreamResponse))
{
String sResponseFromServer = tReader.ReadToEnd();
result.Response = sResponseFromServer;
}
}
}
}
}
catch (Exception ex)
{
result.Successful = false;
result.Response = null;
result.Error = ex;
}
return result;
}
public class AndroidFCMPushNotificationStatus
{
public bool Successful
{
get;
set;
}
public string Response
{
get;
set;
}
public Exception Error
{
get;
set;
}
}
You need change url from https://android.googleapis.com/gcm/send to https://fcm.googleapis.com/fcm/send and change your app library too. this tutorial can help you https://firebase.google.com/docs/cloud-messaging/server#implementing-http-connection-server-protocol
Try to send a json object.
Replace this:
tRequest.ContentType = " application/x-www-form-urlencoded;charset=UTF-8";
string postData = "collapse_key=score_update&time_to_live=108&delay_while_idle=1&data.message=" + value + "&data.time=" + System.DateTime.Now.ToString() + "®istration_id=" + deviceId + "";
Console.WriteLine(postData);
Byte[] byteArray = Encoding.UTF8.GetBytes(postData);
For this:
tRequest.ContentType = "application/json";
var data = new
{
to = deviceId,
notification = new
{
body = "This is the message",
title = "This is the title",
icon = "myicon"
}
};
var serializer = new JavaScriptSerializer();
var json = serializer.Serialize(data);
Byte[] byteArray = Encoding.UTF8.GetBytes(json);
Here's the code for server side firebase cloud request from C# / Asp.net.
Please note that your client side should have same topic.
e.g.
FirebaseMessaging.getInstance().subscribeToTopic("news");
public String SendNotificationFromFirebaseCloud()
{
var result = "-1";
var webAddr = "https://fcm.googleapis.com/fcm/send";
var httpWebRequest = (HttpWebRequest)WebRequest.Create(webAddr);
httpWebRequest.ContentType = "application/json";
httpWebRequest.Headers.Add("Authorization:key=" + YOUR_FIREBASE_SERVER_KEY);
httpWebRequest.Method = "POST";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
string json = "{\"to\": \"/topics/news\",\"data\": {\"message\": \"This is a Firebase Cloud Messaging Topic Message!\",}}";
streamWriter.Write(json);
streamWriter.Flush();
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
result = streamReader.ReadToEnd();
}
return result;
}
You can use this library, makes it seamless to send push notifications using Firebase Service from a C# backend download here
public SendNotice(int deviceType, string deviceToken, string message, int badge, int status, string sound)
{
AndroidFCMPushNotificationStatus result = new AndroidFCMPushNotificationStatus();
try
{
result.Successful = false;
result.Error = null;
var value = message;
WebRequest tRequest = WebRequest.Create("https://fcm.googleapis.com/fcm/send");
tRequest.Method = "post";
tRequest.ContentType = "application/json";
var serializer = new JavaScriptSerializer();
var json = "";
tRequest.Headers.Add(string.Format("Authorization: key={0}", "AA******"));
tRequest.Headers.Add(string.Format("Sender: id={0}", "11********"));
if (DeviceType == 2)
{
var body = new
{
to = deviceToken,
data = new
{
custom_notification = new
{
title = "Notification",
body = message,
sound = "default",
priority = "high",
show_in_foreground = true,
targetScreen = notificationType,//"detail",
},
},
priority = 10
};
json = serializer.Serialize(body);
}
else
{
var body = new
{
to = deviceToken,
content_available = true,
notification = new
{
title = "Notification",
body = message,
sound = "default",
show_in_foreground = true,
},
data = new
{
targetScreen = notificationType,
id = 0,
},
priority = 10
};
json = serializer.Serialize(body);
}
Byte[] byteArray = Encoding.UTF8.GetBytes(json);
tRequest.ContentLength = byteArray.Length;
using (Stream dataStream = tRequest.GetRequestStream())
{
dataStream.Write(byteArray, 0, byteArray.Length);
using (WebResponse tResponse = tRequest.GetResponse())
{
using (Stream dataStreamResponse = tResponse.GetResponseStream())
{
using (StreamReader tReader = new StreamReader(dataStreamResponse))
{
String sResponseFromServer = tReader.ReadToEnd();
result.Response = sResponseFromServer;
}
}
}
}
}
catch (Exception ex)
{
result.Successful = false;
result.Response = null;
result.Error = ex;
}
}
I write this code and It's worked for me .
public static string ExcutePushNotification(string title, string msg, string fcmToken, object data)
{
var serverKey = "AAAA*******************";
var senderId = "3333333333333";
var result = "-1";
var httpWebRequest = (HttpWebRequest)WebRequest.Create("https://fcm.googleapis.com/fcm/send");
httpWebRequest.ContentType = "application/json";
httpWebRequest.Headers.Add(string.Format("Authorization: key={0}", serverKey));
httpWebRequest.Headers.Add(string.Format("Sender: id={0}", senderId));
httpWebRequest.Method = "POST";
var payload = new
{
notification = new
{
title = title,
body = msg,
sound = "default"
},
data = new
{
info = data
},
to = fcmToken,
priority = "high",
content_available = true,
};
var serializer = new JavaScriptSerializer();
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
string json = serializer.Serialize(payload);
streamWriter.Write(json);
streamWriter.Flush();
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
result = streamReader.ReadToEnd();
}
return result;
}
I am using this approach and it is working fine:
public class PushNotification
{
private static readonly ILog Logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
// firebase
private static Uri FireBasePushNotificationsURL = new Uri("https://fcm.googleapis.com/fcm/send");
private static string ServerKey = ConfigurationManager.AppSettings["FIREBASESERVERKEY"];
public static async Task<bool> SendPushNotification(List<SendNotificationModel> notificationData)
{
try
{
bool sent = false;
foreach (var data in notificationData)
{
var messageInformation = new Message()
{
notification = new Notification()
{
title = data.Title,
text = data.Message,
ClickAction = "FCM_PLUGIN_ACTIVITY"
},
data = data.data,
priority="high",
to =data.DeviceId
};
string jsonMessage = JsonConvert.SerializeObject(messageInformation);
//Create request to Firebase API
var request = new HttpRequestMessage(HttpMethod.Post, FireBasePushNotificationsURL);
request.Headers.TryAddWithoutValidation("Authorization", "key=" + ServerKey);
request.Content = new StringContent(jsonMessage, Encoding.UTF8, "application/json");
HttpResponseMessage result;
using (var client = new HttpClient())
{
result = await client.SendAsync(request);
sent = result.IsSuccessStatusCode;
}
}
return sent;
}
catch(Exception ex)
{
Logger.Error(ex);
return false;
}
}
}
Following Approach, I have used for writing Firebase Notification Service inside ASP.Net REST API.
public async Task<bool> NotifyAsync(string to, string title, string body)
{
try
{
//Server key from FCM console
var serverKey = string.Format("key={0}", "Provide your Server key here from Fibase console");
//Sender id from FCM console
var senderId = string.Format("id={0}", "Provide your Sender Id here from Firebase Console");
var data = new
{
to, // Recipient device token
notification = new { title, body }
};
// Using Newtonsoft.Json
var jsonBody = JsonConvert.SerializeObject(data);
using (var httpRequest = new HttpRequestMessage(HttpMethod.Post, "https://fcm.googleapis.com/fcm/send"))
{
httpRequest.Headers.TryAddWithoutValidation("Authorization", serverKey);
httpRequest.Headers.TryAddWithoutValidation("Sender", senderId);
httpRequest.Content = new StringContent(jsonBody, Encoding.UTF8, "application/json");
using (var httpClient = new HttpClient())
{
var result = await httpClient.SendAsync(httpRequest);
if (result.IsSuccessStatusCode)
{
return true;
}
else
{
// Use result.StatusCode to handle failure
// Your custom error handler here
return false;
}
}
}
}
catch (Exception ex)
{
throw ex;
}
return false;
}
Refer This blog for send Group Notification
https://firebase.google.com/docs/cloud-messaging/android/send-multiple
HI i have a webservice IIS with this code:
// Implements multipart/form-data POST in C# http://www.ietf.org/rfc/rfc2388.txt
// http://www.briangrinstead.com/blog/multipart-form-post-in-c
public static class FormUpload
{
private static readonly Encoding encoding = Encoding.UTF8;
public static HttpWebResponse MultipartFormDataPost(string postUrl, string userAgent, Dictionary<string, object> postParameters)
{
string formDataBoundary = String.Format("----------{0:N}", Guid.NewGuid());
string contentType = "multipart/form-data; boundary=" + formDataBoundary;
byte[] formData = GetMultipartFormData(postParameters, formDataBoundary);
return PostForm(postUrl, userAgent, contentType, formData);
}
private static HttpWebResponse PostForm(string postUrl, string userAgent, string contentType, byte[] formData)
{
HttpWebRequest request = WebRequest.Create(postUrl) as HttpWebRequest;
if (request == null)
{
throw new NullReferenceException("request is not a http request");
}
// Set up the request properties.
request.Method = "POST";
request.ContentType = contentType;
request.UserAgent = userAgent;
request.CookieContainer = new CookieContainer();
request.ContentLength = formData.Length;
// You could add authentication here as well if needed:
// request.PreAuthenticate = true;
// request.AuthenticationLevel = System.Net.Security.AuthenticationLevel.MutualAuthRequested;
// request.Headers.Add("Authorization", "Basic " + Convert.ToBase64String(System.Text.Encoding.Default.GetBytes("username" + ":" + "password")));
// Send the form data to the request.
using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(formData, 0, formData.Length);
requestStream.Close();
}
return request.GetResponse() as HttpWebResponse;
}
private static byte[] GetMultipartFormData(Dictionary<string, object> postParameters, string boundary)
{
Stream formDataStream = new System.IO.MemoryStream();
bool needsCLRF = false;
foreach (var param in postParameters)
{
// Thanks to feedback from commenters, add a CRLF to allow multiple parameters to be added.
// Skip it on the first parameter, add it to subsequent parameters.
if (needsCLRF)
formDataStream.Write(encoding.GetBytes("\r\n"), 0, encoding.GetByteCount("\r\n"));
needsCLRF = true;
if (param.Value is FileParameter)
{
FileParameter fileToUpload = (FileParameter)param.Value;
// Add just the first part of this param, since we will write the file data directly to the Stream
string header = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{2}\";\r\nContent-Type: {3}\r\n\r\n",
boundary,
param.Key,
fileToUpload.FileName ?? param.Key,
fileToUpload.ContentType ?? "application/octet-stream");
formDataStream.Write(encoding.GetBytes(header), 0, encoding.GetByteCount(header));
// Write the file data directly to the Stream, rather than serializing it to a string.
formDataStream.Write(fileToUpload.File, 0, fileToUpload.File.Length);
}
else
{
string postData = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"\r\n\r\n{2}",
boundary,
param.Key,
param.Value);
formDataStream.Write(encoding.GetBytes(postData), 0, encoding.GetByteCount(postData));
}
}
// Add the end of the request. Start with a newline
string footer = "\r\n--" + boundary + "--\r\n";
formDataStream.Write(encoding.GetBytes(footer), 0, encoding.GetByteCount(footer));
// Dump the Stream into a byte[]
formDataStream.Position = 0;
byte[] formData = new byte[formDataStream.Length];
formDataStream.Read(formData, 0, formData.Length);
formDataStream.Close();
return formData;
}
public class FileParameter
{
public byte[] File { get; set; }
public string FileName { get; set; }
public string ContentType { get; set; }
public FileParameter(byte[] file) : this(file, null) { }
public FileParameter(byte[] file, string filename) : this(file, filename, null) { }
public FileParameter(byte[] file, string filename, string contenttype)
{
File = file;
FileName = filename;
ContentType = contenttype;
}
}
}
Obtain from here: Multipart forms from C# client
But now, in mi android aplicattion i have this:
HttpParams httpParameters = new BasicHttpParams();
int timeoutConnection = 300000;
HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
int timeoutSocket = 300000;
HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
HttpClient httpClient = new DefaultHttpClient(httpParameters);
HttpPost postRequest = new HttpPost("http://172.21.1.87:9999/Service1.svc");
ByteArrayBody bab = new ByteArrayBody(ficheroAEnviar, "prueba.jpg");
MultipartEntity reqEntity = new MultipartEntity();
postRequest.addHeader("Content-Type", " multipart/form-data");
reqEntity.addPart("Dictionary", new FileBody(new File(fileUri.toString(), "application/zip")));
reqEntity.addPart("boundary", new StringBody("envio"));
postRequest.setEntity(reqEntity);
HttpResponse response = httpClient.execute(postRequest);
BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
String sResponse;
StringBuilder s = new StringBuilder();
postRequest.getAllHeaders();
while ((sResponse = reader.readLine()) != null) {
s = s.append(sResponse);
}
System.out.println("Response: " + s);
}
catch (Exception e) {
// handle exception here
Log.e(e.getClass().getName(), e.getMessage());
}
}
But it return me Bad request 400 error. Can i use the c# code to upload a multipartentity file with android or a need to make any change in some code?
Anyone have a example en c# and android to make this? Is for uppload videos about 10 or 15 MB.
Thanks
dont use multipart entity instead use as here you define the bounderies it is easy
try it
HttpURLConnection connection = null;
DataOutputStream outputStream = null;
DataInputStream inputStream = null;
String pathToOurFile = "/data/file_to_send.mp3";
String urlServer = "http://192.168.1.1/handle_upload.php";
String lineEnd = "\r\n";
String twoHyphens = "--";
String boundary = "*****";
int bytesRead, bytesAvailable, bufferSize;
byte[] buffer;
int maxBufferSize = 1*1024*1024;
try
{
FileInputStream fileInputStream = new FileInputStream(new File(pathToOurFile) );
URL url = new URL(urlServer);
connection = (HttpURLConnection) url.openConnection();
// Allow Inputs & Outputs
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(false);
// Enable POST method
connection.setRequestMethod("POST");
connection.setRequestProperty("Connection", "Keep-Alive");
connection.setRequestProperty("Content-Type", "multipart/form-data;boundary="+boundary);
outputStream = new DataOutputStream( connection.getOutputStream() );
outputStream.writeBytes(twoHyphens + boundary + lineEnd);
outputStream.writeBytes("Content-Disposition: form-data; name=\"uploadedfile\";filename=\""+pathToOurFile +"\"" + lineEnd);
outputStream.writeBytes(lineEnd);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = new byte[bufferSize];
// Read file
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
while (bytesRead > 0)
{
outputStream.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}
outputStream.writeBytes(lineEnd);
outputStream.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
// Responses from the server (code and message)
serverResponseCode = connection.getResponseCode();
serverResponseMessage = connection.getResponseMessage();
fileInputStream.close();
outputStream.flush();
outputStream.close();
}
catch (Exception ex)
{
//Exception handling
}
courtesy rafel