I'm pretty new to ASP/MVC but have had some prior programming experience.
I am trying to retrieve statistics about URL clicks - total clicks and unique clicks by IP address. I started with:
ViewBag.ClicksToday = context.EmailLinkClicks
.Where(c => c.CreatedOn == DateTime.Today).Count();
ViewBag.ClicksWeek = context.EmailLinkClicks
.Where(c => c.CreatedOn > System.Data.Entity.DbFunctions.AddDays(c.CreatedOn, -7)).Count();
ViewBag.ClicksMonth = context.EmailLinkClicks
.Where(c => c.CreatedOn.Month == DateTime.Today.Month).Count();
ViewBag.UniqueClicksToday = context.EmailLinkClicks.Where(c => c.CreatedOn == DateTime.Today)
.Select(c => c.IPAddress).Distinct().Count();
ViewBag.UniqueClicksWeek = context.EmailLinkClicks.Where(c => c.CreatedOn > System.Data.Entity.DbFunctions.AddDays(c.CreatedOn, -7))
.Select(c => c.IPAddress).Distinct().Count();
ViewBag.UniqueClicksMonth = context.EmailLinkClicks.Where(c => c.CreatedOn.Month == DateTime.Today.Month)
.Select(c => c.IPAddress).Distinct().Count();
Then I thought why not make it a function:
private static int GetClicks(AppContext context, string period, bool unique)
{
int Clicks = 0;
switch (period)
{
case "today":
var ClicksToday = context.EmailLinkClicks
.Where(c => c.CreatedOn == DateTime.Today);
Clicks = unique ? ClicksToday.Select(c => c.IPAddress).Distinct().Count()
: ClicksToday.Count();
break;
case "week":
var ClicksWeek = context.EmailLinkClicks
.Where(c => c.CreatedOn > System.Data.Entity.DbFunctions.AddDays(c.CreatedOn, -7));
Clicks = unique ? ClicksWeek.Select(c => c.IPAddress).Distinct().Count()
: ClicksWeek.Count();
break;
case "month":
var ClicksMonth = context.EmailLinkClicks
.Where(c => c.CreatedOn.Month == DateTime.Today.Month);
Clicks = unique ? ClicksMonth.Select(c => c.IPAddress).Distinct().Count()
: ClicksMonth.Count();
break;
}
return Clicks;
}
But I still have to call quite a lot of code:
ViewBag.ClicksToday = GetClicks(context, "today", false);
ViewBag.ClicksWeek = GetClicks(context, "week", false);
ViewBag.ClicksMonth = GetClicks(context, "month", false);
ViewBag.UniqueClicksToday = GetClicks(context, "today", true);
ViewBag.UniqueClicksWeek = GetClicks(context, "week", true);
ViewBag.UniqueClicksMonth = GetClicks(context, "month", true);
My questions:
Is there any way to further simplify/reduce this code?
- perhaps have the total & unique in one value? [total],[unique]
Is it poor practice to pass period as a string and then interrogate it?
Where should you store these kind of database queries? It currently resides in my controller and then returned to the view.