Logging all unhandled exception under hosted environment - c#

I knew that I am re-inventing the wheel. But still, I have to do it as I am instructed to do so :D.
I have to log all unhandled exception of my asp.net website. I am able to dynamically catch all exceptions but I am not able to retrieve the actual class and method name.
Everytime I got Global_asax as class name and Application_Error as the method name. Below is my code.
/// <summary>
/// Determines the log type and saves log to database. Use logtype 1 for exception logging
/// and 2 for normal audit trail.
/// </summary>
/// <param name="obj">Type of object. Accepts exception or audit log string.</param>
/// <param name="logType">Type of logging. Use LogTypes.Exception for Exception and LogTypes.Audit for Normal Logging</param>
/// <param name="fileName"></param>
/// <param name="userId">optional parameter. Accepts userid as integer</param>
/// <param name="userName">optional parameter. Accepts username as string</param>
/// <param name="memberName"></param>
[MethodImpl(MethodImplOptions.NoInlining)]
private void Log( LogTypes logType, object obj, string memberName,string fileName, int userId = 0, string userName = "")
{
var appLog = new ApplicationLog();
var stackFrame = new StackFrame(2,true);
try
{
var isHosted = HostingEnvironment.IsHosted;
appLog.UserId = userId;
appLog.UserName = userName;
appLog.InstanceName = ConfigurationSettingsHelper.InstanceName;
appLog.LoggedOn = DateTime.UtcNow;
if (isHosted)
{
appLog.ProjectName = HostingEnvironment.ApplicationHost.GetSiteName();
appLog.FilePath = HttpContext.Current.Request.RawUrl;
}
else
{
appLog.ProjectName= Assembly.GetCallingAssembly().GetName().Name;
appLog.FilePath = fileName;
}
if (logType == LogTypes.Exception)
{
appLog.LogType = 1;
if (obj is Exception ex)
{
var declaringType = ex.TargetSite.DeclaringType;
if (declaringType != null)
{
appLog.ClassName = declaringType.FullName;
appLog.MethodName = ex.TargetSite.Name;
}
appLog.LogDetails = ex.ToString();
appLog.Message = ex.Message;
}
else
{
appLog.ClassName = stackFrame.GetMethod().DeclaringType.AssemblyQualifiedName;
appLog.MethodName = memberName;
appLog.LogDetails = obj.ToString();
appLog.Message = "User defined custom exception";
}
}
else
{
appLog.LogType = 2;
appLog.ClassName = stackFrame.GetMethod().DeclaringType.AssemblyQualifiedName;
appLog.MethodName = memberName;
appLog.LogDetails = obj.ToString();
appLog.Message = "User defined custom exception";
}
}
catch (Exception ex)
{
//In case of unhandled exceptions.Try logging internal exception once.
//If failed, pass by silently.
try
{
appLog = new ApplicationLog
{
UserId = userId,
UserName = userName,
FilePath = new StackFrame(1).GetFileName(),
Message = ex.Message,
InstanceName = ConfigurationSettingsHelper.InstanceName,
ProjectName = Assembly.GetCallingAssembly().GetName().Name,
LoggedOn = DateTime.UtcNow,
LogType = 1,
LogDetails = ex.ToString()
};
if (ex.TargetSite.DeclaringType != null)
appLog.ClassName = ex.TargetSite.DeclaringType.FullName;
appLog.MethodName = ex.TargetSite.Name;
}
finally
{
HttpWebMethods.PostAsync(ConfigurationSettingsHelper.LoggerApiBaseAddress,
ConfigurationSettingsHelper.SaveLogEndpoint, appLog);
} // intentionally eating exception}
}
finally
{
HttpWebMethods.PostAsync(ConfigurationSettingsHelper.LoggerApiBaseAddress,
ConfigurationSettingsHelper.SaveLogEndpoint, appLog);
}
}
It's logging all good at all places. But for the case of any unhandled exceptions, I need to capture the class name and method name. But instead, its giving me the global.asax details.
Its a class library and i want it work as same as Global.asax works. Automatically recognizes all errors.
Please help.

Related

C# Dynamic Assembly with assembly information

In my code, I create a DLL dynamically. The following code is what I use to create my DLL:
/// <summary>
/// See CodeDom example hon how its used
/// </summary>
/// <param name="source_code"></param>
/// <param name="assemblies"></param>
/// <param name="generate_executable"></param>
/// <param name="compiler_options"></param>
/// <param name="output"></param>
/// <returns></returns>
public static Tuple<Assembly, string> CompileSource(string source_code, List<string> assemblies, bool generate_executable = false, string compiler_options = "/optimize", string output_assembly = "")
{
CompilerParameters compilerParams = null;
CSharpCodeProvider provider = null;
CompilerResults result = null;
string errors = string.Empty;
try
{
provider = new CSharpCodeProvider();
compilerParams = new CompilerParameters();
foreach (var entry in assemblies)
{
compilerParams.ReferencedAssemblies.Add(entry);
}
if (output_assembly != string.Empty)
compilerParams.OutputAssembly = output_assembly;
compilerParams.GenerateExecutable = generate_executable;
compilerParams.GenerateInMemory = false;
compilerParams.IncludeDebugInformation = true;
compilerParams.CompilerOptions = compiler_options;
result = provider.CompileAssemblyFromSource(compilerParams, source_code);
foreach (CompilerError error in result.Errors)
{
errors += String.Format("{0}({1},{2}: error {3}: {4}", error.FileName, error.Line, error.Column, error.ErrorNumber, error.ErrorText);
}
}
catch (Exception err)
{
}
return Tuple.Create(result.CompiledAssembly, errors);
}
What I would like to do is add Assembly Information like the company, product, title, etc.
Looking at this site and site to add it but I'm not sure how to do it.
The CompilerParameters doesn't seem to give an option to add these attributes.
Anyone have a suggestion if it can be done on how to add this information?
Thanks

Get messages which contain an attachment via gmail API

I'm building an app based on the Gmail API. I can see all messages from the current inbox, but I need to limit this to only messages which have an attachment. How can I do this?
This is my GoogleController.cs:
[HttpGet]
[Authorize]
public async Task<IActionResult> GetListEmail(string LabelId, string nameLabel)
{
string UserEmail = User.FindFirst(c => c.Type == ClaimTypes.Email).Value;
var service = GetService();
List<My_Message> listMessages = new List<My_Message>();
List<Message> result = new List<Message>();
var emailListRequest = service.Users.Messages.List(UserEmail);
emailListRequest.LabelIds = LabelId;
emailListRequest.IncludeSpamTrash = false;
emailListRequest.MaxResults = 1000;
var emailListResponse = await emailListRequest.ExecuteAsync();
if (emailListResponse != null && emailListResponse.Messages != null)
{
foreach (var email in emailListResponse.Messages)
{
var emailInfoRequest = service.Users.Messages.Get(UserEmail, email.Id);
var emailInfoResponse = await emailInfoRequest.ExecuteAsync();
if (emailInfoResponse != null)
{
My_Message message = new My_Message();
message.Id = listMessages.Count + 1;
message.EmailId = email.Id;
foreach (var mParts in emailInfoResponse.Payload.Headers)
{
if (mParts.Name == "Date")
message.Date_Received = mParts.Value;
else if (mParts.Name == "From")
message.From = mParts.Value;
else if (mParts.Name == "Subject")
message.Title = mParts.Value;
}
listMessages.Add(message);
}
}
}
ViewBag.Message = nameLabel;
return View("~/Views/Home/Index.cshtml", listMessages);
}
I think a simpler solution would be to query in the Users.messages.list endpoint without the need to create filters.
You can actually use the parameter q to make a query like you would in the GMail searchbox, if not familiar you can look at the whole list of operators.
In fact there is an example to make use of this query parameter in the documentation:
using Google.Apis.Gmail.v1;
using Google.Apis.Gmail.v1.Data;
using System.Collections.Generic;
// ...
public class MyClass {
// ...
/// <summary>
/// List all Messages of the user's mailbox matching the query.
/// </summary>
/// <param name="service">Gmail API service instance.</param>
/// <param name="userId">User's email address. The special value "me"
/// can be used to indicate the authenticated user.</param>
/// <param name="query">String used to filter Messages returned.</param>
public static List<Message> ListMessages(GmailService service, String userId, String query)
{
List<Message> result = new List<Message>();
UsersResource.MessagesResource.ListRequest request = service.Users.Messages.List(userId);
request.Q = query; // inform this with the right query
do
{
try
{
ListMessagesResponse response = request.Execute();
result.AddRange(response.Messages);
request.PageToken = response.NextPageToken;
}
catch (Exception e)
{
Console.WriteLine("An error occurred: " + e.Message);
}
} while (!String.IsNullOrEmpty(request.PageToken));
return result;
}
// ...
}
So for your case you just need to add the line
emailListRequest.Q = "has:attachment";
before executing the request, doing like this will not create a whole filter for your account, so maybe it's more convenient for your case.
use a filter with criteria like this => criteria.query="has:attachment"
see also here => https://developers.google.com/gmail/api/v1/reference/users/settings/filters#resource
For testing any filter you can use GMail:
image

Delete Secret on Azure Keyvault not working

I have a web API method which creates secrets on azure key vault and it works fine, I also have a delete method that deletes an entity and its associated secrets, however, this method is not deleting the key on azure key vault, but it's not throwing an exception either!
Here the helper methods:
public async Task OnCreateSecretAsync(string name, string value)
{
Message = "Your application description page.";
int retries = 0;
bool retry = false;
try
{
/* The below 4 lines of code shows you how to use AppAuthentication library to set secrets from your Key Vault*/
AzureServiceTokenProvider azureServiceTokenProvider = new AzureServiceTokenProvider();
KeyVaultClient keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
var result = await keyVaultClient.SetSecretAsync(ConfigurationManager.AppSettings["VaultUrl"].ToString(), name, value)
.ConfigureAwait(false);
SecretIdentifier = result.Id;
/* The below do while logic is to handle throttling errors thrown by Azure Key Vault. It shows how to do exponential backoff which is the recommended client side throttling*/
do
{
long waitTime = Math.Min(GetWaitTime(retries), 2000000);
result = await keyVaultClient.SetSecretAsync(ConfigurationManager.AppSettings["VaultUrl"].ToString(), name, value)
.ConfigureAwait(false);
Message = result.Id;
retry = false;
}
while (retry && (retries++ < 10));
}
/// <exception cref="KeyVaultErrorException">
/// Thrown when the operation returned an invalid status code
/// </exception>
catch (KeyVaultErrorException keyVaultException)
{
Message = keyVaultException.Message;
if ((int)keyVaultException.Response.StatusCode == 429)
retry = true;
}
}
/// <summary>
/// Deletes secrets
/// </summary>
/// <param name="name">Secret</param>
/// <param name="value">Value</param>
/// <returns></returns>
public async Task OnDeleteSecretAsync(string name)
{
Message = "Your application description page.";
int retries = 0;
bool retry = false;
try
{
/* The below 4 lines of code shows you how to use AppAuthentication library to set secrets from your Key Vault*/
AzureServiceTokenProvider azureServiceTokenProvider = new AzureServiceTokenProvider();
KeyVaultClient keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
var result = await keyVaultClient.DeleteSecretAsync(ConfigurationManager.AppSettings["VaultUrl"].ToString(), name)
.ConfigureAwait(false);
SecretIdentifier = result.Id;
/* The below do while logic is to handle throttling errors thrown by Azure Key Vault. It shows how to do exponential backoff which is the recommended client side throttling*/
do
{
long waitTime = Math.Min(GetWaitTime(retries), 2000000);
result = await keyVaultClient.DeleteSecretAsync(ConfigurationManager.AppSettings["VaultUrl"].ToString(), name)
.ConfigureAwait(false);
Message = result.Id;
retry = false;
}
while (retry && (retries++ < 10));
}
/// <exception cref="KeyVaultErrorException">
/// Thrown when the operation returned an invalid status code
/// </exception>
catch (KeyVaultErrorException keyVaultException)
{
Message = keyVaultException.Message;
if ((int)keyVaultException.Response.StatusCode == 429)
retry = true;
}
}
And here the methods where I call them from:
public async Task<IHttpActionResult> AddGlobalDesignTenant([FromBody]GlobalDesignTenant globaldesigntenant)
{
var telemetry = new TelemetryClient();
try
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
string domainUrl = globaldesigntenant.TestSiteCollectionUrl;
string tenantName = domainUrl.Split('.')[0].Remove(0, 8);
globaldesigntenant.TenantName = tenantName;
var globalDesignTenantStore = CosmosStoreHolder.Instance.CosmosStoreGlobalDesignTenant;
byte[] data = Convert.FromBase64String(globaldesigntenant.base64CertFile);
var cert = new X509Certificate2(
data,
globaldesigntenant.CertificatePassword,
X509KeyStorageFlags.Exportable |
X509KeyStorageFlags.MachineKeySet |
X509KeyStorageFlags.PersistKeySet);
try
{
using (var cc = new AuthenticationManager().GetAzureADAppOnlyAuthenticatedContext(globaldesigntenant.TestSiteCollectionUrl,
globaldesigntenant.Applicationid,
globaldesigntenant.TenantName + ".onmicrosoft.com",
cert, AzureEnvironment.Production))
{
cc.Load(cc.Web, p => p.Title);
cc.ExecuteQuery();
Console.WriteLine(cc.Web.Title);
}
}
catch (Exception ex)
{
return BadRequest("Cant authenticate with those credentials");
}
KeyVaultHelper keyVaultHelperPFX = new KeyVaultHelper();
await keyVaultHelperPFX.OnCreateSecretAsync("GlobalDesignTenantPFXFileBAse64"+ tenantName, globaldesigntenant.base64CertFile);
globaldesigntenant.SecretIdentifierBase64PFXFile = keyVaultHelperPFX.SecretIdentifier;
KeyVaultHelper keyVaultHelperPassword = new KeyVaultHelper();
await keyVaultHelperPassword.OnCreateSecretAsync("GlobalDesignTenantCertPassword" + tenantName, globaldesigntenant.CertificatePassword);
globaldesigntenant.SecretIdentifieCertificatePassword = keyVaultHelperPassword.SecretIdentifier;
globaldesigntenant.CertificatePassword = string.Empty;
globaldesigntenant.base64CertFile = string.Empty;
var added = await globalDesignTenantStore.AddAsync(globaldesigntenant);
return Ok(added);
}
catch (Exception ex)
{
string guid = Guid.NewGuid().ToString();
var dt = new Dictionary<string, string>
{
{ "Error Lulo: ", guid }
};
telemetry.TrackException(ex, dt);
return BadRequest("Error Lulo: " + guid);
}
}
public async Task<IHttpActionResult> DeleteGlobalDesignTenant(string id)
{
var telemetry = new TelemetryClient();
try
{
var globalDesignTenantStore = CosmosStoreHolder.Instance.CosmosStoreGlobalDesignTenant;
var globalDesignTenant = await globalDesignTenantStore.FindAsync(id, "globaldesigntenants");
KeyVaultHelper keyVaultHelperPFX = new KeyVaultHelper();
await keyVaultHelperPFX.OnDeleteSecretAsync("GlobalDesignTenantPFXFileBAse64" + globalDesignTenant.TenantName);
KeyVaultHelper keyVaultHelperPassword = new KeyVaultHelper();
await keyVaultHelperPassword.OnDeleteSecretAsync("GlobalDesignTenantCertPassword" + globalDesignTenant.TenantName);
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var result = await globalDesignTenantStore.RemoveAsync(globalDesignTenant);
return Ok(result);
}
catch (Exception ex)
{
string guid = Guid.NewGuid().ToString();
var dt = new Dictionary<string, string>
{
{ "Error Lulo: ", guid }
};
telemetry.TrackException(ex, dt);
return BadRequest("Error Lulo: " + guid);
}
}
Based on my test, await keyVaultClient.DeleteSecretAsync(ConfigurationManager.AppSettings["VaultUrl"].ToString(), name) will delete the secret with specified name.
So, please set a break-point at the delete calling. Then run your application to see if it hits, and check if the parameters were expected values.

Cant retrieve guid from dropdown

I am trying to save a guid to a database from a populated dropdown.
The data in the class is fine but when i save the guid back to the database for reference i get the error: "guid is not in recognized format".
When i look at the value attribtute it is empty
I am using the following to standardize my lookups
/// <summary>
/// Gets the days of week.
/// </summary>
/// <returns></returns>
public List<StandardLookup> GetStandardLookups(Guid lookkupCode)
{
List<StandardLookup> lookups = new List<StandardLookup>();
try
{
var q = from lookup in fhsNetEntities.fhsLookUps.Where(a => a.lookup_type == lookkupCode).OrderByDescending(o => o.colOrder)
orderby lookup.lookup_description
select new
{
LookLookupValue = lookup.lookup,
LookupDescription = lookup.lookup_Code.Trim(),
Order = lookup.colOrder
};
if (q != null)
{
Array.ForEach(q.ToArray(), l =>
{
lookups.Add(new StandardLookup(l.LookLookupValue, l.LookupDescription, l.Order));
});
}
}
catch (Exception ex)
{
string inner = string.Empty;
if (ex.InnerException != null)
{
inner = ex.InnerException.ToString();
}
logger.Error("Error in GetDaysOfWeek function aperturenetdal " + ex.ToString() + " " + inner);
return null;
}
return lookups;
}
rdSaluation.DataSource = rdSaluations;
rdSaluation.DataValueField = "LookupValue";
rdSaluation.DataTextField = "LookupDescription";
rdSaluation.DataBind();
But when i got to my save event and debug I am getting the following error
And here you can see its grabbing the name value instead by mistake.
Put the whole code on Page_Load inside !IsPostBack. You are re-initializing your _fhsPersonal otherwise. Also you are using a variable by the same name in your btn_Click event. Change that too.

Google Calendar API v3 - Request time out when deploy on server

I tried to logged in localhost and everything works properly.
The code:
public static bool LoginGoogleCalendar(string clientId, string clientSecret, string idGCalendarUser, string calendarServiceScope, string folder)
{
try
{
UserCredential credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
new ClientSecrets
{
ClientId = clientId,
ClientSecret = clientSecret,
},
new[] { calendarServiceScope },
idGCalendarUser,
CancellationToken.None, new FileDataStore(folder)).Result;
return true;
}
catch (Exception ex)
{
Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
return false;
}
}
(I set properly the authorization for fileDataStore)
In Google Developers Console:
Redirect URIs: http://localhost/authorize/
Javascript Origins: http://localhost:8081
I use Visual Studio 2013, IIS 8
When i try the login to the server, will block the entire server for minutes and the answer after is: System.Web.HttpException Request timed out.
In Google Developers Console:
Redirect URIs: http://pippo.pluto.it/authorize/
Javascript Origins: http://pippo.pluto.it
On the server: IIS 7
The reference to my example:
https://developers.google.com/google-apps/calendar/instantiate
I walked into to same problem. Alot of examples on the internet tell you to use this class. For web applications this is not the class to use though. This class wil work perfect for "offline" applications, but when you use this class on the IIS server it wil try to open the popup on the server but it wont let it.
The class I use: GoogleAuthorizationCodeFlow
using Google.Apis.Analytics.v3;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Auth.OAuth2.Flows;
using Google.Apis.Auth.OAuth2.Requests;
using Google.Apis.Auth.OAuth2.Web;
using Google.Apis.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
namespace GoogleOauth2DemoWebApp
{
public class GoogleOauth
{
public AnalyticsService Handle(string _userId, string _connectionString, string _googleRedirectUri, string _applicationName, string[] _scopes)
{
try
{
string UserId = _userId;//The user ID wil be for examlpe the users gmail address.
AnalyticsService service;
GoogleAuthorizationCodeFlow flow;
//use extended class to create google authorization code flow
flow = new ForceOfflineGoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer
{
DataStore = new DbDataStore(_connectionString),//DataStore class to save the token in a SQL database.
ClientSecrets = new ClientSecrets { ClientId = "XXX-YOUR CLIENTID-XXX", ClientSecret = "XXX-YOURCLIENTSECRET-XXX" },
Scopes = _scopes,
});
var uri = HttpContext.Current.Request.Url.ToString();
string redirecturi = _googleRedirectUri;//This is the redirect URL set in google developer console.
var code = HttpContext.Current.Request["code"];
if (code != null)
{
var token = flow.ExchangeCodeForTokenAsync(UserId, code,
uri.Substring(0, uri.IndexOf("?")), CancellationToken.None).Result;
var test = HttpContext.Current.Request["state"];
// Extract the right state.
var oauthState = AuthWebUtility.ExtracRedirectFromState(
flow.DataStore, UserId, HttpContext.Current.Request["state"]).Result;
HttpContext.Current.Response.Redirect(oauthState);
}
else
{
var result = new AuthorizationCodeWebApp(flow, redirecturi, uri).AuthorizeAsync(UserId,
CancellationToken.None).Result;
if (result.RedirectUri != null)
{
// Redirect the user to the authorization server.
HttpContext.Current.Response.Redirect(result.RedirectUri);
}
else
{
// The data store contains the user credential, so the user has been already authenticated.
service = new AnalyticsService(new BaseClientService.Initializer()
{
HttpClientInitializer = result.Credential,
ApplicationName = _applicationName
});
return service;
}
}
return null;
}
catch (Exception ex)
{
throw ex;
}
}
internal class ForceOfflineGoogleAuthorizationCodeFlow : GoogleAuthorizationCodeFlow
{
public ForceOfflineGoogleAuthorizationCodeFlow(GoogleAuthorizationCodeFlow.Initializer initializer) : base(initializer) { }
public override AuthorizationCodeRequestUrl CreateAuthorizationCodeRequest(string redirectUri)
{
var ss = new Google.Apis.Auth.OAuth2.Requests.GoogleAuthorizationCodeRequestUrl(new Uri(AuthorizationServerUrl));
ss.AccessType = "offline";
ss.ApprovalPrompt = "force";
ss.ClientId = ClientSecrets.ClientId;
ss.Scope = string.Join(" ", Scopes);
ss.RedirectUri = redirectUri;
return ss;
}
};
}
}
Also I user a DataStore class. Saving the tokens to a file on you server isnt the best practice. I used a SQL database.
Example of the datastore class. It will make a table for you, not the best way but for testing perpose good enough.
using Google.Apis.Json;
using Google.Apis.Util.Store;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GoogleOauth2DemoWebApp
{
public class DbDataStore : IDataStore
{
readonly string connectionString;
public string ConnectionString { get { return connectionString; } }
private Boolean _ConnectionExists { get; set; }
public Boolean connectionExists { get { return _ConnectionExists; } }
/// <summary>
/// Constructs a new file data store with the specified folder. This folder is created (if it doesn't exist
/// yet) under the current directory
/// </summary>
/// <param name="folder">Folder name</param>
public DbDataStore(String _connectionString)
{
connectionString = _connectionString;
SqlConnection myConnection = this.connectdb(); // Opens a connection to the database.
if (_ConnectionExists)
{
// check if the Table Exists;
try
{
SqlDataReader myReader = null;
SqlCommand myCommand = new SqlCommand("select 1 from GoogleUser where 1 = 0",
myConnection);
myReader = myCommand.ExecuteReader();
while (myReader.Read())
{
var hold = myReader["Column1"];
}
}
catch
{
// table doesn't exist we create it
SqlCommand myCommand = new SqlCommand("CREATE TABLE [dbo].[GoogleUser]( " +
" [username] [nvarchar](4000) NOT NULL," +
" [RefreshToken] [nvarchar](4000) NOT NULL," +
" [Userid] [nvarchar](4000) NOT NULL" +
" ) ON [PRIMARY]", myConnection);
myCommand.ExecuteNonQuery();
}
}
myConnection.Close();
}
/// <summary>
/// Stores the given value for the given key. It creates a new file (named <see cref="GenerateStoredKey"/>) in
/// <see cref="FolderPath"/>.
/// </summary>
/// <typeparam name="T">The type to store in the data store</typeparam>
/// <param name="key">The key</param>
/// <param name="value">The value to store in the data store</param>
public Task StoreAsync<T>(string key, T value)
{
if (string.IsNullOrEmpty(key))
{
throw new ArgumentException("Key MUST have a value");
}
var serialized = NewtonsoftJsonSerializer.Instance.Serialize(value);
SqlConnection myConnection = this.connectdb();
if (!_ConnectionExists)
{
throw new Exception("Not connected to the database");
}
// Try and find the Row in the DB.
using (SqlCommand command = new SqlCommand("select Userid from GoogleUser where UserName = #username", myConnection))
{
command.Parameters.AddWithValue("#username", key);
string hold = null;
SqlDataReader myReader = command.ExecuteReader();
while (myReader.Read())
{
hold = myReader["Userid"].ToString();
}
myReader.Close();
if (hold == null)
{
try
{
// New User we insert it into the database
string insertString = "INSERT INTO [dbo].[GoogleUser] ([username],[RefreshToken],[Userid]) " +
" VALUES (#key,#value,'1' )";
SqlCommand commandins = new SqlCommand(insertString, myConnection);
commandins.Parameters.AddWithValue("#key", key);
commandins.Parameters.AddWithValue("#value", serialized);
commandins.ExecuteNonQuery();
}
catch (Exception ex)
{
throw new Exception("Error inserting new row: " + ex.Message);
}
}
else
{
try
{
// Existing User We update it
string insertString = "update [dbo].[GoogleUser] " +
" set [RefreshToken] = #value " +
" where username = #key";
SqlCommand commandins = new SqlCommand(insertString, myConnection);
commandins.Parameters.AddWithValue("#key", key);
commandins.Parameters.AddWithValue("#value", serialized);
commandins.ExecuteNonQuery();
}
catch (Exception ex)
{
throw new Exception("Error updating user: " + ex.Message);
}
}
}
myConnection.Close();
return TaskEx.Delay(0);
}
/// <summary>
/// Deletes the given key. It deletes the <see cref="GenerateStoredKey"/> named file in <see cref="FolderPath"/>.
/// </summary>
/// <param name="key">The key to delete from the data store</param>
public Task DeleteAsync<T>(string key)
{
if (string.IsNullOrEmpty(key))
{
throw new ArgumentException("Key MUST have a value");
}
SqlConnection myConnection = this.connectdb();
if (!_ConnectionExists)
{
throw new Exception("Not connected to the database");
}
// Deletes the users data.
string deleteString = "delete from [dbo].[GoogleUser] " +
"where username = #key";
SqlCommand commandins = new SqlCommand(deleteString, myConnection);
commandins.Parameters.AddWithValue("#key", key);
commandins.ExecuteNonQuery();
myConnection.Close();
return TaskEx.Delay(0);
}
/// <summary>
/// Returns the stored value for the given key or <c>null</c> if the matching file (<see cref="GenerateStoredKey"/>
/// in <see cref="FolderPath"/> doesn't exist.
/// </summary>
/// <typeparam name="T">The type to retrieve</typeparam>
/// <param name="key">The key to retrieve from the data store</param>
/// <returns>The stored object</returns>
public Task<T> GetAsync<T>(string key)
{
//Key is the user string sent with AuthorizeAsync
if (string.IsNullOrEmpty(key))
{
throw new ArgumentException("Key MUST have a value");
}
TaskCompletionSource<T> tcs = new TaskCompletionSource<T>();
// Note: create a method for opening the connection.
SqlConnection myConnection = new SqlConnection(this.ConnectionString);
myConnection.Open();
// Try and find the Row in the DB.
using (SqlCommand command = new SqlCommand("select RefreshToken from GoogleUser where UserName = #username;", myConnection))
{
command.Parameters.AddWithValue("#username", key);
string RefreshToken = null;
SqlDataReader myReader = command.ExecuteReader();
while (myReader.Read())
{
RefreshToken = myReader["RefreshToken"].ToString();
}
if (RefreshToken == null)
{
// we don't have a record so we request it of the user.
tcs.SetResult(default(T));
}
else
{
try
{
// we have it we use that.
tcs.SetResult(NewtonsoftJsonSerializer.Instance.Deserialize<T>(RefreshToken));
}
catch (Exception ex)
{
tcs.SetException(ex);
}
}
}
return tcs.Task;
}
/// <summary>
/// Clears all values in the data store. This method deletes all files in <see cref="FolderPath"/>.
/// </summary>
public Task ClearAsync()
{
SqlConnection myConnection = this.connectdb();
if (!_ConnectionExists)
{
throw new Exception("Not connected to the database");
}
// Removes all data from the Table.
string truncateString = "truncate table [dbo].[GoogleUser] ";
SqlCommand commandins = new SqlCommand(truncateString, myConnection);
commandins.ExecuteNonQuery();
myConnection.Close();
return TaskEx.Delay(0);
}
/// <summary>Creates a unique stored key based on the key and the class type.</summary>
/// <param name="key">The object key</param>
/// <param name="t">The type to store or retrieve</param>
public static string GenerateStoredKey(string key, Type t)
{
return string.Format("{0}-{1}", t.FullName, key);
}
//Handel's creating the connection to the database
private SqlConnection connectdb()
{
SqlConnection myConnection = null;
try
{
myConnection = new SqlConnection(this.ConnectionString);
try
{
myConnection.Open();
// ensuring that we are able to make a connection to the database.
if (myConnection.State == System.Data.ConnectionState.Open)
{
_ConnectionExists = true;
}
else
{
throw new ArgumentException("Error unable to open connection to the database.");
}
}
catch (Exception ex)
{
throw new ArgumentException("Error opening Connection to the database: " + ex.Message);
}
}
catch (Exception ex)
{
throw new ArgumentException("Error creating Database Connection: " + ex.Message);
}
return myConnection;
}
}
}
using the class:
GoogleOauth g = new GoogleOauth();
AnalyticsService service = g.Handle(userEmailAddress,
connectionString, redirectUrl,
"YOURAPLICATIONNAME",
new[] {AnalyticsService.Scope.AnalyticsReadonly});
DataResource.RealtimeResource.GetRequest request = service.Data.Realtime.Get(String.Format("ga:{0}", profileId), "rt:activeUsers");
RealtimeData feed = request.Execute();
If people are intrested I can upload a sample project to github.

Categories