Arjans blog

Custom ASP.NET DataSource parameters

Originally published on blog.einbu.no February 1. 2010

With ASP.NETs DataSource controls you can parameterize your query and have those parameters automatically fetched from one of a few standard sources. Those include getting a parameter value from the querystring, a form parameter, a control or from a users session variables, profile or cookies.

These parameter types enables us to build a lot of functionality without leaving ASP.NET markup. Still, they don't cover every imaginable scenario. So when someone asked how to get the username as a parameter in this question on Stackoverflow, it inspired me to write this article.

The easiest way would of course be to just use an asp:Parameter, and set the parameter value in code behind, like I do here:

<asp:Parameter name="Username" />
protected void Page_Load(object sender, EventArgs e)
{
    SqlDataSource1.SelectParameters["Username"].DefaultValue = User.Identity.Name;
}

However, this is neither the most elegant nor best way to solve this. We can create our own parameter types instead and then use them in markup. That will save us from the code behind.

Creating a custom parameter

All you need is to inherit from the System.Web.UI.WebControls.Parameter class, and override the Evaluate method.

using System.Web.UI.WebControls;

namespace DemiCode.Web.Parameters
{
    public class LoginParameter : Parameter
    {
        protected override object Evaluate(HttpContext context, System.Web.UI.Control control)
        {
            return context.User.Identity.Name;
        }
    }
}

You can throw in some more functionality if you like. Perhaps a property to decide the format of the username (with or without the domain name) or maybe put in some exception handling...

Using a custom parameter

To use this parameter from ASP.NET markup, you need to register the parameter in the same way as you would with a custom control: Either on each page that uses the parameter by adding the Register directive just below the Page directive:

<%@ Register tagPrefix="dc" assembly="DemiCode.Web" namespace="DemiCode.Web.Parameters" %>

Or in the web.config file in the configuration/system.web/pages/controls element to make it available to all pages in your web:

<system.web>
    <pages>
        <controls>
            <add assembly="DemiCode.Web" namespace="DemiCode.Web.Parameters" tagPrefix="dc" />
      </controls>
    </pages>
</system.web>

Note: I have assumed that the parameter is in the DemiCode.Web project/assembly.

To use the new parameter, see how I changed the asp:Parameter to the new dc:LoginParameter in the markup below:

<dc:LoginParameter name="Username" />

See? We just eliminated the need for the codebehind. Its all done in markup. You just need the LoginParameter class I just created, and you can use this functionality in as many places you want.

But wait! There is more...

Let me get you started with some inspirational samples.

using System.Web.UI.WebControls;
using System.Configuration;

namespace DemiCode.Web.Parameters
{
    public class ConfigParameter : Parameter
    {
        public string Key{get;set;}

        protected override object Evaluate(HttpContext context, System.Web.UI.Control control)
        {
            return ConfigurationManager.AppSettings[Key];
        }
    }

    public class NowParameter : Parameter
    {
        protected override object Evaluate(HttpContext context, System.Web.UI.Control control)
        {
            return DateTime.Now;
        }
    }

    public class TodayParameter
    {
        protected override object Evaluate(HttpContext context, System.Web.UI.Control control)
        {
            return DateTime.Today;
        }
    }
}

Let me know if you created a cool custom parameter!