/// <summary> /// Create new instance of Standard Model /// </summary> /// <param name="content"></param> /// <param name="data"></param> public StandardModel(BaseModule module, IContent content = null, dynamic data = null, int responseCode = 200) { if (content == null) { content = new Page(); } this.Content = content; this.Data = data; this.Site = module.CurrentSite; this.Database = module.SiteDatabase; this.ResponseCode = responseCode; }
public StandardModel(BaseModule module, string title, string metakeywords = null, string metadescription = null, dynamic data = null, int responseCode = 200) { this.Content = new Page() { Title = title, MetaKeywords = metakeywords, MetaDescription = metadescription }; this.Data = data; this.Site = module.CurrentSite; this.Database = module.SiteDatabase; this.ResponseCode = responseCode; }
/// <summary> /// Immediately Send out email /// </summary> public static void ProcessQueue(Nancy.NancyContext ctx) { if (_Outbox == null) { return; } if (ctx.Items.ContainsKey("SiteSettings") == false) { return; } lock (BaseModule.GetLockObject("MailSenderModule.ProcessQueue")) { if (_Outbox == null) { return; } var toSend = _Outbox.ToList(); _Outbox = null; var site = ctx.Items["SiteSettings"] as JObject; Task.Run(() => { Func <SmtpSettings, SmtpClient> getClient = (s) => { SmtpClient client = new SmtpClient(s.server); client.Port = s.port; client.Credentials = new System.Net.NetworkCredential(s.username, s.password); client.EnableSsl = s.useSSL; client.Timeout = 30000; return(client); }; var db = NancyBlackDatabase.GetSiteDatabase(BootStrapper.RootPath); var settings = site.Property("smtp").Value.ToObject <SmtpSettings>(); var count = 0; SmtpClient sender = getClient(settings); foreach (var mail in toSend) { if (count % 100 == 0) { sender.Dispose(); count = 0; sender = getClient(settings); } var log = new NcbMailSenderLog(); log.Body = mail.Body; log.To = string.Join(",", from m in mail.To select m.Address); log.Subject = mail.Subject; log.MessageHash = (log.Body + log.To + log.Subject).GetHashCode(); log.Settings = settings; log.__createdAt = DateTime.Now; log.__updatedAt = DateTime.Now; var today = DateTime.Now.Date; var lastLog = db.Query <NcbMailSenderLog>().Where(l => l.MessageHash == log.MessageHash).FirstOrDefault(); if (lastLog != null) { if (DateTime.Now.Subtract(lastLog.__createdAt).TotalHours < 12) { log.IsSkipped = true; } } if (log.IsSkipped == false) { try { log.IsAttempted = true; mail.From = new MailAddress(settings.fromEmail); sender.Send(mail); log.IsSent = true; } catch (Exception e) { log.Exception = e; } } db.UpsertRecord(log); count++; } db.Dispose(); }); } }
protected dynamic HandleContentRequestCached(dynamic arg) { var key = "ContentModule-" + this.Request.Url.ToString(); if (this.Context.Items.ContainsKey("FBBot")) { this.GlobalInitialize(this.Context); var result = this.HandleContentRequest(arg, false); if (result is int) { return(result); } return(View["_base_facebook", new StandardModel(this, result, result)]); } // Admin will always clear the cache when visit the given page // and will always see content without processing // as admin might be editing the page if (this.CurrentUser.HasClaim("admin")) { this.GlobalInitialize(this.Context); MemoryCache.Default.Remove(key); var result = this.HandleContentRequest(arg, false); if (result is int) { return(result); } return(View[(string)result.Layout, new StandardModel(this, result, result)]); } IContent requestedContent = MemoryCache.Default[key] as IContent; if (requestedContent == null) { lock (BaseModule.GetLockObject(key)) { // other thread may procssed this url already requestedContent = MemoryCache.Default[key] as IContent; if (requestedContent != null) { return(requestedContent); } var result = this.HandleContentRequest(arg, true); if (result is int) { return(result); } requestedContent = result as IContent; MemoryCache.Default.Add(key, requestedContent, DateTimeOffset.Now.AddHours(1)); } } this.SendPageView(requestedContent); return(View[(string)requestedContent.Layout, new StandardModel(this, requestedContent, requestedContent)]); }
/// <summary> /// Get Page View Count for given item in table /// </summary> /// <param name="db"></param> /// <param name="table"></param> /// <param name="id"></param> /// <returns></returns> public static long GetPageViewCount(NancyBlackDatabase db, dynamic siteSettings, string table, int id) { var key = "PageViewCount-" + table + id; object cached = MemoryCache.Default.Get(key); if (cached != null) { return((long)cached); } if (siteSettings.analytics == null) { dynamic result = db.Query (string.Format("SELECT COUNT(Id) as Hit FROM PageView WHERE ContentId = {0} AND TableName = '{1}'", id, table), new { Hit = 0 }).FirstOrDefault(); if (result == null) { result = 0; } MemoryCache.Default.Add(key, result, DateTimeOffset.Now.AddMinutes(10)); return(result); } else { var content = db.QueryAsDynamic(table, "Id eq " + id).FirstOrDefault(); if (content == null) { MemoryCache.Default.Add(key, 0, DateTimeOffset.Now.AddMinutes(10)); return(0); // wrong content } string url = content.Url; if (url == null) { MemoryCache.Default.Add(key, 0, DateTimeOffset.Now.AddMinutes(10)); return(0); // cannot get Url } if (url.Contains("/archive/")) { url = url.Replace("/archive/", "/"); } url = url.Replace('/', '-'); long pageViews = 0; lock (BaseModule.GetLockObject("PageViewSummary-" + url)) // ensure only one thread is working on calculation { // if multiple threads is locked - they will arrive here when lock is released // so check the cache again cached = MemoryCache.Default.Get(key); if (cached != null) { return((int)cached); } CloudTable summaryTable = ContentModule.GetSummaryTable(siteSettings); var queryString = TableQuery.CombineFilters( TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, url), TableOperators.And, TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.Equal, url)); var query = new TableQuery <PageViewSummary>(); var result = summaryTable.ExecuteQuery <PageViewSummary>(query.Where(queryString)).FirstOrDefault(); if (result == null) { result = new PageViewSummary(); result.PageViews = 0; result.Path = url; result.PrepareForAzure(); result.Timestamp = DateTimeOffset.MinValue; summaryTable.Execute(TableOperation.InsertOrReplace(result)); } // find all pageview since the pageview summary timestamp var pvQueryString = TableQuery.CombineFilters( TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, url), TableOperators.And, TableQuery.GenerateFilterConditionForDate("Timestamp", QueryComparisons.GreaterThanOrEqual, result.Timestamp)); CloudTable rawTable = ContentModule.GetPageViewTable(siteSettings); var pageviewQuery = new TableQuery <PageView>(); var count = rawTable.ExecuteQuery <PageView>(pageviewQuery.Where(pvQueryString)).Count(); result.PageViews = result.PageViews + count; summaryTable.Execute(TableOperation.InsertOrReplace(result)); pageViews = result.PageViews; MemoryCache.Default.Add(key, pageViews, DateTimeOffset.Now.AddMinutes(10)); return(pageViews); } } }
/// <summary> /// Get Page View Count /// </summary> /// <param name="arg"></param> /// <returns></returns> private dynamic GetPageViewCount(dynamic arg) { var table = (string)arg.table; var id = (int)arg.id; // invalid data type, also prevent SQL Injection attack when we replace string if (this.SiteDatabase.DataType.FromName(table) == null) { return(400); } var key = table + id; dynamic cached = MemoryCache.Default.Get(key); if (cached != null) { return((string)cached); } if (this.CurrentSite.analytics == null) { dynamic result = this.SiteDatabase.Query (string.Format("SELECT COUNT(Id) as Hit FROM PageView WHERE ContentId = {0} AND TableName = '{1}'", id, table), new { Hit = 0 }).FirstOrDefault(); if (result == null) { return("0"); } MemoryCache.Default.Add(key, result.Hit.ToString("0,0"), DateTimeOffset.Now.AddMinutes(10)); return(result.Hit.ToString("0,0")); } else { var content = this.SiteDatabase.QueryAsDynamic(table, "Id eq " + id).FirstOrDefault(); if (content == null) { MemoryCache.Default.Add(key, "0", DateTimeOffset.Now.AddMinutes(10)); return("0"); // wrong content } string url = content.Url; if (url == null) { MemoryCache.Default.Add(key, "0", DateTimeOffset.Now.AddMinutes(10)); return("0"); // cannot get Url } url = url.Replace('/', '-'); long pageViews = 0; lock (BaseModule.GetLockObject("PageViewSummary-" + url)) // ensure only one thread is working on calculation { // if multiple threads is locked - they will arrive here when lock is released // so check the cache again cached = MemoryCache.Default.Get(key); if (cached != null) { return((string)cached); } var summaryTable = this.GetSummaryTable(); var queryString = TableQuery.CombineFilters( TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, url), TableOperators.And, TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.Equal, url)); var query = new TableQuery <PageViewSummary>(); var result = summaryTable.ExecuteQuery <PageViewSummary>(query.Where(queryString)).FirstOrDefault(); if (result == null) { result = new PageViewSummary(); result.PageViews = 0; result.Path = url; result.PrepareForAzure(); result.Timestamp = DateTimeOffset.MinValue; summaryTable.Execute(TableOperation.InsertOrReplace(result)); } // find all pageview since the pageview summary timestamp var pvQueryString = TableQuery.CombineFilters( TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, url), TableOperators.And, TableQuery.GenerateFilterConditionForDate("Timestamp", QueryComparisons.GreaterThanOrEqual, result.Timestamp)); var rawTable = this.GetPageViewTable(); var pageviewQuery = new TableQuery <PageView>(); var count = rawTable.ExecuteQuery <PageView>(pageviewQuery.Where(pvQueryString)).Count(); result.PageViews = result.PageViews + count; summaryTable.Execute(TableOperation.InsertOrReplace(result)); pageViews = result.PageViews; MemoryCache.Default.Add(key, pageViews.ToString("0,0"), DateTimeOffset.Now.AddMinutes(10)); return(pageViews.ToString("0,0")); } } }