Category Archives: .NET

Logging in C#

I wrote up a very simple C# class that provides logging for C# applications since the C# Logger on sourceforge is still in alpha (and doesn’t appear to be active) and the .NET framework doesn’t seem to provide normal text file logging outside of the EventLog (correct me if I’m wrong):

using System;
using System.IO;
namespace com.ignitionlabs.logging {  
  public class Logger {
    private static int _ALL = 100;
    private static int _INFO = 75;
    private static int _ERROR = 50;
    private static int _OFF = 0;
    private static String logDirectory = System.Configuration.ConfigurationSettings.AppSettings["logging.directory"].ToString();
    public static int ALL {
      get { return _ALL; }
    }
    public static int ERROR {
      get { return _ERROR; }
    }
    public static int INFO {
      get { return _INFO; }
    }
    public static int OFF {
      get { return _OFF; }
    }
    public static void append(String message, int level) {
      int logLevel = _OFF;
      String strLogLevel = System.Configuration.ConfigurationSettings.AppSettings["logging.level"].ToString();
      switch(strLogLevel) {
        case "ALL":
          logLevel = _ALL;
          break;
        case "ERROR":
          logLevel = _ERROR;
          break;
        case "INFO":
          logLevel = _INFO;
          break;
        default:
          logLevel = _OFF;
          break;
      }
      if (logLevel >= level) {
        DateTime dt = DateTime.Now;
        String filePath = logDirectory + dt.ToString("yyyyMMdd") + ".log";
        if (!File.Exists(filePath)) {
          FileStream fs = File.Create(filePath);
          fs.Close();
        }
        try {
          StreamWriter sw = File.AppendText(filePath);
          sw.WriteLine(dt.ToString("hh:mm:ss") + "|" + message);
          sw.Flush();
          sw.Close();
        } catch (Exception e) {
          Console.WriteLine(e.Message.ToString());
        }
      }
    }
  }
}

After compiling, you’ll need to add 2 elements to your <appsettings> in web.config:

<add key=”logDirectory” value=”c:\myapp\logs\” />
<add key=”logLevel” value=”ALL|INFO|ERROR|OFF” />

and then you can use the class like this:

Logger.append(“your application message…”, Logger.ALL);

As always, I’m interested in any design flaws or critiques.

HttpHandlers, HttpModules, Servlets & Filters

I’m in project limbo today, coming off a large ecommerce initiative for FootJoy that uses ASP, C#, Flash and Flash Remoting and moving onto another ecommerce site, this one completely C#.

I’m slowly grokking the .NET packages, I trying to understand the low-level System.Web classes today. I was interested to read about the IHttpHandler interface, which you use to create services that are similar in nature to the Java Servlet interface. Similarities I can see/find:

  • JSP’s are compiled down to servlets at runtime, .NET uses the System.Web.UI.PageHandlerFactory class when handling requests for .aspx files. Don’t believe me? Check the <httpHandlers> element of your machine.config file.
  • Servlets can be configured to respond to a variety endpoints through the <servlet-mapping> element of web.xml, HttpHandlers are added to web.config like this:

    <httpHandlers>
       <add verb=”*” path=”/mypath/somepage.aspx” type=”com.mindseye.handlers.TestHandler, TestHandler” />
    </httpHandlers>

  • Both servlets and httphandlers give you a means of interacting with the low-level request and response services of the web server

In much the same way, HttpModules and the javax.servlet.Filter class perform similar functions. An HttpModule class registers itself to listen for events that are fired in your HttpApplication (for instance the ‘BeginRequest’ event) and then can perform actions based on the occurrence of those events. A Filter is a bit different in that it is mapped to the a specific url pattern in web.xml and is then called when a request is made that matches that pattern. Just like the HttpModule class, it too can then modify the request coming in or the response going back out.

In general, I’m very impressed by ASP.NET (and thus the .NET framework).

Windows Tail

[update 10:08pm] I know that tail exists for Windows by using cgywin or some of the other ports. If you view the article you’ll see that this utility isn’t run from the command line and uses VB.NET code, which I thought was a interesting…]

From the artima newsletter: Windows tail: “The UNIX operating system has long had a set of really good text file processing utilities. On of the utilities is a program named tail. What tail does is it displays the bottom of a file and then waits for any new information to be written to the end of that file then it displays that information, scrolling up as it goes along. This is perfect for monitoring log files to watch them actually grow as information is being written to them.

Windows has no such command. Also, in the spirit of Windows, I thought it would only be appropriate to have this command using a GUI user interface instead of the command line user interface employed by the UNIX version.

Enter Windows Tail, or wtail.exe. This is a program written in VB.NET using the Microsoft DOTNET Framework 1.1 which must be installed on your system in order for this program to run.

Retrieving ‘recordcount’ property in .NET

Spent a bit this morning wading through .NET documentation trying to find out how one retrieves the number of records returned from a query. Turns out it’s pretty simple. First you get your query rolling:

// get the connection string from settings
String cs = System.Configuration.ConfigurationSettings.AppSettings[“connectionString”].ToString();
// get a sql connection using the connection string
SqlConnection sqlcon = new SqlConnection(cs);
SqlDataAdapter adapter= new SqlDataAdapter(“select * from yourtable”, sqlcon);
DataSet dataset = new DataSet();
adapter.Fill(dataset,”mytable”);

At this point you’ve run the query and you have a DataSet which you can then loop over like any other collection, ie:

foreach (DataRow d in dataset.Tables[“mytable”].Rows)

or you can retrieve the number of rows:

DataRowCollection drc = dataset.Tables[“mytable”].Rows;
Console.WriteLine(“there are ” + drc.Count + ” rows in the query.”);

or even quicker like this:

Console.WriteLine(“there are ” + dataset.Tables[“mytable”].Rows.Count + ” rows in the query.”);

Back to work….

.NET code generation

Short article on .NET code generators: .NET code generators enable rapid application development. Only one tool is covered, “DeKlarit”, which you can view a nifty Flash demo on here.

I used the wsdl tool yesterday to generate a C# web service client stub, how handy is that tool? The command line switches allow you to customize the namespace, the generated file name, the name of the key to retrieve from the config file for the webservice endpoint, and the language (C#, VB.NET)… etc…

> wsdl /urlkey:name_of_my_key /n:com.mypackage /o:FileName.cs /l:CS http://hostname/path/mywebservice.asmx

You can then start using the generated class in your code immediately. Very cool.

Flash Remoting Docs bug

Got an email from Scott who was trying to work with C# and Flash Remoting. He couldn’t get the “Creating an assembly that returns an ActionScript object” example to work from the FlashRemoting LiveDocs. Looks to me like the documentation is a bit off. From the documentation:

 public ASObject returnObject()
    {
      ASObject aso = new ASObject();
      aso.ASType = “Calculator”;
      aso.Add(“x”, 100);
      aso.Add(“y”, 300);
      Flash.result = aso;
    }

should probably be:

 public ASObject returnObject()
    {
      ASObject aso = new ASObject();
      aso.ASType = “Calculator”;
      aso.Add(“x”, 100);
      aso.Add(“y”, 300);
      return aso;
    }

Personal rant: I tried creating a Livedocs account, but for whatever reason, the account I created didn’t work… why does everyone make you create a username? Why not just use your email address?

Server-Side Flash Detection Using BrowserHawk @ DEVNET

I wrote an article for Macromedia Devnet which was just published today! Check it out here: Server-Side Flash Detection Using BrowserHawk. If you’ve never used BrowserHawk before, it’ll be a good introduction. However, if you’ve used it with ColdFusion, you should definitely read it, I was able to use BrowserHawk 4J (the Java version) with CFMX rather than using the ASP bridge (which was and is required if you want to access the extended properties of BrowserHawk in versions of ColdFusion prior to MX).

I should thank Shena at my work for bringing it up as an option (she contacted Macromedia originally), thanks Shena!

Web.config vs. Application.cfm

In response to my post about the web.config file in ASP.NET, Ray asked how this was any different from Application.cfm in ColdFusion land. I think that it’s very similar, but there are some things that are better about web.config than Application.cfm.

First, and I think most importantly, web.config is a configuration file and a configuration file only. I’ve seen ColdFusion applications that use Application.cfm for security, some to include the header, some that contain database connection strings, some that contain UDF’s, etc. etc… Application.cfm is more flexible in that sense, but as always, that flexibility comes at the cost of misuse. There is no standard way of providing configuration information to a ColdFusion application.

Second, because web.config contains only XML, you can use your favorite XML parser to create and edit your configuration file. You could programatically generate your configuration file if necessary, while an Application.cfm would require a custom script to be written to first parse the file and then another script to write out the file.

Third, web.config files can be included in multiple directories on an application and inherited. You can include Application.cfm files in multiple directories, but you don’t get inheritance unless you explicitly include the parent level Application.cfm.

Fourth, you can programmaticly access configuration information about the current application without reading web.config. You can’t do this AFAIK in ColdFusion. For instance, let’s say that I have an Application.cfm that includes the following tag:

<cfapplication name=”myApplication” clientmanagement=”Yes” sessionmanagement=”Yes”>

and then somewhere later I wanted to know if sessionmanagement is enabled. How would I do that? Can you? Again, as far as I know, you can’t get that information without parsing the Application.cfm and looking for sessionmanagement=”true”. In ASP.NET, I write a simple line of code:

String sessionMode = Session.Mode;

where Session.Mode has the possible values of Off, Inproc, StateServer, and SQLServer.

I think something like what web.config provides would be a really nice addition to Application.cfm. Maybe Application.cfm just stays as it is and we get Application.config in addition…. maybe it’s better that Application.cfm goes away.

C# Documentation

More fun features in .NET, actually this time specific to C#. Documentation, though not usually the most fun thing to write, is probably one of the most valuable. C# lets you embed your documentation in your source code as XML. Visual Studio users will be pleased to know that their IDE automatically rips out the XML and creates Microsoft MSDN style files automagically. But where does that leave those of us who hack in Notepad or Eclipse? Even better off! Enter your XML documentation (more information on XML documentation within C# below) in your source code and then add a flag to your compilation statement. Here’s a sample compile statement of a class called ‘MyClass’:

csc /t:library /r:System.dll /doc:MyClass.xml MyClass.cs

Given that you entered comments in your source code, the C# compiler will then strip our your comments, package hierarchy, related classes and create an xml file, in the above case, called ‘MyClass.xml’. In and of itself, this doesn’t do you much good. But if you download NDOC from sourceforge, you can create not only Microsoft MSDN style help files, but JavaDoc help files, LaTex helps files and plain xml.

Further Resources:
C# Programmer’s Reference: XML Documentation [msdn]
C# Programmer’s Reference: Tags for Documentation Comments: [msdn]
XML Comments Let You Build Documentation Directly From Your Visual Studio .NET Source Files [msdn mag]

System/App Configuration in .NET

I mentioned I’m working with .NET stuff on my current project. One of the nicer features I’ve found so far is that .NET includes an entire package devoted to System/App Configuration. So I I’m writing an web application, I can put a web.config file in the root of my app and/or any of the subdirectories of my application. Inside that web.config file, I can set security, modify the compiler setting, specify an error handler… you get the picture. IMHO, the best part is that you can extend web.config and add your own custom settings. For instance, almost every web application worth a look uses some sort of database, which usually requires a database connection string or DSN name. You’d add something like this:

<appSettings>
   <add key=”connectionString” value=”user id=sa;password=mypassword;initial catalog=mydb;data source=mydbserver;Connect Timeout=30″ />
</appSettings>

outside of the system.web tag. To use that value in your application, you need not parse the xml file, you don’t have to worry about getting it into application scope, you don’t need to worry about locking. You only need to write one line of code:

private static String CONNECTIONSTRING = System.Configuration.ConfigurationSettings.AppSettings[“connectionString”].ToString();

Pretty simple isn’t it? It gets better. According to this document, “ASP.NET detects changes to configuration files and automatically applies new configuration settings to Web resources affected by the changes. The server does not have to be rebooted for the changes to take effect.” and more importantly, “ASP.NET protects configuration files from outside access by configuring Internet Information Services (IIS) to prevent direct browser access to configuration files.

Further Resources:

ASP.NET Configuration: [source]
Format of ASP.NET Configuration Files: [source]
Configuring Applications in .NET: [source]