How to implement a Custom Parameter in ASP.NET

Resources:
Custom parameters for data sources by Eilon Lipton
Create your own Parameter to the data-source control’s parameters collection by Fredrik Normén

I needed to bind a GridView to an ObjectDataSource, which in turn would call LoadByQuery method on the data class with a parameter of type IQuery and name query.

public DataObjectsList LoadByQuery(IQuery query);
public interface IQuery
{
    string Criteria { get; set; }
    string SortExpression { get; set; }
}

The argument that is usually passed to this method is CustomQuery, which implements IQuery.

public class CustomQuery : IQuery
{
    public CustomQuery();
    public string Criteria { get; set; }
    public string SortExpression { get; set; }
}

Usage scenario:

var query = new CustomQuery();
query.Criteria = "IsActive = 'true'";

DropDownListViews.DataTextField = "en_gb_name ";
DropDownListViews.DataValueField = "Id";
DropDownListViews.DataSource =
                     new EntityView_Resource().LoadByQuery(query);
DropDownListViews.DataBind();

I wanted to bind the DropDownList to an ObjectDataSource instead of setting the datasource in the code-behind by using  a string property in the custom parameter to specify the query criteria, say ‘Isactive = ‘true’, which would then be converted to the CustomQuery object that is passed to the method.
The code is given below:

[assembly: TagPrefix("My.Framework.Common.UIControls", "my")]
namespace DHA.Framework.Common.UIControls
{
    public class QueryParameter : Parameter
    {
        public QueryParameter()
        {
        }

        public QueryParameter(string name, object value)
            : base(name)
        {
            this.Criteria = (string)value;
        }

        public QueryParameter(string name, TypeCode type,
                                                       object value)
            : base(name, type)
        {
            this.Criteria = (string)value;
        }

        protected QueryParameter(QueryParameter original)
            : base(original)
        {
            this.Criteria = original.Criteria;
        }

        public string Criteria
        {
            get
            {
                object criteria = base.ViewState["Criteria"];
                if (criteria != null)
                {
                    return (string)criteria;
                }
                return String.Empty;
            }
            set
            {
                if (this.Criteria != value)
                {
                    base.ViewState["Criteria"] = value;
                    base.OnParameterChanged();
                }
            }
        }

        protected override Parameter Clone()
        {
            return new QueryParameter(this);
        }

        protected override object Evaluate(HttpContext context,
                                                  Control control)
        {
            if (control == null)
            {
                throw new ArgumentNullException("control");
            }

            if (context.Request == null)
            {
                return null;
            }

            CustomQuery query = new CustomQuery();
            query.Criteria = this.Criteria;
            return query;
        }
    }
}

In the ObjectDataSource, the usage will be as follows:


<asp:ObjectDataSource ID="listDataSource" runat="server"
        SelectMethod="LoadByQuery"
        TypeName="BusinessEntities.EntityView_Resource" >
        <SelectParameters>
          <dha:QueryParameter Criteria="IsActive = 'true'"
                     Name="query" Type="Object" />
        </SelectParameters>
</asp:ObjectDataSource>

Issues:

1) This should have worked but didn’t. The page went into a weird infinite loop that culminated in a stack overflow error. Following the advice by a commenter on Lipton’s blog entry, I implemented GetHashCode and Equals on the CustomQuery object (which is a good practice for all custom classes), the returned object from the Evaluate method. The error vanished.

2) I also had to mark the CustomQuery class as Serializable.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s