GCM request in Asp.net - asp.net

I have reffered this link for sending GCM request and it is working perfectly fine. gcm-push-notification-with-asp-net
I referred one more link to post JSON how-to-post-json-to-the-server
On the basis of second link I have tried the following code.
var httprequest = (HttpWebRequest)WebRequest.Create("https://gcm-http.googleapis.com/gcm/send");
httprequest.ContentType = "application/json";
httprequest.Method = "POST";
httprequest.Headers.Add(string.Format("Authorization: key={0}", GCM.APIKey));
httprequest.Headers.Add(string.Format("Sender: id={0}", GCM.ProjectNo));
using (var streamWriter = new StreamWriter(httprequest.GetRequestStream()))
{
string json = new JavaScriptSerializer().Serialize(new GCMValues
{
delay_while_idle = false,
priority = "high",
registration_id = regId,
data = new MessagesValues
{
message = message
}
});
streamWriter.Write(json);
streamWriter.Flush();
streamWriter.Close();
}
var httpResponse = (HttpWebResponse)httprequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
}
Properties that I have used
public class GCMValues
{
public Object data { get; set; }
public bool delay_while_idle { get; set; }
public String priority { get; set; }
public String registration_id { get; set; }
}
public class MessagesValues
{
public String message { get; set; }
public DateTime? time { get; set; }
}
The problem I am facing is at line var httpResponse =(HttpWebResponse)httprequest.GetResponse();
I am getting a response of bad request.
Where I went wrong or what could be done to pass the values in JSON format for GCM post request.
Thanks in advance.

You need registration_ids (plural) not registration_id (singular) in the JSON. It is an array of strings , not a single string value.
If you check the GCM documentation it gives all the JSON options.
Elsewhere the documentation details how to use to if you have just one token to send a notification to, as in this example:
{
"to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"notification" : {
"body" : "great match!",
"title" : "Portugal vs. Denmark",
"icon" : "myicon"
}
}

I have used the following way to get it done, and it worked.
var httprequest = (HttpWebRequest)WebRequest.Create("https://gcm-http.googleapis.com/gcm/send");
httprequest.ContentType = "application/json";
httprequest.Method = "POST";
httprequest.Headers.Add(string.Format("Authorization: key={0}", GCM.APIKey));
httprequest.Headers.Add(string.Format("Sender: id={0}", GCM.ProjectNo));
String[] regid = regId.Split(',');
using (var streamWriter = new StreamWriter(httprequest.GetRequestStream()))
{
string json = new JavaScriptSerializer().Serialize(new GCMValues
{
delay_while_idle = false,
priority = "high",
registration_ids = regid,
data = new MessagesValues
{
message = message
}
});
streamWriter.Write(json);
streamWriter.Flush();
streamWriter.Close();
}
var httpResponse = (HttpWebResponse)httprequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
if (result.Contains("Error"))
{
return false;
}
}
Properties that I have used
public class GCMValues
{
public Object data { get; set; }
public bool delay_while_idle { get; set; }
public String priority { get; set; }
public String[] registration_ids { get; set; }
}
public class MessagesValues
{
public String message { get; set; }
public DateTime? time { get; set; }
}

Related

How to Model Object upload in API with form-data in asp.net Web Api

Model Class:
public class TestAspDotNetModelClass
{
public int Id { get; set; }
public string Name { get; set; }
public byte[] file { get; set; }
}
API Controller Action:
public class ValuesController: ApiController
{
[System.Web.Http.HttpPost]
public HttpResponseMessage PostComplex(TestAspDotNetModelClass update)
{
if (update.fileProfile != null)
{
return Request.CreateResponse(HttpStatusCode.OK);
}
else
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
}
}
File and value post in postman
object post in API but API message show this error
You Can handle the situation with two scenario.
You can use HttpContext.Current.Request
Not required as you mentioned in model class byte[] property.
Ref. Link 1 : https://www.c-sharpcorner.com/UploadFile/2b481f/uploading-a-file-in-Asp-Net-web-api/
public class ValuesController: ApiController
{
[System.Web.Http.HttpPost]
public HttpResponseMessage PostComplex(TestAspDotNetModelClass update)
{
if (update.fileProfile != null)
{
HttpResponseMessage result = null;
var httpRequest = HttpContext.Current.Request;
if (httpRequest.Files.Count > 0)
{
var docfiles = new List<string>();
foreach (string file in httpRequest.Files)
{
var postedFile = httpRequest.Files[file];
var filePath = HttpContext.Current.Server.MapPath("~/" + postedFile.FileName);
postedFile.SaveAs(filePath);
docfiles.Add(filePath);
}
result = Request.CreateResponse(HttpStatusCode.Created, docfiles);
}
else
{
result = Request.CreateResponse(HttpStatusCode.BadRequest);
}
}
else
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
}
}
You can go with same as you mentioned byte[] that is not possible to create json thats why you can convert byte[] to Base64String then it is possible.
Ref. Link 2 : Saving a base64 string as an image into a folder on server using C# and Web Api
Model Class
public class TestAspDotNetModelClass
{
public int Id { get; set; }
public string Name { get; set; }
public string Base64Stringfile { get; set; }
}
API Controller Action
public class ValuesController: ApiController
{
[System.Web.Http.HttpPost]
public HttpResponseMessage PostComplex(TestAspDotNetModelClass update)
{
if (update.Base64Stringfile != null)
{
// Convert base 64 string to byte[]
byte[] fileBytes = Convert.FromBase64String(update.Base64Stringfile);
// Convert your byte[] to file
return Request.CreateResponse(HttpStatusCode.OK);
}
else
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
}
}

How to send object and output param to web api parameters to get or set methods?

I have a web api class in my web api project which has an object parameter and an output parameter
public class ProductsController : ApiController
{
[HttpGet]
public List<Product> GetProducts(out QueryResult queryResult, GlobalInfo globalInfo)
{
var repository = new BusinessRepository();
return repository.GetAllProducts(out queryResult,globalInfo);
}
}
QueryResult and GlobalInfo class is :
class Product
{
public int ProductId { get; set; }
public string ProductName { get; set; }
public decimal Price { get; set; }
}
public class QueryResult
{
private QueryStatus _queryStatus;
public QueryStatus QueryStatus
{
get { return _queryStatus; }
set { _queryStatus = value; }
}
private string _errorCode;
public string ErrorCode
{
get { return _errorCode; }
set { _errorCode = value; }
}
private string _errorText;
public string ErrorText
{
get { return _errorText; }
set { _errorText = value; }
}
}
public enum QueryStatus
{
None,
Error,
RecordFound,
RecordNotFound,
AccessDenied,
Succeded
}
public class GlobalInfo
{
public string UserName { get; set; }
public int UserId { get; set; }
public string IP { get; set; }
}
how to call web api method in console app or asp.net mvc by oject parameter and out object parameter?
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
QueryResult result;
var globalinfo = new GlobalInfo{UserName = "user1",UserId = 12,IP = "98.14.0.1"};
var data = new JavaScriptSerializer().Serialize(globalinfo);
var methodUrl = string.Format("http://localhost/WebApi/api/products/?queryResult={0}&globalInfo={1}",result,data);
var response = client.GetAsync(methodUrl).Result;
response.EnsureSuccessStatusCode();
var content = response.Content.ReadAsAsync<List<Product>>().Result;

How can we pass the more than One class objects to WCF REST API?

I have a WCF REST API method which accepts two class objects (RequestFormat = JSON ) as inputs . I know the process of passing the single object. Can anyone help me the process of passing more than one object as inputs in WCF Rest API method.
You need to set message body style as wrapped: WebMessageBodyStyle.Wrapped.
Here is an example:
Data model:
public class ServiceResult
{
public string ResultCode { get; set; }
}
public class User
{
public string UserId { get; set; }
public string Name { get; set; }
public string Surename { get; set; }
}
public class Account
{
public string AccNumber { get; set; }
public bool IsActive { get; set; }
}
Service interface method:
[OperationContract]
[WebInvoke(UriTemplate = "user/details", Method = "POST", RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped)]
ServiceResult Details(User user, string key, Account account);
Code to request data:
const string json = #"{
""user"":
{
""UserId"":""12"",
""Name"":""Bogdan"",
""Surename"":""Perecotypole""
},
""key"": ""12345"",
""account"":
{
""AccNumber"":""ED12"",
""IsActive"":""true""
}
}";
Uri uri= new Uri("http://localhost/user/details");
var wc = new WebClient();
wc.Headers["Content-Type"] = "application/json";
var resJson = wc.UploadString(uri, "POST", json);

HTTP POST to Many to Many relation using ASP.NET Web API

I am new to ASP.net (and programming in general) and I'm having trouble building a Web API. More specifically I need help in these two areas:
How to configure my DOCcontroller to post a new document (DOC table).
How to make the actual ajax post -- I am having trouble passing the EXT_GUID parameter. As it stands I get an error when I try to post. "Can't bind multiple parameters (doc and parentOwner) to the request's content."
Essentially this is for a simple document management system. I want Get/Post documents (DOC) by having the user supply an GUID from an external database (the EXT_GUID field) as a filter/parameter. Each document can have multiple EXT_GUIDs and each EXT_GUID can have multiple Documents (DOC). You can assume that the EXT_GUID fields we be populated prior to the http post.
This is the DOCcontroller code
//POST api/DOC
public HttpResponseMessage PostDOC(DOC doc, List<string> parentOwners)
{
if (ModelState.IsValid)
{
var parents = db.BIMs.Where(bx => parentOwners.Contains(bx.EXT_GUID));
foreach (var p in parents)
doc.Owners.Add(p);
db.DOCs.Add(doc);
db.SaveChanges();
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, doc);
response.Headers.Location = new Uri(Url.Link("DefaultApi", new { id = doc.Id }));
return response;
}
else
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
}
This is my model setup -- EntityFramework codefirst stuff
public class EXT
{
public int Id { get; set; }
public string EXT_GUID { get; set; }
public int ProjectID { get; set; }
public virtual ICollection<DOC> DOCs { get; set; }
}
public class DOC
{
public int Id { get; set; }
public int ProjectID { get; set; }
public string Subject { get; set; }
public string Link { get; set; }
public virtual ICollection<EXT> EXTs { get; set; }
}
This is more Storage Model...
public StoreDBContext() : base("name=StoreDBContext")
{
}
public DbSet<EXT> EXTs { get; set; }
public DbSet<DOC> DOCs { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//Set FLUENT API config for many to many here
modelBuilder.Entity<EXT>()
.HasMany(a => a.DOCs)
.WithMany()
.Map(x =>
{
x.MapLeftKey("EXT_Id");
x.MapRightKey("DOC_Id");
x.ToTable("EXTsDOCs");
});
}
AJAX Code
function AddDOC() {
var parentOwner = "{\"" + $('#txtaddEXT').val() + "\"}";
jQuery.support.cors = true;
var DOC = {
ProjectId: ProjectID,
Subject: $('#txtaddDOCSubject').val(),
Link: $('#txtaddDOCLink').val(),
parentOwner: parentOwner
};
$.ajax({
url: "http://localhost:54171/api/DOC/",
type: 'POST',
data: JSON.stringify(DOC),
contentType: "application/json;charset=utf-8",
success: function (data) {
WriteResponse(data);
},
error: function (x, y, z) {
alert(x + '\n' + y + '\n' + z);
}
});
}
What you receive from the client and what you will save in the database is two different things.
Your doc object is ok:
var DOC = {
ProjectId: ProjectID,
Subject: $('#txtaddDOCSubject').val(),
Link: $('#txtaddDOCLink').val(),
parentOwner: parentOwner
};
Now you need to change the server logic. Make a model like this:
public class DocReceivedModel
{
public int ProjectID { get; set; }
public string Subject { get; set; }
public string Link { get; set; }
public List<string> parentOwner { get; set; }
}
Then your PostDOC method will be:
public HttpResponseMessage PostDOC(DocReceivedModel docReceived)
{
if (ModelState.IsValid)
{
Doc newDoc = new Doc();
newDoc.ProjectID = docReceived.ProjectID
newDoc.Subject = docReceived.Subject
newDoc.Link = docReceived.Link
var parents = db.BIMs.Where(bx => docReceived.parentOwners.Contains(bx.EXT_GUID));
foreach (var p in parents)
newDoc.Owners.Add(p);
// I not see in your model Owners, maybe this is EXTs but I suppose you catch the idea
db.DOCs.Add(newDoc);
db.SaveChanges();
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, newDoc);
response.Headers.Location = new Uri(Url.Link("DefaultApi", new {id = newDoc.Id}));
return response;
}
else
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
}

Problem with Object Data Type serialization in wcf using DataContract Attribute

I have created a WCF Rest API Service using wcf rest starter kit preview 2 which automatically return JSON or XML data depending on the requested content type. everything is working fine but as my service methods return multiple data type some methods returns a object of a class or collection of class, bool, int or collection type. so I planed to return a same Response in all methods for this I Create a new class as following:
[DataContract(Namespace = "")]
public class ServiceResponse
{
[DataMember]
public bool IsError
{ get; set; }
[DataMember]
public string ResponseMessage
{ get; set; }
[DataMember]
public Object ResponseData
{ get; set; }
}
and User class as following:
[DataContract(Namespace = "")]
public class User
{
[DataMember]
public string UserName
{ get; set; }
[DataMember]
public int UserID
{ get; set; }
}
In ServiceResponse Class I have declared an Object Type property ResponseData and my all method has return type of ServiceResponse. My problem is that when I set any string,bool,int type as ResponseData it is serialized but when I set collection type or an object of another class which also has DataContarct attribute this class is not serialized see below code :
public ServiceResponse GetUser(int userID)
{
User user = getUser(userID); get user data from database
ServiceResponse response=new ServiceResponse();
var response = new ServiceResponse
{
IsError = false,
ResponseMessage = string.Empty,
ResponseData = user; // Setting Result Data here
};
return response;
}
when I called above method(GetUser) I got Null response due to serialization problem, but following code works fine
public ServiceResponse TestMethod(string testMessage)
{
ServiceResponse response=new ServiceResponse();
var response = new ServiceResponse
{
IsError = false,
ResponseMessage = string.Empty,
ResponseData = testMessage; // Setting Result Data here
};
return response;
}
can anyone help me?
The problem that you're having is due to the fact that in your DataContract, you are declaring the ResponseData as an Object, but not telling WCF what types are valid known types. You need to explicitly tell WCF what known types are valid for your service, and you can do this by using the ServiceKnownType attribute. I've taken your code and made a few modifications to demonstrate this:
DataContracts
[DataContract(Name="ServiceResponse")]
public class ServiceResponse
{
[DataMember(Name="IsError", Order=1)]
public bool IsError
{ get; set; }
[DataMember(Name="ResponseMessage", Order=2)]
public string ResponseMessage
{ get; set; }
[DataMember(Name="ResponseData", Order=3)]
public Object ResponseData
{ get; set; }
}
[DataContract(Name="User")]
public class User
{
[DataMember(Name="UserName", Order=1, IsRequired=true)]
public string UserName
{ get; set; }
[DataMember(Name="UserID", Order=2, IsRequired=true)]
public int UserID
{ get; set; }
}
[DataContract(Name = "User2")]
public class User2
{
[DataMember(Name = "UserName", Order = 1, IsRequired = true)]
public string UserName
{ get; set; }
[DataMember(Name = "UserID", Order = 2, IsRequired = true)]
public int UserID
{ get; set; }
}
ServiceCode
[ServiceContract(Namespace = "WebApplication1")]
[ServiceKnownType(typeof(User))]
[ServiceKnownType(typeof(User2))]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class Service1
{
[OperationContract(Name="GetUser")]
[WebGet(UriTemplate = "GetUser/{userID}", ResponseFormat = WebMessageFormat.Json)]
public ServiceResponse GetUser(String userID)
{
User theUser = new User()
{
UserID=Convert.ToInt32(userID),
UserName="bob"
};
ServiceResponse sr = new ServiceResponse()
{
IsError = false,
ResponseMessage = "",
ResponseData = theUser
};
return sr;
}
[OperationContract(Name = "GetUser2")]
[WebGet(UriTemplate = "GetUser2/{userID}", ResponseFormat = WebMessageFormat.Json)]
public ServiceResponse GetUser2(String userID)
{
User2 theUser = new User2()
{
UserID = Convert.ToInt32(userID),
UserName = "bob"
};
ServiceResponse sr = new ServiceResponse()
{
IsError = false,
ResponseMessage = "",
ResponseData = theUser
};
return sr;
}
}
What I did:
Not really necessary, but I added some additional attributes to the DataContract and members. I usually like to do that anyway, so I'm just being OCD there. :)
I created a second DataContract to demonstrate the use of ServiceKnownType.
In the service, I added the ServiceKnownType attributes on my service class, stating what types can be returned from my service methods.
That's pretty much it. Using the ServiceKnownType attributes is kind of ugly - there are some solutions out there to get around it (here).
Let me know if you have additional questions. Hope this helps!

Resources