Click here to Skip to main content
15,915,324 members
Articles / Programming Languages / C#
Tip/Trick

Utlility Function to Compare 2 Objects Using MD5 Hash

Rate me:
Please Sign up or sign in to vote.
4.50/5 (2 votes)
3 Mar 2016CPOL1 min read 10.4K   4  
Utility function to compare 2 objects using MD5 Hash

Introduction

Many a times, while coding, we need to determine if two objects are the same, if not, do some processing further.
Mostly, we write comparison logic to achieve the same. Presented here is one of the many ways, this could be achieved in many other possible ways as well.

Background

In our project page, we had many Kendo UI TextBoxes, that had decimal amounts (called Overrides) - now depending upon whether the Overrides changed from the last time it was edited (i.e., needed to compare the existing Overrides with the ones saved in Database last time around), the requirement was to show a label in Red color to notify the user, that Billing Overrides have been changed, when the page loaded and also when the "Approve" button was clicked.

I had to send all existing values from the text box (UI), make a database call to get the last saved values, compare them to come up with a boolean flag to show the notification. In order to achieve this, formatted my Overrides each with an id with a combination of "override_item.Key" and value as "@item.Value". Before making an Ajax call, added "#" as a separator to each of the Key/Value pair, on the controller side- split the string with "#" values to get splitString, put it in a dictionary of string, string as Key/Value pairs, pass it compare function.

Using the Code

HTML
//code in cshtml file 

var index = 0;
foreach (var item in @Model.AllOverrides)
{
  <input type="hidden" value="@item.Value" 
  id="override_@item.Key" name="@item.Key" />
   index++;
}

//spinner div
<div id="divSpinner" 
style="position:absolute;z-index:10;border-style:none;
margin-left:413px;height:48px;width:48px;">
<img src="~/Content/images/loading-image.gif" /></div>

//div for Notification Message
<table class="xxx" style="margin-left: 20px; 
margin-right: 20px;width:93.7%">
    <tr>
        <td colspan="4" class="xxx" id="billingChangeTd">
            Billing Overrides:
            @(Html.DisplayFor(m => m.BillingOverridesChanged))
        </td>
    </tr>    
</table>


// ui for btnApproval
 <table class="xxx" style="margin-left: 20px; 
 margin-right: 20px;width:95%">
    <tr>
       <td>
    @(Html.Kendo().ToolBar().Name("OrderApproveToolBar")
    .HtmlAttributes(new { style = "font-size:10px;
    line-height:2em", padding = "2px 0px 2px" })
    .Items(items =>
    {        
        items.Add().Type(CommandType.Button).ImageUrl
        ("../../Content/images/approve.jpg").Text("Approve").HtmlAttributes
        (new { id = "btnApproval", padding = "2px 0px 2px" }).Click
        ("clientApproval").Enable(true);//call clientApproval on click
    }))
</td>
</tr>
</table>

<script>
 $(document).ready(function () 
{
        var billingChanged = '@Model.BillingOverridesChanged.ToString()';
        if(billingChanged == 'Yes')
        {
            $("#billingChangeTd").attr("style", 
            "color:red !important"); //show Text in Red color if Overrides changed
        }
});

function clientApproval() 
{
    var overridesStringData = "";
    var overrideKeyList = $('[id^=override]');
    for (var i = 0; i < overrideKeyList.length; i++)
    {
        overridesStringData = overridesStringData + overrideKeyList[i].id + 
        ":" + overrideKeyList[i].value + "#"
    }
    var dataToSend = 
    {
     Note: $('#SelectedNote').val(),
     Overrides: overridesStringData,
    };
    $('#divSpinner').show(); //show spinner
    $.ajax({
    url: "/Order/ApprovalOrderTrue", //call to Controller method
    data: dataToSend,
    type: "POST",
    success: function (result) 
    {
        if (result == "True")
        {
            //Add delay
            clientCloseSubmitWindow(3); //custom logic to have a delay
        }
        else if (result == "False")
        {
            //code here for stop propagation show message            
        }
    }
    });
}
</script>

//Controller code

[AcceptVerbs(HttpVerbs.Post)]
public bool ApprovalOrderTrue(string Note, string Overrides)
{
    _iOrderBusinessService = new OrderBusinessService();
    Guid selectedOpportunity = (Guid)OMSSession.SessionProperties.SelectedOpportunityId;
    if(! string.IsNullOrEmpty(Overrides) && Overrides.EndsWith("#"))
    {
        Overrides = Overrides.Substring(0,Overrides.Length-1);
    }
    var splitString = Overrides.Split('#').ToList();

    Dictionary<string, string> existingOverrides = new Dictionary<string, string>();
    if(splitString != null && !string.IsNullOrEmpty(splitString[0]))
    {
        foreach (var stringItem in splitString)
        {
            existingOverrides.Add(stringItem.Split(':')[0].ToString(),
            stringItem.Split(':')[1].ToString());
        }
    }
    bool overridesMatch = 
    _iOrderBusinessService.ValidateAllOverrides(existingOverrides, selectedOpportunity);
    if (overridesMatch)
    {
        //custom logic
    }
    return overridesMatch;
}

// Order Business Service

public bool ValidateAllOverrides(Dictionary<string,
string> existingOverrides,Guid opportunityId)
{
    bool allOverridesMatched = false;

    Dictionary<string, string> latestOverrides = GetAllOverrides(opportunityId);

    if(latestOverrides.Count == 0 && existingOverrides.Count == 0 
    && latestOverrides.Count == existingOverrides.Count)
    {
        allOverridesMatched = true;
    }
    else if (latestOverrides.Count != existingOverrides.Count)
    {
        allOverridesMatched = false;
    }
    else //both counts not Zero now compare actual data
    {
        StringBuilder sbExistingOverrides = new StringBuilder();
        StringBuilder sbLatestOverrides = new StringBuilder();

        foreach (var existingItem in existingOverrides)
        {
            if (existingItem.Key.Contains("override_"))
            {
                sbExistingOverrides.Append(existingItem.Key.Remove(0, 9) + 
                ":" + existingItem.Value + "#");
            }
        }
        string existingOverridesHash = GetMd5Hash(sbExistingOverrides.ToString()); //Getting hashed string

        foreach (var latestItem in latestOverrides)
        {
            sbLatestOverrides.Append(latestItem.Key+":"+
            latestItem.Value+"#");
        }
        allOverridesMatched = VerifyMd5Hash(sbLatestOverrides.ToString(), 
        	existingOverridesHash); //call to compare passes strings
    }
    return allOverridesMatched;
}

//Utility Functions
public static string GetMd5Hash(string input)
{
    StringBuilder sBuilder = new StringBuilder();
    using (MD5 md5Hash = MD5.Create())
    {
        // Convert the input string to a byte array and compute the hash.
        byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input));

        // Loop through each byte of the hashed data 
        // and format each one as a hexadecimal string.
        for (int i = 0; i < data.Length; i++)
        {
            sBuilder.Append(data[i].ToString("x2"));
        }
    }
    // Return the hexadecimal string
    return sBuilder.ToString();
}

public static bool VerifyMd5Hash(string input, string hash)
{
    // Hash the input.
    string hashOfInput = GetMd5Hash(input);

    // Create a StringComparer an compare the hashes.
    StringComparer comparer = StringComparer.OrdinalIgnoreCase;

    if (0 == comparer.Compare(hashOfInput, hash))
    {
        return true;
    }
    else
    {
        return false;
    }
}

Points of Interest

By just calling the Utility functions and passing what it needed, I was able to infer whether passed strings were the same or different and then accordingly act thereon.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United States United States
I love to code (ASP.NET-C#, SQL, AJAX, HTML, XML, WCF, MVC, JQuery, Kendo, REST Services, Business Analysis are my favourites to work with),play outdoor sports, travel to places, meet new people, be amidst Nature, read inspirational books, listen to music & am a Foodie as well.

Comments and Discussions

 
-- There are no messages in this forum --