Calculating compound interest with .NET and C#


I spent some time looking for a simple compound interest calculation function in .NET today. I couldn't find anything usable, so I grabbed the source formula and reduced it to .NET.

Here's the formula:

A = P * (1 + r / n) ^ n * t
A = final total amount
P = principal amount
r = interest rate (decimal)
n = number of periods per year
t = number of years

The C# code:

decimal CalculateTotalWithCompoundInterest(decimal principal, decimal interestRate, int compoundingPeriodsPerYear, double yearCount)
{
    return principal * (decimal)Math.Pow((double)(1 + interestRate / compoundingPeriodsPerYear), compoundingPeriodsPerYear * yearCount);
}

For example, you can calculate the total loan amount for $10,000.00 (principal and interest), compounded daily for 2 years like so:

decimal total = CalculateTotalWithCompoundInterest(10000m, 8.5m, 365, 2);

author: Chris Hynes | posted @ Tuesday, October 09, 2012 11:11 AM

Fixing Razor intellisense after it breaks during a VS 2012/ASP.NET MVC 4 upgrade


I upgraded an ASP.NET MVC 3 project to MVC 4, and upgraded to VS 2012 at the same time. Everything compiled fine, and worked fine in the browser, but the intellisense was totally broken.

I couldn't for the life of me figure it out. Everything in web.config looked right, the correct assembly versions were referenced, etc.

Finally, I realized that the issue was in the Views\Web.config. The version numbers of assemblies there were pointing to MVC 3 and WebPages 1, rather than MVC 4 and WebPages 2.

To solve the issue, change all the version numbers in that file appropriately (4.0.0.0 for System.Web.Mvc references, and 2.0.0.0 for System.Web.WebPages.Razor references).

author: Chris Hynes | posted @ Thursday, October 04, 2012 6:24 PM

DataBinder.Eval and ExpandoObject with custom TypeDescriptor


I just ran into an issue where DataBinder.Eval was exploding with an exception like this:

'System.Dynamic.ExpandoObject' does not contain a definition for 'Id'.

The problem here is that DataBinder.Eval uses either reflection and type descriptors to bind to properties. ExpandoObject (and dynamic types) don't support reflection. ExpandoObject doesn't implement ICustomTypeDescriptor either, leading to an exception when attempting to bind to an ExpandoObject.

After half an hour of googling, I found Bertrand Le Roy's excellent example of building custom type descriptors: Fun with C# 4.0's dynamic. I'm not sure why it took me so long to find it, so I figure I'll give him a bit of google juice and add some more keywords.

Also, that sample is rather out of date, so you'll have to do a couple of tweaks to make it work in .NET 4/4.5 (see below). Once that's done, you will have a bindable wrapper object that takes an ExpandoObject and can be directly bound to. Given and ExpandoObject "dyn" with a property named "Id", you can do this:

var bindableObj = new DynamicTypeDescriptorWrapper(dyn);

var value = DataBinder.Eval(bindableObj, "Id");

Changes required

First, change DynamicHelper.cs to the following:

public static class DynamicHelper {
    public static object GetValue(object dyn, string propName) {
        // Warning: this is rather expensive, and should be cached in a real app
        var GetterSite = CallSite<Func<CallSite, object, object>>.Create(
                Binder.GetMember(CSharpBinderFlags.None,
                    propName, 
                    dyn.GetType(),
                    new [] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) }
                    ));

        return GetterSite.Target(GetterSite, dyn);
    }

    public static void SetValue(object dyn, string propName, object val) {
        // Warning: this is rather expensive, and should be cached in a real app
        var SetterSite = CallSite<Func<CallSite, object, object, object>>.Create(
                Binder.SetMember(CSharpBinderFlags.None,
                    propName, 
                    dyn.GetType(),
                    new [] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
                                CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.Constant |
                                            CSharpArgumentInfoFlags.UseCompileTimeType, null) }
                    ));

        SetterSite.Target(SetterSite, dyn, val);
    }
}

Then, change GetValue and SetValue in DynamicPropertyDescriptor as follows:

public override object GetValue(object component) {
    if (component is DynamicTypeDescriptorWrapper)
        component = ((DynamicTypeDescriptorWrapper)component).GetPropertyOwner(this);

    if (_owner != component) throw new InvalidOperationException("GetValue can only be used with the descriptor's owner.");
            
    return DynamicHelper.GetValue(component, _propertyName);
}

public override void SetValue(object component, object value) {
    if (component is DynamicTypeDescriptorWrapper)
        component = ((DynamicTypeDescriptorWrapper)component).GetPropertyOwner(this);

    if (_owner != component) throw new InvalidOperationException("SetValue can only be used with the descriptor's owner.");
            
    OnValueChanged(component, EventArgs.Empty);

    DynamicHelper.SetValue(component, _propertyName, value);
}

author: Chris Hynes | posted @ Tuesday, September 25, 2012 3:52 PM

Updating a Git Submodule revision pointer


I haven't found a way to do this with TortiseGit yet, so you have to drop into the actual git command prompt and do (at the root of the repo):

git submodule -q foreach git pull -q origin <branch>

author: Chris Hynes | posted @ Wednesday, July 04, 2012 9:58 AM

Building WiX with MSBuild


The WiX docs on the topic (Integrating WiX Projects Into Daily Builds) give a good starting point, but are incomplete, at least for the recent builds. Two additional things they forget to mention: WixToolPath needs to be an absolute path for the Wix.targets project to function properly, and WixExtDir needs to be set to WixToolPath.

To build WiX from the binaries with MSBuild, do the following (requires MSBuild 4):

  1. Snag the binaries from the latest weekly build: WiX Weekly Releases
  2. Extract them into a folder you can access with a relative path inside your source control root
  3. Edit all of your .wixproj files and do the following snippet before the <Import Project="$(WixTargetsPath)" > tag:
      <WixToolPath>$([System.IO.Path]::GetFullPath('RELATIVEPATHTOWIX\wix\'))</WixToolPath>
      <WixTargetsPath>$(WixToolPath)Wix.targets</WixTargetsPath>
      <WixTasksPath>$(WixToolPath)wixtasks.dll</WixTasksPath>
      <WixExtDir>$(WixToolPath)</WixExtDir>
    </PropertyGroup>
    
  4. Update the RELATIVEPATHTOWIX to be a relative path that points to the WiX binaries you extracted in step 2.

author: Chris Hynes | posted @ Tuesday, March 20, 2012 10:08 AM

Spoofing an ASP.NET MVC request to use a ViewMasterPage with a non MVC content page


Sometimes my application has a section with normal ASP.NET requests that doesn't go through the ASP.NET MVC pipeline. I still want to integrate it with the ASP.NET MVC section of my app, using the same master page for example. The ViewMasterPage validates to make sure that the page being rendered is a ViewPage with the same type, so you can't use a normal page with a ViewMasterPage. If you run a ViewPage without an ASP.NET MVC context, all of the html helper methods will throw NullReferenceExceptions.

The solution to this issue is to make your page inherit from ViewPage, and then spoof the ASP.NET MVC context before the page renders. This will allow the page to work with a normal ASP.NET request (no ASP.NET MVC pipeline), but also use the same ViewMasterPage used for the rest of your site.

Here's what to do:

  • Make your page class inherit from ViewPage instead of Page.
  • Add the following method to your page:
    void SpoofMvc()
    {
        ControllerContext ctx = new ControllerContext();

        ctx.RouteData = new RouteData();

        ctx.HttpContext = new HttpContextWrapper(Context);
        ctx.RouteData.Values.Add("controller", "TightContent");
        ctx.RouteData.Values.Add("action", "View");

        this.Html = new HtmlHelper(new ViewContext(ctx, new WebFormView(this.Request.FilePath), ViewData, new TempDataDictionary(), Response.Output), this);
    }
  • Call the method before the page is rendered. Page_Load or Page_PreRender should work.

author: Chris Hynes | posted @ Tuesday, March 02, 2010 10:36 AM | Feedback (4)

SQL 2008 installation issues


With every new SQL version, it seems there are more and more headaches getting it installed, unless you're installing it on a clean OS install. I ran into error after error trying to install on a Vista box that had been upgraded to Windows 7 and had SQL 2005 already installed.

I finally dug up a blog entry that helped me out on Mark Michaelis's blog. It took a bit of digging, so I figured I'd give him a bit of google juice: SQL 2008 install registry issues and uninstall rollback techniques.

author: Chris Hynes | posted @ Tuesday, October 13, 2009 11:57 PM | Feedback (1)

How to use iBatis/NHibernate in medium trust/partial trust environments like Mosso


Many shared hosting providers (in this case Mosso) run your ASP.NET applications in a medium trust or modified medium trust environment to reduce security risks. This causes issues with certain techniques and components that require permissions removed by medium trust.

One of the biggest issues other than the actual restriction of permissions is the restriction of partially trusted assemblies calling fully trusted code. By default, if an assembly is strong named, partially trusted assemblies (i.e. the application assemblies in your app running under medium/partial trust) can't call it. This hits many open source components such as iBatis and NHibernate. The workaround to this is to add the AllowPartiallyTrustedCallers assembly level attribute. This will mark the assembly as safe for calling by partially trusted assemblies.

Here is an example of how to modify iBatis to support this:

  1. Download the iBatis source from the iBatis website: http://ibatis.apache.org/dotnet.cgi
  2. Extract the source .zip to a folder
  3. Open the IBatisNet.2005.sln solution in VS.NET
  4. For each project in the solution, open it's AssemblyInfo.cs file
    1. Add this using statement at the top of the file: "using System.Security;"
    2. Add this attribute at the bottom of the file: "[assembly: AllowPartiallyTrustedCallers]"
  5. Right click on the solution and select "Configuration Manager..."
  6. In the "Active solution configuration" dropdown, select Release
  7. Uncheck all of the Test projects
  8. Click OK
  9. Build the solution

Or you can download the compiled assemblies: iBatis-PartialTrust.zip

Enabling NHibernate for medium/partial trust is a similar procedure. If there is enough demand I will present steps and compiled assemblies for it as well.

As for the permission restrictions, most shared hosting providers don't actually run in medium trust as this restricts many useful things such as Reflection etc. One example I've run into recently is Mosso's modified medium trust. They take medium trust, which consists of the following denied permission restrictions:

  • Call unmanaged code.
  • Call serviced components.
  • Write to the event log.
  • Access Microsoft Message Queuing queues.
  • Access ODBC, OleDb, or Oracle data sources.
  • Access files outside the application directory.
  • Access the registry.
  • Make network or Web service calls (using the System.Net.HttpWebRequest class, for example).

And then Mosso adds back in the following allowed permission to come up with "modified medium trust":

  • WebPermission Unrestricted="true"
  • OleDbPermission Unrestricted="true"
  • OdbcPermission Unrestricted="true"
  • SocketPermission Unrestricted="true"
  • ConfigurationPermission Unrestricted="true"
  • ReflectionPermission Unrestricted="true"

This is still rather limiting, but at least you can get most things done as long as you can call into the necessary assemblies without getting exceptions as discussed in the workaround section above.

author: Chris Hynes | posted @ Wednesday, August 19, 2009 4:04 PM | Feedback (3)

Optimize Windows Vista for blazing speed


I was working on one of my old laptops the other day, and realized it seemed just as fast as my newer laptop. The newer box is substantially higher specced - dual core proc, 4GB RAM, nVidia graphics etc. For awhile, I couldn't put my finger on just what the difference was, and then it hit me: the old laptop had Aero turned off. I turned off Aero on the new box and bam, it was noticably more snappy. Windows popped in instantly, menus snapped up with no hesitation. Not just a little improvement, but a drastic improvement in speed. You don't get the glitzy glass interface, but it's definitely worth the graphical loss to have a much faster experience.

I haven't tested this on beefier desktop systems, but it gives a great improvement on laptops.

Here are the steps:

  • Open the computer settings window (quickest way to do this is to right click on "My Computer" and select "Properties").
  • Click "Advanced system settings" on the left under Tasks
  • Go to the Advanced tab
  • Click the Settings button under the Performance item
  • On the Visual Effects tab, Select "Adjust for best performance"

This will optimize the visual effects for the best performance, but some important visual effects will be missing - especially font smoothing. To get to the optimal settings, check the following items in the list:

  • Show preview and filters in folder
  • Show thumbnails instead of icons
  • Show window contents while dragging
  • Smooth edges of screen fonts
  • Smooth-scroll list boxes

The resulting selection will look like this:

Click the OK button, and Windows will recalibrate itself for the new settings.

Enjoy the new snappier performance!

author: Chris Hynes | posted @ Monday, May 18, 2009 5:17 PM | Feedback (2)

Test if MasterPage ContentPlaceHolder has content or is empty


UPDATE: Thanks to Jon Hynes of InfoMason, added functionality to support nested master pages. Code updates highlighted.

I've seen several articles on the web that lay out a method for checking to see if a ContentPlaceHolder has any content or is empty. These work some of the time but unfortunately fall down in certain situations – like a placeholder that contains an embedded literal code block for example.

In this case, there is no publicly exposed method that will provide the answer and no way to assemble any information that would tell us whether the ContentPlaceHolder is empty or has content. Fortunately, there is an internal .NET framework property that gives exactly what we need. A little reflection magic and we have a method that works in all circumstances.

The MasterPage has a property called ContentTemplates that is a dictionary of all content templates that have been generated by the content page. If we check this, we can determine whether in fact the ContentPlaceHolder has been overridden by the content page. This, combined with the control check gives us a method that tells us if the ContentPlaceHolder has anything in it.

This means we have three methods that work together to provide the resulting boolean. First, a method to check if there are any non empty controls in the ContentPlaceHolder:

public static bool HasNonEmptyControls(ContentPlaceHolder cph)
{
    if (cph.Controls.Count == 0)
    {
        return false;
    }
    else if (cph.Controls.Count == 1)
    {
        LiteralControl c = cph.Controls[0] as LiteralControl;

        if (string.IsNullOrEmpty(c.Text) || IsWhiteSpace(c.Text))
            return false;
    }

    return true;
}

static bool IsWhiteSpace(string s)
{
    for (int i = 0; i < s.Length; i++)
        if (!char.IsWhiteSpace(s[i]))
            return false;

    return true;
}

Next, a method to check if the ContentPlaceHolder has a content template defined on the content page:

static readonly Type _masterType = typeof(MasterPage);
static readonly PropertyInfo _contentTemplatesProp = _masterType.GetProperty("ContentTemplates", BindingFlags.GetProperty | BindingFlags.NonPublic | BindingFlags.Instance);

public static bool HasContentPageContent(ContentPlaceHolder cph)
{
    IDictionary templates = null;
    MasterPage master = cph.Page.Master;

    while (templates == null && master != null)
    {
        templates = (IDictionary)_contentTemplatesProp.GetValue(master, null);
        master = master.Master;
    }


    if (templates == null)
        return false;

    bool isSpecified = false;

    foreach (string key in templates.Keys)
    {
        if (key == cph.ID)
        {
            isSpecified = true;

            break;
        }
    }

    return isSpecified;
}

This is where the reflection comes in. We grab the ContentTemplates dictionary off the MasterPage and check to see if the specified ContentPlaceHolder is defined.

Finally, we call both methods to come to a final determination of whether the ContentPlaceHolder is empty or has content defined:

public static bool HasContentOrControls(ContentPlaceHolder cph)
{
    return HasNonEmptyControls(cph) || HasContentPageContent(cph);
}

This code will all run on .NET 2.0 and above. If you are using .NET 3.5, you can use the following extension method to add this to the ContentPlaceHolder itself:

public static bool HasContentOrControls(this ContentPlaceHolder cph)
{
    return MasterHelper.HasContentOrControls(cph);
}

MasterHelper source

author: Chris Hynes | posted @ Thursday, January 22, 2009 2:12 PM | Feedback (3)