Yet another round on the ModelState PercentComplete() extension
August 16, 2011
So there were a few issues with the previous version – at least when I wanted to extend it for some custom calculations so here is yet another version:
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
39
40
41
42
43
44
45
public static int PercentComplete(this ModelStateDictionary modelStateDictionary, int? ScalePercentWithValueAsZero = null, int? MaxValue = 100)
{
int totalItems = 0;
int validItems = 0;
int percentComplete = 0;
if (MaxValue.HasValue && (MaxValue.Value < 0 || MaxValue.Value > 100))
throw new ArgumentOutOfRangeException("MaxValue must between 0 and 100!");
if (modelStateDictionary.IsValid)
{
percentComplete = MaxValue.Value;
}
else
{
foreach (var item in modelStateDictionary)
{
totalItems++;
if (item.Value.Errors.Count == 0)
validItems++;
}
if (totalItems > 0)
percentComplete = (100 * validItems) / totalItems;
if (ScalePercentWithValueAsZero.HasValue)
{
if (ScalePercentWithValueAsZero.Value >= percentComplete)
{
percentComplete = 0;
}
else
{
percentComplete = Convert.ToInt32(Math.Ceiling((double)(percentComplete - ScalePercentWithValueAsZero.Value) / (100 - ScalePercentWithValueAsZero.Value) * 100));
}
}
if (MaxValue.HasValue)
{
percentComplete = percentComplete * MaxValue.Value / 100;
}
}
return percentComplete;
}
And if a model has a particularly complicated percentage complete calculation in which one needs to manually check some things and add to the total that can be done:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public int CustomPercentComplete(Func<int?, int?, int> PercentComplete)
{
// scale percent complete 50-100% as 0-100%
int basePercentAsZero = 50;
// actually, scale 50-100% as 0-91%
int max = 91;
// call default PercentComplete
int percentComplete = PercentComplete(basePercentAsZero, max);
// implement here your custom percente complete for the remaining 9%
return percentComplete;
}
An example of calling the custom percentage complete calculator on your model:
1
myModelInstance.CustomPercentComplete(ModelState.PercentComplete);
And if you need to call either calculator but your controller action doesn’t bind to an instance of the model you need to calculate the percentage on, you can add a method in your controller like this one (hopefully there is a better way – let me know if you know of one):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Work around for getting percentage complete when in another action where the model is not the application
// like so:
// int percentComplete = MyPercentComplete(application);
private int MyPercentComplete(MyApplication application)
{
return Convert.ToInt32(MyPercentCompleteAction(application).Content);
}
// Work around for getting percentage complete when in another action where the model is not the application
// like so:
// int percentComplete = Convert.ToInt32(MyPercentComplete(application).Content);
private ContentResult MyPercentCompleteAction(MyApplication application)
{
return Content(application.CustomPercentComplete(ModelState.PercentComplete).ToString());
}
Categories:
ASP.NET MVC
C#