Archive for the ‘tips and tricks’ Category

How to TWEET from a SQL CLR Stored Procedure

Here’s another SQL Server 2005 geek out moment, a CLR SPROC that tweets to Twitter. Big shoutout to Danny Battison for sharing the C# code to post to Twitter. This is what got me started on the C# side of things.  Also, you can skip all my ramblings here and just download code here and fire it up.  The zip file contains all the source code, the compiled assembly file, and install.sql that shows you how to hook this up.

Being the SQL junky that I am, I was interested in trying out SQL Server’s new CLR Stored Procedures. A CLR sproc is a stored procedure that is able to use .net code that you’ve compiled into an assembly file. For you classic ASP heads out there, think of the ASP page being the sproc, and the .net assembly being your COM object ( cringe, let’s talk about classic ASP ). While there are plenty of great articles on writing CLR stored procedures, I’m going to breeze through the code that makes up this project.

First make a .net class library that will be compiled into an assembly file.

using System;
using Microsoft.SqlServer.Server;
using System.Data.SqlTypes;
using System.Net;
using System.IO;
using System.Text.RegularExpressions;

/// <summary>
/// This assembly will be used by a SQL2005 SPROC to communicate
/// with twitter.com
/// </summary>
public sealed class tweetsproc
{
    /*
     * TWITTER CODE BORROWED FROM :
     *  http://www.dreamincode.net/code/snippet2556.htm
     *
     * A function to post an update to Twitter programmatically
     * Author: Danny Battison
     * Contact: gabehabe@hotmail.com
     */

    /// <summary>
    /// Post an update to a Twitter acount
    /// </summary>
    /// <param name="username">The username of the account</param>
    /// <param name="password">The password of the account</param>
    /// <param name="tweet">The status to post</param>
    [Microsoft.SqlServer.Server.SqlProcedure(Name = "PostTweet")]
    //public static void PostTweet( string username, string password, string tweet)
    public static void PostTweet(   SqlString username,
                                    SqlString password,
                                    SqlString tweet)
    {
        try
        {
            // encode the username/password
            string user = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(username.ToString() + ":" + password.ToString()));
            // determine what we want to upload as a status
            byte[] bytes = System.Text.Encoding.ASCII.GetBytes("status=" + tweet.ToString());

            // Create a WebPermission.
            WebPermission myWebPermission1 = new WebPermission();

            // Allow Connect access to the specified URLs.
            myWebPermission1.AddPermission(NetworkAccess.Connect,new Regex("http://www\\.twitter\\.com/.*",
              RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline));

            myWebPermission1.Demand();

            // connect with the update page
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://twitter.com/statuses/update.xml");

            // set the method to POST
            request.Method = "POST";
            request.ServicePoint.Expect100Continue = false; // thanks to argodev for this recent change!
            // set the authorisation levels
            request.Headers.Add("Authorization", "Basic " + user);
            request.ContentType = "application/x-www-form-urlencoded";
            // set the length of the content
            request.ContentLength = bytes.Length;

            // set up the stream
            Stream reqStream = request.GetRequestStream();
            // write to the stream
            reqStream.Write(bytes, 0, bytes.Length);
            // close the stream
            reqStream.Close();

            // Let's get the Response from Twitter
            var webresp = request.GetResponse();
            // Let's read the Response
            var sread = new StreamReader( webresp.GetResponseStream() );

            // Use SqlContext to return data to the QueryAnalyzer results window
            SqlContext.Pipe.Send( sread.ReadToEnd() );

        }
        catch (Exception exc)
        {
            // send error back
            SqlContext.Pipe.Send(exc.Message);
        }
    }
}

Here’s the app.config for this assembly.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.web>
    <trust level="Full" processRequestInApplicationTrust="true" originUrl="" />
  </system.web>
</configuration>

Once you build this project, you should have your assembly ( tweetsproc.dll ) which will be used by your CLR Sproc. Now it’s time to do some SQL server work.

Enable CLR access for SQL server

EXEC sp_configure @configname = 'clr enabled', @configvalue = 1
RECONFIGURE WITH OVERRIDE
GO

Create the SQL Assembly

CREATE ASSEMBLY tweetsproc_clr_assembly from 'C:\Users\eric\Desktop\blog\tweetsproc.dll'
WITH PERMISSION_SET = EXTERNAL_ACCESS
GO

Create your SPROC

CREATE PROC tweetsproc_tweet(	@username as nvarchar(50),
								@password as nvarchar(50),
								@tweet as nvarchar(140)
							)
AS
	-- [Assembly Name].[Class Name].[CLR function Name]
	EXTERNAL NAME tweetsproc_clr_assembly.tweetsproc.PostTweet
GO

Tweet from a sproc

EXEC tweetsproc_tweet 'TwitterUsername', 'TwitterPassword', 'Hey @ericfickes, I''m tweeting from my database too!'

Running this sproc returns the XML response from Twitter.

Twitter response from tweet sproc

Tweetsproc returns the full Twitter response

That’s one sample CLR SPROC in the bank!  Feel free to download this code and try it out yourself.  I’d love to get some feedback on anybody looking to use this for real.  While tweeting from a stored procedure probably isn’t a hot topic for anybody, this is a nice teaser for what you can do with CLR sprocs now.

Download code here.

Inside this zip you’ll find this.

  • install.sql is everything you need to install this on your database
  • tweetsproc.dll is the twitter assembly used by the sproc
  • tweetsproc folder is the .net class library project
Contents of tweetsproc.zip

Everything you need to get TWEETING from a sproc

Using an AS3 object or class as a DataProvider

I have a need to use custom class objects as a DataGrid dataprovider.  After wrestling with flash.utils.describeClass() I gave up and found two other methods for binding my custom objects to a DataGrid.

First here is a look at the sample MXML app I put together.

Using custom object as a DataGrid.dataProvider in Flex 3

Same object bound two different ways

Click here to run this demo in a new window.

In the first grid the DataGrid gets a column per object property.

var dp_horizontal:Array = ArrayUtil.toArray( myCustomObj );
grid_1.dataProvider = dp_horizontal.valueOf();

In the second grid, I run my custom object through a helper function to create an ArrayCollection containing NAME, VALUE pairs for each object property.

/**
 * Convert a class object into an ArrayCollection to be used
 * as a DataProvider
 */
private function objectToDataProvider( obj:Object ):ArrayCollection
{
	// our DataProvider
	var dp:ArrayCollection = new ArrayCollection();
	// get object class info
	var info:Object = mx.utils.ObjectUtil.getClassInfo( obj );
	// split the class property list into Array
	var propsA:Array = String( info.properties ).split(',');
	// loop over class properties grabbing value and filling up dp
	for( var xx:int = 0; xx <= propsA.length-1; xx++)
	{
		dp.addItem( { name : propsA[ xx ], value : obj[ propsA[ xx ] ] } );
	}

	return dp;
}

I’m currently using this helper function to bind the result of WebORB.NET data calls to a DataGrid for testing.  This code could really be used by any type of object though.

Hope this helps somebody else.

Coldfusion and ASP.NET coexisting on IIS, where’d WebResource.axd go?

My Monday morning WTF comes from IIS7 on Windows 7.  I recently installed Coldfusion9 on this machine which has a handful of existing ASP.NET 3.5 web applications.  The problem I ran into came after installing Coldfusion9 and electing to configure all IIS websites to work with CF.  While that is convenient, it ended up breaking one of my ASP.NET applications that was using ASP Validation controls on a login form.  Now that things are figured out, here are the details.

Firing up my ASP.NET application gives me the error message :

The WebResource.axd handler must be registered in the configuration to process this request

Misleading web handler error message

WebResource.axd handler must be registered

Obviously all I could think is WTF?!?!? since this application worked on Friday and now it is broken.  The first thing I want to point out is that in my situation, the suggested solution of mapping WebResource.axd in the httpHandlers section of my web.config did not help this problem.  After some googling I cam across this post on the IIS.NET forums which put me on the right track.  You can read the details there if you want a good background on MS’ response and other users running CF and ASP.NET on the same box.

I’m happy to say I have three workarounds for this issue.  Hopefully these will help you as well.

1. Change your AppPool to run in Classic Mode

  1. In inetmgr, put your web application into it’s own Application Pool ( unless it’s already in it’s own pool )
  2. Change that AppPool’s Managed pipeline mode to “Classic”
  3. You should be good to go
Change Managed Pipeline Mode to Classic

Classic mode is for compatibility ( think IIS6 )

2. Stop using ASP Validation controls

All ASP.NET Validation controls are hosted by WebResource.axd.  If you stop using ASP Validator controls, the server will stop asking for WebResource.axd.

Comment out ASP Validator controls

Removing ASP Validator controls should remove this error

3. Remove Coldfusion handler mappings from your ASP.NET site

If your ASP.NET app isn’t using Coldfusion, I would suggest doing this as your solution.  Even if you do need Coldfusion in your ASP.NET app, you could still host your CF app in it’s own Virtual Directory and request if via ASP.NET.

  1. Open inetmgr
  2. Select your web app on the left ( under Default Web Site )
  3. In Features View on the right, double click Handler Mappings
  4. Sort your Handler Mappings by Name, and remove all entries titled “AboMapperCustom-*”
  5. Now your ASP.NET should work like a champ.
IIS7 inetmgr Handler Mappings

IIS7 Handler Mappings

Coldfusion9 Handler Mappings

Coldfusion9 Handler Mappings

Monday WTF solved.  Now to get back to pushing buttons.

Does SQL Server Management Studio truncate your results?

Ever work with query results that are so long SQL Server Management Studio truncates the results?

truncated query results

sproc results are truncated

I ran into this issue recently while running some utility sprocs that generate C# code for me.  I was thinking I’d have to refactor my sprocs, but then I found this helpful setting under Query Options.

This is the Query Options dialog

Update Max.num characters per column in Query Options > Results > Text

This solved my problem and will hopefully solve yours as well.

  1. Right click the query editor
  2. Left click “Query Options…”
  3. Expand Results in the tree on the left ( in popup dialog )
  4. Click on Text under Results
  5. Set “Maximum number of characters displayed in each column” to a number large enough to see all your results.

Quick and easy, hope I remember this setting.