Friday, 20 April 2007

Fiddler Reverse Proxy Setup

The Fiddler documentation includes instructions on how to configure the tool as a reverse proxy (http://www.fiddlertool.com/Fiddler/help/reverseproxy.asp). Option #1 is only useful if you're setting up Fiddler as a local reverse proxy; if you want to use Fiddler from external clients, you need to go for Option #2.

The code snippet to be added to your custom rules file includes two string listerals: "webserver:8888" and "webserver:80". It's in important to note that "webserver" is not a variable name--it must be replaced with the name of your web server (i.e. MyServer, as in http://myserver). The other important thing is to add the code snippet to the OnBeforeRequest function and not the OnBeforeResponse function. You'll also probably want to allow remote clients to connet via Fiddler so make sure the Tools -> Fiddler Options... Allow remote clients to connect options is selected.

You can change the listen port from 8888 via Tools -> Fiddler Options... Listen Port if you want to use a port other than 8888.

If you implement both Option #1 and Option #2 you might end up with problems like an infinite loop.

The change may take a little while to come into effect so meanwhile, try restarting Fiddler, running an iisreset, or rebooting.

Tuesday, 17 April 2007

How to determine if a page is in edit mode

SPContext.Current.FormContext.FormMode == SPControlMode.Edit

Alternatively, use an EditModePanel (the PageDisplayMode can be set for specific display modes).

Javascript Debugging in VS2005

See this link for a useful article on Javascript debugging with Visual Studio 2005. I managed to get it working using a basic page consisting of a single button with an OnClientClick attribute calling a simple inline function. I also played around with using the Javascript debugger; statement to break into the runtime document, which proved handy when attaching to the running server process instead of starting off via F5.

By the way, Firebug has a Javascript debugger and while it's pretty clunky, it might help get you out of a jam (Firebug is useful for so many other reasons as well).

http://blogs.msdn.com/webdevtools/archive/2007/03/08/jscript-debugging-in-visual-studio-2005.aspx

Thursday, 12 April 2007

Determining the current variation

If you need to find out which variation a client has requested, this code might do the trick.

Start by getting the current VariationLabel; then compare its title against a known variation title.


VariationLabel currentVariation = PublishingWeb.GetPublishingWeb
(SPContext.Current.Web).Label;

if (currentVariation != null &&
currentVariation.Title.ToLowerInvariant () ==
"au")
{
//do something
}

Tuesday, 3 April 2007

Saturday Shopping

I don't understand what went wrong with my parent's generation. They showed so much promise with their bombs, telecommunication, and political reform but they make out as though the race to the moon was only the first stage in the race of life: hussle, bussle--they can't get there fast enough no matter the price. In contrast, I believe our generation is now responsible for putting the humanity back into a world left devoid of everything but some elusive end goal.

Saturday grocery shopping, if you do it regularly, makes the Christmas rush seem like nothing out of ordinary. The shops are busy, the shelves are empty, and no one really wants to be there. I'm a happy Saturday shopper and I use each experience to test and develop my patience. Most times I make it through.

This Saturday seemed especially busy for whatever reason. It was the first cool weekend in a long while so my guess is families were out to stock up after a month of lying around sweating. Nevermind, I thought, I'm in no rush today so I'll just have to try extra hard to be patient and polite; "after you", "go ahead", smile and say "excuse me, thank you." With the narrow isles full of the overweight, carts, and mothers with strollers for triplets, there would be, I knew, a lot of standing around waiting.

At one point, momentarily frozen int time waiting for the isle to clear before I could move past the stacks of broken eggs and on towards the vegetarian sausages, my personal space suddenly vanished as a well-dressed, dark-haired woman well into middle-age squeezed up next to me and then bolted past into the gap only to stop in front of me. "Now that's pushing it, lady," I thought to myself. No "excuse me", no smile, only an in-grained push to get there sooner, get the job done, and trample anyone in the way.

"Have a taste of your own medicine, if you're going to be that way," I shouted at her in my mind as I plowed into the melay of shopping carts and unwashed Saturday shoppers. With her cart in the mix, the gap had narrowed significantly so I pushed forward, nosing my cart into what must have been the one piece of unoccupied real-estate in the entire store. I plowed her cart out of the way and then knocked it again for good measure before continuing on my way, a dazed mother glaring at me all the while. Yes, shame on me for my childish retaliation but let that be a lesson to the pushy woman.

I shuffled on in my sandy thongs not feeling any better for my actions--on reflection, feeling worse. Nevertheless, my calm depened as I resolve to kick back against the rush and hurry imposed on me by this boom-time generation. With all the man-made pressures built into our lives I'm finally beginning to understand why so many of me friends and classmates turned to cigarettes, booze, and pot over the years.

I always think back to my drives between Montreal and Ottawa as a university student returning home for a weekend or during the holidays. The old Grand Marquis I drove (a 5.0 litre V8) handled the drive at 140km/h quite happily but as the car moved ever closer to the scrap heap, exaust fumes seeping in through the salt-rusted holes in the floor meant the trip had to be completed at 90km/h in the slow lane. At either speed, the journey always took two hours.

Sunday, 25 March 2007

XmlSerializer and minOccurs="0" collections: that pesky xxxSpecified magic

I'm attempting to decorate the properties in a class so when it's serialised by the XmlSerializer, it adheres to a schema that looks, in part, like this:

<xs:element minoccurs="0" name="Locations">
<?xml:namespace prefix = xs /><xs:complextype>
<xs:sequence>
<xs:element name="Location" maxoccurs="unbounded" type="xs:string">
</xs:sequence>
</xs:complextype>

Basically, I've got a class that contains a Locations collections; if the collection has one or more items, it should be serialized and if it has zero items, it shouldn't be serialized and, most importantly, the Locations element should NOT appear in the serialized document.

Running the property below through the XmlSerializer works fine if the collection is populated but results in an empty element if the collection is empty.

So this:

[System.Xml.Serialization.XmlArrayItemAttribute ("Location")]
public List Locations
{
get
{
return SearchAttributes.Locations;
}
}

populated at runtime with zero items results in this:

<locations>

And schema validation fails.

I've looked at various attributes trying to find something that will optionally serialize an element or collection but nothing jumps out.

XSD.exe produces the following property from the schema but by itself does nothing to help out here.

[System.Xml.Serialization.XmlArrayAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
[System.Xml.Serialization.XmlArrayItemAttribute("Location", Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=false)]
public string[] Locations {
get {
return this.locationsField;
}
set {
this.locationsField = value;
}
}

Another XSD example produced an xxxSpecified property for a minOccurs="0" element (not a collection) and setting it false does remove the element from the output; I can't figure out why this works though! Sticking it into my own class does some sort of magic though:


private bool locationsSpecified;

[System.Xml.Serialization.XmlIgnoreAttribute ()]
public bool LocationsSpecified
{
get
{
return this.locationsSpecified;
}
set
{
this.locationsSpecified = value;
}
}


The LocationsSpecified property is simply set by the caller and voila, Locations disappears if empty.

Tuesday, 27 February 2007

Metric Time

As a computer scientist, working with standard units of time can be a frustrating experience. I'm sure the existing time and calendar systems made sense when everyone followed the gods, the moon, the sun, and the seasons but I think it's safe to say most of the first world population rely on a digital watch and computer-based calendar (and for those who don't, then there's even more reason to move away from their old world equivalents). Since no sane person uses imperial measurement anymore unless they're American or my mom (are either really sane?), I, Pope Michaelus I, hereby deem it 'time' to make the move to metric time. I think we all can handle it.

Everything in glorious units of ten (except weeks—a ten day week might kill me... oh yeah, and months will be a bit weird). So I propose not quite metric time and it all hangs on the seven-day week:

1 year = 10 months

It's pretty simple and time will seem like it goes even faster but you won't get old as quickly.

1 month = 4 weeks

We definitely need to keep months so we can continue having cake days at work once a month. I guess they're communal birthday celebration days really but it's not like I know half the birthday boys and girls anyway. Anyway, cake day might get lost in a year without months. 4 weeks (or 28 days) is a nice compromise and even though 28 is a weird number, at least it will be static. And no leap years—time can move independent of the sun so let it. A month could, following debate, be drawn out to 5 weeks for quasi-metric support but you know what those 31-day months are like—imagine every month being 35 days long. 28 days = more cake.

1 week = 7 days

I'm working a lot of overtime at work these days—mainly weekends—and from current hands-on experience I can tell you do I don't want a 10 day work week. Without a doubt, the business analysts and project managers would jump at the idea so this one's gotta be a special case and it's got to be set in stone up front. 7 is also a lucky number.

1 day = 10 hours

This is where things start getting a bit difficult. A ten hour 'day' is miles off our current 24-hour day so there'll definitely be some adjusting to do. If you put this in context with a week and weeks in months and months in years, those units also start going a bit wonky. But fingers crossed, it'll all work out something like Mexico with lots of sunshine and siesta time. And burritos.

1 hour = 100 minutes

I'm tempted to stick with 10s on this one but seeing as how we've already shrunk down days and stuff... 100 minutes per hour makes sense anyway. Sort of like those 90-minute classes they made me get through in high school—bearable, just. I think all the clock watchers at work would blow a fuse if an hour went by in ten minutes. At any rate, 100s are still metric, so stop your complaining.

1 minute = 100 seconds

No one cares about seconds anyway so just K.I.S.S.

1 second = 1 second

No more of this milli and micro b.s. Like I said, K.I.S.S. and I can never remember which is which so just forget it. Just talk about half a second or tenths of a second or .0484822999299000123 and you'll be fine. That's the beauty of the metric system. Could even just get rid of seconds altogether and just think about bits of a minute—easy!

And of course, most importantly, there will be no daylight savings. I actually read a post out from some guy who manually hacked the Windows registry to program Western Australia Daylight Savings into his PC before Microsoft released their dodgy patch that doesn't work with Vista. I'm a west-aussie so I had to dig around, you see. Anyway, geeks being geeks, I think this guy could have put his time and talents to better use. The debate rages over here but simplicity for us programmers pretty much blows all other arguments out of the water.

By the way, metric time started about half an hour ago so someone better find that registry hacker and see if he fix up our Windows clocks to work all metric like. No doubt Outlook will be off for a while but meetings are a waste of time anyway.

Monday, 26 February 2007

Basic CSS

1. Styles (classes and selectors) can be declared so they're relative to their physically enclosing block

#container .relativeClass
{
color: red;
}

<div id="container">
<span class="relativeClass">My red paragraph</span>
</div>

If relativeClass is assigned to an element that doesn't have the 'container' id, the style will have no effect.

The .reativeClass name can be safely reused/redefined within different scopes.

Elements can be specified to have a specific style within the scope of an enclosing block as well:

#divContainer p
{
color: red;
}

.classContainer p
{
color: red;
}

2. Styles (classes and selectors) can also be declared so they're relative to another class or selector

.containerClass .nestedClass
{
color: red;
}

#containerId #nestedId
{
color: green;
}

3. Classes and selectors can be constrained to apply only to a specific element

p.elementLimitClass
{
color: red;
}

p#elementLimitId
{
color: green;
}

<p class="elementLimitClass">My elemented limited class paragraph</p>

<p id="elementLimitId">My elemented limited id paragraph</p>

Friday, 16 February 2007

Generic Dictionary Wrapper Class Cannot be Restored from ViewState

The .NET 2.0 generic Dictionary class can be serialised to and deserialised from the ViewState of a web application but extending the Dictionary class to derive a named collection grounded in the business domain requires some extra attention. Essentially, the derived class needs to call a specific constructor in the base class when deserialisation occurs and this doesn't happen implicitly (List-based classes seem to work fine without modification). Note: the derived class will serialise happily--deserialisation is the problem).

The System.Collections.Generic.Dictionary class defines a constructor used to restore the Dictionary's internal data during the deserialisation process:

"Initializes a new instance of the Dictionary class with serialized data."

protected Dictionary (
SerializationInfo info,
StreamingContext context
)


Constructors are not inherited in C# so a wrapper class must explicitly define this constructor and pass the data back up the inheritance hierarchy to the base Dictionary class:

[Serializable]
public class CustomCollection : Dictionary
{
protected CustomCollection (
System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context

) : base (info, context)
{
// no implementation
}
}

Depending on how you construct your wrapper class, you'll most likely want to define additional constructors as well or the default (empty) constructor at a minimum as it will no longer be injected by the compiler with the deserialisation constructor present.

Without this constructor, I was receiving a corrupted ViewState exception

The state information is invalid for this page and might be corrupted.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

.NET Properties – Infinite Loop

What's wrong with this code?

public bool IsModify
{
get
{
return IsModify;
}
set
{
IsModify = value;
}
}

The title of the post might give away the problem. This code will compile happily and any surrounding code will most likely execute without a problem—until the property is accessed. You have to look closely and compare the property name with the variable name but once you do, you'll realise they're identical; the result is get calling get on IsModify and so until a StackOverflowException is thrown—an infinite loop (the same thing occurs with the set).

What I failed to reveal in the code above is the variable name the property should be wrapping (note the casing):

private bool isModify;

Unfortunately, Visual Studio 2005 doesn't issue a warning about this potentially disastrous little bit of code.

What the problem boils down to is a difference in casing between the variable name and the property. My team's coding standards dictate this naming convention but I otherwise might have used _isModify for the local variable to identify it as such and differentiate it from its property name. On a style note, I find the underscores make the code a bit busy and my eye tends to jump to the variable names—which is probably inappropriate. Alternatively, I could give the variable a completely different name from the property name but that severs the implicit connection between the two.

This can result in all sorts of semi-intelligible error messages. Today, after waiting for the server to run its course, I got my old favourite:

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 application event log of the web server. Please review this log entry to discover what caused this error to occur.

The event log reveals two entries of interest:

Event Type: Error
Event Source: .NET Runtime 2.0 Error Reporting
Event Category: None
Event ID: 5000
Date: 16/02/2007
Time: 8:02:51 AM
User: N/A
Computer: PHO02078ITDEV
Description:
clr20r3, P1 aspnet_wp.exe, P2 2.0.50727.210, P3 45063b16, P4 app_web_nr0px690, P5 0.0.0.0, P6 45d4e6d7, P7 8, P8 0, P9 system.stackoverflowexception, P10 NIL.

and

Event Type: Error
Event Source: ASP.NET 2.0.50727.0
Event Category: None
Event ID: 1008
Date: 16/02/2007
Time: 8:02:59 AM
User: N/A
Computer: PHO02078ITDEV
Description:
aspnet_wp.exe (PID: 2168) was recycled because it failed to respond to ping message.