Thursday, April 24, 2008

Quick Tip - Add A Visual Studio File As A Link

Have ever wanted to include a file in a Visual Studio project, but you didn't want it to be copied to the project directory? You could hack the location into the project file, but editing XML seems to be overkill for such a simple task. A colleague at work showed me a better way (thanks Cliff!). Use the Add As Link option. It is in an obscure location. When you go to add an existing item you can click the arrow next to the Add button and find Add as link.

This can really be helpful when you are sharing XML schemas, interfaces, etc... between assemblies that need to keep these resources in sync, such as client and server assemblies.

Save to del.icio.us Add to Technorati Add to dzone

Tuesday, April 22, 2008

When is a LINQ Statement Executed?

LINQ statements are the latest and greatest from Microsoft's .NET Framework. If used correctly they can make complex operations readable, maintainable and simple. Here is a simple example:


string[] characters = { "Ender", "Peter", "Valitine", "Stilson", "Graff", "Anderson" };

var eCharacters = from i in characters where i.Contains("e") select i;

foreach (string character in eCharacters)
// Do something with character

This sample shows a LINQ statement that extracts strings that contain an "e" from the character array. The characters would include Ender, Peter, Valitine and Anderson. One of the keys to understanding LINQ is understanding when this filtering actually occurs. Let's change the example a bit. In this example we will change the source (characters) so that Valitine will now be Val.

string[] characters = { "Ender", "Peter", "Valitine", "Stilson", "Graff", "Anderson" };

var eCharacters = from i in characters where i.Contains("e") select i;

characters[2] = "Val";

foreach (string character in eCharacters)
// Do something with character

The string array was changed after the LINQ statement. So will Valitine be included in eCharacters? No. LINQ statements do not execute until their values are enumerated over. This is called differed execution. If we wanted the LINQ statement to pull the values out at the time of execution we would need to enumerate through the values. Luckly with the extensions provided with LINQ we can do this very easily by changing our LINQ statement to something like this:

string[] eCharacters = (from i in characters where i.Contains("e") select i).ToArray<string>();

With a call to ToArray<string>() we enumerate over the LINQ result and create a string array. If the characters array changes, the values in the eCharacters array will not.

Save to del.icio.us Add to Technorati Add to dzone

Thursday, April 17, 2008

Speech Libraries added to .NET 3.0

Microsoft has wrapped the SAPI into .NET 3.0 with the System.Speech namespace. System.Speech has two main sections. They are Recognition and Synthesis. In order to use the System.Speech library you need to add a reference to it.

Synthesis

Synthesis can be done very easily.

SpeechSynthesizer synthesizer = new SpeechSynthesizer();
synthesizer.Speak("This text is spoken by the computer.");

In SAPI 5.3 (the version that System.Speech wraps) Microsoft Anna is the only voice available. Hopefully Microsoft will make more voices available.

Recognition

Getting started with speech recognition is a little more involved. You need to decide whether you want to recognize text (dictation) or recognize specific commands. The Grammar object will tell the recognition engine whether you want to recognize text or recognize specific commands. First we'll look at dictation (recognizing text).

static void Main(string[] args)
{
SpeechRecognizer recognizer = new SpeechRecognizer();
recognizer.LoadGrammar(new DictationGrammar());
recognizer.SpeechRecognized += new EventHandler(recognizer_SpeechRecognized);
}

static void recognizer_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
{
if (e.Result != null)
Console.WriteLine(e.Result.Text);
}

This will recognize speech from the line in and write text to the console. We can also accept input from a wave file.

SpeechRecognitionEngine engine = new SpeechRecognitionEngine();
engine.LoadGrammar(new DictationGrammar());
engine.SetInputToWaveFile("C:\\My Temp\\Test Audio Search.wav");
RecognitionResult result = engine.Recognize();
if (result != null)
Console.WriteLine("Recognized: " + result.Text);

Command recognition is done by creating a Grammer object that identifies the commands you would like to be recognized. You can build the Grammer object with GrammerBuilder and Choice classes. Here is a simple example:

static void Main(string[] args)
{
SpeechRecognizer recognizer = new SpeechRecognizer();
GrammarBuilder commandGB = new GrammarBuilder();
commandGB.Append(new Choices("open", "close"));
recognizer.LoadGrammar(new Grammar(commandGB));
recognizer.SpeechRecognized += new EventHandler(recognizer_SpeechRecognized);
}

static void recognizer_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
{
if (e.Result != null)
Console.WriteLine("Recognized: " + e.Result.Text);
}

Here we are looking for open or close as commands. The System.Speech namespace makes this very easy to code, but the speech recognition and synthesis aren't the quality you would hope for in 2008. Synthesis can be improved with SSML and SRGS although it still sounds robotic and the only voice available is Anna. Recognition needs to be calibrated to get any sort of reasonably accurate results, at least for dictation. Also the documentation leaves a lot to be discovered. I like that Microsoft has included this in a managed library, but I would like to see even more effort applied to the speech technology itself.

Save to del.icio.us Add to Technorati Add to dzone

Friday, April 11, 2008

The X in AJAX Is For XML Right?

AJAX is generally accepted as asynchronous Javascript and XML. It is documented as such on Wikipedia. Although I've found that XML isn't the best choice in transmitting data with Javascript. I'll show you why. Lets look at my previous AJAX example. Here we sent just the text of the customer's name and then send back their address. We aren't even using XML. This is fine for this simple example, but what if you wanted to send and receive more complex objects? What if you wanted to send a list of first and last names and receive back all of the customer's information like birth date, color, sex, etc... You could make a delimited list. I shouldn't have to tell you why this is not a good idea, but if you need convincing read the Advantages of XML section of the Visual Basic® .NET Developer's Guide to ASP .NET, XML and ADO.NET.

XML does seem to be the logical choice and it's the X in AJAX! So if we have a list of objects that have a first name and a last name how do we get these to XML? In C# you can use the XmlSerializer and serialize your object into XML. Can you do this in Javascript? no. JavaScript doesn't have the extensive group of helper libraries like .NET has. So we have to serialize the object ourselves. Here are some examples: toXML and XmlSerializer. Ok so we can do some copy and paste and now we can send our list of first and last names to the web server.

Now when we get our response we will get more XML. We can use the XmlSerializer to deserialize the objects into Javascript objects, but that requires a schema. Instead we can use the XmlHttpRequest's responseXML property to get a document object that we can traverse to get our object.


var xml=ajaxRequest.responseXML;
var xmlArray=xml.getElementsByTagName("CustomerInfo");
var customers=[];
for (var i=0;i<xmlArray.length;i++) {
var customer={};
var ciNode=xmlArray[i];
for (var j=0;j<ciNode.childNodes.length;j++)
customer[ciNode.childNodes[j].nodeName]=ciNode.childNodes[j].text;
customer[i]=customer;
}

This requires us to use DOM to move through the nodes and extract the data we are interested in and create an array of hash tables that represent our customers. XML is requires processing power to traverse through and is quite bulky running down the wire, but what else can we do? JSON!

JSON


As stated on JSON's website JSON is a subset of the object literal notation of JavaScript. What does that mean well it means that you can use the JavaScript interpreter to create objects from JSON. Why is that important? Because this means that using JSON will make your AJAX calls fast, small and most importantly very transparent to use. Take a look at the JSONized version of the above example:

var customers=eval('('+ajaxRequest.responseText+')');

One line! It doesn't get much better then that. There has to be a downside right? Well it's really not that bad. If you want to send JSON strings to the web server you need to download the JSON library. just use the JSON.stringify on your object to send to the web server and you are all set. Now what about the web server side? If you are using .NET I like to use JSON.NET. You can also look at Scott Hanselman's Blog on a few other JSON serializers.

Summary


XML is not the right fit for JavaScript. I think we need to wipe our hands of AJAX and start web 3.0 with JavaScript with asynchronous notation transport, JANT!

Save to del.icio.us Add to Technorati Add to dzone

Thursday, April 10, 2008

AJAX in ASP.NET

AJAX is simply a callback to the web server that doesn't refresh the current web page. Most AJAX application then use that information to dynamically modify the web page. We can quickly setup an AJAX call in ASP.NET. To start we need to have a web form. For this example we'll add a input text box, a button(not a submit button), and a textarea. You will input a customer's name in the input box and click on the button to get the customer's address in the textarea.


<body>








</body>

On the button's onclick event the javascript method GetCustomer is called. GetCustomer is where we will make our AJAX call. Most of the AJAX magic is done with the XMLHttpRequest object. The XMLHttpRequest object sends a request back to the web server without refreshing the page. To make a request you need three things: a function to handle the response, a handler on the web server and the content to be sent. Since we are sending a request that is asynchronous we need to have a function to handle the response. A handle is a simple web page that will handle our request and send back a response. The content can be null so technically content is optional. The callback function that will handle the request will set the textarea to the response text we will get from the handler. We will set the location of the request to handler that will create in a second. We will also send the customer so the handler will know what customer to lookup. Here is the code we will use to send our request:

function GetCustomer() {
var ajaxRequest=new XMLHttpRequest();

ajaxRequest.onreadystatechange = function() {
if (ajaxRequest.readyState==4)
document.getElementById("TextArea1").value=ajaxRequest.responseText;
}

ajaxRequest.open("POST", "Handler1.ashx", true);
var customer=document.getElementById("Text1").value;
ajaxRequest.send(customer);
}

Next we need to create the Generic Handler, Handler1.ashx. In the Handler1.ashx.cs file you need to handle our AJAX request. The ProcessRequest method will be called when a request is sent so we will place our customer lookup code there. We will first pull out the customer from the request, look it up and then return the address in the response.

public void ProcessRequest(HttpContext context)
{
string customer = new StreamReader(context.Request.InputStream).ReadToEnd();

context.Response.ContentType = "text/plain";
if (String.Compare(customer, "Bob") == 0)
context.Response.Write("123 Bob Ave.\nBobville, BO 12345");
else if (String.Compare(customer, "Foo") == 0)
context.Response.Write("789 Bar St.\nFooville, FB, 01111");
else
context.Response.Write("Unknown customer!");

context.Response.Flush();
context.Response.Close();
}

Be sure to include the Flush method otherwise the response will not be sent. Here we only have two customers: Bob and Foo. Any other values will return "Unknown customer!"

Gotchas


The XMLHttpRequest object is only compatible in Opera 8.0+, Firefox, Safari, IE 7.0+. If we want to have support for other browsers we need to make a small modification. We will create a new factory function to return a AJAX request object.

function getAjaxRequest() {
// Opera 8.0+, Firefox, Safari, IE 7.0+
if (window.XMLHttpRequest) return new XMLHttpRequest();
// IE 5-6
else if (window.ActiveXObject) return new ActiveXObject("Microsoft.XMLHTTP");

return false;
}

We need to make a small change to the GetCustomer class to implement this change.

function GetCustomer() {
var ajaxRequest=getAjaxRequest();

if (ajaxRequest!=false) {
ajaxRequest.onreadystatechange = function() {
if (ajaxRequest.readyState==4)
document.getElementById("TextArea1").value=ajaxRequest.responseText;
}

ajaxRequest.open("POST", "Handler1.ashx", true);
var customer=document.getElementById("Text1").value;
ajaxRequest.send(customer);
}
}

From this example you can see that it is very easy to setup an AJAX call within ASP.NET. The possibles for AJAX are endless. Hope you find it as innovative as I have.

If you are having trouble with any of the code try downloading the full source code for the above example.

Save to del.icio.us Add to Technorati Add to dzone

Thursday, April 3, 2008

Do your .NET assemblies have Trace Statements? Maybe they should.

Have you ever had a problem with your code in a production environment? If not you must be awful lucky. For the rest of us I'm sure we have spent may hours troubleshooting code that worked fine in development, but is now not working in the production environment. If you've used the Debug class to output debug messages you mostly like have found that these don't work in release builds. Yes you can enable them in the release build, but a better way to handle this is to use the Trace class.

You can write a Trace message very easily.


Trace.WriteLine("I'm doing some work");


This will write "I'm doing some work" to the output window. If I'm in a production environment I might want to write to a text file instead. Trace handles this by implementing TraceListeners. The default is the DefaultTraceListener which writes to the output window. We can use the TextWriterTraceListener to output to a file. We can do this via a configuration file or programmatically. If you want to add this to the configuration file add the following to your app.config file.


<configuration>
<system.diagnostics>
<trace autoflush="false" indentsize="2">
<listeners>
<remove name="Default" />
<add name="TextTraceLogger" type="System.Diagnostics.TextWriterTraceListener" initializeData="Log.Txt" />
</listeners>
</trace>
</system.diagnostics>
</configuration>


In this configuration we removed the Default Listener. This isn't required. You can have many listeners if you like. If you are adding Trace messages to libraries be sure to add the Trace configuration to your executing assembly. You can add a Listener programmatically by using the Trace.Listeners property.


Trace.Listeners.Add(new TextWriterTraceListener("Log.Txt"));


Especially in production you don't want detailed output all the time. You just want it when you are troubleshooting. The TraceSwitch class performs this function. The TraceSwitch class stores a TraceLevel that is used to evaluate whether a message should be outputted or not.

public enum TraceLevel
{
Off = 0,
Error = 1,
Warning = 2,
Info = 3,
Verbose = 4,
}


When a TraceSwitch is set to a specific TraceLevel all the lower valued levels are "activated" as well. For example if a TraceLevel is set to Warning, Error messages will be outputted as well.

Like the TraceListeners the TraceSwitch can be created in the configuration file or programmatically. Configuration example:

<configuration>
<system.diagnostics>
<switches>
<add name="General" value="Warning" />
</switches>
</system.diagnostics>
</configuration>


If you are adding TraceSwitches to a library be sure to set the configuration of the executing assembly and not the libraries assembly. Programmatic example:

TraceSwitch GeneralTrace = new TraceSwitch("General", "General Trace Messages");
GeneralTrace.Level = TraceLevel.Warning;


To use a TraceSwitch in code you first need to declare it. If you have defined a TraceSwitch in the configuration file the TraceSwitch name needs to match the name in the configuration file. You then will use the TraceSwitch to evaluate weather a message is outputted or not.

TraceSwitch GeneralTrace = new TraceSwitch("General", "General Trace Messages");

Trace.WriteLineIf(GeneralTrace.TraceVerbose, "A verbose message");
Trace.WriteLineIf(GeneralTrace.TraceError, "an error message");


If you need to do some work to create the Trace message you may want to just include the TraceSwitch evaluation in an if block.

if (GeneralTrace.TraceError)
{
StringBuilder errorMessageBuilder = new StringBuilder();
errorMessageBuilder.Append("Error processing. Details: ");
foreach (ErrorDetail detail in ErrorDetails)
{
errorMessageBuilder.Append(detail.Message);
}

Trace.Write(errorMessageBuilder.ToString());
}


Here are some other TraceListeners:

You can also create your own TraceListener by inheriting from TraceListener.

Save to del.icio.us Add to Technorati Add to dzone

Wednesday, April 2, 2008

Is Enterprise Logging Application Block the best choice for Logging?

I've been using Log4Net for quite some time now, but I recently came across a new logging framework called Microsoft's Enterprise Logging Application Block. That is quite a mouthful, but it sounds promising. The Logging Application Block is part of a collection of other application blocks that is called the Enterprise Library. The Enterprise Library contains eight application blocks:

  • Caching
  • Cryptography
  • Data Access
  • Exception Handling
  • Logging
  • Policy Injection
  • Security
  • Validation

Let's see how the Logging Application Block compares to Log4Net. For this review we will use Microsoft Enterprise Library 3.1 - May 2007 and Log4Net 1.2.10. The four areas we will compare them on are easy of use, configuration, performance, flexibility.

Easy of Use

Setup of Enterprise Logging for flat files and the event log is very easy with the help of the Enterprise Library Configuration utility. Logging to the database was a little more difficult and a little awkward. For instance you need to set the Formatter for the Database Trace Listener even though it doesn't dictate what is entered into the database.

Log4Net doesn't have a UI configuration, but I've always found the setup is documented well and intuitive to implement.

Configuration

The Enterprise Logging application block can be configured using the Enterprise Library Configuration utility. Both Log4Net and Enterprise Logging modify the XML config file, so manual configuration can be done easily. Both of them also support programmatic configuration as well.

Both loggers include logging to text files, databases, event log and email. Log4Net includes logging to the console with colored ANSI for enhanced readability.

Performance

My initial tests showed Log4Net being exponentially faster. Others have found this to be true as well. For more details and stats check out Loren Halvorson's Blog.

Flexibility

The Enterprise Logging provides full source code. And has an extensible trace listeners. Log4Net's Appenders offer similar functionality.

In summary the Enterprise Logging Application Block is a very full featured and extensible logging framework. If you are using any of the other Enterprise Application Blocks this would be the first logger to try. It's only downfall is that it's performance is lacking. Unlike Log4Net the Enterprise Library including the Logging Application Block is being updated quite regularly.

If you would like to try one of these logging frameworks out check out these tutorials:
Some other Logging Frameworks:

Save to del.icio.us Add to Technorati Add to dzone