Posterous theme by Cory Watilo

Filed under: c#

HttpContext vs HttpContextBase vs HttpContextWrapper

Http Context is handled a little differently in C# 3.5 onwards, its a little hard to get the full picture by looking at the msdn docs ("whats with these 2 new context classes???" is what i thought) so here's my take on it.

HttpContext

This is the vintage asp.net context. The problem with this is that it has no base class and isn't virtual, and hence is unusable for testing (cannot mock it). It's recommended to not pass it around as function arguments, instead pass around variables of type HttpContextBase.

HttpContextBase

This is the (new to c# 3.5) replacement to HttpContext. Since it is abstract, it is now mockable. The idea is that your functions that expect to be passed a context should expect to receive one of these. It is concretely implemented by HttpContextWrapper

HttpContextWrapper

Also new in C# 3.5 - this is the concrete implementation of HttpContextBase. To create one of these in a normal webpage, use new HttpContextWrapper(HttpContext.Current).

The idea is that to make your code unit-testable, you declare all your variables and function parameters to be of type HttpContextBase, and use an IOC framework eg Castle Windsor to get it injected. In normal code, castle is to inject the equivalent of 'new HttpContextWrapper(HttpContext.Current)', whereas in test code you're to be given a mock of HttpContextBase.

 

Converting HSV to RGB colour using C#

The other day i had to figure out how to convert HSV to RGB using C#, and after browsing the net i could only find C sample code to do it with, so i had to convert to C#. The code may be useful to someone out there (please let me know if it is):
/// <summary>
/// Convert HSV to RGB
/// h is from 0-360
/// s,v values are 0-1
/// r,g,b values are 0-255
/// Based upon http://ilab.usc.edu/wiki/index.php/HSV_And_H2SV_Color_Space#HSV_Transformation_C_.2F_C.2B.2B_Code_2
/// </summary>
void HsvToRgb(double h, double S, double V, out int r, out int g, out int b)
{
  // ######################################################################
  // T. Nathan Mundhenk
  // mundhenk@usc.edu
  // C/C++ Macro HSV to RGB

  double H = h;
  while (H < 0) { H += 360; };
  while (H >= 360) { H -= 360; };
  double R, G, B;
  if (V <= 0)
    { R = G = B = 0; }
  else if (S <= 0)
  {
    R = G = B = V;
  }
  else
  {
    double hf = H / 60.0;
    int i = (int)Math.Floor(hf);
    double f = hf - i;
    double pv = V * (1 - S);
    double qv = V * (1 - S * f);
    double tv = V * (1 - S * (1 - f));
    switch (i)
    {

      // Red is the dominant color

      case 0:
        R = V;
        G = tv;
        B = pv;
        break;

      // Green is the dominant color

      case 1:
        R = qv;
        G = V;
        B = pv;
        break;
      case 2:
        R = pv;
        G = V;
        B = tv;
        break;

      // Blue is the dominant color

      case 3:
        R = pv;
        G = qv;
        B = V;
        break;
      case 4:
        R = tv;
        G = pv;
        B = V;
        break;

      // Red is the dominant color

      case 5:
        R = V;
        G = pv;
        B = qv;
        break;

      // Just in case we overshoot on our math by a little, we put these here. Since its a switch it won't slow us down at all to put these here.

      case 6:
        R = V;
        G = tv;
        B = pv;
        break;
      case -1:
        R = V;
        G = pv;
        B = qv;
        break;

      // The color is not defined, we should throw an error.

      default:
        //LFATAL("i Value error in Pixel conversion, Value is %d", i);
        R = G = B = V; // Just pretend its black/white
        break;
    }
  }
  r = Clamp((int)(R * 255.0));
  g = Clamp((int)(G * 255.0));
  b = Clamp((int)(B * 255.0));
}

/// <summary>
/// Clamp a value to 0-255
/// </summary>
int Clamp(int i)
{
  if (i < 0) return 0;
  if (i > 255) return 255;
  return i;
}
And here's how you'd use it:
int r,g,b;
HsvToRgb(110, 1, 1, out r, out g, out b);

Opening a TCP connection in C# with a custom timeout

The TcpClient class in C# is great for opening a TCP connection, I must say that it's one of the nicest TCP libraries i've used. You just have to watch out for the occasional bug and you'll be right.

One limitation is a frustration though: the inability to set a timeout when opening a connection to a remote server. The default timeout is 60 seconds, which is quite a while to have the user strumming their fingers waiting for things to happen.

My solution to this is to spawn a thread which opens the TCP connection, while the original thread waits up to a user-specified timeout for it to connect. If it hasn't connected by then, it kills the thread and gives up. Notice the use of the thread's Join function which allows the original thread to stop waiting if the connection is quicker than the timeout. Without further ado, the TcpClientWithTimeout.cs class:

using System;
using System.Net.Sockets;
using System.Threading;

/// <summary>
/// TcpClientWithTimeout is used to open a TcpClient connection, with a 
/// user definable connection timeout in milliseconds (1000=1second)
/// Use it like this:
/// TcpClient connection = new TcpClientWithTimeout('127.0.0.1',80,1000).Connect();
/// </summary>
public class TcpClientWithTimeout
{
  protected string _hostname;
  protected int _port;
  protected int _timeout_milliseconds;
  protected TcpClient connection;
  protected bool connected;
  protected Exception exception;

  public TcpClientWithTimeout(string hostname,int port,int timeout_milliseconds)
  {
    _hostname = hostname;
    _port = port;
    _timeout_milliseconds = timeout_milliseconds;
  }
  public TcpClient Connect()
  {
    // kick off the thread that tries to connect
    connected = false;
    exception = null;
    Thread thread = new Thread(new ThreadStart(BeginConnect));
    thread.IsBackground = true; // So that a failed connection attempt 
    // wont prevent the process from terminating while it does the long timeout
    thread.Start();

    // wait for either the timeout or the thread to finish
    thread.Join(_timeout_milliseconds);

    if (connected == true) 
    {
      // it succeeded, so return the connection
      thread.Abort();
      return connection;
    }
    if (exception != null) 
    {
      // it crashed, so return the exception to the caller
      thread.Abort();
      throw exception;
    }
    else
    {
      // if it gets here, it timed out, so abort the thread and throw an exception
      thread.Abort();
      string message = string.Format("TcpClient connection to {0}:{1} timed out",
        _hostname, _port);
      throw new TimeoutException(message);
    }
  }
  protected void BeginConnect()
  {
    try
    {
      connection = new TcpClient(_hostname, _port);
      // record that it succeeded, for the main thread to return to the caller
      connected = true;
    }
    catch (Exception ex)
    {
      // record the exception for the main thread to re-throw back to the calling code
      exception = ex; 
    }
  }
}

And here's a little example of how to use this to open a connection, send 10 bytes, and receive 10 bytes:

// connect with a 5 second timeout on the connection
TcpClient connection = new TcpClientWithTimeout("www.google.com", 80, 5000).Connect();
NetworkStream stream = connection.GetStream();

// Send 10 bytes
byte[] to_send = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xa};
stream.Write(to_send, 0, to_send.Length); 

// Receive 10 bytes
byte[] readbuf = new byte[10]; // you must allocate space first
stream.ReadTimeout = 10000; // 10 second timeout on the read
stream.Read(readbuf, 0, 10); // read

// Disconnect nicely
stream.Close(); // workaround for a .net bug: http://support.microsoft.com/kb/821625
connection.Close();

Cheers all, please let me know if this is useful or if you have any constructive criticism.

Oracle Explorer - a very simple C# open source Toad alternative

Hi all, here's Oracle Explorer, a very simple C# (VS2005) open source Toad alternative for browsing through oracle databases. It was created in reaction to the awful load times of oracle's java-based Sql Developer, and i can't be bothered with the procurement process for Toad. Maybe someone wants to start a project with this and take it further? Anyway here's the obligatory screenshot:

Media_httpsplintercom_elhni
And the download (including both the EXE and source code):

https://github.com/chrishulbert/OracleExplorer

To install and run it, make sure you get the Instant Client from oracle's website, and copy the oci.dll, orannzsbb*.dll, oraocci*.dll, and oraociicus*.dll files into the same folder as the oracle explorer EXE file.

This project is a follow on from a previous blog entry here: Connecting to Oracle from C# / Winforms / Asp.net without tnsnames.ora 

Easy Integrated Active Directory Security in ASP.Net

Introduction I don't mean to rant, but if I see another 'username | password' prompt i think i'm going to choke. This post is about doing whatever you can to make this world have one less system that needs a logon prompt... This describes how to secure your Asp.Net application if you're inside an Active Directory environment, and you want to use the integrated sign on, so your users don't have to remember yet another login/password. How to limit access to your application This explains how to limit access to your application to members of a certain role/group. First you need to change your web.config so that it uses windows authentication, and make it only allow members of a specific Active Directory group. Here is the cut down web.config, showing the changes to the system.web section:
<?xml version="1.0"?> 
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0"> 
  ...etc... 
  <system.web> 
    <authentication mode="Windows" /> 
    <authorization> 
      <allow roles="MYDOMAIN\MyAppUsers" /> 
      <deny users="*" /> 
    </authorization> 
  </system.web> 
</configuration>
Then you want to make a landing page for users who aren't allowed to log in. This is just a plain HTML page, you can call it 'noaccess.htm'. Now you want to make it send disallowed people to this 'noaccess.htm'. Open or create the Global.asax page, and change/add this function:
// This redirects people without access to the noaccess.htm page 
protected void Application_EndRequest(Object sender, EventArgs e) 
{ 
  HttpContext context = HttpContext.Current; 
  if (context.Response.Status.Substring(0, 3).Equals("401")) 
  { 
    context.Response.ClearContent(); 
    context.Response.Write("<scr" + 
      "ipt language=javascript> self.location='noaccess.htm'; </sc" + 
      "ript>"); 
  } 
}
How to figure out who is logged in Quite simple this one - it is stored in this variable, accessible from your aspx.cs code-behind classes (Update - FIXED):
HttpContext.Current.Request.ServerVariables["AUTH_USER"];
Say you've got a literal control on your webform, and you want to show the currently logged on user, you could do this:
literalLoggedOnUser.Text = HttpContext.Current.Request.ServerVariables["AUTH_USER"];
How to give different permissions to different users Say you want to give some people more access than others, you'll want to create another AD group for these users: "MYDOMAIN\MyAppAdmins". Open up your web.config and add the appSettings section like so:
<?xml version="1.0"?> 
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0"> 
  <appSettings> 
    <add key="AdminGroup" value="MYDOMAIN\MyAppAdmins"/> 
  </appSettings> 
  ...etc... 
</configuration>
The reason for adding the name of the admin group in the web.config is so that if you have different AD groups for the development vs production environments, it'll be a simple matter of only changing the web.config. The principle adhered to here is that the only difference between development and production should be the web.config file. Then you'll use this piece of code to check if the current user is in that group:
string group = ConfigurationManager.AppSettings["AdminGroup"]; 
if (User.IsInRole(group)) 
{ 
  // this user is an administrator 
} 
else 
{ 
  // this user is a common pleb 
}
Hint: You're most likely to place code like that in the Page_Load function for the admin pages. Notes This is for C# ASP.Net 2. Some things may be different with VB.Net or .Net 1.1 Redirect to noaccess.htm: http://www.codeproject.com/aspnet/Custon401Page.asp