2012-10-15

Calculating Age in C# (Subtract DateTime from DateTime?)

So far I have seen many attempts from many people to determine the age of a person in reference to a given date in many languages. But actually the examples I have seen in C# were the strangest and partially buggiest attempts I have seen.
Maybe the main problem is, that C#'s DateTime class does not offer a direct method to subtract a DateTime from a DateTime.
This is one particular attempt I have seen these days (trying to debug some age related calculation):
- Given are birthdate A and reference date B
- let integer C be B.Year - A.Year
- decrease C by one based on some strange 3-line formula doing something with A.month, A.day, B.month and B.day
... This may work if the Dates A and B are accidently chosen correctly but basically what happend in most cases I tested this calculation with resulted in an age beeing 1 year lower than it actually was.
So, if you ever have to determine the age of someone based on a reference date, just use the maybe simplest approach to solve this problem using an extension to DateTime:

     public static class DateTimeExtensions
    {
        public static int GetAge(this DateTime birthdate, DateTime referencedate)
        {
            DateTime x = referencedate.AddTicks(-1 * birthdate.Ticks);
            return x.Year;
        }
    }

That way if you want to know someones Age based on a reference date... as in, how old will Person X (born July 4th, 1950) be at January, 1st 2012 you can do
    int age = new DateTime(1950,7,4).GetAge(new DateTime(2012,1,1));



2012-09-05

Combine SkyDrive with GoogleDrive


For both SkyDrive and GoogleDrive I am a long-time user. I never really put much data into these as the max bandwidth I can get at home is about 1 MBit only. So relying on those services while working from my home office is a de facto NO GO.

Still I am just refurbishing a house we bought and into that house I am integrating a Cat7 infrastructure and the maximum bandwith available at the new location will be 50 - 100 MBit... so in the end I think the time has come to think about a more extensive use of GoogleDrive and SkyDrive (I don't think I'd need more alternatives ... but I am sure that there are enough services available if the need should ever arise).

So ... where was I ... right ... I was about to think about Sky- and GoogleDrive and how to get the best out of them.

The idea is to combine the two of them to have doubled Backup. Sure there are already posts about doing that as in nesting the google drive folder into sky drive folder. Technically that would work, but I like to have things arranged in a more convenient way.

Therefore what I want is to have GoogleDrive and SkyDrive to use exactly the same base folder. As both Tools don't allow you to change the name of the actual base folder it seems this will not work. But then again I don't like to give up so I played around with the setups (wasting about 2 GB of my monthly mobile data package for repeated GoogleDrive-ReSynchronisations) to actually get to what I wanted.

Steps necesary:
1) Download and install the SkyDrive Application (Default Options) 
2) Let the app do the initial Sync of your SkyDrive 
3) Exit the SkyDrive Application 
4) Download and install the GoogleDrive Application (Default Options) 
5) Let the app do the initial Sync of your GoogleDrive 
6) Exit the GoogleDrive Application

At this point you have 2 new Directories in your user folder at

  • C:\Users\...\SkyDrive
  • C:\Users\...\Google Drive
Now that the applications are shut down.,
7) Rename the SkyDrive folder to SkyDriveX 
8) Rename the Google Drive folder to SkyDrive (EEK ... yah, I know ;-P ) 
9) Copy the content of the SkyDriveX folder to the SkyDrive folder 
10) Start Google Drive Application

The Google Drive Application at this point will tell you that it can't find the synchronisation folder and that it wants to disconnect your account => DONT DO THAT... if you do that you have to reinstall Google Drive and repeat the whole procedure. Instead tell the Google Drive Application that you want to search the directory manually. Choose the SkyDrive folder and hit ok. Then the Google Drive App will automatically Sync all the new content you copied into it from the Ex-SkyDrive folder ...

And SkyDrive? Right...
11) Start SkyDrive App 

and it too will immediately start to synchronize the new Content from the Ex-Google Drive folder.

It is necessary to do the renaming of the folders this way and not vice versa as the Google Drive Application would realize that the other directory is not the one it created (I guess it stores additional information about the folder location or content somewhere, not sure how it does it but it won't allow the application to another directory than the one it created itself... ignoring a new folder name tho)

Additionally the SkyDrive Application works with a '.lock'-File inside the directory. Google Drive will not be able to synchronize that as SkyDrive has a permanent grip on the file. So far that didn't cause any trouble. If it will, I will try to find out a solution and post more about it.

Now what do I have now using this setup? 
I have 1 folder on my computer(s) in which I keep files I want to access and keep in sync wherever I am working from. Additionally that folder is backed up not only once, but twice.

The downsides? 
The sync takes slightly longer and of course my data transfer size has doubled. 

Another thought: 
Also GoogleDrive is limited to 5GB so as soon as I reach that I will have to think about getting the upgrade to 25GB for 2.49 $ per month. At SkyDrive, as I have a very old account there, I already have the 25GB limit. 

2012-08-27

SimpleMembershipProvider ... HUH?!?!

UPDATE (2012-08-30):
John Galloway of Microsoft has put together a very helpful insight into Simple Membership Provider at http://bit.ly/PtkPN1 So, if any of you is still looking for some background information or the basic idea behind Simple Membership Provider, have a go and read his blog post. Thanks John!
Hi,
Yesterday I was playing around with the new Visual Studio 2012 and MVC4.
So far I am impressed with Visual Studio and asp.net 4.5 but my yesterday's adventure made me go HUH?!?!

Well, I created a new MVC4-Application. That should not be too hard, just hit File -> New -> Project and select Web -> MVC 4 Application.

So far so good, a new application was created and ready to run. Then to use the default 'localDB' file, I followed what I had learned to work fine with the previous release candidates and installed the corresponding Default Membership Provider package via Nu-Get (based on Scott Hanselman - Introducing System.Web.Providers), which worked well in some previous release candidate of vs2012
install-package System.Web.Providers.localDB
After the installation was finished I ran the application and hit 'Register' so the application would create the corresponding database-file. Which it did and the server explorer even listed it correctly. Then I entered the credentials of a new testuser 'tommy', 'test123$', 'test123$' and clicked 'Register' and then the application gave up:


Zeile 80:                 try
Zeile 81:                 {
Zeile 82:                     WebSecurity.CreateUserAndAccount(model.UserName, model.Password);
Zeile 83:                     WebSecurity.Login(model.UserName, model.Password);
Zeile 84:                     return RedirectToAction("Index", "Home");

Quelldatei: c:\Users\igambin\Documents\Visual Studio 2012\Projects\MvcApplication6\MvcApplication6\Controllers\AccountController.cs    Zeile: 82
At some point before the final release of Visual Studio 2012, Microsoft seems to have decided to use the SimpleMembershipProvider (see Matthew M. Osborne - Using SimpleMembership With ASP.NET WebPages) by Default instead of the DefaultMembershipProvider.
Basically and in relation to Azure or Web Pages that might be helpful and even advantageous, but for someone used to the old MembershipProviders at first it seems a strange decision. I mean, I loved the MembershipProviders as they represented a full-fledged and secure means of user/role/membership data management which Visual Studio even offered a built in solution to manage.

Well, that built-in management won't work with SimpleMembership (at least not yet) but I wanted at least to get the "NEW Default" MembershipProvider up and running. So I decided instead of using localDB I would want to use SqlServer Compact Edition. So I installed that
install-package sqlservercompact
And again based on ScottHa's BlogPost mentioned above, I added a corresponding "ConnectionString" to my web.config:
At that moment I realized: "hey, there is nothing that relates SimpleMembership to use that new ConnectionString". Therefore I started looking into the SimpleMembership files and did find the AccountModel.cs which named the connection string in its constructor
public class UsersContext : DbContext
{
    public UsersContext()
        : base("Sql_CE")
    {
    }
    public DbSet UserProfiles { get; set; }
}
where I put my SqlServerCompact ConnectionString so SimpleMembership would use the right file.

Yes, at that point I was a bit surprised that the ConnectionString was hardcoded into the model file. The old Membership Providers had that kind of configuration done in the web.config file. Actually I think I would have preferred the old way to do it. Well, again I tried to start my application and add a new user and again the application stroke back


Zeile 39: }
Zeile 40:
Zeile 41: WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);Zeile 42: }
Zeile 43: catch (Exception ex)

Quelldatei: c:\Users\igambin\Documents\Visual Studio 2012\Projects\MvcApplication5\MvcApplication5\Filters\InitializeSimpleMembershipAttribute.cs    Zeile: 41             


Not only is the ConnectionString hardcoded into SimpleMembership once, it indeed has been done twice!

I modified that line to also use the connectionString I defined in my web.config. At that point the application worked and the SimpleMembership Provider provided what it should.

Still... I really miss hitting PROJECT->ASP.NET Configuration to just open up the Asp.net configuration web-site where I would manage my users and roles and user-role memberships.




2012-06-29

Dead LCD Screen revived for < 1€

Last week, when I came home I wanted to quickly check something on the internet. So I walked to my office, switched on my computer and the screen and ... waited ... 

While the computer ran the usual noises and beeps the screen stayed black...

What do you do when the screen fails? Right... 

check the powerplug,
 then 
switch it off an on
then
check the video connectors...

All the basic stuff failed... so next Step

Warranty?!? -> screen is too old .. no more warranty

So, I went to my usual computer store and asked what the repair would cost. The estimation of my favorite vendor was, "45€ for sending the screen in to Samsung + 15€ - 50€ for the parts that need replaced + 50€ - 100€ for the time some worker needs to repair the screen".

R i g h t !!! 

My luck will produce the Worst Case: I pay more for the repair than I would for a new screen. 

End of story. Screen is dead. Thanks God I got a 2nd one on my desk. 

O R . . . m a y b e   N O T !!!

There are many cases where I am way too nosy. Then I start collecting information to try and figure out what is wrong and why it is. 

So I asked Google about "Samsung Syncmaster 245B screen stays black".

I did get a couple of links that listed comments, threads from people in blogs and forums who had a similar problem.

First thread mentioned a set of probably blown capacitators. They would be easily to find so I opened up the screen and had a look. No luck there though, didn't find a blown one. 

Next thread said something about "broken resistors". The post even pointed out 3 resistors that are often broken because they were chosen too cheap and are not really fit to do their task. To check out this possible source of the screens death I needed to unpack my meter from our packing cases of our last move. 

S T R I K E !!!

One of the three resitors was broken indeed. So today I went to a store that has all kinds of electronic parts waiting to be sold. As those resistors were said to not beeing fit for their job, I chose to replace all three of them instead of only the broken one by a set of 3 68 Ohm resistors that can process a higher power demand (1W instead of the original resistors 0.5W). 

I reconnected all connectors and closed the screen again, hooked it up to my computer and...

TADAAA! It works again.


Well giving it to the repair center would have cost me 100 - 200€. 

Repairing it myself cost me 90 cents (Theoretically I could have done it for 30cents, if I had only replaced the broken resistor). Well putting an avg. hourly cost of 30€ if I would calculate my own work time, the self repair would cost 60.90€. But as I still like to spend time on such problems .. just for the fun of it, I keep thinking I repaired my screen for 90 cents. And the time I've spent???  Well I'd call that taking a recreational timeout. 


2012-06-04

Wann im Jahr ist Ostersonntag? (When is easter sunday?)

- Wann ist Ostersonntag?

- Warum?

- Damit ich Feiertage bestimmen kann.

- Wo brauchst Du es?

- In meiner Excel-Datei... Zeitnachweise und so...


... hat mich ein Kollege kürzlich gefragt. Ich sagte ihm, er finde die Lösung zu seinem Problem unter "Gaußsche Osterformel" bei de.Wikipedia.org

Da ihn die Ausführungen dort mehr oder weniger verwirrten, gab ich ihm einfach die für den gregorianischen Kalender passende Excel-Formel. Dabei ist A2 die Referenz auf die Zelle, in welcher die Jahreszahl des zu berechnenden Ostersonntag-Termins steht:
= DATUM(A2;3;(21 + (REST( 19*(REST(A2;19)) + (15 + GANZZAHL( (3*(GANZZAHL(A2/100))+3) / 4 ) - GANZZAHL( (8*(GANZZAHL(A2/100))+13) / 25)); 30)) - (GANZZAHL(GANZZAHL( ((REST( 19*(REST(A2;19)) + (15 + GANZZAHL( (3*(GANZZAHL(A2/100))+3) / 4 ) - GANZZAHL( (8*(GANZZAHL(A2/100))+13) / 25)); 30)) + (REST(A2;19))) /11 ) / 29)))+(7 - REST((21 + (REST( 19*(REST(A2;19)) + (15 + GANZZAHL( (3*(GANZZAHL(A2/100))+3) / 4 ) - GANZZAHL( (8*(GANZZAHL(A2/100))+13) / 25)); 30)) - (GANZZAHL(GANZZAHL( ((REST( 19*(REST(A2;19)) + (15 + GANZZAHL( (3*(GANZZAHL(A2/100))+3) / 4 ) - GANZZAHL( (8*(GANZZAHL(A2/100))+13) / 25)); 30)) + (REST(A2;19))) /11 ) / 29))) - (7 - REST( A2 + GANZZAHL(A2 / 4) + (2 - GANZZAHL( (3*(GANZZAHL(A2/100))+3) / 4)); 7 )); 7)))

(english)
A short while ago a friend asked me how to calculate "easter sunday" based on a given "gregorian" year. He would need a formula for his excel file. So I gave him the following formula with A2 referring to the cell that contains an integer determining the year for which the easter sunday is to be calculated:
= DATE(A2;3;(21 + (MOD( 19*(MOD(A2;19)) + (15 + INT( (3*(INT(A2/100))+3) / 4 ) - INT( (8*(INT(A2/100))+13) / 25)); 30)) - (INT(INT( ((MOD( 19*(MOD(A2;19)) + (15 + INT( (3*(INT(A2/100))+3) / 4 ) - INT( (8*(INT(A2/100))+13) / 25)); 30)) + (MOD(A2;19))) /11 ) / 29)))+(7 - MOD((21 + (MOD( 19*(MOD(A2;19)) + (15 + INT( (3*(INT(A2/100))+3) / 4 ) - INT( (8*(INT(A2/100))+13) / 25)); 30)) - (INT(INT( ((MOD( 19*(MOD(A2;19)) + (15 + INT( (3*(INT(A2/100))+3) / 4 ) - INT( (8*(INT(A2/100))+13) / 25)); 30)) + (MOD(A2;19))) /11 ) / 29))) - (7 - MOD( A2 + INT(A2 / 4) + (2 - INT( (3*(INT(A2/100))+3) / 4)); 7 )); 7)))

2012-03-21

ASP.Net Default Password Hash (+Salt)

Today I played around with custom user controls so I wondered if I could create my own login control, that would allow me to check credentials against the built-in ASP.net security mechanisms. The included Table structure is easy enough to understand, but it took me a while to find out how to apply salt and hashing algorithms to the entered user password to get the same hash that the ASP.net security mechanisms generate. Just to not forget it or to whoever might need it:


        public static string EncodePassword(string pass, string saltBase64)
        {
            byte[] bytes = Encoding.Unicode.GetBytes(pass);
            byte[] src = Convert.FromBase64String(saltBase64);
 
            byte[] dst = new byte[src.Length + bytes.Length];
            System.Buffer.BlockCopy(src, 0, dst, 0, src.Length);
            System.Buffer.BlockCopy(bytes, 0, dst, src.Length, bytes.Length);
            HashAlgorithm algorithm = HashAlgorithm.Create("SHA1");
 
            byte[] inArray = algorithm.ComputeHash(dst);
            return Convert.ToBase64String(inArray);
        }


And if you have to create a new Salt, just use:


        public string CreateSalt(int saltLength)
        {
            //Create and populate random byte array
            byte[] randomArray = new byte[length];
            string randomString;
 
            //Create random salt and convert to string
            RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
            rng.GetBytes(randomArray);
            randomString = Convert.ToBase64String(randomArray);
            return randomString;
        }


Resources: forums.asp.netPeter Stathakos Blog

ASP.Net DateTime vs. Javascript Date

Lately I am spending quite some time with programming C# ASP.net applications. It is fun and far easier than I thought it would be. Of course, occasionally, one gets to the point where one wonders, 'WTF... Why doesn't this work!!!'

Yesterday, I got to that point, so as it was late I went to bed and started looking for a solution around the net today.

My problem was, that if you receive JSONified data from ASP the Date will be something like
 "/Date(139356000000+0200)/"

This is not necessarily a problem as one can guess what this string represents. The part before the '+' is the time in Milliseconds and the rest (including the '+') is the TimezoneOffzet as in '+/-hhmm', but there is no natural way to easily transform it (or at least, if it exists, it slipped my attention) to a Javascript Date-Object.

So in the end, the value above, that you get by JSON.parsing a ASP.net Webservice-Response, can be transformed by this Javascript-Function:
function DateTime2Date(input) {
    return new Date(parseInt(input.replace("/Date(""").replace(")/"""), 10))
}
And then of course, there is the next problem handling the Javascript Date when you want to send it back to the ASP.net WebService. The natural representation of the Javascript-Date when JSON.stringified looks like
"2012-03-06T23:00:00:000Z"
which again is a value that the ASP.net Webservice won't even consider to route through to the according Webservice Recipient. So in order to send (POST/PUT) this Date to the Webservice you will again have to modify the representation into a String using this Javascript Function:
function Date2DateTime(input) {
    var tzo = (input.getTimezoneOffset() / 60 * -100);
    tzo = (tzo < 0  ?    "" + ( tzo / -1000 >= 1 ? tzo : "0"+tzo )
                    :   "+" + ( tzo /  1000 >= 1 ? tzo : "0"+tzo ));
    return "\/Date(" + input.valueOf() + tzo + ")\/";
}
This method looks a bit odd, but if you know that 'getTimezoneOffset()' returns the offset in minutes rather than hours or in the '+/-hhmm' format and if you know that the value is returned is not the offset based on GMT but based on your local Timezone, it might make a bit more sense.

I hope this will help anyone who faces a similar situation.