Wednesday, December 29, 2010

ASP.NET MVC 3 Custom Validation

Data annotations Rock!  Using data annotations on your model classes make data validation (client and server) trivial.  Just add the data annotation to you model class, wire up an edit/create view to your controller via the 'Add View' wizard, and you have client- and server-side validation with very little effort.

A little disclaimer here - the implementation below it not MVC 3 specific; however, I developed the solution using MVC 3, tested using MVC 3, and it works using MVC 3.  I'm pretty sure it will work as-is using MVC 2.

What if you need validation that is not provided via data annotations out-of-box?  You create your own.  That's what this post is all about.

Creating your own validators that support client- and server-side validation is essentially a four-step process:
  1. Create a custom attribute that extends the ValidationAttribute, or better yet, you extend one of the existing data annotations.
  2. Create a custom validator that extends the DataAnnotationsModelValidator, where T is the type of custom attribute you created in step one.
  3. Create a client-side script to handle the client-side validation.
  4. Register the attribute/validator classes in your app's bootstrapper or Global.asax.
Side note: It seems that every time I have a good idea for a post, Phil Haack has beat me to the punch... and this pattern is also true in this scenario :-) For a similar article on the same subject, please see Phil's ASP.NET MVC 2 Custom Validation post.

This post is very code centric; therefore, if the concepts are unfamiliar or a brushing up is necessary, please take a look at Phil's post.  Also, Brad Wilson has a few different blog posts/series on Data Annotations and ModelMetadata.  Brad and Phil's knowledge of the ins and outs of anything ASP.NET MVC (and arguably C#) scares me...

The custom attribute and validator that I'm going to create is an Email validator.  There are plenty examples on the net, including here, here, etc...  What these email validator solutions don't provide is client-side validation.  I will show you how.  So, lets start with step one:

1. Create a Custom Attribute
Below are two solutions.  They both result in the same functionality.  The first solution is a full implementation that extends the ValidationAttribute class, while the second solution extends the RegularExpressionAttribute.

EmailAttribute Extending Validation Attribute
using System;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Text.RegularExpressions;

namespace Validation
{
    /// <summary>
    /// Email Attribute class used for email validation. Used similar to the System.ComponentModel.DataAnnotations.RegularExpressionAttribute.
    /// </summary>
    public class EmailAttribute : ValidationAttribute
    {
        #region Properties

        /// <summary>
        /// Gets or sets the Regular expression.
        /// </summary>
        /// <value>The regex.</value>
        private Regex Regex { get; set; }

        /// <summary>
        /// Gets the pattern used for email validation.
        /// </summary>
        /// <value>The pattern used for email validation.</value>
        /// <remarks>
        /// Regular Expression Source - Comparing E-mail Address Validating Regular Expressions
        /// <see cref="http://fightingforalostcause.net/misc/2006/compare-email-regex.php"/>
        /// </remarks>
        public string Pattern
        {
            get
            {
                return
                    @"^([\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*[\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+@((((([a-zA-Z0-9]{1}[a-zA-Z0-9\-]{0,62}[a-zA-Z0-9]{1})|[a-zA-Z])\.)+[a-zA-Z]{2,6})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)$";
            }
        }

        #endregion Properties

        #region Ctors

        /// <summary>
        /// Initializes a new instance of the <see cref="EmailAttribute"/> class.
        /// </summary>
        public EmailAttribute()
        {
            this.Regex = new Regex(this.Pattern);
        }

        #endregion Ctors

        /// <summary>
        /// Determines whether the specified value of the object is valid.
        /// </summary>
        /// <param name="value">The value of the object to validate.</param>
        /// <returns>
        /// true if the specified value is valid; otherwise, false.
        /// </returns>
        public override bool IsValid(object value)
        {
            // convert the value to a string
            var stringValue = Convert.ToString(value, CultureInfo.CurrentCulture);

            // automatically pass if value is null or empty. RequiredAttribute should be used to assert an empty value.
            if (string.IsNullOrWhiteSpace(stringValue)) return true;

            var m = Regex.Match(stringValue);

            // looking for an exact match, not just a search hit.
            return (m.Success && (m.Index == 0) && (m.Length == stringValue.Length));
        }
    }
}

EmailAttribute Extending RegularExpressionAttribute
using System.ComponentModel.DataAnnotations;

namespace Validation
{
    /// <summary>
    /// Email Attribute class used for email validation. Used similar to the System.ComponentModel.DataAnnotations.RegularExpressionAttribute.
    /// </summary>
    public class EmailAttribute : RegularExpressionAttribute
    {
        #region Ctors

        /// <summary>
        /// Initializes a new instance of the <see cref="EmailAttribute"/> class.
        /// </summary>
        public EmailAttribute()
            : base(
                @"^([\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*[\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+@((((([a-zA-Z0-9]{1}[a-zA-Z0-9\-]{0,62}[a-zA-Z0-9]{1})|[a-zA-Z])\.)+[a-zA-Z]{2,6})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)$"
                )
        {
        }

        #endregion Ctors
    }
}
ddd
Again, whatever implementation you choose is up to you.  Both implementations have the same resulting functionality - Email validation via data annotations.

2. Create a custom validator that extends the DataAnnotationsModelValidator
This class - the validator class - is the class that provides metadata to enable client-side validation.  This class essentially transfers settings, in our case the ErrorMessage and Pattern properties of the EmailAttribute class, from the attribute decorations on your model object to the client-side consumer.  The client-side consumer is what provides the client-side validation.

using System.Collections.Generic;
using System.Web.Mvc;
using Chinook.Framework.Validation;

namespace Chinook.Web.Core.Validation
{
    /// <summary>
    /// Provides a model validator for the EmailAttribute annotation.
    /// </summary>
    public class EmailValidator : DataAnnotationsModelValidator<EmailAttribute>
    {
        #region Fields

        private readonly string _errorMessage;
        private readonly string _pattern;

        #endregion Fields

        #region Ctors

        /// <summary>
        /// Initializes a new instance of the <see cref="EmailValidator"/> class.
        /// </summary>
        /// <param name="metadata">The metadata.</param>
        /// <param name="context">The context.</param>
        /// <param name="attribute">The attribute.</param>
        public EmailValidator(ModelMetadata metadata, ControllerContext context, EmailAttribute attribute)
            : base(metadata, context, attribute)
        {
            this._errorMessage = attribute.ErrorMessage;
            this._pattern = attribute.Pattern;
        }

        #endregion Ctors

        #region Methods

        /// <summary>
        /// Retrieves a collection of client validation rules.
        /// </summary>
        /// <returns>A collection of client validation rules.</returns>
        public override IEnumerable<ModelClientValidationRule> GetClientValidationRules()
        {
            var rule = new ModelClientValidationRegexRule(this._errorMessage, this._pattern);
            return new[] {rule};
        }

        #endregion Methods
    }
}
So now that we have the attribute and validator classes created, we need to...

3. Create a client-side script to handle the client-side validation
I feel like I'm cheating on you here.  Out scenario - email validation - and it's implementation do not require us to write client-side script.  I know, I know... if you feel robbed, you can create your own client-side script, and register is with the jQuery Validate plugin.  I'll try and create a future post will another validator that requires writing client-side script and jQuery Validate registration, but for now we going to enjoy the luxuries of extending and using existing functionality.  But, HOW do we get away with using existing client-side script?

Take a look at the following code snippet from step two:
public override IEnumerable<ModelClientValidationRule> GetClientValidationRules()
{
    var rule = new ModelClientValidationRegexRule(this._errorMessage, this._pattern);
    return new[] {rule};
}

This method 'retrieves' a collection of client validation rules.'  And since we are essentially using a RegularExpressionAttribute class (via extension), we can use the client validation rules used by the RegularExpressionAttribute's Model Validator class via the ModelClientValidationRegexRule passing our Error Message and Regular Expression pattern.

This bring us to our last step...

4. Register the attribute/validator classes in your app's bootstrapper or Global.asax
To make all this sweetness happen, we need to register the attribute and validator classes when the app domain kicks off its like cycle.  In your Global.asax's Application_Start method, register the attribue and validator classes using the following code snippet:
// register custom model validators
DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(EmailAttribute), typeof(EmailValidator));
To use the attribute and validator classes use just created, you need to decorate you model/POCO classes with data annotations, including your EmailAttribute class.  The following shows how the EmailAttribute is used (along with other data annotations) to decorated a property in your model class:
[Display(Name = "Email")]
[Required(ErrorMessage = "Email is Required.")]
[Email(ErrorMessage = "Not a valid Email Address.")]
[StringLength(60, ErrorMessage = "Email must be under 60 characters.")] 
public string Email { get; set; }

Once you create strongly typed Edit and/or Create Views using your models, include the script libraries, and run the application, you will see the fruits of your labor and get client-side validation.  The screenshot below is an example.

Anyway, I hope you got a little something out of this post.

Thanks for reading...

Thursday, December 16, 2010

SQL Server - Get Table Dependencies via INFORMATION_SCHEMA - Template for SSMS

The following is a SQL Server script used to get a table's dependencies. The script uses SSMS template syntax, so you can add it to the SSMS Template Explorer and use the (Ctrl-Shift-M) keyboard sequence to set the script's parameters. The script returns the following for each dependency:
  • Parent Table Schema Name
  • Parent Table Name
  • Parent Table Primary Key Field Name
  • Foreign Table Schema Name
  • Foreign Table Name
  • Foreign Table Foreign Key Field Name
  • Foreign Table Foreign Key Constraint Name
What's nice is that the script uses INFORMATION_SCHEMA, so it may be used with other databases that support INFORMATION_SCHEMA; however, I have not tested the script with other databases. If you give the script a run on another database, I'd love to here about your experience.
-- ======================================================================
-- Template used to determine a specific table's dependencies.
--
-- Use the Specify Values for Template Parameters command (Ctrl-Shift-M) 
-- to fill in the parameter values below.
-- @schema_name:  the schema name of the table to retrieve dependencies
-- @table_name:  the table name of the table to retrieve dependencies
-- ======================================================================

DECLARE @SchemaName VARCHAR(128), @TableName VARCHAR(128);
SELECT @SchemaName = N'<schema_name, VARCHAR(128), dbo>', @TableName = N'<table_name, VARCHAR(128),>'

SELECT DISTINCT  
       pt.TABLE_SCHEMA AS ParentSchema, 
       pt.TABLE_NAME AS ParentTable, 
       pt.COLUMN_NAME AS ParentPrimaryField, 
       fk.TABLE_SCHEMA AS ForeignSchema, 
       fk.TABLE_NAME AS ForeignTable, 
       cu.COLUMN_NAME AS ForeignKeyField, 
       c.CONSTRAINT_NAME AS ForeignKeyConstraint 
FROM   INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS c 
       INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS fk 
            ON  c.CONSTRAINT_NAME = fk.CONSTRAINT_NAME 
       INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS pk 
            ON  c.UNIQUE_CONSTRAINT_NAME = PK.CONSTRAINT_NAME 
       INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE cu 
            ON  c.CONSTRAINT_NAME = CU.CONSTRAINT_NAME 
       INNER JOIN ( 
                SELECT tc.TABLE_SCHEMA, 
                       tc.TABLE_NAME, 
                       kcu.COLUMN_NAME 
                FROM   INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc 
                       INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu 
                            ON  tc.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME 
                WHERE  (tc.CONSTRAINT_TYPE = 'PRIMARY KEY') 
            ) pt 
            ON  pt.TABLE_NAME = pk.TABLE_NAME 
WHERE  (pk.TABLE_NAME = @TableName) 
       AND (pk.TABLE_SCHEMA = @SchemaName) 
ORDER BY 
       ForeignTable ASC; 
Thanks for reading...

Friday, September 10, 2010

jQuery Theme Switcher Reset Plugin

User Experience!  That's what bring 'um back.  Remember the first time you saw AJAX in action?  Maybe it was via your GMail or Hotmail account.  Whatever it was, you kept coming back to it.  Why?  Because it was cool; maybe because it was something that you've never seen before; or, maybe it was your fascination with 'How'd they do that?'  Bottom Line: User Experience!

Okay, I'll admit it - I'm not a designer!  I try, and I typically come up with some good solutions; however, it takes quite awhile.  Looking back at all the time I've spent making the UI look pretty, I could have added all that 'cool' functionality that the client wanted.

Finding patterns that are tried and trued, well known, relatively easy to implement, predicable, and reusable is a developers dream.  Unlike software development, I don't believe (well, I don't know...) that there a set of pervasive UI design patterns that all designers could pull out of their toolbox and share with other designers.  I'll spare you the details, but when a developer chats with another developer common design patterns are used to communicate the intent, architecture, design, and implementation of a software component - Singleton, Repository, Decorator, etc...

So, where am I going with this...?  User Experience!

Back to the 'cool' factor of AJAX, what else might bring back a user?  What's that?  A nice decision?  Easy to use interface?  Maybe, a UI customization feature where the user can select the way the UI is styled?  That's where I'm going with this...

Windows has (as far back as Windows 95 - probably farther) a function for a user to select various themes and background to change their Windows experience.  iGoogle, Windows Live, and Yahoo all have theming support.  Visual Studio even has theme support.

jQuery UI ThemeRoller is nothing new.  ThemeRoller gives you the ability to create common component themes, download the themes, and easily integrate the themes with you application/Web site.  Again, this is nothing new.  There is also a pluging for Firefox.  A sister jQuery project is the Theme Switcher widget.  The ThemeSwitcher widget gives the developer the opportunity to integrate theme switching functionality into their Web site to enhance the Use Experience - there's that phrase again...  The Theme Switcher is not as well known as the ThemeRoller, but it's nothing new either.

What the Theme Switcher lacks is a way to integrated a custom theme that you designed and downloaded from the ThemeRoller tool.  I've created a simple jQuery Theme Switcher proxy plugin that will integrate the Theme Switcher and all the outstanding jQuery UI themes with your default theme.

Rather than bore you with the implementation details, you can view a demonstration here: Theme Switcher Reset Proxy  Here's a screenshot:

You can download the code via View Source.
Thanks for reading...

Thursday, September 2, 2010

jQuery UI Frame Dialog - Loading Pane

An updated posted is located here.  This includes modifications to the plugin to avoid multiple iFrame source loads.

I like to use dialogs.  Specifically, I like to use inline dialogs rendered within the current window.  A popular implementation is the jQuery UI Dialog Widget.  I also like to render full page content in dialogs via iFrame object; however, jQuery UI Dialog Widget does not provide this functionality out-of-the-box.

There is a plethora of home grown solutions for rendering iFrames wrapped within the jQuery UI Dialog Widget; however, none really fit well with what I wanted to do.  That is, until I found the jQuery UI Frame Dialog Plugin.  The jQuery UI Frame Dialog Plugin provides extensions to the jQuery UI Dialog Widget for rendering iFrame content.  The implementation is as simple as it gets, and IMHO is the best solution for rendering iFrame content wrapped by the jQuery UI Dialog Widget.

The only this missing in the jQuery UI Frame Dialog Plugin was a way to provide a loading panel (eye candy) while the iFrame's source is loading.  You know the type - where an animated image is displayed while the content is acquired, loaded, and rendered and the animated image disappears when the the content is ready.

I made a few modification to the jQuery UI Frame Dialog Plugin to support the loading panel concept.  Essentially, I added a new property (loadingClass) to the options hash parameter.  The loadingClass property is a CSS class containing styles to apply to the jQuery Dialog Widget while the iFrame's content is being acquired, loaded, and rendered.  The following is an example of a CSS class used for the loadingClass parameter:
.loading-image { background: transparent url('assets/im/progress-indicator-alpha.gif') no-repeat center center; }
The following is the JavaScript used to open the dialog (initiated via an anchor):
$('#dialog_link').click(function(){
var $dialog =
   jQuery.FrameDialog.create({
      url: 'http://espn.go.com',
      loadingClass: 'loading-image',
      title: 'This is the Dialog\'s Title',
      width: 900,
      height: 600,
      autoOpen: false
   });
   $dialog.dialog('open');
   return false;
});
If you're interested, an online demo is located here: jQuery UI Frame Dialog Plugin with Loading Panel. The JavaScript file is accessible via View Source.

I wanted to notify the developer of my addition to the jQuery UI Frame Dialog Plugin.  So, I navigated to the plugin page, clicked the 'View Pending Feature Requests', successfully logged in with my account, and received the following error.  The crazy thing about this error, I keep getting this error if I navigate anywhere on the Plugins site while logged in.  Strange behavior!  Hopefully this is a temporary issue...


Thanks for reading...

Tuesday, August 17, 2010

C# Delegates

Nice post on Action, Predicate, and Func delegates: Cool Delegates

Quick Reference:
/*
* Action -    
*    o accepts zero or up to four parameters and returns void
*    o Action                         :: public delegate void DelegateName()
*    o Action<T>                      :: public delegate void DelegateName(T)
*    o Action<T1, T2>                 :: public delegate void DelegateName(T1, T2)
*    o Action<T1, T2, T3>             :: public delegate void DelegateName(T1, T2, T3)
*    o Action<T1, T2, T3, T4>         :: public delegate void DelegateName(T1, T2, T3, T4)
* 
* Predicate - 
*    o accepts a single parameter and returns a bool  
*    o Predicate<T>                   :: public delegate bool DelegateName(T)
*     
* Func -
*    o acepts zero or up to four parameters and returns any type (TResult)
*    o Func<TResult>                  :: public delegate <TResult> DelegateName()
*    o Func<T, TResult>               :: public delegate <TResult> DelegateName(T1)
*    o Func<T1, T2, TResult>          :: public delegate <TResult> DelegateName(T1, T2)
*    o Func<T1, T2, T3, TResult>      :: public delegate <TResult> DelegateName(T1, T2, T3)
*    o Func<T1, T2, T3, T4, TResult>  :: public delegate <TResult> DelegateName(T1, T2, T3, T4)
* 
*/

System.Environment - EnvironmentList Utility Class

I'm traditionally a Web developer; however, lately I've found myself doing a bunch of console work to help automate various tasks (including work flow, file and report merging, moving builds to various environments, etc...).  I've come to embrace, among many, the System.IO.Path, System.Environment, and System.Diagnostics.Process classes.  These classes help manipulate file and directory paths, provide information about means of manipulating the current environment, and access to starting and stopping local services.

I often find myself investigating these class and their members and forgetting exactly what the member does.  I'll locate a property or method that sounds like and is described (via comments) as something I would like to use; however, the comments are short and sweet and I must have a dozen questions pop in my mind.  Note to self - create a framework for interactive library documentation .  I digress... I'll typically create a quick console app an determine if the respective member is what I really need.  This takes time - every time!  So, I came up with a utility class...

The following is a informational utility class that builds a collection of key: value pair of the current environment.  Fundamentally, all that this class does is abstract and enumerate the various members of the System.Environment class, puts the results into a list of key: value pairs, and provides a property that exposes the results.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq.Expressions;

/// <summary>
/// Environment List Class.
/// </summary>
public partial class EnvironmentList
{
   #region Fields
   #endregion Fields

   #region Properties
   /// <summary>
   /// Gets the Environment Key: Value collection.
   /// </summary>
   /// <value>The items.</value>
   public List<KeyValuePair<string, string>> Items { get; private set; }
   #endregion Properties

   #region Methods
   /// <summary>
   /// Builds the Environment dictionary/list.
   /// </summary>
   private void BuildDictionary()
   {
      this.Items.Add(new KeyValuePair<string, string>(ReflectionUtility.GetPropertyName(() => Environment.SystemDirectory), Environment.SystemDirectory));
      this.Items.Add(new KeyValuePair<string, string>(ReflectionUtility.GetPropertyName(() => Environment.CurrentDirectory), Environment.CurrentDirectory));
      this.Items.Add(new KeyValuePair<string, string>(ReflectionUtility.GetPropertyName(() => Environment.MachineName), Environment.MachineName));
      this.Items.Add(new KeyValuePair<string, string>(ReflectionUtility.GetPropertyName(() => Environment.OSVersion), Environment.OSVersion.ToString()));
      this.Items.Add(new KeyValuePair<string, string>(ReflectionUtility.GetPropertyName(() => Environment.Version), Environment.Version.ToString()));
      this.Items.Add(new KeyValuePair<string, string>(ReflectionUtility.GetPropertyName(() => Environment.UserName), Environment.UserName));
      this.Items.Add(new KeyValuePair<string, string>(ReflectionUtility.GetPropertyName(() => Environment.UserDomainName), Environment.UserDomainName));
      this.Items.Add(new KeyValuePair<string, string>(ReflectionUtility.GetPropertyName(() => Environment.ProcessorCount), Environment.ProcessorCount.ToString()));

      foreach (string name in Enum.GetNames(typeof(Environment.SpecialFolder)))
         this.Items.Add(new KeyValuePair<string, string>(name, Environment.GetFolderPath((Environment.SpecialFolder)Enum.Parse(typeof(Environment.SpecialFolder), name))));

      this.Items.Add(new KeyValuePair<string, string>("Logical Drives", string.Join("; ", Environment.GetLogicalDrives())));

      ParseEnvironmentVariables(EnvironmentVariableTarget.Machine);
      ParseEnvironmentVariables(EnvironmentVariableTarget.Process);
      ParseEnvironmentVariables(EnvironmentVariableTarget.User);
   }

   /// <summary>
   /// Parses the environment variables in the context of @target.
   /// </summary>
   /// <param name="target">The target.</param>
   private void ParseEnvironmentVariables(EnvironmentVariableTarget target)
   {
      foreach (DictionaryEntry item in Environment.GetEnvironmentVariables(target))
      {
         this.Items.Add(new KeyValuePair<string, string>(item.Key.ToString(), item.Value.ToString()));
      }
   }
   #endregion Methods

   #region Event Handlers
   #endregion Event Handlers

   #region Ctors
   /// <summary>
   /// Initializes a new instance of the <see cref="EnvironmentList"/> class.
   /// </summary>
   public EnvironmentList()
   {
      this.Items = new List<KeyValuePair<string, string>>();
      this.BuildDictionary();
   }
   #endregion Ctors
}

/// <summary>
/// Reflection Utility Class
/// <see cref="http://handcraftsman.wordpress.com/2008/11/11/how-to-get-c-property-names-without-magic-strings/"/>
/// </summary>
public static class ReflectionUtility
{
   /// <summary>
   /// Gets the name of the property.
   /// </summary>
   /// <typeparam name="T"></typeparam>
   /// <param name="expression">The expression.</param>
   /// <returns></returns>
   public static string GetPropertyName<T>(Expression<Func<T>> expression)
   {
      MemberExpression body = (MemberExpression)expression.Body;
      return body.Member.Name;
   }
}
To use the class, instantiate the EnvironmentList object and enumerate the Items property.

Console:
EnvironmentList el = new EnvironmentList();
Array.ForEach(el.Items.ToArray(), i => Console.Out.WriteLine("{0}: {1}{2}", i.Key, i.Value, Environment.NewLine));
Web:

Add a GridView to the markup and bind the grid on page load:
<asp:GridView runat="server" id="gv"/>
EnvironmentList el = new EnvironmentList();
this.gv.DataSource = el.Items;
this.gv.DataBind();
Nothing Earth shattering here, but a nice utility if you need to view the properties of the System.Environment class for the current environment.

Thanks for reading...

Wednesday, July 28, 2010

UPDATE STATISTICS for all database tables

/***** BEGIN - UPDATE STATISTICS *****/
DECLARE @t TABLE(RowID INT IDENTITY(1,1), SchemaName VARCHAR(128), TableName VARCHAR(128))

INSERT INTO @t(SchemaName, TableName)
SELECT t.TABLE_SCHEMA, t.TABLE_NAME FROM INFORMATION_SCHEMA.TABLES t
WHERE t.table_type = 'BASE TABLE'

DECLARE @Rows INT, @i INT;

SELECT @Rows = (SELECT COUNT(RowID) FROM @t), @i = 1;

WHILE(@i <= @Rows)
BEGIN
 DECLARE @sqlCommand NVARCHAR(512);

 SELECT @sqlCommand =
     'UPDATE STATISTICS ' +
     t.SchemaName + '.' +
     t.TableName +
     ' WITH FULLSCAN'
 FROM @t t
 WHERE t.RowID = @i;

 PRINT @sqlCommand
 EXEC sp_executesql @sqlCommand;

 SET @i = @i + 1;
END
GO
/***** END - UPDATE STATISTICS *****/

Wednesday, July 21, 2010

WCF Communications using wsHttpBinding with Username Authentication and TransportWithMessageCredentials

It's always a good idea to secure the transport medium and require authentication when invoking Enterprise-Level Web Services.  In the .NET World, these services are WCF - Windows Communications Foundation.

The challenge with WCF is all the required configuration and getting it right - at least for me...  Another challenge is choosing the right Authentication implementation.

In my specific scenario, we have a partner system that communicates with a WCF service.  The parter system is just that - a system.  With respect to Authentication, you may be thinking that the obvious choice is Windows Authentication.  Well, network engineers typically cringe when your requirement requires them to create Window's accounts for service-based transactions.  In all fairness, creating a bunch of Windows Accounts for services can become maintenance nightmare, so I wouldn't necessarily disagree with the network engineers' concerns.

So, what are the alternatives?  Create you own authentication implementation?  Probably not a good idea!  What does ASP.NET use?  That's right, ASP.NET uses the Membership Provider design pattern.  Microsoft provides two two out-of-box Membership Providers: SQLMembershipProvider (SQL Server table-based accounts), and ActiveDirectoryMembershipProvider (Windows account/Active Directory).

In my scenario, the ActiveDirectoryMembershipProvider presents the same challenges as Windows Authentication.  My network engineers would still need to create Windows accounts.  As for the SQLMembershipProvider, creating, implementing, and maintaining a SQL Server to authenticate and authorize a service request is a bit overkill (IMHO).  So, what how did I ultimately implement my solution?  Good question...

I used a composite implementation using Microsoft's WCF Implementation Guidance How to article 'How to: Use wsHttpBinding with Username Authentication and TransportWithMessageCredentials in WCF Calling from Windows Forms' and the open source ASP.NET XMLProviders project hosted on CodePlex.  I'm very happy with this implementation.

Thanks for reading...

Tuesday, June 15, 2010

Just Published The IconizedButton Control Set on CodePlex

Open the floor for criticism... I just published an open source control library on CodePlex titled IconizedButton Control Set. CodePlex description: Replaces the dull Button/LinkButton/HyperLink controls with styling and left and right aligned icons (via FamFamFam icon set). Contains built-in control styles/skins. Available customized user-configured styles/skins via CSS.

The IconizedButton Control Set documentation is location here.

I hope someone find the control library helpful and useful.

I'd appreciate any feedback you can provide.

Thanks for reading...

IconizedButton ASP.NET Control Set Documentation

Iconized Button Documentation

Contents

  • Summary
  • Goals
  • Features
  • Properties
  • Examples
  • Customization
  • Configuration
  • Known Issues (and Solutions)
  • Design (and Performance) Considerations
  • Credits
  • Downloads

Summary

IconizedButton is an ASP.NET Web Forms control set providing buttons and hyperlink controls with icons and styles. IconizedButton extends the standard ASP.NET LinkButton control, while IconizedHyperLink extends the standard ASP.NET Hyperlink. Extending the standard controls makes using the IconizedButton controls painless and familiar. Use the controls as if they were the standard controls.

Goals

  • Extend the standard ASP.NET control to include icons and skinning (without including user-defined resources);
  • no JavaScript dependencies; however, allow the user to include scripting;
  • easy deployment and integration is existing/new Web Projects;
  • light (as possible) footprint; and,
  • those features included in the 'Features' section.
  • Include text or Solo (no text) buttons

Features

  • Visual Studio Integration and Design Support
  • Buttons and hyperlinks with icons - ~ 1000 included icons (see FamFamFam in 'Credits' below)
  • Built-In Button Skinning - 20 skins
  • Button with or without text
  • Left or right align the icons (relative to the button text)

Properties

VS Properties
  • ButtonSkin : enumeration of button skins - Skin the button using one of 20 built-in skins, or set to 'Custom' and use your own via CSS. See 'Customization' section for more information on customizing the button using user-defined styles and icons.
  • CustomCssClass : string - Add custom button skinning and/or additional CSS classes.
  • CustomIconType : string - Set this property to your own custom icon via CSS class. IconType property must be equal to IconType.Custom or this property will be ignored.
  • DisplyMouseOutStyle : boolean - Whether (or not) to display the background skin/style on mouse out - meaning no initial background and no background on mouse out.
  • IconPosition : enumeration of icon positioning - Positions the icon. Enum values:

    • None - no icon. Button with text only.
    • Left - left align the icon relative to the button text.
    • Right - right align the icon relative to the button text.
    • Solo - icon only button.
    • SmallSolo - icon only button with a smaller footprint than the Solo value.
  • IconType : enumeration of icon types - Choose from ~1000 icons to render with the button.
  • RoundCorners : boolean - Whether (or not) the button should render with round corners. Implemented via CSS3; therefore, no available in IE.

Examples

  • The project page on CodePlex - IconizedButton - contains a sample Web application that you can download and use to test/sample the control set.
  • The following markup gives you the IconizedButton in the screenshot:

    <shp:IconizedButton 
                        runat="server" 
                        id="ibReturnHome" 
                        Text="Return Home" 
                        ButtonSkin="OfficeBlue" 
                        IconPosition="Left" 
                        IconType="HouseGo" 
                        RoundCorners="true"                            
                    />
                    
    IconizedButton Screenshot

Customization

  • The following markup gives you the customized IconizedButton in the screenshot (shout out to the troops). Custom styles and images are included in the sample Web application on CodePlex.

    <shp:IconizedButton
                        runat="server" 
                        id="ibArmyStrong" 
                        IconType="Custom" 
                        IconPosition="Left" 
                        ButtonSkin="Custom" 
                        CustomIconType="army-of-one" 
                        CustomCssClass="army" 
                        Text="Army Strong"                          
                    />
                    
    IconizedButton Screenshot

Configuration

  • Toolbox - IconizedButton control set can be added to the Visual Studio Toolbox. IconButton controls have their own icons that will help identify the controls from other controls in your toolbox.

    VS Toolbox
  • Page/User Control Registration - Dragging and dropping a control from the toolbox (like standard ASP.NET controls) will add the control to the page/user control. It will register the IconizedButton control on the top of the page/user control.
  • web.config Registration - for site/project wide registration, register the IconizedButton control set in the web.config as a child element of the <pages><controls></controls></pages> element.

    <add tagPrefix="shp" namespace="Shp.Web.UI.WebControls.Iconized" assembly="Shp.Web.UI.WebControls.Iconized"/>

Known Issues (and Solutions)

  • The button set controls are floated left (float: left). This means that you must clear the float in a container control. Or use a clearfix implementation - my favorite is from Perishable Press

Design (and Performance) Considerations

  • Button Skin Sprites - The button skins are image sprites. This helps minimize HTTP traffic and increases server and client performance. For more info, check this link out: CSS Sprites: What They Are, Why They're Cool, and How To Use Them
  • Icons are NOT Sprites - I created sprites for the icons categorized by alphabetical groups. While this task was tedious and time consuming, the resulting image files got a bit big for my taste (each sprite ~ 25 KB), so I decides to go with one image file per icon (~600 B). E.g. Lets say you had three iconized button on your page. The IconTypes started with 'A', 'C', and 'S' respectively. Using the sprite implementation, the resource hit would be ~ 75 KB, while using individual icon images, your resource hit would be ~ 1.8 KB. Make sense? A design decision that I didn't take lightly.
  • No JavaScript - One of my goals was to have no JavaScript dependencies. Understanding that the .NET Framework will add JavaScript to perform PostBacks, validations, etc..., IconizedButton control set adds no additional JavaScript resources. This also helps when the user/developer wants to customize the buttons an not have to hack around JavaScript dependencies. Just use the buttons (and additional JavaScript) as you would use LinkButton and HyperLink controls.
  • Visual Studio Designer - Selecting an IconType will display a default icon for the control. During the IconizedButton control set development, rendering the icon associated with the IconType gave me the infamous Visual Studio design-time delay. The design time delay (the pause in Visual Studio while it retrieves, processes, and renders a resource) is probably my biggest gripe with Visual Studio. I love the IDE; however, this really annoys me. Rendering only a default icon at design-time significantly improves design-time performance.

Credits

  • The icons are designed, developed, and licensed by Mark James of FamFamFam. The specific FamFamFam library of icons used in the IconizedButton control set is the Silk Icon set. If you need icons for your application, check out FamFamFam. FamFamFam icons are licensed under the Creative Commons Attribution 3.0 License.

Downloads

Friday, June 11, 2010

Test code for my previous post Telerik RadWindow Client-Side Content Container.  Sorry, the formatting is a little off.
CSS:
ul#actionList, ul#actionList li {margin: 0; padding: 0; list-style: none; line-height: 20px;}
ul#actionList { margin: 5px 10px; } ul#actionList li { margin-bottom: 5px; }
div#echoConsole { margin: 20px; border: 1px solid #ababab; background-color: #fbfec2; padding: 5px; }
p { padding: 5px; margin: 0; font-family: Arial; font-size: 12px; }
.mar-b-10 {margin-bottom: 10px;}
   
JavaScript:
$(document).ready(function() {
      // attach the click event to the buttons - button will open the new RadWindow dialog
      $('ul#actionList button').click(function(e) {
         e.preventDefault();
         var btnID = $(this).get(0).id;
         switch (parseInt(btnID.substring(btnID.length - 1))) {
            case 0:
               radWindowExtensions.openDialog({ width: 400, height: 400, title: 'This is the Dialog Title', content: $('div#hiddenDiv'), resizable: false, onOpen: dialogHandlers.onOpen, onClosing: dialogHandlers.onClosing, onClosed: dialogHandlers.onClosed });
               break;
            case 1:
               radWindowExtensions.openDialog({ width: 500, height: 600, title: 'This is the Dialog Title', content: $('div#hiddenDiv').html(), resizable: true, onOpen: dialogHandlers.onOpen, onClosing: dialogHandlers.onClosing, onClosed: dialogHandlers.onClosed });
               break;
            case 2:
               radWindowExtensions.openDialog({ xPos: '100', yPos: 10, onOpen: dialogHandlers.onOpen, onClosing: dialogHandlers.onClosing, onClosed: dialogHandlers.onClosed });
               break;
            case 3:
               radWindowExtensions.openDialog();
               break;
         }
      });
   });

   // test handlers object - will echo event handler messages to a div tag
   var dialogHandlers = {
      _getConsole: function() { if (!dialogHandlers._console) { dialogHandlers._console = $('div#echoConsole').show(); } return dialogHandlers._console; },
      _echo: function(msg) { var c = dialogHandlers._getConsole(); c.append($('<div/>').addClass('mar-b-10').html(msg)); },
      onOpen: function(content) {
         // use onOpen event handler to modify the content - e.g. add event handlers to buttons, etc...
         dialogHandlers._echo('onOpen event fired on RadWindow with ID of ' + this.get_name());
         $(content).find('p:first').css('color', 'red');
      },         
      onClosing: function(content) {
         // use onClosing event handler to clean up content - e.g. unbind event handlers.
         dialogHandlers._echo('onClosing event fired on RadWindow with ID of ' + this.get_name());            
         dialogHandlers._echo('number of paragraphs: ' + $(content).find('p').size());
      },
      onClosed: function(content) {
         dialogHandlers._echo('onClosed event fired on RadWindow with ID of ' + this.get_name());
         dialogHandlers._echo('number of paragraphs: ' + $(content).find('p').size());
      }
   };
HTML:
  • Content set to a jQuery wrapped object, non-resizable
  • Content set to HTML
  • No Content, positioned dialog
  • No Content, no options (default) dialog
Morbi scelerisque urna aliquam sapien dictum eget lacinia justo eleifend. Morbi eu nibh nibh? Morbi non justo id magna fermentum accumsan. Donec nunc mi, facilisis a venenatis eu, congue in ligula? Praesent nisl turpis, aliquet vitae eleifend non, auctor id erat. Nam a felis ac mauris ornare lacinia. Cras a massa sit amet leo tempor tincidunt. Curabitur pellentesque enim id est porta ornare. Morbi orci leo, sodales et lobortis vel, egestas at magna. Nam a nisi odio, suscipit ullamcorper quam. Pellentesque ullamcorper est vel quam blandit vel laoreet libero euismod. Nam orci sem, condimentum id interdum feugiat, laoreet nec mi. Duis varius cursus dolor id porttitor. Nulla id ligula sit amet leo imperdiet sollicitudin. Donec pulvinar, sem quis condimentum pellentesque, orci nisl placerat tellus, at egestas ante arcu nec lectus. Nullam cursus porta molestie. Sed in auctor metus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Fusce volutpat vestibulum erat quis ultrices.

Telerik RadWindow Client-Side Content Container

Telerik RadControls for ASP.NET AJAX is a powerful set of .NET controls for Web Forms (they also have control sets for MVC, Silverlight, Windows Forms, WPF, and other productivity tools).  We use 'RadControls' all the time.  RadControls provide near Windows Forms-based controls functionality.  The RAD ability of RadControls is untouchable.

The caveat with RadControls is that if you want to go out-of-box Telerik box and extend the functionality or use it in a way that different for the Telerik way of developing Web interface, you're often let down after hours of 'trying' to make the controls work 'your' way.  Case in-point: RadWindow.

RadWindow is your basic inline popup that provide an IFRAME for rendering external content.  Until last year, displaying inline content (Telerik describes it at 'internal content') where the RadWindow's source is not an external page was close to impossible.  Rendering inline content in a RadWindow still isn't documented all that well.

I'll save you the details on the Telerik recommended solution to providing inline content (you can read about it here and somewhere in here).  Well, you've probably realized that this did not meet my requirements.  I wanted to have client-side RadWindow support to render dialogs with content retrieved from Web services, inline hidden elements, JavaScript, etc...  So, I created a small library that I can include as a reference in my pages to give me my desired functionality.

Before I post my solution, I need to give you a quick background on my design and code structure for Web Forms.  I tend to have a Master Page that includes common libraries (jQuery, Telerik Core, project specific, etc...).  When I use RadWindows I add a RadWindowsManager to my Master Page.  This provides all the Telerik RadWindow client-side libararies that I need.  My Master Pages also implement an Interface that contain references to .NET controls on the Master Page.  This gives Page controls type-safe access to the Master Page and the controls contained with in the Master Page.

So, here's the code.  It's fully documented, so you shouldn't have a problem using it.

/*
* File Name: telerik.radwindow.extensions.js
* Requirements:
* - Telerik.Web.UI.RadWindowManager client-side library
*   - adding a RadWindowManager control to the top of the page will add all the necessary libraries, include Telerik Core and jQuery.
*/

// namespace this libarary to avoid namespace clashes.
var radWindowExtensions = (radWindowExtensions || {});

radWindowExtensions.openDialog = function(options) { /* @options: extend the 'defaults' object map of the function. */
   // get the rad window manager - throw exception if RadWindowManager client-side library is not loaded.
   var rwm = null; try { rwm = GetRadWindowManager(); } catch (e) { throw new Error('Telerik.Web.UI.RadWindowManager client-side library is not loaded.'); }
   var defaults = {
      width: 500, /* outer width of rad window */
      height: 500, /* outer height of rad window */
      modal: true, /* is modal? */
      center: true, /* center rad window? */
      resizable: true, /* is rad window resizable? */
      title: '', /* rad window title */
      content: '', /* rad window content */
      xBorderSize: 16, /* the size of the horizontal borders */
      yBorderSize: 61, /* the size of the vertical borders */
      xPos: Number.NaN, /* x-position of the rad window */
      yPos: Number.NaN, /* y-position of the rad window */
      // event handler 'this' reference is to the current RadWindow.  @content parameter is a reference to the jQuery wrapped content
      onOpen: function(content) { }, /* onOpen event handler */
      onClosing: function(content) { }, /* onClosing event handler */
      onClosed: function(content) { } /* onClosed event handler */
   };
   // merge @options with default settings
   options = $telerik.$.extend({}, defaults, (options) ? options : {});

   // parse the x and y positions
   options.xPos = parseInt(options.xPos); options.yPos = parseInt(options.yPos);

   // create a rad new window (and open - this is required)
   var win = rwm.open(null, null);

   // remove the iframe from the default rad window
   $(win._iframe).remove();

   // render the window as modal
   if (options.modal) { win.set_modal(options.modal); }

   // set the window width
   win.set_width(options.width);

   // set the window height
   win.set_height(options.height);

   // set the window xy coordinates or center the window or use default positioning
   if ((!isNaN(options.xPos)) && (!isNaN(options.yPos))) win.moveTo(options.xPos, options.yPos);
   else if (!!options.center) win.center();

   // set the window title
   win.set_title(options.title);

   // create the content and wrap in a parent div
   var $content = $telerik.$('<div></div>').width(options.width - options.xBorderSize).height(options.height - options.yBorderSize).css('overflow', 'auto').append(options.content);
// destroy on close
   win.set_destroyOnClose(true);

   // add onClosing and onClosed event handlers
   win.add_beforeClose(function() { options.onClosing.call(win, $content); });
   win.add_close(function() { options.onClosed.call(win, $content); });

   // set the window behaviors (Move and Close)
   win.set_behaviors(Telerik.Web.UI.WindowBehaviors.Move + Telerik.Web.UI.WindowBehaviors.Close + ((!!options.resizable) ? Telerik.Web.UI.WindowBehaviors.Resize : 0));

   // add the wrapped content to the rad window - use the set_contentElement(content) function
   setTimeout(function() {
      win.set_contentElement($content.get(0));
      // fire the onOpen event handler
      if (options.onOpen) options.onOpen.call(win, $content);
   }, 0);
};

When using this library, I use a minimized version of the file.  To minimize JavaScript and CSS files, I use Yahoo! UI Compressor Library: YUI Compressor for .NET located on CodePlex or I use the Online YUI Compressor located here.

EDIT:  the formatting for the JavaScript above is parsed incorrectly and displaying two code blocks.  If you are copying and pasting the code, copy both blocks and create a single code file.  Sorry about that...

Thanks for reading...

Thursday, June 10, 2010

Redirect to HTTPS

I got asked a question today from one of my System Engineers with respect to redirecting HTTP traffic to HTTPS.  The Web server is IIS, but it shouldn't make a difference.
Explicit Requirements:
  • Web Server Global Redirect (vs. per individual Web application).
  • Present to the user a generic message stating that the URI has changed and suggesting to the user update any associated bookmarks.
  • Minimize any IIS metabase modifications.
Implicit Requirements:
  • Web request discovery so that redirect is identical to the original request with the exception of the protocol - this eliminates a metadata redirect.
  • Redirect delay - present the user with the aforementioned redirect and once a configured delay has expired, redirect the user using the secure protocol.
Solution:
Searching around the Internet, I found a few excellent examples; however, I could not find a solution that fulfilled all of our requirements, so I designed a solution. We decided to create a custom 403 error page.  This error page includes the aforementioned generic message  and some JavaScript  for redirect.  The JavaScript includes an optional parameter for redirect delay.  The JavaScript implementation is below:
var rdcore = {
    redirectToSsl: function(delay){ /* @delay:int or null - delay in seconds before the redirect is executed. */
        delay = (delay) ? (delay * 1000) : 0;
        setTimeout(function(){
            var oldUrl = window.location.hostname + window.location.pathname + window.location.search;
            window.location = 'https://' + oldUrl;
        }, delay);
    }
};
// parameter is the delay in seconds (integer or null) before the redirect is executed.
rdcore.redirectToSsl(10);

Monday, June 7, 2010

SSRS - SQL Server Reporting Server - External Image Issue (and Solution)

The other day I encountered some complicated issues with SQL Server Reporting Server (SSRS) and including external images from a file store that was not directly accessible to users (or SSRS).  I've always assumed that the credentials that you pass to SSRS to generate reports where the contextual credentials in which the reports were generated (aka impersonation).  Well, that assumption FAILED to materialize.

The intent of this post is to hopefully assist others with similar issues and to document my findings for future use and reference.

So, here the scenario and configuration (all in a TEST environment which parallels the PRODUCTION environment):
  • Box 1: Web Server
    • IIS 6
    • Web App: MyWebApp
    • File Store Virtual Directory: MyWebAppFileStoreVd
  • Box 2: SQL Server
  • Box 3: SSRS
  • Box 4: File Store
    • MyWebApp File Store: MyWebAppFileStore
As a developer, I had access to the file store (Windows permissions).  So, while creating reports in Visual Studio's Report Designer with hard coded image paths (for testing, because dynamic wasn't working - this is the issue), I could view the images in the report.  However, once the reports were deploy to SSRS, the image placeholders contained no path information and the infamous 'red X.'  This was also the case when the report was request and render via the Web app.

Ahhhh!  What's the problem?  The file store contained permissions for the SSRS user with the credentials passed to SSRS from the Web app.  After a couple of day of 'banging head on desk, computer, floor, etc...), I had an epiphany - maybe the SSRS user is not impersonated???  That was it - the user is NOT impersonated!  Reports are actually generated via the service account of SSRS - this makes perfect sense now; however, I had always assumed that impersonation was taking place.  I digress...

I've read that Microsoft's solution is to run the SSRS service as a domain account and give that domain account whatever permissions it needs on the file store.  Well, that is NOT a solution in our environment.  So, what did we do to solve the issue?  Well, we...

We decided to create a virtual directory on the Web Server (Box 1) that points to the aforementioned File Store (Box 4) and restricts access (over http) to a specific computer via IP - the SSRS IP (Box 3).  This essentially creates a File Store (Box 4) web share proxy on the Web Server (Box 1) accessible only to SSRS (Box 3) over http.

The following is the process and associated steps taken to successfully enable this scenario:
  1. Create a Virtual Directory outside of the MyWebApp Virtual Directory that points to the MyWebAppFileStore File Store - /MyWebAppFileStoreVd/
  2. Set MyWebAppFileStoreVd Virtual Directory’s Directory Security to ‘Enable Anonymous Access’ and clear all ‘Authenticated Access’ checkboxes.
    1. Virtual Directory Properties -- Directory Security Tab - Edit button (red highlighted button).

    2. Check the ‘Enable Anonymous Access’ checkbox.
    3. Clear ‘Authenticated Access’ checkboxes.
    4. Click ‘Ok’ and then ‘Apply.’

  3. Restrict access by the Report Server’s IP.
    1. Virtual Directory Properties -- Directory Security Tab -- Edit button (green highlighted button).

    2. Select the ‘Denied Access’ radio button within the ‘IP Address Access Restrictions’ group box.
    3. Click the ‘Add…’ button.

    4. Select the ‘Single Computer’ radio button in the ‘Grant Access’ dialog box.
    5. Enter the Report Server’s IP address in the IP Address masked textbox.

    6. Click ‘Ok’, ‘Ok’, ‘Apply’, and ‘Ok.’
That should about do it...

While this implementation works and works well for my specific scenario, this may not be the best implementation for your specific scenario.  I hope that this post saves at least one person the hours of troubleshooting and headaches that I incurred getting the implementation to work...

Thanks for reading...

Monday, May 17, 2010

Drop All Schemas in a SQL Server Database

This post extends my previous post Drop All Objects in a SQL Server Database and drops all non-system related Schemas in a database.
/***** BEGIN - DROP SCHEMAs *****/
DECLARE @name VARCHAR(128), @sqlCommand NVARCHAR(1000), @Rows INT = 0, @i INT = 1;
DECLARE @t TABLE(RowID INT IDENTITY(1,1), ObjectName VARCHAR(128));

INSERT INTO @t(ObjectName)
SELECT s.[SCHEMA_NAME] FROM INFORMATION_SCHEMA.SCHEMATA s
WHERE s.[SCHEMA_NAME] NOT IN('dbo', 'guest', 'INFORMATION_SCHEMA', 'sys', 'db_owner', 'db_accessadmin', 'db_securityadmin', 'db_ddladmin', 'db_backupoperator', 'db_datareader', 'db_datawriter', 'db_denydatareader', 'db_denydatawriter')

SELECT @Rows = (SELECT COUNT(RowID) FROM @t), @i = 1;

WHILE (@i <= @Rows) 
BEGIN
    SELECT @sqlCommand = 'DROP SCHEMA [' + t.ObjectName + '];', @name = t.ObjectName FROM @t t WHERE RowID = @i;
    EXEC sp_executesql @sqlCommand;        
    PRINT 'Dropped SCHEMA: [' + @name + ']';    
    SET @i = @i + 1;
END
GO
/***** END - DROP SCHEMAs *****/

Drop All Objects in a SQL Server Database

The following SQL script is similar to Paige Cook's Drop All Objects in a SQL Server Database; however, is if fully INFORMATION_SCHEMA based and supports Schema-based objects (e.g. SchemaName.TableName).
/***** BEGIN - DROP non-sys PROCs *****/
DECLARE @schema VARCHAR(128), @name VARCHAR(128), @sqlCommand NVARCHAR(1000), @Rows INT = 0, @i INT = 1;
DECLARE @t TABLE(RowID INT IDENTITY(1,1), SchemaName VARCHAR(128), ObjectName VARCHAR(128));

INSERT INTO @t(SchemaName, ObjectName)
SELECT r.ROUTINE_SCHEMA, r.SPECIFIC_NAME
FROM INFORMATION_SCHEMA.ROUTINES r
WHERE r.ROUTINE_TYPE = 'PROCEDURE'
ORDER BY r.ROUTINE_SCHEMA, r.ROUTINE_NAME

SELECT @Rows = (SELECT COUNT(RowID) FROM @t), @i = 1;

WHILE (@i <= @Rows) 
BEGIN
    SELECT @sqlCommand = 'DROP PROC [' + t.SchemaName + '].[' + t.ObjectName + '];', @schema = t.SchemaName, @name = t.ObjectName FROM @t t WHERE RowID = @i;
    EXEC sp_executesql @sqlCommand;        
    PRINT 'Dropped PROC: [' + @schema + '].[' + @name + ']';    
    SET @i = @i + 1;
END
GO
/***** END - DROP non-sys PROCs *****/

/***** BEGIN - DROP FUNCTIONs *****/
DECLARE @schema VARCHAR(128), @name VARCHAR(128), @sqlCommand NVARCHAR(1000), @Rows INT = 0, @i INT = 1;
DECLARE @t TABLE(RowID INT IDENTITY(1,1), SchemaName VARCHAR(128), ObjectName VARCHAR(128));

INSERT INTO @t(SchemaName, ObjectName)
SELECT r.ROUTINE_SCHEMA, r.SPECIFIC_NAME
FROM INFORMATION_SCHEMA.ROUTINES r
WHERE r.ROUTINE_TYPE = 'FUNCTION'
ORDER BY r.ROUTINE_SCHEMA, r.ROUTINE_NAME

SELECT @Rows = (SELECT COUNT(RowID) FROM @t), @i = 1;

WHILE (@i <= @Rows) 
BEGIN
    SELECT @sqlCommand = 'DROP FUNCTION [' + t.SchemaName + '].[' + t.ObjectName + '];', @schema = t.SchemaName, @name = t.ObjectName FROM @t t WHERE RowID = @i;
    EXEC sp_executesql @sqlCommand;        
    PRINT 'Dropped FUNCTION: [' + @schema + '].[' + @name + ']';    
    SET @i = @i + 1;
END
GO
/***** END - DROP FUNCTIONs *****/

/***** BEGIN - DROP VIEWs *****/
DECLARE @schema VARCHAR(128), @name VARCHAR(128), @sqlCommand NVARCHAR(1000), @Rows INT = 0, @i INT = 1;
DECLARE @t TABLE(RowID INT IDENTITY(1,1), SchemaName VARCHAR(128), ObjectName VARCHAR(128));

INSERT INTO @t(SchemaName, ObjectName)
SELECT t.TABLE_SCHEMA, t.TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES t
WHERE t.TABLE_TYPE = 'VIEW'
ORDER BY t.TABLE_SCHEMA, t.TABLE_NAME

SELECT @Rows = (SELECT COUNT(RowID) FROM @t), @i = 1;

WHILE (@i <= @Rows) 
BEGIN
    SELECT @sqlCommand = 'DROP VIEW [' + t.SchemaName + '].[' + t.ObjectName + '];', @schema = t.SchemaName, @name = t.ObjectName FROM @t t WHERE RowID = @i;
    EXEC sp_executesql @sqlCommand;        
    PRINT 'Dropped VIEW: [' + @schema + '].[' + @name + ']';    
    SET @i = @i + 1;
END
GO
/***** END - DROP VIEWs *****/

/***** BEGIN - DROP FOREIGN KEY CONSTRAINTs *****/
DECLARE @schema VARCHAR(128), @name VARCHAR(128), @tableSchema VARCHAR(128), @tableName VARCHAR(128), @sqlCommand NVARCHAR(1000), @Rows INT = 0, @i INT = 1;
DECLARE @t TABLE(RowID INT IDENTITY(1,1), SchemaName VARCHAR(128), ObjectName VARCHAR(128), TableSchema VARCHAR(128), TableName VARCHAR(128));

INSERT INTO @t(SchemaName, ObjectName, TableSchema, TableName)
SELECT tc.CONSTRAINT_SCHEMA, tc.CONSTRAINT_NAME, tc.TABLE_SCHEMA, tc.TABLE_NAME
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc
WHERE (tc.CONSTRAINT_CATALOG = DB_NAME()) AND (tc.CONSTRAINT_TYPE = 'FOREIGN KEY')
ORDER BY tc.TABLE_SCHEMA, tc.TABLE_NAME, tc.CONSTRAINT_SCHEMA, tc.CONSTRAINT_NAME

SELECT @Rows = (SELECT COUNT(RowID) FROM @t), @i = 1;

WHILE (@i <= @Rows) 
BEGIN
    SELECT @sqlCommand = 'ALTER TABLE [' + t.TableSchema + '].[' + t.TableName + '] DROP CONSTRAINT [' + t.ObjectName + '];', 
        @schema = t.SchemaName, @name = t.ObjectName, @tableSchema = t.TableSchema, @tableName = t.TableName
    FROM @t t WHERE RowID = @i;
    EXEC sp_executesql @sqlCommand;        
    PRINT 'Dropped FOREIGN KEY CONSTRAINT: ' + @name + ' on [' + @tableSchema + '].[' + @tableName + ']';
    SET @i = @i + 1;
END
GO
/***** END - DROP FOREIGN KEY CONSTRAINTs *****/

/***** BEGIN - DROP PRIMARY KEY CONSTRAINTs *****/
DECLARE @schema VARCHAR(128), @name VARCHAR(128), @tableSchema VARCHAR(128), @tableName VARCHAR(128), @sqlCommand NVARCHAR(1000), @Rows INT = 0, @i INT = 1;
DECLARE @t TABLE(RowID INT IDENTITY(1,1), SchemaName VARCHAR(128), ObjectName VARCHAR(128), TableSchema VARCHAR(128), TableName VARCHAR(128));

INSERT INTO @t(SchemaName, ObjectName, TableSchema, TableName)
SELECT tc.CONSTRAINT_SCHEMA, tc.CONSTRAINT_NAME, tc.TABLE_SCHEMA, tc.TABLE_NAME
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc
WHERE (tc.CONSTRAINT_CATALOG = DB_NAME()) AND (tc.CONSTRAINT_TYPE = 'PRIMARY KEY')
ORDER BY tc.TABLE_SCHEMA, tc.TABLE_NAME, tc.CONSTRAINT_SCHEMA, tc.CONSTRAINT_NAME

SELECT @Rows = (SELECT COUNT(RowID) FROM @t), @i = 1;

WHILE (@i <= @Rows) 
BEGIN
    SELECT @sqlCommand = 'ALTER TABLE [' + t.TableSchema + '].[' + t.TableName + '] DROP CONSTRAINT [' + t.ObjectName + '];', 
        @schema = t.SchemaName, @name = t.ObjectName, @tableSchema = t.TableSchema, @tableName = t.TableName
    FROM @t t WHERE RowID = @i;
    EXEC sp_executesql @sqlCommand;        
    PRINT 'Dropped PRIMARY KEY CONSTRAINT: ' + @name + ' on [' + @tableSchema + '].[' + @tableName + ']';
    SET @i = @i + 1;
END
GO
/***** END - DROP PRIMARY KEY CONSTRAINTs *****/

/***** BEGIN - DROP TABLEs *****/
DECLARE @schema VARCHAR(128), @name VARCHAR(128), @sqlCommand NVARCHAR(1000), @Rows INT = 0, @i INT = 1;
DECLARE @t TABLE(RowID INT IDENTITY(1,1), SchemaName VARCHAR(128), ObjectName VARCHAR(128));

INSERT INTO @t(SchemaName, ObjectName)
SELECT t.TABLE_SCHEMA, t.TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES t
WHERE t.TABLE_TYPE = 'BASE TABLE'
ORDER BY t.TABLE_SCHEMA, t.TABLE_NAME

SELECT @Rows = (SELECT COUNT(RowID) FROM @t), @i = 1;

WHILE (@i <= @Rows) 
BEGIN
    SELECT @sqlCommand = 'DROP TABLE [' + t.SchemaName + '].[' + t.ObjectName + '];', @schema = t.SchemaName, @name = t.ObjectName FROM @t t WHERE RowID = @i;
    EXEC sp_executesql @sqlCommand;        
    PRINT 'Dropped TABLE: [' + @schema + '].[' + @name + ']';    
    SET @i = @i + 1;
END
GO
/***** END - DROP TABLEs *****/

SyntaxHighlighter 2.0 integration with Blogger

Link to a clear, concise, and complete tutorial on how to integrate the SyntaxHighlighter 2.0 library with Blogger: Syntax Highlighting with Blogger Engine