How to get Azure service pricing details programmatically? - azure

Can anybody please tell me how can I programmatically get Azure service pricing details (pricing for Compute, Data Services , App Services, Network Services) from Azure website?
Does Azure provide the pricing details in JSON format?

Windows Azure does'not provide any such API as of today, although it is a much asked feature and hopefully they are working on it.
Check here:
http://feedback.windowsazure.com/forums/170030-billing/suggestions/1143971-billing-usage-api#comments
The only way for now could be to build your own data store with details mentioned here : http://azure.microsoft.com/en-us/pricing/calculator/
Unit wise price will be mentioned in the usage data csv, but unfortunately the only way for now is to download this csv for your subscription here: https://account.windowsazure.com/Subscriptions

Azure now provides API's to get usage and billing data. You can have a look at this blog which gives an overview of these API's and the feedback form here which contains links to some useful pages.
In summary use the following API's to get usage and billing data:
Resource usage
Resource ratecard

Not sure, if i am too late to answer.
I was looking for the same thing and stumble upon this post on stack overflow: Azure pricing calculator api. I was able to generate JSON string using this git hub repo: https://github.com/Azure-Samples/billing-dotnet-ratecard-api.
Hope this helps!

Late to the party but I found myself looking for this and nothing here got me what I wanted. Then I found this https://learn.microsoft.com/en-us/rest/api/cost-management/retail-prices/azure-retail-prices
It is pretty straight forward. Add the reference to the Json.NET .NET 4.0 to your project It shows up in your references as Newtonsoft.Json
//You will need to add these usings
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Net.Http;
private void btnGetRates_Click(object sender, EventArgs e)
{
string strUrl = "https://prices.azure.com/api/retail/prices?$filter=serviceName eq 'Virtual Machines' and skuName eq 'E64 v4' and reservationTerm eq '3 Years'";
string response = GetDataFromAPI(strUrl);
// Here is am turning the Json response into a datatable and then loading that into a DataGridView.
//You can use the Json response any way you wish
DataTable dt = Tabulate(response);
dgvAzureSKU.DataSource = null;
dgvAzureSKU.DataSource = dt;
}
public string GetDataFromAPI(string url)
{
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Add("Accept", "application/json");
var response = httpClient.GetStringAsync(new Uri(url)).Result;
return response;
}
}
public static DataTable Tabulate(string json)
{
var jsonLinq = JObject.Parse(json);
// Find the first array using Linq
var srcArray = jsonLinq.Descendants().Where(d => d is JArray).First();
var trgArray = new JArray();
foreach (JObject row in srcArray.Children<JObject>())
{
var cleanRow = new JObject();
foreach (JProperty column in row.Properties())
{
if (column.Value is JValue) // Only include JValue types
{
cleanRow.Add(column.Name, column.Value);
}
}
trgArray.Add(cleanRow);
}
return JsonConvert.DeserializeObject<DataTable>(trgArray.ToString()); //This is what loads the data into the table
}

You can find some examples for that here https://learn.microsoft.com/en-us/azure/billing/billing-usage-rate-card-overview. Azure provides invoice, usage and ratecard APIs which can help you to do things like:
Azure spend during the month
Set up alerts
Predict bill
Pre-consumption cost analysis

Related

Get Receipt number on Stripe C#

Please how can I get the receipt number on Stripe with c#
My image :
https://www.casimages.com/i/191231053006538388.png.html
Maybe with a Session ID ?
You'd access the Charge object and it's a field on that resource.
You say you're using Checkout. So the Charge is under session.payment_intent.charges.data[0]. It requires a little digging to get it but it's all there. I'd suggest that when you receive the event as part of fulfilling the order etc, retrieve the Session(stripe.com/docs/api/checkout/sessions/retrieve) and expand "payment_intent". Then session.PaymentIntent.Charges.Data[0].ReceiptNumber is the value you're looking for.
static void CheckoutSessionReceiptEmail()
{
var service = new Stripe.Checkout.SessionService();
var session = service.Get(
"cs_test_nHUZtpUvaI80YAKGgCMGyeHfjQ6nMtUhVLeVpowWsgpfyGujccGxnAuJ",
new Stripe.Checkout.SessionGetOptions
{
Expand = new List<string> { "payment_intent" }
}
);
Console.WriteLine(session.PaymentIntent.Charges.Data[0].ReceiptNumber);
}

How to fix performance issue in azure search

I am implementing azure search in my application to provide autosuggestion feature like google, big, and amazon. I have implemented the same available github code using below URL.All is working fine but getting result in more than 1.5 second for each term of sentence.
https://github.com/Azure-Samples/search-dotnet-getting-started/tree/master/DotNetHowToAutocomplete
Currently I am using two indexes for searching and created in basic tier. Below is code
public ActionResult Suggest(bool highlights, bool fuzzy, string term)
{
InitSearch();
// Call suggest API and return results
SuggestParameters sp = new SuggestParameters()
{
UseFuzzyMatching = fuzzy,
Top = 5,
Filter="name eq 'testid'",
OrderBy=new List<string>() { "Date desc"}
};
if (highlights)
{
sp.HighlightPreTag = "<b>";
sp.HighlightPostTag = "</b>";
}
DocumentSuggestResult suggestResult = _indexClient1.Documents.Suggest(term, "index1",sp);
if (suggestResult.Results.Count<5)
{
SuggestParameters sp2 = new SuggestParameters()
{
UseFuzzyMatching = fuzzy,
Top = 5- suggestResult.Results.Count,
Filter = "Product eq 'PAAS'",
OrderBy = new List<string>() { "Count desc" }
};
if (highlights)
{
sp2.HighlightPreTag = "<b>";
sp2.HighlightPostTag = "</b>";
}
DocumentSuggestResult suggestResult2= _indexClient2.Documents.Suggest(term, "index2", sp2);
suggestResult.Results = suggestResult.Results.Union(suggestResult2.Results).Distinct().ToList();
// final = suggestResult.Results.GroupBy(s => s.Text, StringComparer.CurrentCultureIgnoreCase).ToList();
}
// Convert the suggest query results to a list that can be displayed in the client.
List<string> suggestions = suggestResult.Results.Select(x => x.Text).Distinct().ToList();
return new JsonResult
{
JsonRequestBehavior = JsonRequestBehavior.AllowGet,
Data = suggestions
};
}
To test it- when I am typing any word it's taking too much time in populating results around 1.5 to 1.8 seconds, it's working like other web app searchbox.
Timing I am checking using inspect element of chrome browser. Attaching sreenshot.see screenshot
Please suggest.
I answered a similar question on another post: Why is Azure Search taking 1400 miliiseconds to return query results for simple query
The main thing is, you shouldn't be using the Chrome timer to measure the performance of azure search. Use the "elapsed-time" field of the HTTP response you receive (take an average over multiple call), since it accurately tells you how much time was spent getting your results from azure search. The chrome timer can be affected by your network/machine configuration. If that doesn't help, you can follow the other tips I suggested in the post I linked above.

How to get the names and ids of test cases that are under the Tested By section of a user story in tfs

Tested BY(19)
Under tested by there are 19 test cases.
If the id of the user story is given how to get these test cases.
If (Link link is Related) returns all the links.
How to get just the test cases.
Any help would be appreciated. I just started working with tfs using c#
You could use TFS REST API to get the information you need, the Microsoft.VSTS.Common.TestedBy-Forward relation is the TestedBy link type. The API is as below:
GET https://{account}.visualstudio.com/{project}/_apis/wit/workitems/{id}?$expand=Relations&api-version=5.0-preview.3
The following screenshot is the response of the REST API:
Here is a sample with client library to get test case ids from the User Story for your reference:
using System;
using Microsoft.VisualStudio.Services.Client;
using Microsoft.VisualStudio.Services.WebApi;
using Microsoft.TeamFoundation.WorkItemTracking.WebApi;
using Microsoft.TeamFoundation.WorkItemTracking.WebApi.Models;
namespace GetWorkItemFullyExpanded
{
class Program
{
static void Main(string[] args)
{
GetWorkItemFullyExpanded();
}
public static WorkItem GetWorkItemFullyExpanded()
{
int id = xx;
var myCredentials = new VssClientCredentials();
var connection = new VssConnection(new Uri(#"https://xxxx.visualstudio.com"), myCredentials);
WorkItemTrackingHttpClient workItemTrackingClient = connection.GetClient<WorkItemTrackingHttpClient>();
WorkItem workitem = workItemTrackingClient.GetWorkItemAsync(id, expand: WorkItemExpand.Relations).Result;
Console.WriteLine(workitem.Id);
Console.WriteLine("Relations: ");
foreach (var relation in workitem.Relations)
{
if (relation.Rel == "Microsoft.VSTS.Common.TestedBy-Forward")
Console.WriteLine(relation.Url);
}
return workitem;
}
}
}

Paging in MS Graph API

Graph API Paging explains that the response would contain a field #odata.nextLink which would contain a skiptoken pointing to the next page of contents.
When I test the API, I'm getting a fully-qualified MS Graph URL which contains the skiptoken as a query param. E.g. Below is the value I got for the field #odata.nextLink in the response JSON.
https://graph.microsoft.com/v1.0/users?$top=25&$skiptoken=X%27445370740200001E3A757365723134406F33363561702E6F6E6D6963726F736F66742E636F6D29557365725F31363064343831382D343162382D343961372D383063642D653136636561303437343437001E3A7573657235407368616C696E692D746573742E31626F74322E696E666F29557365725F62666639356437612D333764632D343266652D386335632D373639616534303233396166B900000000000000000000%27
Is it safe to assume we'll always get the full URL and not just the skiptoken? Because if it's true, it helps avoid parsing the skiptoken and then concatenating it to the existing URL to form the full URL ourselves.
EDIT - Compared to MS Graph API, response obtained from Azure AD Graph API differs in that the JSON field #odata.nextLink contains only the skipToken and not the fully-qualified URL.
if you would like to have all users in single list, you can achieve that using the code that follows:
public static async Task<IEnumerable<User>> GetUsersAsync()
{
var graphClient = GetAuthenticatedClient();
List<User> allUsers = new List<User>();
var users = await graphClient.Users.Request().Top(998)
.Select("displayName,mail,givenName,surname,id")
.GetAsync();
while (users.Count > 0)
{
allUsers.AddRange(users);
if (users.NextPageRequest != null)
{
users = await users.NextPageRequest
.GetAsync();
}
else
{
break;
}
}
return allUsers;
}
I am using graph client library
Yes. In Microsoft Graph you can assume that you'll always get the fully qualified URL for the #odata.nextLink. You can simply use the next link to get the next page of results, and clients should treat the nextLink as opaque (which is described in both OData v4 and in the Microsoft REST API guidelines here: https://github.com/Microsoft/api-guidelines/blob/master/Guidelines.md#98-pagination.
This is different from AAD Graph API (which is not OData v4), which doesn't return the fully qualified next link, and means you need to do some more complicated manipulations to get the next page of results.
Hence Microsoft Graph should make this simpler for you.
Hope this helps,
The above code did not work for me without adding a call to 'CurrentPage' on the last line.
Sample taken from here.
var driveItems = new List<DriveItem>();
var driveItemsPage = await graphClient.Me.Drive.Root.Children.Request().GetAsync();
driveItems.AddRange(driveItemsPage.CurrentPage);
while (driveItemsPage.NextPageRequest != null)
{
driveItemsPage = await driveItemsPage.NextPageRequest.GetAsync();
driveItems.AddRange(driveItemsPage.CurrentPage);
}
I followed Tracy's answer and I was able to fetch all the messages at one go.
public List<Message> GetMessages()
{
var messages = new List<Message>();
var pages = Client.Users[_email]
.Messages
.Request(QueryOptions)
// Fetch the emails with attachments directly instead of downloading them later.
.Expand("attachments")
.GetAsync()
.Result;
messages.AddRange(pages.CurrentPage);
while (pages.NextPageRequest != null)
{
pages = pages.NextPageRequest.GetAsync().Result;
messages.AddRange(pages.CurrentPage);
}
return messages;
}

Project Server Online CSOM - GeneralSecurityAccessDenied while reading TimePhase Assignments

This is my first SO question so please let me know if this question is not very clear or if I am missing anything.
FYI SO prevented me from attaching links, so sorry for all the bad formatting.
Overview
I'm trying to read (and write) the "Actual work" for a resource in Project Server Online by using the CSOM library available by Microsoft. Reading and writing the assignments and Actual work is working perfectly, as long as I am reading the assignments for the currently authenticated user. If I attempt to read this for another resource, I receive a GeneralSecurityAccessDenied error.
I've done this in the past using Impersonation, which is supposed to be called transparently in the background if the user has the StatusBrokerPermission, but it doesn't seem to be working for me. Impersonation has been removed in 2013+, so that's no longer an option.
Problem summary
The CSOM is supposed to transparently enable statusing extensions to allow status updates to be made for resources other than the currently authenticated user (as long as the user has the status broker permission). This works fine for adding new assignments, but does not work when trying to update actual TimePhased hours via the TimePhased assignments. The assignments cannot be queried, and thus, we cannot call SubmitAllStatusUpdates to submit the hours.
Research
Usage scenarios for the CSOM: https:// msdn.microsoft.com/en-us/library/office/jj163082(v=office.15).aspx#pj15_WhatTheCSOM_UsageScenarios
Impersonation Deprecated: https:// msdn.microsoft.com/en-us/library/office/ee767690(v=office.15).aspx#pj15_WhatsNew_Deprecated)
Picture: Supposed to read on behalf of another user...
People with the same problem # 1: https:// social.technet.microsoft.com/Forums/projectserver/en-US/dccdb543-18a1-4a0e-a948-5d861305516e/how-to-get-resource-assignments-summary-view-data-project-server-online-2013?forum=projectonline)
People with the same problem # 2: http:// uzzai.com/ZB43wp95/ps2013-app-how-to-read-and-update-timephased-data-with-jsom-javascript-csom.html
People with the same problem # 4: https:// social.technet.microsoft.com/Forums/Sharepoint/en-US/be27d497-e959-44b6-97cb-8f19fe0278fe/csom-how-to-set-timephase-data-on-an-assignment?forum=project2010custprog
Other things I've tried
Using the CSOM with the MsOnlineClaimsHelper to retrieve the FedAuth cookies for a user (and assigning them using the CookieContainer).
Using the REST/OData API.
a) https:// URL.sharepoint.com/sites/pwa/_api/ProjectServer/EnterpriseResources('c39ba8f1-00fe-e311-8894-00155da45f0e')/Assignments/GetTimePhaseByUrl(start='2014-12-09',end='2014-12-09')/assignments
Enabling the "StatusBrokerPermission" for the user
Unchecking the “Only allow task updates via Tasks and Timesheets.” Option within the server settings screen (Task settings and display).
Creating a SharePoint-hosted app and using JSOM code equivalent to the CSOM code above.
a) The code we wrote was JavaScript being executed from within SharePoint app, so we did not need to provide authentication. The user who was logged in had the StatusBrokerPermission.
Using a Provider-hosted SharePoint app and using the CSOM code above. We tried using all authentication methods for CSOM above, with an additional test:
a) using Fiddler to view the FedAuth cookies being set by the SharePoint app authentication, and overriding the WebRequest to manually insert the FedAuth/rtFA cookies: webRequestEventArgs.WebRequestExecutor.WebRequest.CookieContainer = getStaticCookieContainer();
Using timesheets to submit time phased data.
a) We can only create a timesheet for the currently-authenticated user, and cannot populate timesheet lines with projects / assignments not available to him (or a GeneralItemDoesNotExist error is thrown).
Manually issuing a “SubmitAllStatusUpdates” CSOM request using fiddler, as a different user.
a) The purpose of this test was to determine if we can write time phased data, even if we can’t read it.
Making sure the project was checked out to the current user.
Using administrative delegation for a resource.
Setting all available options within project permissions.
Using the Project Web UI to enter the TimePhased data for other resources.
Using SharePoint permission mode instead of Project Permission Mode.
The code
See failing code screenshot here
using System;
using System.Security;
using Microsoft.ProjectServer.Client;
using Microsoft.SharePoint.Client;
namespace ProjectOnlineActuals
{
static class Program
{
const string projectSite = "https://URL.sharepoint.com/sites/pwa/";
private const string edward = "c39ba8f1-00fe-e311-8894-00155da45f0e";
private const string admin = "8b1bcfa4-1b7f-e411-af75-00155da4630b";
static void Main(string[] args)
{
TestActuals();
}
private static void TestActuals()
{
Console.WriteLine("Attempting test # 1 (login: admin, resource: admin)");
TestActuals("admin#URL.onmicrosoft.com", "123", admin);
Console.WriteLine("Attempting test # 2 (login: admin, resource: edward)");
TestActuals("adminy#hmssoftware.onmicrosoft.com", "123", edward);
Console.ReadLine();
}
private static void TestActuals(string username, string password, string resourceID)
{
try
{
using (ProjectContext context = new ProjectContext(projectSite))
{
DateTime startDate = DateTime.Now.Date;
DateTime endDate = DateTime.Now.Date;
Login(context, username, password);
context.Load(context.Web); // Query for Web
context.ExecuteQuery(); // Execute
Guid gResourceId = new Guid(resourceID);
EnterpriseResource enterpriseResource = context.EnterpriseResources.GetByGuid(gResourceId);
context.Load(enterpriseResource, p => p.Name, p => p.Assignments, p => p.Email);
Console.Write("Loading resource...");
context.ExecuteQuery();
Console.WriteLine("done! {0}".FormatWith(enterpriseResource.Name));
Console.Write("Adding new resource assignment to collection...");
enterpriseResource.Assignments.Add(new StatusAssignmentCreationInformation
{
Comment = "testing comment - 2016-02-17",
ProjectId = new Guid("27bf182c-2339-e411-8e76-78e3b5af0525"),
Task = new StatusTaskCreationInformation
{
Start = DateTime.Now,
Finish = DateTime.Now.AddDays(2),
Name = "testing - 2016-02-17",
}
});
Console.WriteLine("done!");
Console.Write("Trying to save new resource assignment...");
enterpriseResource.Assignments.Update();
context.ExecuteQuery();
Console.WriteLine("done!");
Console.Write("Loading TimePhase...");
TimePhase timePhase = enterpriseResource.Assignments.GetTimePhase(startDate.Date, endDate.Date);
context.ExecuteQuery();
Console.WriteLine("done!");
Console.Write("Loading TimePhase assignments...");
context.Load(timePhase.Assignments);
context.ExecuteQuery();
Console.WriteLine("done! Found {0} assignments.".FormatWith(timePhase.Assignments.Count));
Console.WriteLine("Updating TimePhase assignments...");
foreach (var assignment in timePhase.Assignments)
{
Console.WriteLine("Updating assignment: {0}. ActualWork: {1}".FormatWith(assignment.Name, assignment.ActualWork));
assignment.ActualWork = "9h";
assignment.RegularWork = "3h";
assignment.RemainingWork = "0h";
}
timePhase.Assignments.SubmitAllStatusUpdates("Status update comment test 2016-02-17");
context.ExecuteQuery();
Console.WriteLine("done!");
Console.WriteLine("Success (retrieved & updated {0} time phase assignments)!".FormatWith(timePhase.Assignments.Count));
}
}
catch (Exception ex)
{
if (ex.ToString().Contains("GeneralSecurityAccessDenied"))
Console.WriteLine("ERROR! - GeneralSecurityAccessDenied");
else
throw;
}
finally
{
Console.WriteLine();
Console.WriteLine();
}
}
private static void Login(ProjectContext projContext, string username, string password)
{
var securePassword = new SecureString();
foreach (char c in password)
securePassword.AppendChar(c);
projContext.Credentials = new SharePointOnlineCredentials(username, securePassword);
}
static string FormatWith(this string str, params object[] args)
{
return String.Format(str, args);
}
}
}
Can anyone help??

Resources