Optimal way to cache time of day description - c#

What is the best method to cache the following? I am creating an intranet web application template that will display the message, e.g., Good Morning, Justin Satyr! near the top of my master page header. Obviously, I will have to determine whether to show Morning, Afternoon or Evening. For clarity, my code is below:
string partOfDay;
var hours = DateTime.Now.Hour;
if (hours > 16)
{
partOfDay = "evening";
}
else if (hours > 11)
{
partOfDay = "afternoon";
}
else
{
partOfDay = "morning";
}
I do not want to re-determine this on each page load because that seems moderately redundant and because I have to poll a SQL server to retrieve the user's full name. What is the best way to cache this information? If I cache it for the length of the session, then if the user begins using the application at 11:00 AM and finishes at 3:00 PM, it will still say Good Morning.
Is the best thing to do simply re-determine the M/A/E word each page load and cache the person's full name for the session? Or is there a better way?

I would just keep the user name in the Session object, the rest honestly is not worth caching and checking if it is out of date etc., just re-run it on each page - provided you put the implementation into a common library /class so you keep your code DRY.

In my opinion there is absolutely no need to cache the part of day. User information can be made available in the Session.

If you are talking in ASP.NET MVC context, you can use System.Web.Helpers namespace, where you can find WebCache helper. Than you need to calculate minutes to time of day_time will be changed and call WebCache.Set method with paramters: value="your string", minutesToCache=calculated_value.

Old, I know, but I don't cache mine, due to the obvious reason that the users time may change during the session. I store their calculated time in my session (calculates based on their timezone), and then use this code at the top of all pages:
<strong>#string.Format("Good {0}, ", SessionManager.GetUserCurrentDate().Hour > 16 ? "Evening" : SessionManager.GetUserCurrentDate().Hour > 11 ? "Afternoon" : "Morning") + SessionManager.GetDisplayName())</strong>
Works well for me!

Related

How to get a date in a link? MVC 5

I'm implementing a web page, doing the homepage, I have a button that the user uses in order to recover his password (due to forgetting it). Then my program sends him a link to his e-mail after verifying it in the database. This link let's the user reset his password.
I want to add a date to the link, so that if when the user gets redirected to the reset pass page, it's date is verified and if it is higher than 1 hour it tells the user he needs to re-do the process.
Do I use,
DateTime saveNow = DateTime.Now;?
Sorry for the bad English, thank you
You can use DateTime.Now.Ticks. This gives you an integer that can easily be posted in an url and then be converted to a DateTime again.
Ok, this doesn't quite answer your question, however there is a better way of handling password reset timeouts. If you are using the following code in your action:
WebSecurity.GeneratePasswordResetToken(emailAddress);
You can also pass in a second parameter which specifies how long the password token is valid for in minutes otherwise the default time out is 24 hours.
From there you can validate the token is valid in a bool type action by using something similar to the below:
var repository = repository.GetByPasswordResetToken(resetToken);
isValid = membership != null && repository.PasswordVerificationTokenExpirationDate > DateTime.Now;
This is based on the assumption you are utilising WebMatrix within your server side logic.

What would be the best way to synchronize my application's time with outside server's time?

I was thinking of changing system's local time to server's time and then use it but I bet there are other ways to do this. I've been trying to find something like a clock in c#, but couldnt find anything. I'm receiving server's time in a DateTime format.
edit:
I need my application to use while working same time server does. I just want to get server's time once and after that, make my application work in a while loop using the time I've obtained from the server. There might be a difference between my system's time and server's time (even 5 seconds) and that's why I want to do this.
It's not entirely clear what you mean, but you could certainly create your own IClock interface which you'd use everywhere in code, and then write an implementation of that which is regularly synchronized with your server (or with NTP).
My Noda Time project already uses the idea of an injectable clock - not for synchronization purposes, but for testability. (A time service is basically a dependency.) Basically the idea is workable :) You may well not find anything which already does this, but it shouldn't be too hard to write. You'll want to think about how to adjust time though - for example, if the server time gets ahead of your "last server time + local time measurements" you may want to slew it gradually rather than having a discrete jump.
This is always assuming you do want it to be local to your application, of course. Another alternative (which may well not be appropriate, depending on your context) is to require that the host runs a time synchronization client (I believe Windows does by default these days) and simply start failing if the difference between your server and the client gets too large. (It's never going to be exactly in sync anyway, or at least not for long - you'll need to allow for some leeway.)
The answer #JonSkeet's provided to synch the times looks good, I just wanted to point out some things.
As #Alexei already said, users require admin privileges to be able to change their local time (in Windows as least), but there may also be other issues that can cause the time to be out of synch (bad internet connection, hacks etc.). This means there is no guarantee that the client time is indeed the same as the server time, so you will at least need to check the time the request was received serverside anyway. Plus there might also be a usability issue at hand here, would I want an application to be able change the time of my own local machine? Hell no.
To sum things up:
Check the time of the request serverside at least
Don't change the time of the client machine but show some kind of indicator in your application
How to handle the indicator in your application can be done in various ways.
Show a clock in your application (your initial idea) that is periodically synched with the server
Show some kind of countdown ("you can submit after x seconds.."), push a resetCountdown request to the clients when a request is received.
Enable a 'send button' or what ever you have, this would work kind of similar to the countdown.
Just remember, it's nearly impossible validate a request such as this clientside. So you have to build in some checks serverside!
I actually wanted to write a comment but it got kind of long.. :)
Okay a bit of necromancy as this is 6 years old, but had to deal with a similar problem for a network game.
Employed a technique I referred to as "marco-polo" for reasons that will be obvious soon. It requires the two clocks to be able to exchange messages, and its accuracy is dependent on how fast they can do that.
Disclaimer: I am fairly certain I am not the first to do this, and that this is the most rudimentary way to synchronize two clocks. Still I didn't find a documented way of doing so.
At Clock B (The clock we're trying to synchronize) we do the following ::
// Log the timestamp
localTime_Marco_Send = DateTime.UtcNow;
// Send that to clock A
SendSyncRequest();
// Wait for an answer
Sleep(..);
At Clock A (the reference clock) we have the following handler ::
// This is triggered by SendSyncRequest
OnReceiveSyncRequest()
{
// We received "Marco" - Send "Polo"
SendSyncReply(DateTime.UtcNow);
}
And back at Clock B ::
// This is triggered by SendSyncReply
OnReceiveSyncReply(DateTime remoteHalfTime)
{
// Log the time we received it
DateTime localTime_Polo_Receive = DateTime.UtcNow;
// The remote time is somewhere between the two local times
// On average, it will be in the middle of the two
DateTime localHalfTime = localTime_Marco_Send +
(localTime_Polo_Receive - localTime_Marco_Send) / 2;
// As a result, the estimated dT from A to B is
TimeSpan estimatedDT_A_B = localHalfTime - remoteHalfTime;
}
As a result we now have access to a nifty TimeSpan we can subtract from our current local time to estimate the remote time
DateTime estimatedRemoteTime = DateTime.UtcNow - estimatedDT_A_B;
The accuracy of this estimate is subject to the Round Trip Time of send-receive-send-receive, and you should also account for Clock drift (you should be doing this more than once):
Round-trip-time. If it were instant, you'd have the exact dT. If it takes 1 second to come and return, you don't know if the delay was on the sending or the receiving. As a result, your error is 0 < e < RTT, and on average will be RTT/2. If you know send (or receive) takes more than the other, use that to your advantage - the time you received is not the half-time, but is shifted relatively to how long each leg takes
Clock drift. CPU clocks drift, maybe 1s per day. So poll again once potential drift may play an important role.
Your server should always save the time in UTC mode.
You save time in UTC like this in the server:
DateTime utcTime = new DateTime(0, DateTimeKind.Utc);
or:
DateTime utcTimeNow = DateTime.UtcNow;
In the client, when you get the time which is stored in utc you can sonvert it to local time like this:
public DateTime ToLocalTime(DateTime utcTime)
{
//Assumes that even if utcTime kind is no properly deifned it is indeed UTC time
DateTime serverTime= new DateTime(utcTime.Ticks, DateTimeKind.Utc);
return TimeZoneInfo.ConvertTimeFromUtc(serverTime, m_localTimeZone);
}
If You want to change your local time zone , here is a code example on how to read time zone to use from config:
string localTimeZoneId = sysParamsHelper.ReadString(LOCAL_TIME_ZONE_ID_KEY, LOCAL_TIME_ZONE_DEFAULT_ID);
ReadOnlyCollection<TimeZoneInfo> timeZones = TimeZoneInfo.GetSystemTimeZones();
foreach (TimeZoneInfo timeZoneInfo in timeZones)
{
if(timeZoneInfo.Id.Equals(localTimeZoneId))
{
m_localTimeZone = timeZoneInfo;
break;
}
}
if (m_localTimeZone == null)
{
m_logger.Error(LogTopicEnum.AMR, "Could not find time zone with id: " + localTimeZoneId + " . will use default time zone (UTC).");
m_localTimeZone = TimeZoneInfo.Utc;
}

Retrieve old searches from Google web history

I want to retrieve old Google searches which I did a few years/months back and that are present in Google web history. How can I programmatically retrieve them all?
https://www.google.com/history/?output=rss only provides recent Google searches, but not all of them.
Also this question : How can I retrieve my Google search history? doesn't provide any answer for my question!
You can pass month, day and year as parameters to obtain history of a specific day.
E.g. https://www.google.com/history/lookup?month=12&day=1&yr=2010&output=rss for Dec, 1 2010.
There are no ways to obtain history for a full month or year, let alone the entire history. But this information about the parameters must at least enable you to obtain the entire history in some loop which goes one day further back in the time everytime. Be carecul that you don't leech too much in a too short time.
You really need to parse HTML page by page and then fetch your data, because i dont think there is any alternative!
I think this will be very difficult.
I know this doesn't answer you question completely but at least the web pages may be preserved. There are organizations and tools that allow you to recreate web pages from past dates - see for example http://www.mementoweb.org/.
UPDATE: I have just learnt that Memento has won a digital preservation award (http://www.dpconline.org/newsroom)
I know you're not looking to go back through every page, but you don't really need to parse the whole page, just look for the html that always precedes an entry. From me just starting up google web history and doing some simple searches, if you look through a history page, each String that you've searched follows: <td style="padding:3px 0"><table id=bkmk_view_ class=noborder ><tr><td><table class="elem noborder"><tr><td class="grey" nowrap>Searched for </td><td nowrap><a title="http://www.google.com/search?q=
and is followed by & (ampersand). This sequence of preceding html is unique on the page, only occuring when historical search terms are listed.
If you use two terms, you get a + in between the terms. Other conventions for different searching modes, I didn't go through them all.
It looks like if you use BalusC's method to pass parameters, then you could retreive the html, search the document for the string I mentioned(be sure to \" and other special characters), then copy the next String until you reach a & character. Then, all you need to do is parse your search term, not the whole page. Go through source code until you reach the end, then go to your next iteration in the loop.
static void GetGoogleWebHistory(int month, int day, int yr, string UserName, string Pass)
{
string iURL = "http://www.google.com/history/lookup?month=" + month + "&day=" + day + "&yr=" + yr + "&output=rss";
WebClient client = new WebClient();
GDataCredentials gdc = new GDataCredentials(UserName, Pass);
RequestSettings rs = new RequestSettings(Guid.NewGuid().ToString(), gdc);
XmlDocument XDoc = new XmlDocument();
XDoc.LoadXml(client.DownloadString(iURL));
}

How to implement Stack Overflow's "are you a human" feature?

On this site if you do too many clicks or post comments too fast or something like that you get redirected to the "are you a human" screen. Does anybody know how to do something similar?
It's almost certainly a heuristic that tries to "guess" that a user is some form of automated process, rather than a person, for example:
More than "x" requests to do the same thing in a row
More than "x" actions in a "y" period of time
Ordinarily the "x" and "y" values would be formulated to be ones that it would be unlikely for a "real person" to do, like:
Editing the same answer 5 times in a row
Downvoting 10 questions within 1 minute
Once you've got your set of rules, you can then implement some code that checks them at the start of each request, be it in a method that's called in Page_Load, something in your masterpage, something in the asp.net pipeline, that's the easy bit! ;)
Here is a very nice Captcha Control for asp.net that first of all you need
http://www.codeproject.com/KB/custom-controls/CaptchaControl.aspx
Then you can use it together with this idea that try to find the dos attacks
http://weblogs.asp.net/omarzabir/archive/2007/10/16/prevent-denial-of-service-dos-attacks-in-your-web-application.aspx
be ware of a bug in this code in line if( context.Request.Browser.Crawler ) return false;, its must return true, or totally remove it for sure.
and make it your compination for the clicks, or submits.
If a user make too many clicks on a period of time, or many submits, then you simple open the capthaControl, and if the clicks are by far too many, then triger the dos attact. This way you have 2 solution in one, Dos attact prevent, with captcha at the same time.
I have made somthing similar my self, but I have change the source code of both, a lot to feet my needs.
One more interesting link for a different code for the dos attack.
http://madskristensen.net/post/Block-DoS-attacks-easily-in-ASPNET.aspx
Hope this help you.
At a guess...
Write a HTTP handler that records requests and store them in session.
When a new request comes in, check to see how many requests are stored (and expire old ones).
If the amount of requests in the past few minutes exceeds a given threshold, redirect the user.
If you're doing this in ASP.NET webforms, you could do this check on the site master page, ( or write a IHttpHandler).
If you're using an MVC framework, you could write a base controller that does this check for every action.
With rails, you could write a before_request filter.
With asp.net MVC, you could write a [ActionFilterAttribute] attribute
You should have a session to track the user activity.
In session you can have counter for commenting and posting like:
(pseudo code instead of C#, sorry :)
if (post_event) {
posts_during_1_minute_interval++;
if (time_now-reference_time > 1_minute) {
reference_time = time_now;
posts_during_1_minute_interval=0;
}
}
...
if (posts_during_1_minute_interval > 10) redirect("/are-you-human.htm");
where on are-you-human.htm page you can have recaptcha, as they have here on StcakOverflow.com
see also:https://blog.stackoverflow.com/2009/07/are-you-a-human-being/
just check how many hit / minutes you get from a specific ip or session or whatever and decide what are your preferred threshold and your good to go
I'd also check the user agent header of the request - if it doesn't look like a popular browser (or is empty) then throw the "are you a human?" page.

Hard Code List of Years?

This is the scenario. You've got a web form and you want to prompt the customer to select their birth year.
a) hard code the values in the dropdown list?
b) Grab valid years from a DB table
I can see a maintenance nightmare with copying a set of years hard coded in .aspx files everywhere.
updated:
for loop is not ideal (maintenance nightmare and error prone). The user then has to sift through 120 years that haven't even got here yet.
I still like the DB approach:
* Single point of data
* No duplication of code
* Update the table as needed to add more years
* Year table values could be used for some other dropdown for some other purpose entirely for something other than Birth year
Simple as that. No need to go updating code everywhere. I feel for data that is universal like this, we shouldn't be hard coding this shiza into a bunch of pages which is totally going against reuse and error prone...really it's not pratical. I'd take the hit to the DB for this.
Updated (again...after thinking about this):
Here's my idea. Just create a utility or helper method called GetYears that runs that loop and returns a List<int> back and I can bind that to whatever I want (dropdownlist, etc.). And I like the web.config idea of maintaining that end year.
C) Use a for-loop to generate the years in a range of your choice.
Something as simple as this pseudocode:
for (int i = 1900 ; i < THIS_YEAR - 13 ; i++)
{
validyears.options.Add(i);
}
Neither - provide a centralized service which can decide which mechanism to use, then the application doesn't care, and you are free to choose hardcoding, sliding window or database mechanisms.
To expand, typically, I would do something like this:
Define IPopulatableYear interface which has a single AddYear method taking an int and constructing an appropriate ListItem or whatever.
Make MyYearListBox inherit from regular ListBox implement IPopulatableYear (this works for winForms or WebForms)
Create static method or singleton or method in your DAL or whatever.
Like this:
PopulateYears(IPopulatableYear pl) {
// Very simple implementation - change at will
for (int lp = 2009 ; lp < 2009 + 10 ; lp++) {
pl.Add(lp);
}
}
or
PopulateYears(IPopulatableYear pl) {
// A DB implementation
SQLDataReader dr = DAL.YearSet() ; // Your choice of mechanism here
while ( dr.Read() ) {
pl.Add(dr[YEAR]);
}
}
or
PopulateYears(IPopulatableYear pl) {
// A DB limits implementation with different ranges defined in database by key - key determined by control itself - IPopulatableYear needs to implement a .YearSetKey property
SQLDataReader dr = DAL.YearLimits(pl.YearSetKey) ; // Your choice of mechanism here
for ( int lp = dr[YEAR_MIN] ; lp <= dr[YEAR_MAX] ; lp++ ) {
pl.Add(lp);
}
}
The mechanism is now centrally managed.
Use MyYearListBox on your forms and call PopulateYears() on it. If your forms are smart, they can detect all MyYearListBox instances and call it, so you no longer have any new code - just drag it on.
Take a look at Enumerable.Range. I think making DB calls is FAR less performant than Enumerable.Range.
E) Use a text input box, because that will always work.
(Be sure to validate it, of course, as a number. Include "Y2K" and "The year World War II started" in a dictionary of years, of course.)
How you present the year selection in the web form is irrelevant. It's an interface decision. Your server should not trust the data coming in, and should validate it accordingly. It's trivial to emulate a form submission, so it doesn't matter how it's presented. Heck, you can generate the drop down with javascript so there is no load on the server.
You can validate with a rule on the backend, rather than a lookup.
Since you're raising this whole issue (and making a bunch of comments), maybe it's within your power to think long and hard this.
For the end user, it's hard to beat the ease-of-use of a text box. Yup, you're going to get bogus data, but computers are supposed to make things easier, not harder. Scrolling through a long list of years to find the year I know I was born is a nuisance. Especially with all those young whippersnappers and old farts who want to enter birth years that aren't anywhere close to mine!
But stepping back even further...do you really need to ask the user their birth year in the first place? Is it that important to your application? Could you avoid the issue entirely by letting somebody else deal with that? Say by using OpenID, Windows Live ID or Facebook Connect?

Categories

Resources