Wednesday, November 9, 2011

Windows Service follow up

I have a .NET 2.0 version and a .NET 4.0 version. Now to get the time to set up a Codeplex project and upload... Or Git... Not sure which yet...

Thursday, February 10, 2011

New sample project coming soon...

In the works is a sample project of an admin panel controlled, installed, and fully self contained Windows service. This project will take you through some pretty cool steps involved in setting up a WinForms app that will extract a Windows service application and its dependencies, install it, and start it. Then, you will also get a small sample of how to use the admin tool to control the service and run a process on it. I'm thinkin' multiparter...

ASP.NET Unhandled Exception Handler

This little bit of code from Jeff Atwood works equally well in an ASP.NET 1.1 application as well as the most recent ASP.NET 4.0 applications. If you need a bit of code to throw and email and/or a friendly message back to your users, this my friends is it... This was written in VB.NET, but I ported it over easily to C# and added some minor enhancements. If you'd like to have my version, let me know and I'll put it out somewhere for you to get it.

Tuesday, September 28, 2010

2 years later...

Sounds like a title to another bad sequel to "28 Days Later". but it's been a while, thought I'd just point out that fact. Maybe I'll have more later.

Friday, October 10, 2008

Daily humor

I found this on Stack Overflow and started thinking of all of my comments in my code. Which are funny and which make no sense at all. If anyone actually reads my blog, what's some of your favor comments or code snippets that make you chuckle?

Wednesday, July 23, 2008

Reflection, Dynamically In C#

On the current project I am working at my job, I need to call web services dynamically. What I am trying to do is add additional functionality to a web page that receives its data from several web services. The web services are called through a proxy web service that puts the data into an XML format that is then past on to the web page and parsed through XSLT transforms into HTML. What I want to do is to be able to add a web service at most anytime without having to touch the web page.

All of the web page configuration is stored in a table, so getting a new web service added is simple enough in that all I need to do is update the proxy web service and add the configuration to the database.

To do all of this, I need to be able to call the methods dynamically using Reflection.

Here's how:

In my application, I use a criteria (or request) object to pass in parameters to the method and a response object on the return. So, here are those objects:

   1:  namespace Namespace
   2:  {
   3:      public class Request
   4:      {
   5:          public Request() { }
   6:  
   7:          private string name;
   8:  
   9:          public string Name
  10:          {
  11:              get { return name; }
  12:              set { name = value; }
  13:          }
  14:  
  15:          private string message;
  16:  
  17:          public string Message
  18:          {
  19:              get { return message; }
  20:              set { message = value; }
  21:          }
  22:      }
  23:  }

   1:  namespace Namespace
   2:  {
   3:      public class Response
   4:      {
   5:          public Response() { }
   6:  
   7:          private string name;
   8:  
   9:          public string Name
  10:          {
  11:              get { return name; }
  12:              set { name = value; }
  13:          }
  14:  
  15:          private string message;
  16:  
  17:          public string Message
  18:          {
  19:              get { return message; }
  20:              set { message = value; }
  21:          }
  22:      }
  23:  }

Next up, we have our class which has the method we are going to call.

   1:  namespace Namespace
   2:  {
   3:      public class DisplayName
   4:      {
   5:          public DisplayName() { }
   6:  
   7:          public Response Write(Request req)
   8:          {
   9:              // Run once just to show we are actually doing something.
  10:              Console.WriteLine(string.Format("{0}: {1}", req.Name, req.Message));
  11:              Response resp = new Response();
  12:              resp.Name = req.Name;
  13:              resp.Message = req.Message;
  14:              return resp;
  15:          }
  16:      }
  17:  }

Finally, our method to process our dynamic call.

   1:  using System;
   2:  using System.Reflection;
   3:   
   4:  class ReflectionSample
   5:  {
   6:      static void Main()
   7:      {
   8:          // Get our assembly loaded.
   9:          Assembly asm = Assembly.Load("Namespace");
  10:          
  11:          // Define our main type. This is the type that 
  12:          // we will use to get our actual object.
  13:          Type mainType = asm.GetType("Namespace.DisplayName");
  14:          
  15:          // Create our object based on the type we defined
  16:          // in the last step.
  17:          object obj = Activator.CreateInstance(mainType);
  18:   
  19:          // Now, we define our request type. The request object
  20:          // is in the same assembly.
  21:          System.Type reqTyp = asm.GetType("Namespace.Request");
  22:          
  23:          // Next, create our request object. 
  24:          object reqObj = Activator.CreateInstance(reqTyp);
  25:          
  26:          // After we create our object, we set the properties.
  27:          // In my actual application, these properties are set
  28:          // via a loop, assuming multiple dynamic properties.
  29:          PropertyInfo piName = reqTyp.GetProperty("Name");
  30:          piName.SetValue(reqObj, "John", null);
  31:          PropertyInfo piMess = reqTyp.GetProperty("Message");
  32:          piMess.SetValue(reqObj, "Hello", null);
  33:   
  34:          // The next step is to create the array of parameters
  35:          // we need to pass into the method we will be calling.
  36:          // In the case of my application, we only need one.
  37:          System.Type[] prmTyp = new System.Type[1];
  38:          prmTyp.SetValue(reqTyp, 0);
  39:          
  40:          // The next step is to get our MethodInfo object.
  41:          // We pass in to GetMethod the name of the method
  42:          // and the parameter type list.
  43:          MethodInfo mi = mainType.GetMethod("Write", prmTyp);
  44:   
  45:          // Next, we create our actual parameter array.
  46:          object[] prm = new object[1];
  47:          
  48:          // In this case we only have one parameter, so 
  49:          // we set it as our request object.
  50:          prm.SetValue(reqObj, 0);
  51:   
  52:          // Here is where we get tricky. Since we are trying to be
  53:          // dynamic with this process, we don't want to assume a 
  54:          // definitive type for our return type. Also, in my application
  55:          // I use response objects that contain multiple properties,
  56:          // this makes passing multiple properties back easier.
  57:          System.Type respType = asm.GetType(mi.ReturnType.ToString());
  58:          
  59:          // Now, we create an object of our return type.
  60:          object respObj = Activator.CreateInstance(respType);
  61:          
  62:          // Finally, we Invoke our method passing in the parameter array.
  63:          respObj = mi.Invoke(obj, prm);
  64:   
  65:          // This is where we can parse through the properties in the 
  66:          // response object. This is similar to the setting of the 
  67:          // request properties, but there are additional Reflection 
  68:          // methods to parse these dynamically. Here, I'll just use
  69:          // predefned properties.
  70:          PropertyInfo piRespName = respType.GetProperty("Name");
  71:          string name = piRespName.GetValue(respObj, null).ToString();
  72:          PropertyInfo piRespMessage = respType.GetProperty("Message");
  73:          string message = piRespMessage.GetValue(respObj, null).ToString();
  74:   
  75:          // Prove we actualy did something.
  76:          Console.WriteLine(string.Format("{0}: {1}", name, message));
  77:      }
  78:  }

I hope this little sample helps someone else in their struggle to dynamically call code in .NET. Translation to VB shouldn't be too difficult. And as far as I know, this should work in all versions of .NET from 1.0 to 3.5.

Friday, June 6, 2008

Visual Studio Debugging with Siteminder

I've seen a few sites mentioning techniques for debugging within a Siteminder world.

This may be a little out dated since it uses Visual Studio 2003, but I'm pretty sure the technique is the same.

Without further ado, here's the steps to do debugging:

  1. Make sure Visual Studio is not running. It's not mandatory, but it makes it an easier approach.
  2. Disable Siteminder. This is usually done via config file called WebAgent.conf and is generally located in C:\Program Files\netegrity\webagent\bin\IIS\. Look for a line that looks like EnableWebAgent="YES". Change "YES" to "NO". Note: Case is VERY important!
  3. Restart IIS. Normally, this is done through the IIS management console, but a reboot will also work. However, that approach won't work later on.
  4. Start your Visual Studio instance and your Siteminder protected project.
  5. Next, after the project has fully loaded, change the "NO" back to "YES" and restart IIS. (See why rebooting doesn't work?)
  6. Now, debug using "Attach to process" and attach to the ASP.NET worker process for your Windows version.

This is a rather simplistic approach, but it works very effectively. It's a pain, but once you get used to it, it becomes second nature. One of these days, I'd like to write a script that automates this, but for now I'll settle for the extra manual steps.

Happy coding!

Update:

In VS 2008, most of these steps are not needed. In particular, steps 1 through 5 are not needed, You just need to make sure that Siteminder is enabled and you attach to the ASP.NET worker process running through IIS. This will not work in the "built in" web server in VS 2008.

Good luck!