Thursday, July 06, 2006

Using Validators to Verify User Input from a Web Part's Custom EditorPart


This article applies to the ASP.NET 2.0 Web Part Framework, Windows SharePoint Services v3 (WSS v3), and Microsoft Office SharePoint Server 2007 (MOSS 2007).

ASP.NET 2.0 input validation controls allow for client side verification of data and quickly inform the user of input errors before form data is posted back to the web server.  Using validators saves on server resources and provides the user with a richer, more responsive experience.  This article will illustrate how input validation controls can be leveraged in a web part’s custom EditorPart to validate user input of web part properties.  

For illustration, assume we have a Visual Studio 2005 web control library project which contains a very simple web part of type JustPrintAuthorWebPart who’s sole responsibility is to render a book author’s full name in a web part page.  A book author’s full name may consist of either two words e.g. ‘FirstName LastName’ or three words e.g. ‘FirstName Middle LastName’.  JustPrintAuthorWebPart has associated with it a custom EditorPart of type AuthorEditorPart who’s job is to accept user input of the author full name, validate the author full name, and apply changes back to JustPrintAuthorWebPart for rendering and serialization.

All told, the example web control library project (download from the link at the end of this article) looks this:

SPSolutionsDemoJuly072006

The JustPrintAuthorWebPart implementation is trivial, with only one property BookAuthor of type Author.

[WebBrowsable(true)]
[Personalizable(PersonalizationScope.User)]
[Bindable(true)]
[Category("Data")]
[DefaultValue(typeof(Author), "")]
[PersistenceMode(PersistenceMode.InnerProperty)]
public Author BookAuthor
{
    get { return m_author; }
    set { m_author = value; }
}

The complex data type Author has three properties FirstName, MiddleName and LastName.  In order to use a complex data type as a personalizable property in an ASP.NET 2.0 web part, there must also exists a type converter who’s sole job is to convert instances of type Author to type String and back again for the purpose of serialization and deserializaton. 

ASP.NET includes six validation controls RequiredFieldValidator, RangeValidator, CompareValidator, RegularExpressionValidator, CustomValidator and ValidationSummary.  The project’s implementation of AuthorEditorPart utilizes RequiredFieldValidator, RegularExpressionValidator and CustomValidator to verify user input of the book author’s full name.

SPSolutionsDemoJuly072006-editorpart

RequiredFieldValidator ensures that a null value cannot be entered by the user.

SPSolutionsDemoJuly072006-requiredvalidator

Implementation of RequiredFieldValidator takes place in the overidden CreateChildControls method of AuthorEditorPart.

// Required field validator
RequiredFieldValidator authorRequiredValidator =
  new RequiredFieldValidator();
authorRequiredValidator.ControlToValidate = m_txtAuthor.ClientID;
authorRequiredValidator.ErrorMessage = "Author's name cannot be blank";
authorRequiredValidator.Display = ValidatorDisplay.Dynamic;
authorRequiredValidator.Text = "<img src=\"/_layouts/images/CNSCA16.GIF\"/>";

RegularExpressionValidator makes sure that the user input comes only in the form of two words e.g. ‘FirstName LastName’ or three words e.g. ‘FirstName Middle LastName’.

SPSolutionsDemoJuly072006-regexvalidator

RegularExpressionValidator is also implemented in AuthorEditor’s CreateChildControls method.

// Format validator
RegularExpressionValidator authorRegexValidator =
  new RegularExpressionValidator();
authorRegexValidator.ControlToValidate = m_txtAuthor.ClientID;
authorRegexValidator.ErrorMessage =
  "Author's name must be in the form of 'First Last' or 'First Middle Last'.";
authorRegexValidator.Display = ValidatorDisplay.Dynamic;
authorRegexValidator.Text = "<img src=\"/_layouts/images/CNSCA16.GIF\"/>";
authorRegexValidator.ValidationExpression = @"^\w+\s\w+\s\w+$|^\w+\s\w+$" ;

The final validator used in AuthorEditor is a CustomValidator which acts to inform the user if a server side ArgumentExceptionError is thrown during  the process of converting the user input into an Author object for serialization.

SPSolutionsDemoJuly072006-customvalidator

The CustomValidator is actually used within a try/catch block in the ApplyChanges() method of AuthorEditor.  The logic of ApplyChanges saves the user’s input to JustPrintAuthorWebPart for rendering and serialization.  If the process of converting the user’s input String into an instance of type Author fails, then the CustomValidator’s IsValid property is set to false and the user is informed.  This pattern doesn’t save a trip to the server, but does provide the user with an informative message in a consistent manner.

public override bool ApplyChanges()
{
    EnsureChildControls();
    JustPrintAuthorWebPart part = WebPartToEdit as JustPrintAuthorWebPart;
    if (part != null)
    {
        // Set web part properties based on editor control values
        try
        {
            AuthorConverter converter = new AuthorConverter();
            part.BookAuthor = (Author)converter.ConvertFrom(m_txtAuthor.Text);
        }
        catch (ArgumentException ex)
        {
            m_authorValidator.ErrorMessage =
                string.Format("{0} {1}", ex.GetType().ToString(), ex.Message);
            m_authorValidator.Text =
                "<img src=\"/_layouts/images/CNSCA16.GIF\"/>";
            m_authorValidator.IsValid = false;
            throw ex;
        }
    }
    else
        return false
;

    return true;
}

The Visual Studio 2005 web part library project containg all code shown in this article can be downloaded in this zip archive.

9 comments:

Anonymous said...

Hi,

The article is great!
Just have a question:
if I Click the cancel button, the validation logic still gets called. How to disable the validation when cancel button gets clicked?

Thanks,
Greg

Anonymous said...

How to disable Cancel button validation.

I added the following code to my Editor Part's CreateChildControls method

ToolPane pane = Zone as ToolPane;
if (pane != null)
  pane.Cancel.CausesValidation = false;

Anonymous said...

To disable the cancel button also firing the validations you need to disable its CausesValidation property.

this.ParentToolPane.Cancel.CausesValidation = false;

Anonymous said...

The article is very useful and interesting. Thanks so much for sharing your knowledge.

Anonymous said...

Hi,
Thanks for your article.
In regards to the question above, I think CausesValidation = false; is the answer.
I have a problem too: when I add multiple RequiredFieldValidator's CreateChildControls crashes. Just 2 are accepted. Does anyone know the solution?
Thanks,
Ben*

Anonymous said...

Nice article but could you supply a link to a complete sourcecode download?

dunxd said...

Thanks - I found this really useful for understanding validation in general. A couple of comments - Sharepoint provides its own validation controls.

Also, when using validation in the public part of the form, making changes to the EditorPart triggers all validation. Is there a way to prevent this?

Unknown said...

Below is the code for preventing the Cancel button from causing validation.

Button cancelButton = (this.Parent as Microsoft.SharePoint.WebPartPages.ToolPane).FindControl("MSOTlPn_CnclBtn") as Button;
if (cancelButton != null)
cancelButton.CausesValidation = false;

Suresh Pydi said...

Thank you very much for the blog post. Here is my blog post to get the input values from custom webpart

http://sureshpydi.blogspot.in/2011/03/get-input-values-from-web-part-editor.html