Server controls in separete assembly part 2

Yesterday I was writing about creating server controls in separate assembly. Today I will cover more complicated example then simple “Hello World!” control. My goal was to create text box that will take handler method to run when validation event will be triggered, and when validation fail will show appropriate message. Text box with builtin validation would be nice, since you always should validate user input, right? But lets start creating our control.

First create new control named TextBoxWithValidation.ascx in our yesterday web site WebSite1 project.

Lets now fill it with some html code.

<span>
    <asp:TextBox runat="server" ID="tbText" OnTextChanged="tbText_TextChanged"></asp:TextBox>
    <asp:CustomValidator runat="server" ID="cvValidator" ControlToValidate="tbText" 
        OnServerValidate="cvValidator_ServerValidation"
        EnableClientScript="false"
        ErrorMessage="Dummy text error message" 
        Display="None" ValidateEmptyText="true">
        <%--validator must have ErrorMessage string--%>
    </asp:CustomValidator>
    <div class="ui-widget validation-error" id="divValidationContainer" runat="server"
        visible="false">
        <div class="ui-state-error ui-corner-all">
            <span style="float: left; margin-right: .3em;" class="ui-icon ui-icon-alert"></span>
            <asp:Label ID="lValidationMessage" CssClass="validation-message" runat="server"></asp:Label>
        </div>
    </div>
</span>

This HTML is using some CSS classes as it some HTML code from jQueryUI. So it will be good if you grab newest version from http://jqueryui.com/.

You can of course use you own html for validation error message.

.ascx file contains 2 ASP.NET controls, text box and custom validator. Validator will be validating value of our text box by custom handler assigned from external page or control. We are setting ErrorMessage property with "Dummy text error message" because validator would not run validation event without it. It’s some kind internal logic in .NET Framework. That’s why we set it to ‘dummy’ to in case some um… error it would display some hint that there is something wrong with validation, and this is not validation message. Lets jump to .cs file.

public partial class TextBoxWithValidation : System.Web.UI.UserControl
{
    public string Text
    {
        get
        {
            return tbText.Text;
        }
        set
        {
            tbText.Text = value;
        }
    }

    public bool IsValid
    {
        get
        {
            return cvValidator.IsValid;
        }
    }
    
    public string ErrorMessage
    {
        get
        {
            return cvValidator.ErrorMessage;
        }
        set
        {
            cvValidator.ErrorMessage = value;
        }
    }

    public event ServerValidateWithMessageEventHandler ServerValidate;

    protected void cvValidator_ServerValidation(object source, ServerValidateEventArgs args)
    {
        if (ServerValidate != null && Visible)
        {
            var argsWithMessage = new ServerValidateWithMessageEventArgs(args);
            ServerValidate(source, argsWithMessage);
            argsWithMessage.ToServerValidateEventArgs(args);
            divValidationContainer.Visible = !argsWithMessage.IsValid;
            if (!argsWithMessage.IsValid)
            {
                if (string.IsNullOrEmpty(argsWithMessage.ErrorMessage))
                {
                    lValidationMessage.Text = cvValidator.ErrorMessage;
                }
                else
                {
                    lValidationMessage.Text = argsWithMessage.ErrorMessage;
                }
            }
            else
            {
                lValidationMessage.Text = "";
            }
        }
    }
}

First we are making proxy of properties IsValid and ErrorMessage, and also of property Text of TextBox. They will be handy in future 🙂

Next are public event for text box value Validation ServerValidate and protected function that will run this event cvValidator_ServerValidation. Argument of this method args is defined as below:

public delegate void ServerValidateWithMessageEventHandler
            (object source, ServerValidateWithMessageEventArgs args);

public class ServerValidateWithMessageEventArgs : ServerValidateEventArgs
{

    public ServerValidateWithMessageEventArgs(ServerValidateEventArgs args)
        : base(args.Value, args.IsValid)
    { }

    public string ErrorMessage { get; set; }

    internal void ToServerValidateEventArgs(ServerValidateEventArgs args)
    {
        args.IsValid = IsValid;
    }
}

In this argument in parent control or page we can set ErrorMessege property and will obtain IsValid property value after event execution will complete. In control method cvValidator_ServerValidation we will also show or hide our custom validation message depending if value of text box is valid or not.

Let’s try it out. We will publish WebControl project, and add reference to this new control by adding App_Web_textboxwithvalidation.ascx.cdcab7d2.dll file. Next add another line to web.config like yesterday:

<add tagPrefix="WebControls" namespace="ASP" assembly="App_Web_textboxwithvalidation.ascx.cdcab7d2" />

Now we can add our new control to page:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <link href="JqueryUI/css/redmond/jquery-ui.custom.min.css" rel="stylesheet" type="text/css" />
    <link href="jQueryUI.Validation.css" rel="stylesheet" type="text/css" />
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <WebControls:helloworld_ascx runat="server" />
        <WebControls:textboxwithvalidation_ascx ID="test" runat="server" ErrorMessage="testMessage" OnServerValidate="test_ServerValidate" />
        <br />
        <asp:Button runat="server" Text="Validate" />
    </div>
    </form>
</body>
</html>

with some button to trigger postback and some method to validate:

        protected void test_ServerValidate(object source, ServerValidateWithMessageEventArgs args)
        {
            if (args.Value.Length > 5)
            {
                args.ErrorMessage = "Value is too long!";
                args.IsValid = false;
            }
        }

As for styles first is standard jQueryUI redmond theme css file and second is custom css for jQueryUI theme which places validation message right from text box as popup with nice eye-candy effects 🙂

/*validation*/
.validation-error
{
    display: inline-block;
    position: absolute;
    z-index: 1000;
}
.validation-error .ui-icon-alert, .errorResultContainer .ui-icon-alert
{
    float: left;
    margin-right: .3em;
}
.validation-error .ui-state-error
{
    padding: 5px;
    box-shadow: 5px 5px 5px #888888;
}
.validation-error .validation-message
{
    display: none;
    position: relative;
    text-shadow: 2px 2px 2px activeborder;
}
.validation-error:hover .validation-message
{
    display: block;
}
.validation-error:hover
{
    z-index: 1001;
}
.ui-icon-alert
{
    float: none !important;
}

After running our project and clicking on button when value of text box is longer then 5 chars we will see validation popup:

when you hover on popup you will see error description:

You can validate value for more then one constraint. Just remember to set ErrorMessage property and IsValid property to false of args parameter. That is all.

Leave a Reply

Your email address will not be published. Required fields are marked *

Solve : *
8 + 27 =