| Join | Help

October 2006 - Posts

Tuesday, October 31, 2006 4:11 PM

MVP Nomination

I recently found out I am nominated for MVP. I consider just the nomination itself an honor. Thank you Ryan for the support.
Share this post: | bookmark it! | digg it! | reddit! | kick it! | live it!
Posted by Kevin Jones with 3 comment(s)
Sunday, October 29, 2006 3:48 PM

A Persistent Application State

We all know that an application state lasts while the application is running, but if the AppDomain gets restarted, from something like a change in the web.config file or a recompile. What if we want an Application State that always persists? One that is never lost, even if the entire server is restarted? Well I set off to do exactly that, and here is what I got.

The first thing I had to do when deciding how this would work is how I would store the values for this state. Logically a SQL Server came to mind, so I had to build an underlying way of communicating with a SQL Server, and an HttpModule seemed like the best way to accomplish this. So I was going to use SQL Server for holding my values. The next task is how to store everything in the SQL Server. I came up with 3 fields. The first being the key, the second being the application name (that way if you have two applications using the same key names, they won't conflict) and the 3rd being the value. I decided to go with Binary Serialization for storing values, to the value field is VARBINARY(MAX). This way we can store anything in our Persistent Application State so long as the object is serializable. To keep performance up, it doesn't read and write from the SQL Server exclusively. It caches everything for reading, so when you get a value it is getting it from an underlying dictionary, and during an update it updates the cache and the SQL Server values. The only time a read is done on the SQL Server is when the Init() method is called on the HttpModule. A SQL Script for creating the table is included in the project.

Since we are using an HttpModule, the module must be correctly registered in the web.config file, which would look something like this:

                    
                  

The next thing I had to accomplish was making this thing configurable. The web.config file seemed like the best way to do this, so I made a quick ConfigurationSection class to handle the configuration. The configuration has 2 basic attributes. applicationName and connectionStringName . applicationName should be a string that uniquely identifies the application. The connectionStringName is the name of the connection string that should be used to connect to the SQL Server that is in the section. An example of the web.config is included in the project.

The last thing I had to deal with is how to make this accessable from the Page. To solve this, I created a BasePage that exposes a Dictionary that works exactly like the Application, and hooks into the Module. To use it, derrive all of your pages from the class KGJ.PersistentApplicationState.BasePage and set the web.config file to use that as the base as well. This will expose the Dictionary PersistentApplication. From there on, use it like the Application State, except they will always be there until you delete them. How to use it: Simply put the compiled DLL in your BIN folder.

As far as other Databases, this code is easily adoptable to an Oracle or MySql client. Eventually I will adopt it so that it works like a provider.

Download the source code and projects here: Persistent Application State

Feel free to leave comments and suggestions, there is always room for improvement.

Share this post: | bookmark it! | digg it! | reddit! | kick it! | live it!
Posted by Kevin Jones with no comments
Filed under:
Wednesday, October 25, 2006 4:55 PM

AJAX Beta 1

It appears that Microsoft has dropped the ball with Beta 1 of AJAX, more over it is riddled with bugs and quirks. Here are some known issues and some work arounds for Beta 1

Web Service Calls Issue
http://forums.asp.net/thread/1441680.aspx

Extenders in Templated Controls Issue
http://forums.asp.net/thread/1441672.aspx

Share this post: | bookmark it! | digg it! | reddit! | kick it! | live it!
Posted by Kevin Jones with no comments
Filed under:
Thursday, October 19, 2006 10:35 AM

Announcing: IE 7 RTM!

It's finally here. IE7 RTM has finally hit the spot. Download it here:

http://www.microsoft.com/windows/ie/downloads/default.mspx

Share this post: | bookmark it! | digg it! | reddit! | kick it! | live it!
Posted by Kevin Jones with no comments
Filed under:

A Fun Windows Form Application

Ever play around with the Text-To-Speech in Windows XP? I thought that was fun when XP first came out and I always made it say crazy stuff, especially during computer lab. Later as a developer I wanted to implement this into a Windows Application I was making, just for fun.

The Speech API (SAPI) is a COM library, and it is no secret to .NET Developers that .NET has excellent support for COM libraries. The sapi.dll can usually be found in C:\Program Files\Common Files\Microsoft Shared\Speech. Using the .NET SDK, we can easily make a managed assembly for this using the Type Library Import, tlbimp.exe. You can run it from the SDK Command prompt in the start menu. Using the command prompt we can generate the Managed Version of it, what I called sapi.net.dll using this in the .NET SDK Command Prompt:

C:\Program Files\Microsoft.NET\SDK\v2.0 64bit>tlbimp "C:\Program Files\Common Files\Microsoft Shared\Speech\sapi.dll" /out:C:\sapi.net.dll

The Type Library Mashaler won't be able to completely marshal it for you, but it will be able to do enough of it for us to get what we want. (Note that in my example I used the 64-bit platform, so your SDK path won't be the same). This will generate the Assembly we need for making a taking application.

So now we can use this assembly in a Windows Form Project, and all we have to do is add a reference for it.

The primary interface and class we will be using is SpVoice and SpVoiceClass, which were made by our type library importer. SpVoiceClass is what we will use to make our application talk. The method "Speak" accepts two arguements, the text to be spoken (as a string) and flags (as an int enumeration). Type Library Importer automatically generated a flag enumeration called SpeechVoiceSpeakFlags. The two I use in this application is SVSFIsNotXML and SVSFlagsAsync. SVSFlagsAsync is important so your thread won't lockup when you start speaking. Optionally, you can use your own worker thread, which is recommended since we don't want to be talking on the UI thread:

private SpVoiceClass voice = new SpVoiceClass ();

SpVoiceClass voice = new SpVoiceClass ();

ThreadPool . QueueUserWorkItem(( delegate ( object arg)
{
voice . Speak( "Hello!" , SpeechVoiceSpeakFlags . SVSFIsNotXML | SpeechVoiceSpeakFlags . SVSFlagsAsync);
}),
null );

this.voice is an instance of the SpVoiceClass class.

Assuming one has Office installed, you have extra voices. I got bored of Microsoft Sam so I wanted to use others voices, for which I created a helper method like this:

static List < DictionaryEntry > AvailableVoices
{
get
{
SpVoiceClass voice = new SpVoiceClass ();
List < DictionaryEntry > voices = new List < DictionaryEntry > ();
for ( int i = 0 ; i < voice . GetVoices( null , null ) . Count; i ++ )
voices
. Add( new System . Collections . DictionaryEntry (voice . GetVoices( null , null ) . Item(i) . GetDescription(System . Globalization . CultureInfo . CurrentCulture . LCID), voice . GetVoices( null , null ) . Item(i)));
return voices;
}
}

The reasoning for using a List filled with DictionaryEntry's is for databinding purposes, since the binding must implement the interface IList. This returns a List of DictionaryEntries, the dictionary key being the voices name, the value being the actual voice itself, which is the interface ISpObjectToken. So now we have a list of the voices installed on the machine.

The SpVoiceClass has a method called SetVoice which accepts an ISpObjectToken for setting the voice.

The SpVoice class can also allow you to save a WAV recording of the voice, just by changing around the output stream. I used a BackgroundWorker class to help me with this so I can do it on another thread.

The stream we will be using for this is SpFileStreamClass, which must exist on the same thread as the SpVoice class, so we need to pass it as an arguement in the RunWorkAsync method.

You can download the full sourcecode and run it for yourself here: Speech

Share this post: | bookmark it! | digg it! | reddit! | kick it! | live it!
Posted by Kevin Jones with 1 comment(s)
Filed under: , ,