Display Google Analytics Data in View - c#

I'm working on a Google Analytics Client for an MVC application that collects data from Analytics API and I'm trying display the data in a view. The ultimate goal is to display the Google Analytics Data with Google Charts.
However I'm not sure how to properly structure the Data. Each metric is a dictionary with a KeyValuePair where metric name is key and value is the actual value. For example ga:visitors, 3000. I need to organize each metric with its KeyValuePair in to a dictionary that I can return to the view.
For example, first I wrote a console application that returned 3 metrics:
ga:visitors
ga:newVisits
ga:percentNewVisits
Note: each of this metrics is a separate dictionary with KeyValuePair. Ex: [ga:visitors, 3000]
When displaying the data in the console, the code looks like this:
Console.WriteLine("VisitorStatistics" + " " +
d.Query.StartDate + " " + "-" + " " + d.Query.EndDate + "\r\n" +
"------------------------------------------" + "\r\n" +
"Visitors:" + " " + d.TotalsForAllResults["ga:visitors"] + "\r\n" +
"New Visitors:" + " " + d.TotalsForAllResults["ga:newVisits"] + "\r\n" +
"Percent New Visitors:" + " " + d.TotalsForAllResults["ga:percentNewVisits"] +"%");
I need to display this data in my MVC 4 /asp.net application but I'm not sure how to achieve this. All code is located here in my controller:
public void GAnalyticsService()
{
var serviceAccountEmail = "xxxxx.gserviceaccount.com";
var certificate = new x509Certificate2(#"C:\Users\User\Desktop\MyApp\Presentation\Nop.Web\key.p12", "notasecret", X509KeyStorageFlags.Exportable);
var credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail) {
Scopes = new[] { AnalyticsService.Scope.Analytics }
}.FromCertificate(certificate));
// Create the service.
//NopCommerce
var GoogleAnalyticsService = new AnalyticsService(new BaseClientService.Initializer() {
HttpClientInitializer = credential,
ApplicationName = "MyApp",
});
var request = GoogleAnalyticsService.Data.Ga.Get("ProfileID", "2010-02-24", "2014-02-24", "ga:visitors,ga:newVisits,ga:percentNewVisits");
//Specify some addition query parameters
request.Dimensions = "ga:visitCount";
request.Sort = "-ga:visitors";
request.MaxResults = 10000;
//Execute and fetch the results of our query
Google.Apis.Analytics.v3.Data.GaData d = request.Execute();
}
public ActionResult GAStatistics() {
//GAnalyticsService();
return View(new GAStatisticsListModel());
}
}
Here's the data i'm recieving from Google Analytics API:
Total results with 3 metrics (each a dictionary with KeyValuePair)
The KeyValuePair:
I just need to organise this data and display it in the view, just plain data (text) is fine. How do i do this?
Any suggestions would be of great help.

Did a temporary fix just to display the data. It serves it's purpose for the time beeing.
Changed GAnalyticsService from a void to a string method.
Returned this:
return "Besöksstatistik" + " " +
d.Query.StartDate + " " + "-" + " " + d.Query.EndDate + "<br/>" +
"------------------------------------------" + "<br/>" +
"Antal besökare:" + " " + d.TotalsForAllResults["ga:visitors"] + "<br/>" +
"Antal nya besökare:" + " " + d.TotalsForAllResults["ga:newVisits"] + "<br/>" +
"Procent nya besökare:" + " " + d.TotalsForAllResults["ga:percentNewVisits"] + "%".ToString();
Got the following output in the view:
Besöksstatistik 2010-02-24 - 2014-02-24
------------------------------------------
Antal besökare: 343272
Antal nya besökare: 147693
Procent nya besökare: 42.54700702044485%

Related

Using apostrophe in email subject while sent email via gmail api creating an issue

While sent email using below subject which apostrophe replacing with another characters
Actual Subject : We’ll make 100,800 cold calls for you
Mail Shows Subject : We’ll make 100,800 cold calls for you
Issue happens when I'm sent email via api , when sent email from SMTP it's working fine
Please check my api code below
string msg = "From: " + FromName + "<" + From + ">" + " \r\n" +
"To: " + ToName + "<" + To + ">" + " \r\n" +
"BCC: " + BCCEmail + " \r\n" +
"Subject: " + Subject + " \r\n" +
"Message-ID: mID_" + messageID + "\r\n" +
"References: "+encryptMessageID + "\r\n" +
"In-Reply-To: " + encryptMessageID + "\r\n" +
"Content-Type: " + contentType + "; charset=us-ascii\r\n\r\n" + Body;
dynamic objSendMsg = new { raw = commonFunction.Base64UrlEncode(msg) };
if (!string.IsNullOrEmpty(messageThreadID))
objSendMsg = new { raw = commonFunction.Base64UrlEncode(msg), threadId = messageThreadID };
var _objSendMsg = JsonConvert.SerializeObject(objSendMsg);
var strSendMsg = new StringContent(_objSendMsg, UnicodeEncoding.UTF8, "application/json");
When same content i'm applying in body with apostrophe working fine for body
Please check attached screenshot
Email copy
You need to base64_encode of the subject header your sending it as plain text. the API is getting confused.
Subject: " + Convert.ToBase64String(Subject) + " \r\n" +

Add pause to Alexa without using SSML

Is there a way to add a pause (preferably 1 second) in Amazon Alexa without using SSML? Perhaps there is a trick I can do with the Outputspeech.Text and I just don't know it.
Below, I am saying "Here are works of art by {artist name}" but the name and the start of the works of art become mixed together - in spite of the period - so I end up with things like "Here are the works of art by Pablo Picasso Harlequin..."
I am using C# and my own https endpoint, not AWS Lambda.
Any suggestions? Otherwise I will add it as SSML. Thanks.
var output = new StringBuilder();
var outputCard = new StringBuilder();
string m_location;
string m_current_location;
string m_artist = dt_artist.Rows[0]["DisplayName"].ToString();
output.Append("here are works of art for " + m_artist + ". ");
outputCard.Append("Here are works of art for " + m_artist + ".\n\n");
foreach (DataRow dr in dt_artist_objs.Rows)
{
m_current_location = dr["CurrentLocation"].ToString();
if (m_current_location == " ")
{
m_location = "The location is not available.";
}
else
{
m_location = "It is located on the " + m_current_location;
}
output.Append(dr["Title"].ToString() + " is a " + dr["Classification"].ToString() + ". The medium is " + dr["Medium"].ToString() + ". " + m_location);
outputCard.Append(dr["Title"].ToString() + ", " + dr["Dated"].ToString() + " is a " + dr["Classification"].ToString() + ". The medium is " + dr["Medium"].ToString() + ". " + dr["Creditline"].ToString() + ". " + m_location + ".\n"); // It is located on the " + dr["CurrentLocation"].ToString());
}
sql_conn_data.Close();
response.Response.OutputSpeech.Text = output.ToString();
response.Response.Card.Title = "Art";
response.Response.Card.Type = "Standard";
response.Response.Card.Text = outputCard.ToString();
response.Response.ShouldEndSession = true;
return response;
UPDATE
OK. Ended up going the SSML route which looks like this:
var output = new StringBuilder();
var outputCard = new StringBuilder();
string m_location;
string m_current_location;
string m_location_card;
string m_artist = dt_artist.Rows[0]["DisplayName"].ToString();
output.Append("<speak>");
output.Append("here are works of art for " + m_artist + ". <break time='1s'/> ");
outputCard.Append("Here are works of art for " + m_artist + ".\n\n");
foreach (DataRow dr in dt_artist_objs.Rows)
{
m_current_location = dr["CurrentLocation"].ToString();
if (m_current_location == " ")
{
m_location = "The location is not available. <break time='1s' />";
m_location_card = "The location is not available. ";
}
else
{
m_location = "It is located on the " + m_current_location + "<break time = '1s' />";
m_location_card = "It is located on the " + m_current_location;
}
output.Append(dr["Title"].ToString() + " is a " + dr["Classification"].ToString() + ". The medium is " + dr["Medium"].ToString() + ". " + m_location);
outputCard.Append(dr["Title"].ToString() + ", " + dr["Dated"].ToString() + " is a " + dr["Classification"].ToString() + ". The medium is " + dr["Medium"].ToString() + ". " + dr["Creditline"].ToString() + ". " + m_location_card + ". \n");
}
output.Append("</speak>");
sql_conn_data.Close();
response.Response.OutputSpeech.Ssml = output.ToString();
response.Response.OutputSpeech.Type = "SSML";
response.Response.Card.Title = "Art";
response.Response.Card.Type = "Standard";
response.Response.Card.Text = outputCard.ToString();
response.Response.ShouldEndSession = true;
return response;
}
There is not a way to introduce a pause in Alexa without SSML. You will need to build the ssml string and return it back to Alexa using the pause, or the cadence strings.

How to generate the Azure Table Service SAS token from c# code?

I would like to generate the SAS token for Azure table service from C# code. I generated the one from the portal which looks like
?sv=2016-05-31&ss=t&srt=sco&sp=rwdlacu&se=2017-03-23T20:05:14Z&st=2017-03-23T12:05:14Z&sip={MY_IP}&spr=https&sig=fL9GNAZqybSlQKWvaspwr%2FrFFtWO%2F5jVgFu1Ayu94Ic%3D
How to generate such kind of token from c# code? If there is any tutorial please redirect me to it.
I tried with a method below, but the token generated is invalid.
UPDATED CODE
I am still getting an error 403 Forbidden. Is my code to compute the signature correct?
var StringToSign = "{Storage_account_name}" + "\n" +
"rwdlacu" + "\n" +
"t" + "\n" +
"sco" + "\n" +
"2017-03-24T12:05:14Z" + "\n" +
"2017-03-24T20:05:14Z" + "\n" +
"{IP}" + "\n" +
"https" + "\n" +
"2016-05-31" + "\n";
string encodedString = HttpUtility.UrlEncode(StringToSign);
HMACSHA256 hmac = new HMACSHA256(Convert.FromBase64String("accountkey"));
var signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(encodedString)));
The reason you're running into the issue is because you're calculating signature for SAS based on the logic for calculating Authorization header. StringToSign is different in both cases.
For SAS, this should be (for Service SAS):
StringToSign = signedpermissions + "\n" +
signedstart + "\n" +
signedexpiry + "\n" +
canonicalizedresource + "\n" +
signedidentifier + "\n" +
signedIP + "\n" +
signedProtocol + "\n" +
signedversion + "\n" +
startingPartitionKey + "\n"
startingRowKey + "\n"
endingPartitionKey + "\n"
endingRowKey
If you want to use Account SAS (which is what Portal does), it should be:
StringToSign = accountname + "\n" +
signedpermissions + "\n" +
signedservice + "\n" +
signedresourcetype + "\n" +
signedstart + "\n" +
signedexpiry + "\n" +
signedIP + "\n" +
signedProtocol + "\n" +
signedversion + "\n"
So based on your parameters, the StringToSign for Account SAS would be:
StringToSign = {youraccountname} + "\n" +
"rwdlacu" + "\n" +
"t" + "\n" +
"sco" + "\n" +
"2017-03-23T12:05:14Z" + "\n" +
"2017-03-23T20:05:14Z" + "\n" +
{yourip} + "\n" +
"https" + "\n" +
"2016-05-31 + "\n"
The computation for signature is correct.
You may find these links helpful to learn more about computing SAS: Account SAS and Service SAS.
UPDATE
There's an issue with hmac calculation as well. It should be using your account key and also it should use Convert.FromBase64String.
HMACSHA256 hmac = new HMACSHA256(Convert.FromBase64String(accountKey));
Also, you should not URLEncode StringToSign. Elements there should be URL decoded.
Lastly the SAS token should look like what you're getting back from the portal.
Code Sample
static void AccountSasSample()
{
var accountName = "your-account-name";
var accountKey = "your-account-key";
var start = DateTime.UtcNow.AddHours(-1).ToString("yyyy-MM-ddTHH:mm:ssZ");
var end = DateTime.UtcNow.AddHours(1).ToString("yyyy-MM-ddTHH:mm:ssZ");
var permission = "rwdlacu";
var serviceType = "t";
var resourceTypes = "sco";
var ipAddress = "your-ip-address";
var protocol = "https";
var serviceVersion = "2016-05-31";
var stringToSign = string.Format("{0}\n{1}\n{2}\n{3}\n{4}\n{5}\n{6}\n{7}\n{8}\n", accountName, permission, serviceType, resourceTypes, start, end, ipAddress, protocol, serviceVersion);
Console.WriteLine(stringToSign);
HMACSHA256 hmac = new HMACSHA256(Convert.FromBase64String(accountKey));
string signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));
var sasToken = string.Format("?sv={0}&ss={1}&srt={2}&sp={3}&se={4}&st={5}&sip={6}&spr={7}&sig={8}", serviceVersion,
serviceType, resourceTypes, permission, end, start, ipAddress, protocol, HttpUtility.UrlEncode(signature));
Console.WriteLine(sasToken);
var urlToListTables = string.Format("https://{0}.table.core.windows.net/Tables{1}", accountName, sasToken);
//Copy this urlToListTables & paste it in browser's address bar. You should be able to see the list of tables in your storage account.
}
//account name
var storageAccountName = ConfigProvider.AccountName;
// your storage account access key here
var accessKey = ConfigProvider.BlobKey;
// connect to our storage account and create a blob client
var connectionString = String.Format("DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1}",
storageAccountName,
accessKey);
var storageAccount = CloudStorageAccount.Parse(connectionString);
var blobClient = storageAccount.CreateCloudBlobClient();
SharedAccessAccountPolicy policy = new SharedAccessAccountPolicy()
{
Permissions = SharedAccessAccountPermissions.Write | SharedAccessAccountPermissions.Create,
Services = SharedAccessAccountServices.Blob,
ResourceTypes = SharedAccessAccountResourceTypes.Container | SharedAccessAccountResourceTypes.Object,
SharedAccessExpiryTime = DateTime.UtcNow.AddMonths(1),
Protocols = SharedAccessProtocol.HttpsOnly,
};
string sasToken = storageAccount.GetSharedAccessSignature(policy);
Why not use Azure Storage Client Library to generate SAS? You can refer to: https://learn.microsoft.com/en-us/azure/storage/storage-dotnet-shared-access-signature-part-1

Loop LDAP memberOf as return to show all for single user

Pretty new to using LDAP, and C# in general, and I did more than a few searches, but most of my attempted fixes have lead nowhere.
I am pulling information from the LDAP. Everything works, except I can only pull the memberOf information if I am explicit in which array number I want. Attempts to use a foreach, or a for statement have lead nowhere. I know I am probably missing something simple, but I figured I should just ask.
public static String FindOther(String userAccount)
{
DirectoryEntry entry = GetDirectoryEntry();
DirectorySearcher search = new DirectorySearcher(entry);
try
{
search.Filter = "(SAMAccountName=" + account + ")";
search.PropertiesToLoad.Add("distinguishedName");
search.PropertiesToLoad.Add("displayName");
search.PropertiesToLoad.Add("mail");
search.PropertiesToLoad.Add("CN");
search.PropertiesToLoad.Add("Title");
search.PropertiesToLoad.Add("sn");
search.PropertiesToLoad.Add("givenname");
search.PropertiesToLoad.Add("telephoneNumber");
search.PropertiesToLoad.Add("memberOf");
SearchResult result = search.FindOne();
if (result != null)
{
return
"Results for " + userAccount + "\n" +
" DistinguishedName..: " + result.Properties["distinguishedName"][0].ToString() + "\n" +
" Displayname........: " + result.Properties["displayname"][0].ToString() + "\n" +
" eMail..............: " + result.Properties["mail"][0].ToString() + "\n" +
" Common Name........: " + result.Properties["CN"][0].ToString() + "\n" +
" Title..............: " + result.Properties["Title"][0].ToString() + "\n" +
" Last Name..........: " + result.Properties["sn"][0].ToString() + "\n" +
" First Name.........: " + result.Properties["givenname"][0].ToString() + "\n" +
" Telephone..........: " + result.Properties["telephoneNumber"][0].ToString() + "\n" +
" Member Of..........: " + result.Properties["memberOf"][0].ToString() + "\n" +
" Member Of..........: " + result.Properties["memberOf"][1].ToString() + "\n" +
"End Transmission" + "\n";
}
else
{
return "Object not found... User ID: " + account;
}
}
catch (Exception ex)
{
return "Big Ol Error: " + ex.Message + " User ID: " + account;
}
}
Thank you all for any help you could provide.
You can enumerate through an PropertyCollection this way:
string Ret = string.Empty;
...
foreach(object memberOf in result.Properties["memberOf"])
{
Ret += " Member Of..........: " + memberOf.ToString() + "\n";
}
I'm going to give a slight disclaimer here, mostly because I've never coded to Active Directory or the Lightweight Directory Access Protocol. Some of the things that I do know, is a DirectoryEntry usage recommends:
Use GetDirectoryEntry when you want to look at the live entry instead
of the entry that was returned through DirectorySearcher, or when you
want to invoke a method on the object that was returned.
This particular method will return the information directly from Active Directory. Where DirectorySearcher will only generate through what is currently available in the collection. I mention this, because without the collection being filled it won't generate much.
I'm not sure what type of application your building, but Microsoft has an entire area within Microsoft Developer Network that mentions how to integrate several LDAP / AD features into an application.
I'm not sure of your entire goal, but I believe this is what you are seeking. If not let me know and I'll modify the code.
static void Main(string[] args)
{
string groupName = "Domain Users";
string domainName = "";
PrincipalContext ctx = new PrincipalContext(ContextType.Domain, domainName);
GroupPrincipal grp = GroupPrincipal.FindByIdentity(ctx, IdentityType.SamAccountName, groupName);
if (grp != null)
{
foreach (Principal p in grp.GetMembers(false))
{
Console.WriteLine(p.SamAccountName + " - " + p.DisplayName);
}
grp.Dispose();
ctx.Dispose();
Console.ReadLine();
}
else
{
Console.WriteLine("\nWe did not find that group in that domain, perhaps the group resides in a different domain?");
Console.ReadLine();
}
}
This code was actually from a book, it was used to accomplish such a goal. But as I stated up top, I've never physically done such a task- I'm just hoping to point you in the proper direction.
Another question similar to yours can be found here, which contains good reference and answers your question I believe.

How to search Complex Arraylist & Insert at given point

I am trying to create a simple appplication that can read from a text file and write to the text file. I have a main form which is shown below, also i have a secondary form also shown below; there are also getter and setter classes for Customers, accounts and Transactions. What i would like to do is search for a Customer based on any data held, but mostly there account number. How would i get it to return the correct customer with ALL of there information. Linked to this it would be good to use the search as a point for inserting say a new account.
Below is the main form for pritning out the customer and getting the information from the file.
//create account if all ok
if (allInputOK)
{
//create Account
Account temp = new Account(tempAccSortCode, tempAccNumber, tempAccNickName, tempAccDate, tempAccCurBal, tempAccOverDraft, tempNumTrans);
//add to array
Form1.accDetails.Add(temp);
//finish up
MessageBox.Show("Success Account added ");
resetForm();
}
}
foreach (Customer c in bankDetails)
{
lstOutput.Items.Add(" ");
lstOutput.Items.Add(c.getCustomerNumber() + " " + c.getCustomerTitle() + " " + c.getFirstName()
+ " " + c.getInitials() + " " + c.getSurname() + " " + c.getDateOfBirth()
+ " " + c.getHouseNameNumber() + " " + c.getStreetName() + " " + c.getArea()
+ " " + c.getCityTown() + " " + c.getCounty() + " " + c.getPostcode()
+ " " + c.getPassword() + " " + c.getNumberAccounts());
foreach (Account a in c.Accounts)
{
lstOutput.Items.Add("\t" + a.getAccSort() + " " + a.getAccNumber() + " " + a.getAccNick() + " " + a.getAccDate()
+ " " + a.getAccCurBal() + " " + a.getAccOverDraft() + " " + a.getAccNumTrans());
foreach (Transaction t in a.Transactions)
{
lstOutput.Items.Add("\t \t" + t.getDate() + " " + t.getType() + " " + t.getDescription() + " " + t.getAmount()
+ " " + t.getBalAfter());
}
}
}
In the above code for adding an account, where is adds it to the class Account and the arraylist i think is incorrect with the rest of the program on the main form which uses an underlying list to store the customer information and there accounts/transactions.
EDIT: the above code snippet shows the adding of a new account, however it doesnt seem to be working as i need to find the correct customer by searching the customer array, and then inserting it into the correct place. The second snippet of code shows the arraylist with the underlying lists connected to each customer.
Where to begin?
Generally, for querying objects you can use Linq to Objects.
Also, I would recommend against using text files to keep track of things. They are fine at first, but quickly grow unwieldy and slow. On top of that, what if your app crashes before you saved? Look into a "light database" like SQLite (yes, that's one 'L').

Categories