Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Utlility Function to Compare 2 Objects Using MD5 Hash

0.00/5 (No votes)
3 Mar 2016 1  
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

//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 has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here