Was writing some XSLT for an Umbraco site recently, needed a copyright block in the footer so thought i’d just use the standard

©

syntax to add the copyright symbol, ©. When I tried to save the file, I got an error that the xml was invalid.

Turns out that © is not allowed so I used the numeric value instead

©

which works a treat.

I wonder how many times this has caught people out!

Speak to Simon Steed about any of the topics discussed this site.

Ever had a long webpage with validation that fails on postback but returns the user to the top of the page instead of where you want them?

Annoying isnt it. Well in .Net Framework 2.0 (yes it’s been there a while now), you can use the property:

Page.MaintainScrollPositionOnPostBack = true;

Well this will force the user to be returned back to the last point they clicked i.e. could be a control, button, checkbox etc

Very useful and helps with improving the user experience, something we should all be striving for!

Speak to Simon Steed about any of the topics discussed this site.

Need to know which specific control posted back to your page? (Original article at http://geekswithblogs.net/mahesh/archive/2006/06/27/83264.aspx)

/// <summary>
 /// Tells us which control posted back
 /// </summary>
 /// <returns></returns>
 public Control getPostBackControlName()
 {
 Control control = null;
 //first we will check the "__EVENTTARGET" because if post back made by       the controls
 //which used "_doPostBack" function also available in Request.Form collection.
 string ctrlname = Page.Request.Params["__EVENTTARGET"];
 if (ctrlname != null && ctrlname != String.Empty)
 control = Page.FindControl(ctrlname);

 // if __EVENTTARGET is null, the control is a button type and we need to
 // iterate over the form collection to find it
 else
 {
 string ctrlStr = String.Empty;
 Control c = null;
 foreach (string ctl in Page.Request.Form)
 {
 //handle ImageButton they having an additional "quasi-property" in their Id which identifies
 //mouse x and y coordinates
 if (ctl.EndsWith(".x") || ctl.EndsWith(".y"))
 {
 ctrlStr = ctl.Substring(0, ctl.Length - 2);
 c = Page.FindControl(ctrlStr);
 }
 else
 c = Page.FindControl(ctl);

 if (c is System.Web.UI.WebControls.Button || c is System.Web.UI.WebControls.ImageButton)
 {
 control = c;
 break;
 }
 }
 }
 return control;
 }

If you are using master pages, simply add this to the master.cs file and where you need to call the method use the following code:

MasterPage masterPage = (MasterPage)Page.Master; // where MasterPage is the class name
 Control rep = masterPage.getPostBackControlName();
 if (rep.Parent.Parent.ID == "rpRegion")// only if postback is the regions control
 GetSelectedRegion();
Speak to Simon Steed about any of the topics discussed this site.

Searching google turned up nothing on this so did some digging in MSDN and worked out a method of disabling all the style sheets, javascript etc to produce a text only page:

1/ Add a content block to your master page – i’ve called mine ‘cssContentHolder’

<asp:contentplaceholder id=”cssContentHolder” runat=”server”>
<link rel=”stylesheet” href=”css/master.css” type=”text/css” media=”all” />
<link href=”css/flyout.css” media=”screen” rel=”stylesheet” type=”text/css” />
<script src=”scripts/APIs/JQuery/JQuery-1.3.2.min.js” type=”text/javascript”></script>
<script src=”scripts/APIs/JQuery/Plugins/jquery-ui-1.7.1.custom.min.js” type=”text/javascript”></script>
</asp:contentplaceholder>

2/ In the markup, add a link button so the user can click it to remove the formatting

<asp:LinkButton  PostBackUrl=”#” ID=”textLink”  runat=”server” Text=”Text Only Version” onclick=”textLink_Click” ></asp:LinkButton>

3/ In the code behind, create an event handler for the button and add the following code

protected void textLink_Click(object sender, EventArgs e)
{
bool Hidden = Page.Master.FindControl(“cssContentHolder”).Visible ;
Page.Master.FindControl(“cssContentHolder”).Visible = !Hidden;
if (Hidden)
textLink.Text = “Switch to Graphical Version”;
else
textLink.Text = “Text Only Version”;
}

That’s it. When you click on the link, you will perform a postback to the server, get the state of the control and show/hide accordingly. It will also change the text so you can click back again.

Simple when you know how!

Using Javascript, another method to remove all the CSS but not update any link text etc is to call the following function:

function hideCSS(){
	if(document.getElementsByTagName){
		for(n=0;n<document.getElementsByTagName("link").length;n++){
			if(document.getElementsByTagName("link")[n].getAttribute){
				if(document.getElementsByTagName("link")[n].getAttribute("rel").indexOf("stylesheet")!=-1){
					document.getElementsByTagName("link")[n].disabled="disabled"
					}
				}
			}
		}
	}
Speak to Simon Steed about any of the topics discussed this site.

I recently had a problem on a job where no matter what we did, we could not control the left/right balance programmatically on two specific PC’s.

We tried using various methods:

  1. Windows Media player API
  2. DirectSound APi
  3. WinMM.dll
  4. Praying

None of them worked although you could control the balance using the Windows sound vol (sndvol.exe) program from the taskbar.

We decided to try and use the same method so out came Depends.exe and we loaded the sndvol.exe to see what libraries and methods it was loading. We discovered a likely method called mixerSetControlDetails() and promptly started to google it to discover how it worked.

The following example is the result. After a lot of searching for c# code samples, I found a chinese site that had a code listing that I could modify to possibly fix our problem.

Well to cut a long story very short (not much time today), I got it working and implemented into the project. The code is below so feel free to use as you wish.

SoundControl.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

class SoundControl
{
#region declarations

const int MAXPNAMELEN = 32;
const int MIXER_SHORT_NAME_CHARS = 16;
const int MIXER_LONG_NAME_CHARS = 64;

[Flags]
enum MIXERLINE_LINEF : uint
{
ACTIVE = 0x00000001,
DISCONNECTED = 0x00008000,
SOURCE = 0x80000000
}
[Flags]
enum MIXER : uint
{
GETLINEINFOF_DESTINATION = 0x00000000,
GETLINEINFOF_SOURCE = 0x00000001,
GETLINEINFOF_LINEID = 0x00000002,
GETLINEINFOF_COMPONENTTYPE = 0x00000003,
GETLINEINFOF_TARGETTYPE = 0x00000004,
GETLINEINFOF_QUERYMASK = 0x0000000F,

GETLINECONTROLSF_ALL = 0x00000000,
GETLINECONTROLSF_ONEBYID = 0x00000001,
GETLINECONTROLSF_ONEBYTYPE = 0x00000002,
GETLINECONTROLSF_QUERYMASK = 0x0000000F,

GETCONTROLDETAILSF_VALUE = 0x00000000,
GETCONTROLDETAILSF_LISTTEXT = 0x00000001,
GETCONTROLDETAILSF_QUERYMASK = 0x0000000F,

OBJECTF_MIXER = 0x00000000,
OBJECTF_WAVEOUT = 0x10000000,
OBJECTF_WAVEIN = 0x20000000,
OBJECTF_MIDIOUT = 0x30000000,
OBJECTF_MIDIIN = 0x40000000,
OBJECTF_AUX = 0x50000000,
OBJECTF_HANDLE = 0x80000000,
OBJECTF_HMIXER = OBJECTF_HANDLE | OBJECTF_MIXER,
OBJECTF_HWAVEOUT = OBJECTF_HANDLE | OBJECTF_WAVEOUT,
OBJECTF_HWAVEIN = OBJECTF_HANDLE | OBJECTF_WAVEIN,
OBJECTF_HMIDIOUT = OBJECTF_HANDLE | OBJECTF_MIDIOUT,
OBJECTF_HMIDIIN = OBJECTF_HANDLE | OBJECTF_MIDIIN
}
[Flags]
enum MIXERCONTROL_CT : uint
{
CLASS_MASK = 0xF0000000,
CLASS_CUSTOM = 0x00000000,
CLASS_METER = 0x10000000,
CLASS_SWITCH = 0x20000000,
CLASS_NUMBER = 0x30000000,
CLASS_SLIDER = 0x40000000,
CLASS_FADER = 0x50000000,
CLASS_TIME = 0x60000000,
CLASS_LIST = 0x70000000,

SUBCLASS_MASK = 0x0F000000,

SC_SWITCH_BOOLEAN = 0x00000000,
SC_SWITCH_BUTTON = 0x01000000,

SC_METER_POLLED = 0x00000000,

SC_TIME_MICROSECS = 0x00000000,
SC_TIME_MILLISECS = 0x01000000,

SC_LIST_SINGLE = 0x00000000,
SC_LIST_MULTIPLE = 0x01000000,

UNITS_MASK = 0x00FF0000,
UNITS_CUSTOM = 0x00000000,
UNITS_BOOLEAN = 0x00010000,
UNITS_SIGNED = 0x00020000,
UNITS_UNSIGNED = 0x00030000,
UNITS_DECIBELS = 0x00040000, /* in 10ths */
UNITS_PERCENT = 0x00050000, /* in 10ths */
}
[Flags]
enum MIXERCONTROL_CONTROLTYPE : uint
{
CUSTOM = MIXERCONTROL_CT.CLASS_CUSTOM | MIXERCONTROL_CT.UNITS_CUSTOM,
BOOLEANMETER = MIXERCONTROL_CT.CLASS_METER | MIXERCONTROL_CT.SC_METER_POLLED | MIXERCONTROL_CT.UNITS_BOOLEAN,
SIGNEDMETER = MIXERCONTROL_CT.CLASS_METER | MIXERCONTROL_CT.SC_METER_POLLED | MIXERCONTROL_CT.UNITS_SIGNED,
PEAKMETER = SIGNEDMETER + 1,
UNSIGNEDMETER = MIXERCONTROL_CT.CLASS_METER | MIXERCONTROL_CT.SC_METER_POLLED | MIXERCONTROL_CT.UNITS_UNSIGNED,
BOOLEAN = MIXERCONTROL_CT.CLASS_SWITCH | MIXERCONTROL_CT.SC_SWITCH_BOOLEAN | MIXERCONTROL_CT.UNITS_BOOLEAN,
ONOFF = BOOLEAN + 1,
MUTE = BOOLEAN + 2,
MONO = BOOLEAN + 3,
LOUDNESS = BOOLEAN + 4,
STEREOENH = BOOLEAN + 5,
BASS_BOOST = BOOLEAN + 0x00002277,
BUTTON = MIXERCONTROL_CT.CLASS_SWITCH | MIXERCONTROL_CT.SC_SWITCH_BUTTON | MIXERCONTROL_CT.UNITS_BOOLEAN,
DECIBELS = MIXERCONTROL_CT.CLASS_NUMBER | MIXERCONTROL_CT.UNITS_DECIBELS,
SIGNED = MIXERCONTROL_CT.CLASS_NUMBER | MIXERCONTROL_CT.UNITS_SIGNED,
UNSIGNED = MIXERCONTROL_CT.CLASS_NUMBER | MIXERCONTROL_CT.UNITS_UNSIGNED,
PERCENT = MIXERCONTROL_CT.CLASS_NUMBER | MIXERCONTROL_CT.UNITS_PERCENT,
SLIDER = MIXERCONTROL_CT.CLASS_SLIDER | MIXERCONTROL_CT.UNITS_SIGNED,
PAN = SLIDER + 1,
QSOUNDPAN = SLIDER + 2,
FADER = MIXERCONTROL_CT.CLASS_FADER | MIXERCONTROL_CT.UNITS_UNSIGNED,
VOLUME = FADER + 1,
BASS = FADER + 2,
TREBLE = FADER + 3,
EQUALIZER = FADER + 4,
SINGLESELECT = MIXERCONTROL_CT.CLASS_LIST | MIXERCONTROL_CT.SC_LIST_SINGLE | MIXERCONTROL_CT.UNITS_BOOLEAN,
MUX = SINGLESELECT + 1,
MULTIPLESELECT = MIXERCONTROL_CT.CLASS_LIST | MIXERCONTROL_CT.SC_LIST_MULTIPLE | MIXERCONTROL_CT.UNITS_BOOLEAN,
MIXER = MULTIPLESELECT + 1,
MICROTIME = MIXERCONTROL_CT.CLASS_TIME | MIXERCONTROL_CT.SC_TIME_MICROSECS | MIXERCONTROL_CT.UNITS_UNSIGNED,
MILLITIME = MIXERCONTROL_CT.CLASS_TIME | MIXERCONTROL_CT.SC_TIME_MILLISECS | MIXERCONTROL_CT.UNITS_UNSIGNED
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
struct MIXERLINE
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct TargetInfo
{
public uint dwType;
public uint dwDeviceID;
public ushort wMid;
public ushort wPid;
public uint vDriverVersion;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAXPNAMELEN)]
public string szPname;
}

public uint cbStruct;
public uint dwDestination;
public uint dwSource;
public uint dwLineID;
public MIXERLINE_LINEF fdwLine;
public uint dwUser;
public uint dwComponentType;
public uint cChannels;
public uint cConnection;
public uint cControls;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MIXER_SHORT_NAME_CHARS)]
public string szShortName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MIXER_LONG_NAME_CHARS)]
public string szName;
public TargetInfo Target;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
struct MIXERCONTROL
{
[StructLayout(LayoutKind.Explicit)]
public struct BoundsInfo
{
[FieldOffset(0)]
public int lMinimum;
[FieldOffset(4)]
public int lMaximum;
[FieldOffset(0)]
public uint dwMinimum;
[FieldOffset(4)]
public uint dwMaximum;
[FieldOffset(8), MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public uint[] dwReserved;
}
[StructLayout(LayoutKind.Explicit)]
public struct MetricsInfo
{
[FieldOffset(0)]
public uint cSteps;
[FieldOffset(0)]
public uint cbCustomData;
[FieldOffset(4), MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
public uint[] dwReserved;
}

public uint cbStruct;
public uint dwControlID;
public MIXERCONTROL_CONTROLTYPE dwControlType;
public uint fdwControl;
public uint cMultipleItems;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MIXER_SHORT_NAME_CHARS)]
public string szShortName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MIXER_LONG_NAME_CHARS)]
public string szName;
public BoundsInfo Bounds;
public MetricsInfo Metrics;
}
[StructLayout(LayoutKind.Explicit)]
struct MIXERLINECONTROLS
{
[FieldOffset(0)]
public uint cbStruct;
[FieldOffset(4)]
public uint dwLineID;
[FieldOffset(8)]
public uint dwControlID;
[FieldOffset(8)] // not a typo! overlaps previous field
public uint dwControlType;
[FieldOffset(12)]
public uint cControls;
[FieldOffset(16)]
public uint cbmxctrl;
[FieldOffset(20)]
public IntPtr pamxctrl;
}
[StructLayout(LayoutKind.Explicit)]
struct MIXERCONTROLDETAILS
{
[FieldOffset(0)]
public uint cbStruct;
[FieldOffset(4)]
public uint dwControlID;
[FieldOffset(8)]
public uint cChannels;
[FieldOffset(12)]
public IntPtr hwndOwner;
[FieldOffset(12)] // not a typo!
public uint cMultipleItems;
[FieldOffset(16)]
public uint cbDetails;
[FieldOffset(20)]
public IntPtr paDetails;
}
[StructLayout(LayoutKind.Sequential)]
struct VOLUME
{
public int left;
public int right;
}
struct MixerInfo
{
public uint volumeCtl;
public uint muteCtl;
public int minVolume;
public int maxVolume;
}

[DllImport("WinMM.dll", CharSet = CharSet.Auto)]
static extern uint mixerGetLineInfo(IntPtr hmxobj, ref MIXERLINE pmxl, MIXER flags);

[DllImport("WinMM.dll", CharSet = CharSet.Auto)]
static extern uint mixerGetLineControls(IntPtr hmxobj, ref MIXERLINECONTROLS pmxlc, MIXER flags);

[DllImport("WinMM.dll", CharSet = CharSet.Auto)]
static extern uint mixerGetControlDetails(IntPtr hmxobj, ref MIXERCONTROLDETAILS pmxcd, MIXER flags);

[DllImport("WinMM.dll", CharSet = CharSet.Auto)]
static extern uint mixerSetControlDetails(IntPtr hmxobj, ref MIXERCONTROLDETAILS pmxcd, MIXER flags);

#endregion declarations

#region private methods

static MixerInfo GetMixerControls()
{
MIXERLINE mxl = new MIXERLINE();
MIXERLINECONTROLS mlc = new MIXERLINECONTROLS();
mxl.cbStruct = (uint)Marshal.SizeOf(typeof(MIXERLINE));
mlc.cbStruct = (uint)Marshal.SizeOf(typeof(MIXERLINECONTROLS));

mixerGetLineInfo(IntPtr.Zero, ref mxl, MIXER.OBJECTF_MIXER | MIXER.GETLINEINFOF_DESTINATION);

mlc.dwLineID = mxl.dwLineID;
mlc.cControls = mxl.cControls;
mlc.cbmxctrl = (uint)Marshal.SizeOf(typeof(MIXERCONTROL));
mlc.pamxctrl = Marshal.AllocHGlobal((int)(mlc.cbmxctrl * mlc.cControls));

mixerGetLineControls(IntPtr.Zero, ref mlc, MIXER.OBJECTF_MIXER | MIXER.GETLINECONTROLSF_ALL);

MixerInfo rtn = new MixerInfo();

for (int i = 0; i < mlc.cControls; i++)
{
MIXERCONTROL mxc = (MIXERCONTROL)Marshal.PtrToStructure((IntPtr)((int)mlc.pamxctrl + (int)mlc.cbmxctrl * i), typeof(MIXERCONTROL));
switch (mxc.dwControlType)
{
case MIXERCONTROL_CONTROLTYPE.VOLUME:
rtn.volumeCtl = mxc.dwControlID;
rtn.minVolume = mxc.Bounds.lMinimum;
rtn.maxVolume = mxc.Bounds.lMaximum;
break;
case MIXERCONTROL_CONTROLTYPE.MUTE:
rtn.muteCtl = mxc.dwControlID;
break;
}
}

Marshal.FreeHGlobal(mlc.pamxctrl);

return rtn;
}
static VOLUME GetVolume(MixerInfo mi)
{
MIXERCONTROLDETAILS mcd = new MIXERCONTROLDETAILS();
mcd.cbStruct = (uint)Marshal.SizeOf(typeof(MIXERCONTROLDETAILS));
mcd.dwControlID = mi.volumeCtl;
mcd.cMultipleItems = 0;
mcd.cChannels = 2;
mcd.cbDetails = (uint)Marshal.SizeOf(typeof(VOLUME));
mcd.paDetails = Marshal.AllocHGlobal((int)mcd.cbDetails);

mixerGetControlDetails(IntPtr.Zero, ref mcd, MIXER.GETCONTROLDETAILSF_VALUE | MIXER.OBJECTF_MIXER);

VOLUME rtn = (VOLUME)Marshal.PtrToStructure(mcd.paDetails, typeof(VOLUME));

Marshal.FreeHGlobal(mcd.paDetails);

return rtn;
}
static bool IsMuted(MixerInfo mi)
{
MIXERCONTROLDETAILS mcd = new MIXERCONTROLDETAILS();
mcd.cbStruct = (uint)Marshal.SizeOf(typeof(MIXERCONTROLDETAILS));
mcd.dwControlID = mi.muteCtl;
mcd.cMultipleItems = 0;
mcd.cChannels = 1;
mcd.cbDetails = 4;
mcd.paDetails = Marshal.AllocHGlobal((int)mcd.cbDetails);

mixerGetControlDetails(IntPtr.Zero, ref mcd, MIXER.GETCONTROLDETAILSF_VALUE | MIXER.OBJECTF_MIXER);

int rtn = Marshal.ReadInt32(mcd.paDetails);

Marshal.FreeHGlobal(mcd.paDetails);

return rtn != 0;
}

static void MuteIt(MixerInfo mi, bool left, bool right)
{
VOLUME volume = GetVolume(mi);
if (!left && !right) // mute off
{
volume.left = 65530;
volume.right = 65530;
}
else if (left) //mute left channel
{
volume.left = 0;
volume.right = 65530;
}
else if (right) // mute right channel
{
volume.left = 65530;
volume.right = 0;
}

SetVolume(mi, volume);
}

static void SetVolume(MixerInfo mi, VOLUME volume)
{
MIXERCONTROLDETAILS mcd = new MIXERCONTROLDETAILS();
mcd.cbStruct = (uint)Marshal.SizeOf(typeof(MIXERCONTROLDETAILS));
mcd.dwControlID = mi.volumeCtl;
mcd.cMultipleItems = 0;
mcd.cChannels = 2;
mcd.cbDetails = (uint)Marshal.SizeOf(typeof(VOLUME));
mcd.paDetails = Marshal.AllocHGlobal((int)mcd.cbDetails);

Marshal.StructureToPtr(volume, mcd.paDetails, false);

mixerSetControlDetails(IntPtr.Zero, ref mcd, MIXER.GETCONTROLDETAILSF_VALUE | MIXER.OBJECTF_MIXER);

Marshal.FreeHGlobal(mcd.paDetails);
}

#endregion private methods

#region public methods

/// <summary>
/// Mutes the left hand channel and transfers audio fully to the right
/// </summary>
public void MuteLeftChannel()
{
MixerInfo mi = GetMixerControls();
MuteIt(mi, false, true);
}

/// <summary>
/// Mutes the right hand channel and transfers audio fully to the left
/// </summary>
public void MuteRightChannel()
{
MixerInfo mi = GetMixerControls();
MuteIt(mi, true, false);
}

public void MuteOff()
{
MixerInfo mi = GetMixerControls();
MuteIt(mi, false, false);
}

#endregion public methods
}

You call it as follows:

private void CreateSoundControl()
{
if (sndMute != null) return;
sndMute = new SoundControl();
}

private void btnRight_Click(object sender, EventArgs e)
{
CreateSoundControl();
sndMute.MuteRightChannel();
}

private void btnLeft_Click(object sender, EventArgs e)
{
CreateSoundControl();
sndMute.MuteLeftChannel();
}

private void btnCenter_Click(object sender, EventArgs e)
{
CreateSoundControl();
sndMute.MuteOff();

}

Download the source files here

Enjoy – remember if your machine blows up or crashes, do not blame me :)

Speak to Simon Steed about any of the topics discussed this site.

URL Rewriting in asp.net (c#). (Download Example Project for URL Rewriting in asp.net at the end of this article)

One way to get yourselves rated better in the search engines is to get rid of the basic aspx page and replace it with something much more descriptive i.e.:

If I were selling Nokia phones, I may have a page called http://www.mydomain.com/nokia.aspx – not much good if I am trying to target a specific phone though is it? What about this then?

http://www.mydomain.com/Nokia-E71-Mobile-Phone-With-Email-And-Internet-Browser

Much more descriptive and much more likely to get the search engines juices flowing more and hence get you rated higher in the listings.

After searching around for a few solutions, I found this article by Scott GU (Microsoft Guru Extraordinaire) http://weblogs.asp.net/scottgu/archive/2007/02/26/tip-trick-url-rewriting-with-asp-net.aspx which got me excited.

He mentions a few methods, one of which I use on http://www.simonantony.co.uk which is running IIS7 by using the Rewrite module built into IIS – works a treat and has allowed me to convert a static html site into a more dynamic and search engine friendly version.

The other is to use a library from http://urlrewriter.net/ which is the other route I have taken. I’ve successfully implemented this on a project I am currently working upon and thought it would be nice of me to post some fully working example code that you can actually understand – the examples on the urlrewriter website/demos are very poor and not clear at all – no wonder so many people struggle to get it working.

Some blurb from the URLRewriting website will explain it more:

UrlRewriter.NET is an open-source, light-weight, highly configurable URL rewriting component for ASP.NET 1.1 and 2.0. UrlRewriter.NET provides similar IIS Rewrite capabilities that the Apache web server provides with mod_rewrite and .htaccess. You don’t need to install an ISAPI Rewrite filter to use the component. Best of all, UrlRewriter.NET is free and licensed with a very permissive MIT-style licence.

UrlRewriter.NET is a great Search Engine Optimization (SEO) tool. Using UrlRewriter.NET, you can create URL’s containing your target keywords, boosting your rankings.

With UrlRewriter.NET, you can:

* Rewrite URL’s from “user and Search Engine” friendly urls to the actual .aspx pages (also known as URL Masking, IIS Rewrite or ASP Rewrite)
* Redirect from old URL patterns to the new ones, ensuring the Search Engine spiders continue to follow your links (also known as URL Replace)
* Block certain visitors based on the User-Agent – very helpful for blocking crawlers that don’t obey the robots.txt protocol
* Ban users based on IP range (provides the capabilities of mod_rewrite on IIS)
* And much more…

UrlRewriter.NET is a pure .NET component written in C#, and does not require any ISAPI rewrite dll’s to be installed in IIS. You configure rules in a very readable XML format, either in your web.config file or an external rewriter configuration file.

UrlRewriter.NET is in use in many websites large and small such as DotNetKicks, and is embedded in several open source packages, such as the fantastic Yet Another Forum.NET.

Anyway here is how the project is constructed and how to get it working.

  1. Create a new web project – I am using C# but if you really want to you can use VB
  2. Download the urlrewriting library from the official site http://urlrewriter.net
  3. Add a reference to the UrlRewritingNet.UrlRewriter.dll to your project
  4. Open up the web.config file and replace the content with the following code:

<?xml version=”1.0″?>
<configuration>
<configSections>
<section name=”urlrewritingnet” requirePermission=”false”  type=”UrlRewritingNet.Configuration.UrlRewriteSection, UrlRewritingNet.UrlRewriter”  />
</configSections>

<urlrewritingnet
rewriteOnlyVirtualUrls=”true”
contextItemsPrefix=”QueryString”
defaultPage=”default.aspx”
defaultProvider=”RegEx”
xmlns=”http://www.urlrewriting.net/schemas/config/2006/07″ >
<rewrites>
<add name=”this-is-a-long-page-name”  virtualUrl=”^~/this-is-a-long-page-name”
rewriteUrlParameter=”ExcludeFromClientQueryString”
destinationUrl=”~/longpage.aspx”
ignoreCase=”true” />

<add name=”Product-Search-uk”  virtualUrl=”^~/Product-Search-uk”
rewriteUrlParameter=”ExcludeFromClientQueryString”
destinationUrl=”~/search.aspx”
ignoreCase=”true” />

<add name=”submit-your-company”  virtualUrl=”^~/submit-your-company”
rewriteUrlParameter=”ExcludeFromClientQueryString”
destinationUrl=”~/submit_company.aspx”
ignoreCase=”true” />

<add name=”this-is-my-site-blog”  virtualUrl=”^~/this-is-my-site-blog”
rewriteUrlParameter=”ExcludeFromClientQueryString”
destinationUrl=”~/blog.aspx”
ignoreCase=”true” />

<add name=”contact-my-company”  virtualUrl=”^~/contact-my-company”
rewriteUrlParameter=”ExcludeFromClientQueryString”
destinationUrl=”~/contact.aspx”
ignoreCase=”true” />

<add name=”Product-Search-uk-partnumber”  virtualUrl=”^~/product(.*).aspx”
rewriteUrlParameter=”ExcludeFromClientQueryString”
destinationUrl=”~/search.aspx?id=$1″
ignoreCase=”true” />

<!–<add name=”Rewrite”  virtualUrl=”^~/(.*)/Detail(.*).aspx”
rewriteUrlParameter=”ExcludeFromClientQueryString”
destinationUrl=”~/Default.aspx?language=$1&amp;id=$2″
ignoreCase=”true” />

<add name=”RedirectInApplication”  virtualUrl=”^~/(.*)/Default.aspx”
rewriteUrlParameter=”ExcludeFromClientQueryString”
destinationUrl=”~/$1/Detail_Redirected.aspx”
redirect=”Application”
redirectMode=”Permanent”
ignoreCase=”true” />

<add name=”KickBrowserToDomain”  virtualUrl=”^http\://(.*)/SampleWeb/kickto/(.*).aspx”
rewriteUrlParameter=”ExcludeFromClientQueryString”
destinationUrl=”http://$2?source=$1″
redirect=”Domain”
redirectMode=”Permanent”
ignoreCase=”true” />–>
</rewrites>
</urlrewritingnet>

<appSettings/>
<system.web>
<customErrors mode=”Off”>
</customErrors>
<httpModules>
<add name=”UrlRewriteModule” type=”UrlRewritingNet.Web.UrlRewriteModule, UrlRewritingNet.UrlRewriter” />
</httpModules>
<compilation debug=”true” />
</system.web>
</configuration>

    • Create the aspx pages
      1. blog.aspx
      2. contact.aspx
      3. default.aspx (this should already exist)
      4. longpage.aspx
      5. search.aspx
      6. submit_company.aspx
        • In Default.aspx add the following code:

          <div id=”nav”>
          <div id=”navcontainer”>
          <ul id=”navlist”>
          <li><a href=”default.aspx”>Home</a></li>
          <li><a href=”this-is-a-long-page-name”>this-is-a-long-page-name</a></li>
          <li><a href=”Product-Search-uk”>Product Search</a></li>
          <li><a href=”submit-your-company”>Submit your company</a></li>
          <li><a href=”this-is-my-site-blog”>Blog</a></li>
          <li><a href=”contact-my-company”>Contact</a></li>
          <li><a href=”product123.aspx”>Note that this aspx page does not actually exist – click it and see what happens</a></li>

          </ul>
          </div>
          </div>

          You will notice that the href links are defined in the web.config file.

            • In search.aspx, add the following html code:

              <div>
              This is the region page – if you click on <a href=”product12345.aspx”>product12345.aspx</a>, you will be redirected here but the code will show the arguments of the page i.e. 12345 – confused? You will be!

              </div>

                • Now open up the code behind file for search.aspx and add in the Page_Load event:

                  if(Request.QueryString[“id”] != null)
                  Response.Write(“querystring passed in: ” + Request.QueryString[“id”]);
                  else
                  Response.Write(“No query string passed in”);

                    • Run the project. If you click on the search link, you will be taken to the search page but notice the URL in the browser window as it should be reading Product-Search-UK. Same for the other url’s as well except for the last one, if you click on that, a product id will be passed into the page as a querystring that you can use to display specific products on a single page – clever eh!

                      Anyway I hope this has helped you understand how to get a basic implementation of URL Rewriting in your site – i’d love to hear of any more examples you have used, if you want to post them here let me know.

                      Si

                      Download Example Project for URL Rewriting in asp.net

                      Speak to Simon Steed about any of the topics discussed this site.

                      Today the Prime Minister Gordon Brown visited Manchester based company EDM Ltd. He was shown around the factory by the staff members and had a hands on with some of the training simulators that the company produces and then went on to present an hour long seminar on business and export.

                      Mr Brown visited the site due to the strong exports that the company produces, especially in these trying times. EDM exports strongly all over the world with their trainer systems and the MD Kevin Bird has recently returned from a trip to China to secure more business in the coming weeks.

                      Mr Brown was particularly interested in the railway simulator recently purchased by Northern Ireland Railways and also the Continental Boeing 787 dreamliner door trainer systems – both of which Simon Steed (author) actually worked upon and helped design the software.

                      The railway simulator uses touch screen technology to provide a means to train signallers on railway operations. The door trainers provide means to train cabin crew in the operation of the various parts of the aircraft, primarily door operation but also cabin procedures etc.

                      All the software was written using the Microsoft Dotnet framework by EDM

                      Gordon Brown arriving at EDM with his entourageGordon Brown arrives at EDM

                      Quoted from the Number 10 website:

                      Thursday 12 March 2009

                      PM pledges support for exporters

                      Gordon Brown in Manchester - PA copyrightThe Prime Minister has pledged more support for British exporters to help expansion into new foreign markets during the downturn.

                      The Government plans to provide specialist and tailored financial and legal advice to over 1,200 businesses in the coming year.

                      The PM said that although times are tough, opportunities for new export growth still exist.

                      “There are still markets for British goods if we help businesses access them. That is why it is vital we give British businesses world class support to make the most of global opportunities and increase their activity in overseas markets.”

                      Gordon Brown and the Minister for Trade and Investment, Lord Davies, spoke to 100 of the North West’s largest business exporters this morning.

                      The PM said that a recent survey found companies that export tend to be more resilient in a downturn. He said 42% of exporters increased their turnover in the past 12 months, compared with only 23% overall.

                      But Lord Davies said small and medium businesses needed to continue to be flexible and innovative to seek out new export opportunities.

                      “Small businesses can find it hard to break into new markets on their own and UKTI is there to help. The £3.5 million programme ‘Gateway to Global Growth’ will start from April helping SMEs to access foreign markets where they see potential for their business.”

                      The Prime Minister’s visit coincided with the launch of the Real Help Now guide for the North West.

                      http://www.number10.gov.uk/Page18581

                      Speak to Simon Steed about any of the topics discussed this site.

                      Add META keywords and Description in ASP.NET

                      Here is the syntax for programmatically adding META tags to an ASP.NET 2.0 page.

                      HtmlMeta metaDesc = new HtmlMeta();

                      metaDesc.Name = “description”;

                      metaDesc.Content = “Tips on roasting coffee at home”;

                      Page.Header.Controls.Add(metaDesc);

                      HtmlMeta metaKey = new HtmlMeta();

                      metaKey.Name = “keywords”;

                      metaKey.Content = “roast, coffee, home, tips”;

                      Page.Header.Controls.Add(metaKey);

                      ASP.NET will render the above code to valid XHTML META tags.

                      via Add META keywords and Description in ASP.NET (DigitalColony.com).

                      Speak to Simon Steed about any of the topics discussed this site.
                      Fatal error: Allowed memory size of 41943040 bytes exhausted (tried to allocate 376093 bytes) in D:\Sites\xploiter.com\public_html\blog\wp-includes\formatting.php on line 300