For Create Registration on azure notification hub
We want authorization token for below rest api
https://{namespace}.servicebus.windows.net/{NotificationHub}/registrations/?api-version=2015-01
please see follwing link
https://msdn.microsoft.com/en-us/library/azure/dn223265.aspx
// Add Nuget package
Install-Package Microsoft.Azure.NotificationHubs
using Microsoft.Azure.NotificationHubs;//Add namespace
string accessTokenstring = GetAccessToken();
private string GetAccessToken()
{
var hubName = "<Notification Hub>";
string connectionString = "Endpoint=sb://<Notification Hub Namespace>.servicebus.windows.net/;SharedAccessKeyName=DefaultFullSharedAccessSignature;SharedAccessKey=<Key>";
var apiVersion = "?api-version=2015-01";
string endpoint = null;
string sasKeyValue = null;
string sasKeyName = null;
string targetUri = null;
var parts = connectionString.Split(';');
foreach (var part in parts)
{
if (part.IndexOf("Endpoint") == 0)
{
endpoint = "https" + part.Substring(11);
}
else if (part.IndexOf("SharedAccessKeyName") == 0)
{
sasKeyName = part.Substring(20);
}
else if (part.IndexOf("SharedAccessKey") == 0)
{
sasKeyValue = part.Substring(16);
}
}
targetUri = endpoint + hubName;
var registrationPath = targetUri + "/Registrations/";
var resourceUri = registrationPath + apiVersion;
TimeSpan sinceEpoch = DateTime.UtcNow - new DateTime(1970, 1, 1);
string accessTokenstring = SharedAccessSignatureTokenProvider.GetSharedAccessSignature(sasKeyName, sasKeyValue, resourceUri, sinceEpoch);
return accessTokenstring;
}
Trying to follow Direct Send (https://msdn.microsoft.com/en-us/library/mt608572.aspx) I faced the same problem.
I was able to use #Sama's solution just changing the "Registrations" to "messages". The Solution provided is working in .Net Core.
Related
I am trying to get the list of users in ADO using .NET clients. I am referring to this git repository:
https://github.com/microsoft/azure-devops-dotnet-samples/blob/master/ClientLibrary/Quickstarts/dotnet/GraphQuickStarts/Samples/EnumerateUsers.cs
I tried same thing but still it shows error that GetUsersAsync needs assembly reference. I have tried all the references. I am getting GetUserAsync but that is for one user. I need to fetch all the users.
Instead of using GetUsersAsync, please use ListUsersAsync:
PagedGraphUsers users = graphClient.ListUsersAsync().Result;
In the following two code samples i'm returning the users' emails. You can use Azure DevOps' userentitlements to return the information you need like the license details.
SDK
//string organization = ...
//string userName = ...
//string pat = ...
List<string> users = new List<string>();
var uri = new Uri($"https://vsaex.dev.azure.com/{organization}");
var credentials = new VssBasicCredential(userName, pat);
using (var connection = new VssConnection(uri, credentials))
using (var client = connection.GetClient<MemberEntitlementManagementHttpClient>())
{
string continuationToken = null;
do
{
var data = await client.SearchUserEntitlementsAsync(continuationToken);
continuationToken = data.ContinuationToken;
foreach (var member in data.Members)
{
string email = member.User.MailAddress.ToLower();
users.Add(email);
}
}
while (continuationToken != null);
}
Rest API
//string organization = ...
// HttpClient client = ...
List<string> users = new List<string>();
string baseUrl = $"https://vsaex.dev.azure.com/{organization}/_apis/userentitlements?api-version=6-preview.3";
string url = baseUrl;
string continuationToken = string.Empty;
do
{
var response = await client.GetAsync(url);
if (response.IsSuccessStatusCode)
{
dynamic data = await response.Content.ReadAsAsync<object>();
foreach (var member in data.members)
{
users.Add(member.user.mailAddress.ToString());
}
continuationToken = HttpUtility.UrlEncode(data.continuationToken.ToString());
url = baseUrl + "&continuationToken=" + continuationToken;
}
}
while (!string.IsNullOrWhiteSpace(continuationToken));
I'm trying to access Azure Cosmos DB using Table API.
The challenge is, despite creating SharedKeyLite, server is still returning Unauthorized - seems like SharedKeyLite is not supported or I'm generating the signature or headers wrong.
Here is the code
static readonly string storageAccountName = "accountName";
static readonly string storageAccountKey = "xxxx";
static readonly string uri = "https://accountName.table.cosmosdb.azure.com/Contacts()";
static readonly string utc_date = DateTime.UtcNow.ToString("r");
static void Main(string[] args)
{
Console.WriteLine(GetResult().Result);
}
static async Task<string> GetResult()
{
// Set this to whatever payload you desire. Ours is null because
// we're not passing anything in.
Byte[] requestPayload = null;
var requestDateString = DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture);
var requestUri = new Uri(uri);
DateTime now = DateTime.UtcNow;
//Instantiate the request message with a null payload.
using (var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, uri)
{ Content = (requestPayload == null) ? null : new ByteArrayContent(requestPayload) })
{
ConstructHeaders(httpRequestMessage.Headers, requestDateString);
string authorizationHeader = GenerateSharedKeyLite(storageAccountKey, storageAccountName, uri,requestDateString);
httpRequestMessage.Headers.Authorization = new AuthenticationHeaderValue("SharedKeyLite", authorizationHeader);
// Send the request.
using (HttpResponseMessage httpResponseMessage = await new HttpClient().SendAsync(httpRequestMessage))
{
string json = await httpResponseMessage.Content.ReadAsStringAsync();
return json;
}
}
}
These are the headers I"m adding, expansion of ConstructHeaders method.
Refer this link for request parameters
//Construct the headers
static void ConstructHeaders(HttpRequestHeaders headers, string now)
{
headers.Add("x-ms-date", now);
headers.Add("x-ms-version", "2017-04-17");
// If you need any additional headers, add them here before creating
// the authorization header.
headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
if (headers.Contains("DataServiceVersion"))
headers.Remove("DataServiceVersion");
headers.Add("DataServiceVersion", "3.0;NetFx");
if (headers.Contains("MaxDataServiceVersion"))
headers.Remove("MaxDataServiceVersion");
headers.Add("MaxDataServiceVersion", "3.0;NetFx");
}
And this is the method that creates the SharedKeyLite
//Created Shared Key Lite
static string GenerateSharedKeyLite(string accessKey, string account, string url, string date)
{
var uri = new Uri(url);
var canonicalizedResourceString = uri.PathAndQuery;
var queryStart = canonicalizedResourceString.IndexOf('?');
if (queryStart > -1)
{
if (queryStart < canonicalizedResourceString.Length - 1)
{
var path = canonicalizedResourceString.Substring(0, queryStart);
var parameters = HttpUtility.ParseQueryString(canonicalizedResourceString.Substring(queryStart + 1));
var sb = new StringBuilder();
foreach (var keyOri in parameters.Keys)
{
var value = parameters[keyOri];
var key = keyOri.ToLowerInvariant();
sb.Append("\n");
sb.Append(key);
sb.Append(":");
sb.Append(value);
}
canonicalizedResourceString = canonicalizedResourceString + sb.ToString();
}
else
{
canonicalizedResourceString = canonicalizedResourceString.Substring(0, canonicalizedResourceString.Length - 1);
}
}
canonicalizedResourceString = $"/{account}{canonicalizedResourceString}";
var stringToSign = $"{date}\n{canonicalizedResourceString}";
var signedSignature = string.Empty;
using (var hmac = new HMACSHA256(Convert.FromBase64String(accessKey)))
{
var outputBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign));
var signature = Convert.ToBase64String(outputBytes);
return $"{account}:{signature}";
}
}
Any Help? Ideally I want to perform the odata query using simple.odata, but first trying to make this work using HttpClient
Just copy your code and it works on my side. If you haven't modified your code, please make sure your storageAccountName and storageAccountKey are correct.
BTW, in method GenerateSharedKeyLite there's no need to add query parameters to canonicalizedResourceString for entity operation. You only need to add comp if you want to operate component info for table or service. See constructing-the-canonicalized-resource-string.
The query string should include the question mark and the comp parameter (for example, ?comp=metadata). No other parameters should be included on the query string.
I am trying to send a push notification from an iOS device (iPhone) via Azure NotificationHub REST Api. I am attempting this from a Xamarin.iOS solution following the Azure documentation I found online.
Response returns following info:
Error: '50002: Provider Internal Error'
Status code: 500
Code used to invoke NotificationHub REST Api (from iOS client app):
var hubUtil = new NotificationHubUtility("Endpoint=sb://company-name.servicebus.windows.net/;SharedAccessKeyName=DefaultFullSharedAccessSignature;SharedAccessKey=00000000000000011111111111111122222222222222");
hubUtil.SendNotificationMessage("This is a TEST Notification!").ConfigureAwait(false);
public class NotificationHubUtility
{
public string Endpoint { get; private set; }
public string SasKeyName { get; private set; }
public string SasKeyValue { get; private set; }
public string HubName { get; private set; }
public string ApiVersion { get; private set; }
public NotificationHubUtility(string connectionString)
{
//Parse Connectionstring
string[] parts = connectionString.Split(new char[] {';'});
for (int i = 0; i < parts.Length; i++)
{
if (parts[i].StartsWith("Endpoint", StringComparison.CurrentCulture))
Endpoint = "https" + parts[i].Substring(11);
if (parts[i].StartsWith("SharedAccessKeyName", StringComparison.CurrentCulture))
SasKeyName = parts[i].Substring(20);
if (parts[i].StartsWith("SharedAccessKey", StringComparison.CurrentCulture))
SasKeyValue = parts[i].Substring(16);
}
HubName = "my-hub";
ApiVersion = "?api-version=2014-09-01";
}
public string GetSaSToken(string uri, int minUntilExpire)
{
string targetUri = Uri.EscapeDataString(uri.ToLower()).ToLower();
// Add an expiration in seconds to it.
long expiresOnDate = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
expiresOnDate += minUntilExpire * 60 * 1000;
long expires_seconds = expiresOnDate / 1000;
var toSign = targetUri + "\n" + expires_seconds;
// Generate a HMAC-SHA256 hash or the uri and expiration using your secret key.
IMacAlgorithmProvider hasher = WinRTCrypto.MacAlgorithmProvider.OpenAlgorithm(MacAlgorithm.HmacSha256);
var messageBuffer = WinRTCrypto.CryptographicBuffer.ConvertStringToBinary(toSign, Encoding.UTF8);
var keyBuffer = WinRTCrypto.CryptographicBuffer.ConvertStringToBinary(SasKeyValue, Encoding.UTF8);
var hmacKey = hasher.CreateKey(keyBuffer);
var signedMessage = WinRTCrypto.CryptographicEngine.Sign(hmacKey, messageBuffer);
string signature = Uri.EscapeDataString(WinRTCrypto.CryptographicBuffer.EncodeToBase64String(signedMessage));
var token = "SharedAccessSignature sig=" + signature + "&se=" + expires_seconds + "&skn=" + SasKeyName + "&sr=" + targetUri;
return token;
}
public async Task SendNotificationMessage(string message)
{
try
{
// basic http client (if needed)
var httpClient = new HttpClient();
httpClient.MaxResponseContentBufferSize = 1024000;
var notificationPayload = "{\"aps\":{\"alert\":\"" + message + "\"}}";
var notificationHubUrl = $"{Endpoint}{HubName}/messages/{ApiVersion}";
var authToken = GetSaSToken(notificationHubUrl, 10);
var request = new HttpRequestMessage(HttpMethod.Post, notificationHubUrl);
//request.Headers.Add("Content-Type", "application/json;charset=utf-8");
request.Headers.Add("ServiceBusNotification-Format", "apple");
request.Headers.Add("ServiceBusNotification-Apns-Expiry", DateTime.UtcNow.AddYears(1).ToString("YYYY-MM-DDThh:mmTZD"));
request.Headers.Add("Authorization", authToken);
var requestBody = new StringContent(notificationPayload, Encoding.UTF8, "application/json");
request.Content = requestBody;
var response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseContentRead);
}
catch (Exception ex)
{
Console.Error.WriteLine(#"ERROR - Sending Notification {0}", ex.Message);
}
}
}
Example of Connection String:
Endpoint=sb://company-name.servicebus.windows.net/;SharedAccessKeyName=DefaultFullSharedAccessSignature;SharedAccessKey=00000000000000011111111111111122222222222222
Environment and Assumptions:
Xamarin.iOS solution using C#
Using PCLCrypto library for encryption
I am attempting to recreate the solution demonstrated in an Example in Azure examples github repo but using Xamarin.iOS
The connection string is taken directly from Azure portal
The code for generating SaS token is adapted from Azure NotificationHub REST Api Documentation
Notification hub works, I am able to send a test push notification through the hub UI and i see it come in on the device
What am I missing here? I wasn't able to find much relevant documentation for this error online. Any help would be greatly appreciated.
Update with Fix:
The following 2 changes to the code above fixed the issue for me:
Changed
ApiVersion = "?api-version=2014-09-01";
to
ApiVersion = "?api-version=2016-07";
Changed
request.Headers.Add("ServiceBusNotification-Apns-Expiry", DateTime.UtcNow.AddYears(1).ToString("YYYY-MM-DDThh:mmTZD"));
to
request.Headers.Add("ServiceBusNotification-Apns-Expiry", DateTime.UtcNow.AddYears(1).ToString("yyyy-MM-ddTHH:mm:sszzz"));
The Api Version 2014-09-01 is not correct. Please use 2016-07 as the Api version and you should be good.
Thanks
Sohrab
I've figured out the issue(s):
+1 to Sohrab for pointing out the Api Version, I updated it to ApiVersion = "?api-version=2016-07";
There was an error in the ServiceBusNotification-Apns-Expiry header value format, the date was not being correctly formatted to string. Corrected format string is this ToString("yyyy-MM-ddTHH:mm:sszzz")
I have the following code(facebook C# SDK) to post to facebook wall :
public long? UploadPost(string intLinkTitle, string inMessage, string inLinkCaption, string inLinkUrl, string inLinkDescription, string inLinkUrlPicture)
{
object obj;
Facebook.JsonObject jsonObj;
FacebookClient client;
string access_token = ConfigurationManager.AppSettings["FacebookPageAccessToken"].ToString();
client = new FacebookClient(access_token);
var args = new Dictionary<string, object>();
args["message"] = inMessage;
args["caption"] = inLinkCaption;
args["description"] = inLinkDescription;
args["name"] = intLinkTitle;
args["picture"] = inLinkUrlPicture;
args["link"] = inLinkUrl;
if ((obj = client.Post("/" + ConfigurationManager.AppSettings["FacebookPageId"].ToString() + "/feed", args)) != null)
{
if ((jsonObj = obj as Facebook.JsonObject) != null)
{
if (jsonObj.Count > 0)
return long.Parse(jsonObj[0].ToString().Split('_').Last().ToString());
}
}
return null;
}
}
This works great as long as I post to my public facebook website page but when changing the FacebookPageId to a group id instead I get (FacebookApiException - #200) Permissions error.
My user are admin of both the group and the page.
I have tried to post the message from the Graph API Explorer with the following line : 294632750660619/feed/?message=test but there is a syntax problem here, have also tried 294632750660619/feed?message=test but with no success.
How do I post to the closed facebook group?
Okay, I found the correct way. This is what I hade to do :
Go to the https://developers.facebook.com/ and create a new application
Settings > Add platform(Website and set the site URL(for example localhost..)
Set the app to go live(status & review > Yes), to do this a email adress needs to be set under settings > Contact Email
Go to the Graph API Explorer
Choose the new app from the dropdown
Click Get Access Token
Choose correct permissions(user_groups, user_status, user_photos, manage_pages, publish_actions, read_insights and read_stream) and click Get Access Token. Now we bot a short lived tooken
Generate a extended user token (valid for 60 days) by using this URL(change parameters(3)) : https://graph.facebook.com/oauth/access_token?grant_type=fb_exchange_token&client_id=[app-id]&client_secret=[app-secret]&fb_exchange_token=[short-lived-token]
Use the generated none expiring access token in the application
Validate the Access token here : https://developers.facebook.com/tools/debug/access_token/
Use this code to upload post :
public long? UploadPost(string intLinkTitle, string inMessage, string inLinkCaption, string inLinkUrl, string inLinkDescription, string inLinkUrlPicture)
{
object obj;
Facebook.JsonObject jsonObj;
FacebookClient client;
string access_token = ConfigurationManager.AppSettings["FacebookPageAccessToken"].ToString();
client = new FacebookClient(access_token);
var args = new Dictionary<string, object>();
args["message"] = inMessage;
args["caption"] = inLinkCaption;
args["description"] = inLinkDescription;
args["name"] = intLinkTitle;
args["picture"] = inLinkUrlPicture;
args["link"] = inLinkUrl;
if ((obj = client.Post("/" + ConfigurationManager.AppSettings["FacebookPageId"].ToString() + "/feed", args)) != null)
{
if ((jsonObj = obj as Facebook.JsonObject) != null)
{
if (jsonObj.Count > 0)
return long.Parse(jsonObj[0].ToString().Split('_').Last().ToString());
}
}
return null;
}
And to get feed, use this :
private void GetFeed()
{
object obj;
Facebook.JsonObject jsonObj;
Facebook.JsonObject jsonPaging;
FacebookClient client;
int pageCount = 0;
string access_token;
string URL;
DateTime fetchFaceBookFeedFromDate;
DateTime? oldestPostFetched = null;
fetchFaceBookFeedFromDate = DateTime.Now.AddDays(-30);
access_token = ConfigurationManager.AppSettings["FacebookPageAccessToken"].ToString();
URL = "/" + ConfigurationManager.AppSettings["FacebookPageId"].ToString() + "/feed";
client = new FacebookClient(access_token);
while (URL.Length > 0 && pageCount < 1000)
{
if ((obj = client.Get(URL)) != null)
{
if ((jsonObj = obj as Facebook.JsonObject) != null && jsonObj.Count > 0)
{
if (jsonObj[0] is Facebook.JsonArray)
oldestPostFetched = SaveFacebookForumThread(jsonObj[0] as Facebook.JsonArray, fetchFaceBookFeedFromDate);
if (jsonObj.Keys.Contains("paging") && (jsonPaging = jsonObj["paging"] as Facebook.JsonObject) != null && jsonPaging.Keys.Contains("next"))
URL = jsonPaging["next"].ToString();
else
break;
}
}
pageCount++;
if (oldestPostFetched.HasValue && fetchFaceBookFeedFromDate > oldestPostFetched)
break;
}
}
I trying using Google Analytics with C# to get stats information to display in my webiste
Here is my code
public ActionResult Index()
{
string userName = "admin#email.com";
string passWord = "mypass";
string profileId = "ga:xxxxxxxx";
string key = "2d751338cb092ef8da65f716e37a48604386c9sw";
string dataFeedUrl = "https://www.google.com/analytics/feeds/data"+key;
var service = new AnalyticsService("API Project");
service.setUserCredentials(userName, passWord);
var dataQuery = new DataQuery(dataFeedUrl)
{
Ids = profileId,
Metrics = "ga:pageviews",
Sort = "ga:pageviews",
GAStartDate = new DateTime(2010, 3, 1).ToString("yyyy-MM-dd"),
GAEndDate = DateTime.Now.ToString("yyyy-MM-dd")
};
var dataFeed = service.Query(dataQuery);
var totalEntry = dataFeed.Entries[0];
ViewData["Total"] = ((DataEntry)(totalEntry)).Metrics[0].Value;
dataQuery.GAStartDate = DateTime.Now.AddDays(-1).ToString("yyyy-MM-dd");
dataQuery.GAEndDate = DateTime.Now.AddDays(-1).ToString("yyyy-MM-dd");
dataFeed = service.Query(dataQuery);
var yesterdayEntry = dataFeed.Entries[0];
ViewData["Yesterday"] = ((DataEntry)(yesterdayEntry)).Metrics[0].Value;
dataQuery.GAStartDate = DateTime.Now.ToString("yyyy-MM-dd");
dataQuery.GAEndDate = DateTime.Now.ToString("yyyy-MM-dd");
dataFeed = service.Query(dataQuery);
var todayEntry = dataFeed.Entries[0];
ViewData["Today"] = ((DataEntry)(todayEntry)).Metrics[0].Value;
return View(dataFeed.Entries);
}
But when i run the code it always said "{"Invalid credentials"}"
Not sure why i facing this error while i checked many time about the key,username,password and profileId
Anyone facing this problem,can help me?
Many thanks
I think that your url is wrong. try in this way (you are missing ?key=).
string dataFeedUrl = "https://www.google.com/analytics/feeds/data?key="+key;
refer this google example where there is this example that should help you
public DataFeedExample()
{
// Configure GA API.
AnalyticsService asv = new AnalyticsService("gaExportAPI_acctSample_v2.0");
// Client Login Authorization.
asv.setUserCredentials(CLIENT_USERNAME, CLIENT_PASS);
// GA Data Feed query uri.
String baseUrl = "https://www.google.com/analytics/feeds/data";
DataQuery query = new DataQuery(baseUrl);
query.Ids = TABLE_ID;
query.Dimensions = "ga:source,ga:medium";
query.Metrics = "ga:visits,ga:bounces";
query.Segment = "gaid::-11";
query.Filters = "ga:medium==referral";
query.Sort = "-ga:visits";
query.NumberToRetrieve = 5;
query.GAStartDate = "2010-03-01";
query.GAEndDate = "2010-03-15";
Uri url = query.Uri;
Console.WriteLine("URL: " + url.ToString());
// Send our request to the Analytics API and wait for the results to
// come back.
feed = asv.Query(query);
}
refer also this guide to configure your project
Also follow this guide to use OAuth 2.0