Archive for ASP.NET

brief list of things that make working in C# frustrating

Problem: .NET framework classes don’t use interfaces enough

Specific example: DataSource / DataBind()are separately defined on Repeater and GridView, (and Control, and many, many others), and my abstract base class doesn’t care which option an implementor chooses, it just wants to bind the data however the base control wants it.

Possible Solutions:

  • Define interface IDataBinding, class MyRepeater : Repeater, IDataBinding, class MyGridView : GridView, IDataBinding, etc.
  • Define interface IDataBinding, upgrade to C# 3, use extension methods to add IDataBinding nope, extension methods can’t do this
  • Copy/paste identical code from my base class into concrete classes
  • Use reflection to set DataSource and call DataBind(), completely sidestepping the C# type system

Problem: .NET framework classes not designed for extension: “cannot override inherited member 'System.Collections.Generic.Dictionary<X, Y>.Add(X, Y)' because it is not marked virtual, abstract, or override

Specific Example: Extending System.Collections.Generic.Dictionary to do some permit a list of values for one key, so adding the first item is stored as a single value, but adding a second value to the same key stores both values in a list. Error message is: “cannot override inherited member 'System.Collections.Generic.Dictionary<X, Y>.Add(X, Y)' because it is not marked virtual, abstract, or override

Possible Solutions:

  • Define wrapper classes that encapsulates the framework class and implements all the base interfaces, with the vast majority of the code being straight delegation to the framework class:
    class MyDict : IDictionary, [other interfaces...] {
    private Dictionary<X,Y> dict = new Dictionary<X,Y>;
    public bool Contains(X key){ return dict.Contains(key);}
    [... other simple wrappers...]
    }
  • Find a less appropriate framework class that is designed for extension, duplicate behavior of the proper framework class manually, eg: add run-time type checks for Hashtable.Add(object, object) in place of the letting the compiler handle the types as in Dictionary<X,Y>.Add(X, Y)
  • Extend Dictionary<X,Y>, define a method AddList(X,Y), and avoid using IDictionary in the rest of my code
  • Upgrade the C# 3, use extension to add function AddList to IDictionary, be sure to include those extensions on every consumer of IDictionary

Problem: .NET framwork classes not designed for extension: members declared private/ internal / protected internal

Specific Example: Storing additional data in ViewState on 2 different controls that have different base classes. One is a user control, another extends RadioButtonList to provide different UI for the same data

Possible solutions:

  • Upgrade to C# 3, use extension methods to add functions nope, extension methods can only see public members, ViewState is protected
  • Use reflection to set ViewState
  • Copy/paste code into each control
  • Define interface IPublicViewstate, class MyRadioButtonList : RadioButtonList, IPublicViewState, class MyUserControl : UserControl, IPublicViewState, etc

As Nathan said, I’m stuck between a rock and IHardPlace.

Comments (2)

CAS Authentication in C#

For a recent project I wanted to authenticate using Central Authentication Service (CAS), a single-sign on server deployed world-wide. My project is in ASP.NET, so I hunted down CASP, a C# class produced by John Tantalo at Case Western Reserve University. Coincidentally, John was also responsible for Planarity, a flash game which has only stolen mere days of my life.

I had a few nits to pick with it, so at the risk of calling his baby ugly:

  1. Doesn't handle the latest CAS protocol, CAS2
  2. Dumps the authenticated username into Session, which isn't what I wanted
  3. Doesn't use "using" statements when dealing with IDisposable objects
  4. Doesn't use XML comments, which .NET tools prefer
  5. Some minor duplication in specifying the login URL and the validation URL.

So, all in all nothing really big. I ended up going a little nuts with it resolving all my complaints. It can now speak CAS1 or CAS2, and has a bunch of options that I added in to solve my specific needs. It seems a little overcomplicated now, but I always get that feeling when I'm thinking in C#.

Installation

Pretty simple:

  1. Download the source: CASP.cs (BSD license)
  2. Add it to your project

Example usage

Like Tantalo's CASP, mine is designed to be used from a System.Web.UI.Page, and will redirect the browser about as needed.

Simplest example, uses CAS2 by default

C#:
  1. protected void Page_Load(object sender, EventArgs e) {
  2.   string username = CASP.Authenticate("https://login.case.edu/cas/", this.Page);
  3.   //do whatever with username
  4. }

Slightly more complex, using CAS1 and always renewing the authentication ticket

C#:
  1. protected void Page_Load(object sender, EventArgs e) {
  2.   string username = CASP.Authenticate("https://login.case.edu/cas/", this.Page, true, false);
  3.   //do whatever with username
  4. }

Most complex example, giving you flexibility to decide what to do about errors, etc

C#:
  1. protected void Page_Load(object sender, EventArgs e) {
  2.   CASP casp = new CASP("https://login.case.edu/cas/", this.Page, true); //re-login every time
  3.   if (casp.Login()) {
  4.     try {
  5.       string username = casp.ServerValidate(); //or casp.Validate() for CAS1
  6.       //do whatever with username
  7.     }catch (CASP.ValidateException ex) {
  8.       //try again, something was messed up
  9.       casp.Login(true);
  10.     }
  11.   }
  12. }

This code is certified:
works on my machine

Comments

Server Application Unavailable, no event log, .NET 2

A perplexing error while setting up my new system:

Server Application Unavailable

The web application you are attempting to access on this web server is currently unavailable.

Please hit the "Refresh" button in your web browser to retry your request.

Administrator Note: An error message detailing the cause of this specific request failure can be found in the system event log of the web server. Please review this log entry to discover what caused this error to occur.

The web leads me far astray. I did not have anything in the event log.

The solution? Give MACHINE/ASPNET permission to my project. I found this a LOT faster by switching to .NET 1.1 in IIS, and that gave a much more useful error message. I guess "Server Application Unavailable" is .NET 2's way of crapping its pants.

Comments (1)