Cymen Vig

Software Craftsman

Updated percentage complete calculator for ASP.NET MVC

Update: there is a bug with this code. Please see this new post with updated code.

This version adds a baseline value so the percentage is scaled from that baseline (as 0) to 100%. This is to accommodate the case where the form starts out at say 50% complete. In this case, the call in the controller would be:

1
    x.PercentComplete = ModelState.PercentComplete(50);

Note this will cause some odd results if you pick a base value that isn’t truly a base value. In that case, the percentage calculation as the model is “completed” will increase, dip to zero at the false base value and then increase to 100 from there.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
    public static class ModelStatePercentCompleteCalculator
    {
        // Very rough but reusable % complete calculator that is an extension so can be
        // called simply as ModelState.PercentComplete() in a controller action. Iterates
        // over the items in ModelState returns percentage complete where a complete field
        // is seen as having no errors. If the ModelState.IsValid returns true, the
        // model is 100% complete.
        public static int PercentComplete(this ModelStateDictionary modelStateDictionary, int? ScalePercentWithValueAsZero = null)
        {
            int totalItems = 0;
            int validItems = 0;
            int percentComplete = 0;

            if (modelStateDictionary.IsValid)
            {
                percentComplete = 100;
            }
            else
            {
                foreach (var item in modelStateDictionary)
                {
                    totalItems++;
                    if (item.Value.Errors.Count == 0)
                        validItems++;                   
                }

                if (totalItems > 0)
                    percentComplete = (100 * validItems) / totalItems;
            }

            if (ScalePercentWithValueAsZero.HasValue && ScalePercentWithValueAsZero.Value > 0 && percentComplete >= ScalePercentWithValueAsZero)
            {
                percentComplete = 100 / ScalePercentWithValueAsZero.Value * (percentComplete - ScalePercentWithValueAsZero.Value);
            }

            return percentComplete;
        }
    }