Background (you can skip this section)
I have a large amount of data (about 3 mb) that needs to be updated on several hundred machines. Some of the machines run C #, and some run Java. Data may change at any time and should be transmitted to customers within minutes. Data is delivered in Json format from 4 load-balanced servers. These 4 servers run ASP.NET 4.0 with Mvc 3 and C # 4.0.
The code that runs on 4 servers has a hash algorithm that hashes the Json response and then converts the hash to a string. This hash is provided to the client. Then, every few minutes, clients ping the server with a hash, and if the hash is out of date, a new Json object is returned. If the hash remains current, 304 is returned with the body of emptry.
Sometimes the hashes generated by the four boxes are inconsistent across all fields, which means that clients constantly download data (each request can go to another server).
Code sniper
Here is the code that is used to generate the hash.
internal static HashAlgorithm Hasher { get; set; } ... Hasher = new SHA1Managed(); ... Convert.ToBase64String(Hasher.ComputeHash(Encoding.ASCII.GetBytes(jsonString)));
To try and debug the problem, I split it like this:
Prehash = PreHashBuilder.ToString(); ASCIIBytes = Encoding.ASCII.GetBytes(Prehash); HashedBytes = Hasher.ComputeHash(ASCIIBytes); Hash = Convert.ToBase64String(HashedBytes);
Then I added a route that spits out the above values and uses Beyond Compare to compare the differences.
Byte arrays are converted to string format for use by BeyondCompare with:
private static string GetString(byte[] bytes) { StringBuilder sb = new StringBuilder(); foreach (byte b in bytes) { sb.Append(b); } return sb.ToString(); }
As you can see, the byte array is displayed as a sequence of bytes. He is not "transformed."
Problem
I found that the Prehash and ASCIIBytes values were the same, but the HashedBytes values were different - this meant that the hash was also different.
I restarted IIS websites on four server boxes several times and, when they had different hashes, compared the values in BeyondCompare. In any case, the value of "HashedBytes" was different (SHA1Managed.ComputeHash (...) results)
Question
What am I doing wrong? The input to the ComputeHash function is identical. Is SHA1Managed machine dependent? This does not happen because half the time when 4 machines have the same hash.
I searched for StackOverFlow and Bing but could not find anyone else with this problem. The closest I could find were people with problems with their encoding, but I think I proved that encoding is not a problem.
Exit
I was hoping not to dump everything here because of how long this takes, but here's a sniper dump that I compare:
Hash: o1ZxBaVuU6OhE6De96wJXUvmz3M =
HashedBytes: 163861135165110831631611916022224717299375230207115
ASCIIBytes: .... Prehash: ...
When I compare two pages on different servers, the ASCII bytes are identical, but HashedBytes are not. The dump method that I use for bytes does not do any conversion, it just unloads each byte in the sequence. I could limit the bytes to the character '.' I guess.
Follow Up I changed the value of b.ToString (CultureInfo.InvariantCulture) and made the HashAlgorithm a local variable instead of a static property. I am waiting for the code to be deployed to the servers.