I am writing an API that sends an firebase message (using the official FirebaseAdmin library) when requested to a android device. I got it working perfect in normal C#, but in ASP.NET core I always get a 404 not found exception.
Response status code does not indicate success: 404 (NotFound)
{
"error": {
"code": 404,
"message": "Requested entity was not found.",
"errors": [
{
"message": "Requested entity was not found.",
"domain": "global",
"reason": "notFound"
}
],
"status": "NOT_FOUND"
}
}
I run the following code at startup:
if (FirebaseApp.DefaultInstance == null)
{
FirebaseApp.Create(new AppOptions
{
Credential = GoogleCredential.FromFile($#"{env.WebRootPath}\app-5a821-firebase-adminsdk-pf36f-6f44114d87.json")
});
}
And this is the request that I made, very simple:
[HttpGet]
public async Task<ActionResult<IEnumerable<string>>> Get()
{
var message = new Message
{
Token = "dgY8UMXhEZ4:APA91bFnrZTGJKkCCBJHzbghvsvEaq-w-ee1XBAVqAaS-rsmR3Ald23rHGgpfdgVb09r97jDQBVSc6GtDHWtLHWAnn4Lm3EM_j-sh7cu-RaRSrfnk3X124v4co3Q9ID6TxFdGgv7OXWt",
Data = new Dictionary<string, string>
{
{"title", "test" }
}
};
try
{
var fcmResult = await FirebaseMessaging.DefaultInstance.SendAsync(message);
} catch (FirebaseException ex)
{
}
return new string[] { "value1", "value2" };
}
Github test project: https://github.com/kevingoos/FirebaseAdminTest
Solved problem: https://github.com/firebase/firebase-admin-dotnet/issues/73
This happens when the token is invalid/expired or does not belong to the same project as the credentials used to initialize the Admin SDK.
Related
We are trying to import test execution result in json format to xray Jira cloud by cloud Rest API call. After importing through Rest API call we are getting below error.
I gone through the solutions but couldn't got working solution.
{"error": "Error retrieving Project from Jira with key "null": No project could be found with key 'null'."}
Below is my code snippet:
public void postAPICall(){
File dataFile = new File("src/main/resources/Payloads/auth.json");
String url ="https://xray.cloud.getxray.app/api/v2/authenticate";
RequestSpecification request = RestAssured.given();
request.header("Content-Type", "application/json");
request.body(dataFile);
Response response = request.post(url);
ResponseBody body = response.getBody();
tokenResult=body.asString();
}
#Test
public void postCallUpdateTestResult(){
postAPICall();
File jsonDataInFile = new File("src/main/resources/Payloads/SimpleExecutionResult.json");
String url ="https://xray.cloud.getxray.app/api/v2/import/execution?testExecKey=XX-XX";
RequestSpecification request = RestAssured.given();
request.header("Content-Type", "application/json");
request.header("Authorization", "Bearer "+tokenResult.substring(1,(tokenResult.length()-1)));
request.body(jsonDataInFile);
Response response = request.post(url);
ResponseBody body = response.getBody();
System.out.println(body.asString());
}
auth.json
{
"client_id": "XXXXXXXXXXXXXXXXXX",
"client_secret": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
}
SimpleExecutionResult.json
{
"testExecutionKey": "XX-XX",
"tests": [
{
"testKey": "XX-XX",
"status": "FAILED"
},
{
"testKey": "XX-XX",
"status": "PASSED"
}
]
}
I am getting the error while inserting image file into the firebase Stroage. I am using HTTP rest api's for the same.
The code is as follows:
Future<void> upload(Image image2) async {
var accountCredentials = ServiceAccountCredentials.fromJson({
"private_key_id": " ",
"private_key": " ",
"client_email":"< >.iam.gserviceaccount.com",
"client_id": "",
"type": "service_account"
});
var scopes = [
'https://www.googleapis.com/auth/cloud-platform',
];
var client = Client();
AccessCredentials credentials =
await obtainAccessCredentialsViaServiceAccount(accountCredentials, scopes, client);
String accessToken = credentials.accessToken.data;
var request = Request(
'POST',
Uri.parse(
'https://www.googleapis.com/upload/storage/v1/b/mybucket/o?uploadType=media&name=$image2'),
);
request.headers['Authorization'] = "Bearer $accessToken";
request.headers['Content-Type'] = "image/png";
Response response = await Response.fromStream(await request.send());
print("response is ");
print(response.statusCode);
print("response body");
print(response.body);
client.close();
}
The Error is as follows:
{
"error": {
"code": 403,
"message": "< >.iam.gserviceaccount.com does not have storage.objects.create access
to the Google Cloud Storage object.",
"errors": [
{
"message": "< >.gserviceaccount.com does not have storage.objects.create access to the
Google Cloud Storage object.",
"domain": "global",
"reason": "forbidden"
}
]
}
}
I have given the permission of storage.objects.create through IAM service management but this is not working
Click here to view ScreenShot of assigned permission
I am trying to send a Firebase Cloud Message from Google Apps Script. I have followed the following questions & links & assembled the following code:
Get 403 response with the "new" Firebase Cloud Messaging API
The res|error I am receiving is:
{
"error": {
"code": 403,
"message": "Request had insufficient authentication scopes.",
"status": "PERMISSION_DENIED"
}
}
My Code in Google Apps Script is:
function sendFCM(text){
text = {
"message": {
"topic": "news",
"notification": {
"title": "Breaking News",
"body": "New news story available."
},
"data": {
"story_id": "story_12345"
}
}
}
var projectId = "xxxxxxx";
var apiUrl = "https://fcm.googleapis.com/v1/projects/"+projectId+"/messages:send";
var authKey = "AAAU.......Cs";
var token = ScriptApp.getOAuthToken();
var options = {
'method' : 'post',
'contentType': 'application/json',
'muteHttpExceptions' : true,
'payload' : JSON.stringify(text),
headers:{Authorization: "Bearer "+ token},
};
var res = UrlFetchApp.fetch(apiUrl, options);
Logger.log(res);
}
Script's properties > User Scopes list follwoing:
https://www.googleapis.com/auth/firebase.database
https://www.googleapis.com/auth/script.external_request
https://www.googleapis.com/auth/spreadsheets
https://www.googleapis.com/auth/userinfo.email
FCM & GCM Api is enabled in project's developer console.
Edit:
From Ref's comment, I added the following scope to app manifest:
https://www.googleapis.com/auth/firebase.messaging
Upon Run, it asked me to authorize & now the response is an instance of a Message. But still I do not know how to define a to device i.e. to which device the message should go.
{
"name": "projects/send-xxxx3/messages/866xxxxx92"
}
I am using a webhook and c# to fulfill my logic within an Action.
I have subscribed to two intents, and have captured the "UpdateUserId".
Here is the notification payload
{
"customPushMessage": {
"target": {
"userId": "ABwppHFW6M9ASVqbKFBigM8N0mgssCJmPlwarmgzil_Nk_YsdZ1evzTAggEh0aEsctjOIYg2uHc8n7KfzNuHLuJoirXW",
"intent": "NotificationIntent",
"argument": {
"rawText": "Notification Argument Raw Text",
"textValue": "Notification Argument Text Value",
"name": "Notification Argument"
},
"locale": "en-US"
},
"userNotification": {
"title": "Notification Title",
"text": "Notification Text"
}
}
}
I am sending my notification using the following code blocks
private static async Task<string> GetAccessTokenFromJsonKeyAsync(string jsonKeyFilePath, params string[] scopes)
{
using (var stream = new FileStream(jsonKeyFilePath, FileMode.Open, FileAccess.Read))
{
return await GoogleCredential
.FromStream(stream) // Loads key file
.CreateScoped(scopes) // Gathers scopes requested
.UnderlyingCredential // Gets the credentials
.GetAccessTokenForRequestAsync(); // Gets the Access Token
}
}
public async Task<HttpResponseMessage> SendNotificationMessage(ProactiveMessage proactiveMessage)
{
try
{
var accessToken = await GetAccessTokenFromJsonKeyAsync("key.json", "https://www.googleapis.com/auth/actions.fulfillment.conversation");
var serialized = JsonConvert.SerializeObject(proactiveMessage);
var payload = "{\"customPushMessage\": " + serialized + "}";
// Wrap our JSON inside a StringContent which then can be used by the HttpClient class
var httpContent = new StringContent(payload, Encoding.UTF8, "application/json");
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
var httpResponseMessage = await _httpClient.PostAsync($"{_hostUrl}", httpContent);
Console.WriteLine(httpResponseMessage.IsSuccessStatusCode ? "Successfully sent notification message." : $"Failed to send notification message with {httpResponseMessage.StatusCode}.");
return httpResponseMessage;
}
catch (Exception ex)
{
Debug.WriteLine($"Google Assistant Service: Failed to send notification message with exception: {ex.Message}");
return new HttpResponseMessage(HttpStatusCode.BadRequest);
}
}
The method returns a 200 Response. However, a notification never shows up on my phone.
I am not sure what my next steps for debugging are.
Since notifications are stil not public, is this a common issue?
I had the same issue. I received 200 status code but no notifications arrived at the target device.
I tried it again in approximately 2 days and it worked with no problems and have been working ever since.
The only explanation I could come up with is that there is some configuration running in the background.
What is the best response to give, if a number of objects are sent to my web api controller, to be inserted into my database, where some may be successful, and some may fail? A normal HTTP response I don't think will suffice - would it be better to find some way of returning a JSON string of what has been successful, and what has not? If so, how would I do that?
My Post controller is shown below.
Thanks for any help,
Mark
public HttpResponseMessage PostBooking(Booking[] bookings)
{
if (ModelState.IsValid)
{
foreach (var booking in bookings)
{
// check if there are any bookings already with this HID and RID...
var checkbooking = db.Bookings.Where(h => h.HID == booking.HID && h.RID == booking.RID).ToList();
// If so, return a response of conflict
if (checkbooking.Count != 0 || checkbooking.Any())
{
throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.Conflict));
}
else
{
// If not add the booking to the database and return a response of Created
db.Bookings.Add(booking);
db.SaveChanges();
}
}
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created);
return response;
}
else
{
// Model is not valid, so return BadRquest
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
}
You could return a JSON list containing the ids of the objects that failed to be inserted:
{
"failedIds": [
4,
7,
9
]
}
500 HTTP response status code also seems appropriate as the request didn't complete successfully.
You could even bring that a step further and provide an explanation why insertion failed for each particular id:
{
"failed": [
{
"id": 4,
"reason": "database unavailable"
},
{
"id": 7,
"reason": "network cable unplugged"
},
{
"id": 9,
"reason": "a thief is currently running away with our server"
}
]
}