Notice: This site is no longer being updated!

For more recent posts, please visit my blog.

ControlBuilderFaq
   > Home
   > Search
   > About

Links
   > MSDN
   > ASP.net Forums

Search

Custom parameters for data sources
by Eilon Lipton
1/31/2006 11:28:40 PM

As the author of the SqlDataSource and ObjectDataSource controls, I often get asked what is the best way to insert the current date into a query. Every single time I give the simple answer: Write a custom parameter! The next question is always: How hard is it? Once again I have a simple answer: It's literally just one line of actual code.

Writing simple parameters is easy, so let's start with that. The key to writing a custom System.Web.UI.WebControls.Parameter is the Evaluate() method that you must override. This role of this method is to evaluate the state of the parameter and return the value that this parameter represents. In this case, the value is always DateTime.Now, which is what makes this parameter so easy.

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

namespace ControlBuilderFaq.Samples {
    public class TodayParameter : Parameter {
        protected override object Evaluate(HttpContext context, Control control) {
            return DateTime.Now;
        }
    }
}

Now we can use this parameter in a data source:

            <asp:SqlDataSource ID="SqlDataSource1" runat="server"
                InsertCommand="INSERT INTO [MyTable] ([Field1], [Field2], [PostedDate]) VALUES (@Field1, @Field2, @PostedDate)">
                <InsertParameters>
                    <asp:Parameter Name="Field1" />
                    <asp:Parameter Name="Field2" />
                    <cbf:TodayParameter Name="PostedDate" />
                </InsertParameters>
            </asp:SqlDataSource>

That's really all you need to do. Now you can use the new parameter anywhere you used to have some custom code. If you want fancier behavior, you're going to need a fancier parameter. For example, what if the parameter has some additional properties? Thankfully, that's not too hard to do either, but there are definitely a few things you need to keep in mind. The main thing that's a bit tricky is the cloning behavior that all parameters must have in order to work properly in the designer tool, but we'll save that for the end.

To make our parameter more interesting, let's add a new property indicating which day you really want: Yesterday, Today, or Tomorrow. Anyone who has written a control before will find this a familiar task. Parameters have ViewState, just like controls.

using System;
using System.ComponentModel;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace ControlBuilderFaq.Samples {
    public enum DaySetting {
        Today = 0,
        Yesterday = 1,
        Tomorrow = 2,
    }

    public class DayParameter : Parameter {
        [DefaultValue(DaySetting.Today)]
        public DaySetting DaySetting {
            get {
                object o = ViewState["DaySetting"];
                if (o != null) {
                    return (DaySetting)o;
                }
                return DaySetting.Today;
            }
            set {
                ViewState["DaySetting"] = value;
            }
        }

        protected override object Evaluate(HttpContext context, Control control) {
            switch (DaySetting) {
                case DaySetting.Today:
                    return DateTime.Now;
                case DaySetting.Yesterday:
                    return DateTime.Now.AddDays(-1);
                case DaySetting.Tomorrow:
                    return DateTime.Now.AddDays(1);
            }
            throw new InvalidOperationException("Unknown day setting.");
        }
    }
}

Now, along with having renamed the parameter to DayParameter, we can use its new property.

                    <cbf:DayParameter Name="PostedDate" DaySetting="Yesterday" />

The next problem you'll run into is when you try to use this parameter in the designer. Some very strange things happen at design time when it detects a custom parameter. First, a somewhat unfortunate behavior is that it won't let you create parameters of the new type with any fancy user interface. The developer is restricted to typing them manually in source view. The second issue is that when you try to even just edit the InsertParameters of the SqlDataSource, it appears as though the new parameter has disappeared!

This is where the cloning behavior come into play. The parameter design time behavior has to be able to clone a parameter in its entirety to preserve its settings in case the user cancels an edit operation. Since our parameter hasn't implemented custom cloning behavior, it is inheriting the base class's cloning behavior, which is to return a regular Parameter, and not a DayParameter. There are two basic steps you have to follow to do this:

  1. Implement a new constructor that will perform the cloning.
  2. Override the Clone() method to call the new constructor.
    public class DayParameter : Parameter {

        public DayParameter() {
        }

        protected DayParameter(DayParameter original)
            : base(original) {
            DaySetting = original.DaySetting;
        }

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

        ...
    }
    

Now you can use this parameter in the designer and write your app with less code on each page.

One thing to beware of is that the parameter editing dialog (launched when you edit one of the "Query" properties on a SqlDataSource or edit one of the Parameters collections on an ObjectDataSource) isn't all that friendly to custom parameters. Although it will always preserve a custom parameter, it's not friendly about letting you edit them. Due to what appears to be a bug, you have to follow a work around to be able to edit the new parameter. You can only edit custom parameters when "Show advanced properties" is enabled, but that option isn't available on custom parameters. You have to first go to a standard parameter, then switch to advanced properties, and then go back to the new DayParameter. At that point you can use the property grid to edit the parameter's properties.

Using parameters to encapsulate common logic for parts of queries is one of the best features of data source controls. Any time you notice code being duplicated in your data source's Selecting, Inserting, Updating, or Deleting events to handle specific types of values, you should consider packaging up that code into a custom parameter.

- Eilon




Comments
data is reloaded on every postback.... :-(
by Koldan
(Posted on 3/30/2006 7:50:00 AM)
"Hi Eilon!

Thank you! Very good tutorial! But i have a problem with my custom parameter. Everytime when a postback occurs my ObjectDataSource will reload my data. This behavior does not appear if i use a ControlParameter (my custom parameter gets the value of a static field of a class by using refelction). What is the reason for reloading the data on every postback!?!? I'm going crazy... i can not figure it out! Can you please help me? Thanks."
solved the postback problem!!! :-)
by Koldan
(Posted on 4/2/2006 12:05:00 AM)
I've solved the postback problem. The object returned by the 'Evaluate' method of the custom parameter must implement "Equals" and "GetHashCode". Then everything is fine... :-)
Web Page not correctly visible
by Paolo
(Posted on 4/6/2006 12:39:00 AM)
Hi, I am sorry for this OT but I wanted to inform you that this page (http://www.leftslipper.com/ShowFaq.aspx?FaqId=11) is not correctly visible on my system: Win2K, IE6, 1024x768. The content is larger than my window size but I have no horizontal scrollbar to access it. Everything is fine with Firefox. Hope this helps.
Getting value from Page's ViewState
by Fabio
(Posted on 5/15/2006 1:05:00 PM)
"I have some value in Page's Viewstate, and I wish use how SelectParameter, but I can't! I will need create a custom ControlParameter in order to access some property from Page? Actually I'm using a HiddenField, but I think a better solution to use the Page ViewState instead...

Regards
Fabio"
Error registering the custom preperty
by Pedro
(Posted on 6/10/2006 5:22:00 PM)
"Hello,

I've created a custom parameter to user with a object data source. (All this trouble just to pass the user.identity.name ...)
But I'm receiving the following error after build the project.

Parser Erro Message: Unknow server tag 'usernp:UserNameParameter'

the register tag I've used is:
<@ Register Namespace="SGD.MyParam" TagPrefix="usernp" %>


The custom parameter code is:

Imports SystemWeb.UI.WebControls
Namespace MyParam
Public Class UserNameParameter
Inherits Parameter

Protected Overrides Function Evaluate(ByVal context as HtttpContext, ByVal as Control) as Object
Return context.User.Identity.Name
End Function
End Class
End Namespace



My project is in VB.
I'm using the VS 2005 Web Application Project

Can you help me?

Thank you
Pedro Cunha"
Custom Parameter with viewstate
by Jason
(Posted on 6/28/2006 9:02:00 AM)
"Dear Sir,

Is it possible to make a custom parameter to access viewstate on the page? I try to do it and pass data to ObjectDataSource, but without success..

"
Parameter check before insert, delete, update
by Liz
(Posted on 7/6/2006 2:54:00 PM)
"Hi

I would like to create a parameter check before the database executes that checks security stuff. Is there any place in SQLDataSourceControl or the page that the application pages inherits? For instance, I currently find all the SQLDataSource Controls and then replace out all single quotes from SelectCommand, DeleteCommand, InsertCommand and UpdateCommand. Can I do something similar for the parameters.

Thanks!
Liz"
ObjectDataSource binden on every page load.
by Flaxon
(Posted on 7/10/2006 8:53:00 AM)
"Hello,

I have a problem using an ObjectDataSource control with select parameters (declarative) and a FormView control.

When using a control as parameter source (here a label holding the key value), the DataBind will be executed every page load even the value is not changed in the label.

I think this is because of the binding logic in data bound controls.

Can you help on this?

Thanks,
Flaxon

"
can't get this to work
by Gary
(Posted on 11/29/2006 1:47:00 PM)
I've tried every which way to do a custom parameter control but I keep getting the same error "Could not load file or assembly 'MyControls' or one of its dependencies. The system cannot find the file specified.". I created the control in a separate project, built it and put the dll in the bin directory of the project i want to use it in. I put the "register" directive at the top with the correct namespace and assembly name but continue to get the above error. Any help would be greatly appreciated. Thanks, Gary
Custom Parameter for User Control Property
by Travis
(Posted on 11/30/2006 1:00:00 AM)
"I want a custom parameter that can pass a user control's public property.

Any ideas?"
Custom Parameter for Page Members
by Jonathan Roes
(Posted on 7/5/2007 7:50:00 AM)
"Thanks to this article, I've created a custom parameter for instance data on a page.

http://jonathanroes.blogspot.com/2007/07/custom-parameter-that-should-have.html"
KJHE
by Kieth James Hersey
(Posted on 2/4/2008 8:19:42 PM)
contact.
Other
by Pat Williams
(Posted on 6/9/2008 2:47:44 AM)
Cool Site.
Input with return value
by max
(Posted on 12/30/2009 11:44:32 AM)
I am trying to input an order into an order table and return the orderid that is generated by the SQL Server Primary Key. I want to use the SQLDatasource with an InputCommand of type TEXT but when I try to access the parameter , SQLDatasource.InputParameter("intOrderID") gives me an error because it tells me the parameter is not an integer. heelp. How to I access the value of the parameter??


Post a comment:
Name:  
E-mail:
(Optional; Will not be shown)
Title:
 
Content:  

(Maximum length 1000 characters. Newlines will be preserved, and HTTP URLs will become links automatically.)
Post Comment