Manipulating Request.QueryString

January 25, 2012

The Request.QueryString property is declared as System.Collections.Specialized.NameValueCollection but the internal implementation is really a derived (undocumented) class called System.Web.HttpValueCollection.

You can access each query string parameter using the index operator [], but you cannot modify the parameter values or add or delete a parameter from the collection:

var q = Request.QueryString;
// => read-only System.Web.HttpValueCollection
if (q["param"] == null)
  q.Add("param", "some-value");

This code will throw a System.NotSupportedException.

Why do you want to manipulate the query string anyway? Say you have a request and you want to add/change/remove a parameter of the query string, and then redirect to the modified URL. Of course, you want to make sure that each parameter is in the URL exactly once. Request.QueryString[] provides a simply mechanism to access and modify the parameters and their values.

To get a modifiable NameValueCollection from the current request, we need the helper method System.Web.HttpUtility.ParseQueryString (which again returns an HttpValueCollection):

var q = System.Web.HttpUtility.ParseQueryString(
    Request.QueryString.ToString());
if (q["param"] == null)
    q.Add("param", "some-value");
var r = Request.Path + "?" + q.ToString();
Response.Redirect(r);

To redirect from the current request, we take the request’s Path and concatenate the collection’s ToString() result. The HttpValueCollection.ToString() adds ‘&’ and ‘=’ between parameters and their values (as opposed to NamedValueCollection.ToString() which just returns the class name).


New (empty) Window in IE9

January 25, 2012

If you press Ctrl-N in Internet Explorer (e.g. IE9), it opens a new window with the same web page. So how do you open a new empty window?

This thread lists 3 methods to open a new IE window from the taskbar:

  • Right-click an IE icon, and select “Internet Explorer”
  • Shift + Left-click on an IE icon
  • Middle-click on an IE icon

Of course, you can also select Internet Explorer from the Program Menu to get a new window.


xcopy to c:\inetpub\wwwroot fails with “Access denied”

January 25, 2012

Rather than manually copying files from \\tsclient\some\path to c:\inetpub\wwwroot\webdir I wanted to write a small batch file using xcopy and /exclude to deploy web application files.

However, even when starting the .cmd from a command line in administrator mode, I received an “Access denied” message for each file to be copied due to User Account Control prohibiting write access.

As it turns out, the task can be successfully performed using robocopy with the /zb (or /b ?) switch. (Use robocopy /? to find the huge collection of switches.)

Consequently, the feature known as xcopy deployment should therefore be renamed to robocopy deployment ;)


C# Wishlist: Null-Safe Dereferencing

January 19, 2012

During tests of a web application I came across a runtime error cause by the line:

var startUrl = Request.UrlReferrer.AbsoluteUri;

From within the application, the line works fine. However, if you paste the current URL into the address bar and hit Enter, it will cause a NullReferenceException. The obvious solution is to rewrite as

string startUrl = null;
if (Request.UrlReferrer != null)
    startUrl = Request.UrlReferrer.AbsoluteUri;

Suddenly I *knew* I wanted that null-safe dereferencing operator everybody is talking about:

Personally I prefer the ?. notation to -> or ??? I found elsewhere:

var startUrl = Request?.UrlReferrer?.AbsoluteUri;

This answer on SO illustrates a solution that is currently possible, but a bit verbose for my taste:

R NotNull<T, R>(this T src, Func<T, R> f)
      where T : class
      where R : class
{
    return src != null ? f(src) : null;
}

The class constraint on R is not necessary if you replace null with default(R):

R NotNull<T, R>(this T src, Func<T, R> f)
      where T : class
{
    return src != null ? f(src) : default(R);
}

404.2

January 19, 2012

WordPress protest: Join Our Censorship Protest!

The day after.

The Register to publish other sites’ blacked-out content in SOPA protest

Two PROTECT IP sponsors drop support for their own bill

A preview of SOPA: Web shut down before my eyes

Supporters are backing away from SOPA and PIPA

Tim Berners-Lee hits out at SOPA and PIPA

The Pirate Bay breaks its silence over PIPA and SOPA

MPAA opposes SOPA blackouts

Pirate Party, Mozilla plot anti-SOPA campaigns


404.1

January 18, 2012

More SOPA News

Google to join Wednesday’s anti-SOPA protest including other sites also going dark today.

White House shelves SOPA… now what?

Wikipedia Blackout

Imagine a World Without Free Knowledge

For over a decade, we have spent millions of hours building the largest encyclopedia in human history. Right now, the U.S. Congress is considering legislation that could fatally damage the free and open Internet. For 24 hours, to raise awareness, we are blacking out Wikipedia. Learn more.

Obama administration joins the ranks of SOPA skeptics

White House is opposing SOPA and PIPA

SOPA, Internet regulation, and the economics of piracy

SOPA blackout spreads across the Internet

Protesting SOPA: how to make your voice heard


Synchronizing Scrolling WinForms TreeViews

January 17, 2012

In my previous post I sketched the mechanism to implement a TreeView class which raises scroll events and allows setting the scrollbar positions of a custom TreeView.

Now we need to wire up the events and the scroll methods of two TreeView controls.

First, each TreeNode object needs to know its corresponding TreeNode in the other TreeView for synchronization. We can use the Tag property to store the other TreeNode like this:

var tnL = tnLeftRoot.Nodes.Add("this is node " + i);
var tnR = tnRightRoot.Nodes.Add("this is node " + i);

tnL.Tag = tnR;
tnR.Tag = tnL;

Apart from the ScrollH/V messages, we also want to synchronize the Collapse and Expand actions. If one TreeNode is collapsed or expanded, its corresponding TreeNode in the other TreeView should perform the same action:

private void tvLeft_AfterCollapse(object sender, TreeViewEventArgs e)
{
    (e.Node.Tag as TreeNode).Collapse();
}

private void tvLeft_AfterExpand(object sender, TreeViewEventArgs e)
{
    (e.Node.Tag as TreeNode).Expand();
}

Let’s also synchronize the scroll position:

private void tvLeft_ScrollH(object sender, devio.Windows.Controls.ScrollEventArgs e)
{
    tvRight.ScrollToPositionH(e.ScrollInfo);
}

private void tvLeft_ScrollV(object sender, devio.Windows.Controls.ScrollEventArgs e)
{
    tvRight.ScrollToPositionV(e.ScrollInfo);
}

Of course, these events need to be implemented for the other TreeView (tvRight) as well.

The control library and a sample WinForms application is available for download at my gforge site.


Scrolling WinForms TreeViews in Sync

January 16, 2012

For a WinForms application that implements the comparison of hierarchical data I needed to synchronize the scrollbar position of two TreeView controls: if the user moves the scrollbar in one TreeView, the other TreeView should move to the same position.

A first approach of the solution is sketched under this question on SO which subclasses the TreeView class and responds to the WM_VSCROLL message. Other discussions pointed to a solution which is currently not available, but can be fetched from the Wayback Machine.

The subclassed TreeView interacts with the Windows TreeView using the GetScrollInfo and SetScrollInfo functions of the Win32 API and the SCROLLINFO structure.

I extended the code I had found to also handle the WM_HSCROLL and WM_MOUSEWHEEL messages by implementing the WndProc() method:

protected override void WndProc(ref Message m)
{
    base.WndProc(ref m);

    switch (m.Msg)
    {
        case NativeMethods.WM_VSCROLL:
        case NativeMethods.SBM_SETSCROLLINFO:
            RaiseScrollVEvent(m.HWnd);
            break;

        case NativeMethods.WM_HSCROLL:
            RaiseScrollHEvent(m.HWnd);
            break;

        case NativeMethods.WM_MOUSEWHEEL:
            RaiseScrollVEvent(m.HWnd);
            RaiseScrollHEvent(m.HWnd);
            break;
    }
}

The RaiseScroll?Event() methods retrieve the scrollbar position (vertical or horizontal) of the tree view and raise a corresponding event in the Form’s code:

private void RaiseScrollVEvent(IntPtr handle)
{
    ScrollInfoStruct si = new ScrollInfoStruct();
    si.fMask = NativeMethods.SIF_ALL;
    si.cbSize = Marshal.SizeOf(si);

    NativeMethods.GetScrollInfo(handle, NativeMethods.SB_VERT, ref si);

    ScrollEventArgs e = new ScrollEventArgs();
    e.ScrollInfo = si;

    OnScrollV(e);
}

To adjust the scrollbar position of a tree view, we need a ScrollToPosition?() method like this:

public void ScrollToPositionV(ScrollInfoStruct si)
{
    ScrollInfoStruct siOwn = new ScrollInfoStruct();
    siOwn.fMask = NativeMethods.SIF_ALL;
    siOwn.cbSize = Marshal.SizeOf(si);

    NativeMethods.GetScrollInfo(this.Handle, NativeMethods.SB_VERT,
        ref siOwn);

    if (siOwn.nPos != si.nPos)
    {
        NativeMethods.SetScrollInfo(this.Handle.ToInt32(),
            NativeMethods.SB_VERT, ref si, true);
        NativeMethods.SendMessageLong(this.Handle.ToInt32(),
            NativeMethods.WM_VSCROLL,
            NativeMethods.SB_THUMBTRACK + 0x10000 * si.nPos, 0);
    }
}

404

January 13, 2012

I admit it was very tempting to celebrate the 404th post on this blog, rather than the 400th. Just like 1024 instead of 1000.

Incidentally however, recent events mean that the 404 jokes may turn into reality as two proposed bills are discussed and probably passed in the US.

Normally we stay away from from politics here at the official WordPress project

but the proposals of SOPA and PIPA have serious impacts on the way we can use the internet. From the Wikipedia article:

Threat to online freedom of speech

Negative impact on websites that host user content

Weakening of “safe harbor” protections for websites

General threat to web-related businesses

Threat to users uploading content

Threat to internal networks

Threat to free and open source software

Ineffectual against piracy

Deep-packet inspection and invasion of privacy

Negative impact on DNS, DNSSEC and Internet security

No doubt that in recent days SOPA is covered more frequently in online tech magazines:

Help Stop SOPA/PIPA

Reddit is ready for SOPA and PIPA protest

Fighting Internet piracy: CES takes on SOPA vs. OPEN debate

Is a pro-PIPA lobbying group guilty of e-mail “content theft?”

Congress considers anti-piracy bills that could cripple Internet industries

How SOPA would affect you: FAQ

Over 40 Internet Companies Come Out Publicly Against SOPA (Including Us)

Anonymous will shut down to protest SOPA

reddit going dark for a day to protest SOPA online censorship bill

See Ars Technica for stories about some supporters of the bill

MPAA attacks Ars for “challenging efforts to curb content theft”

Smoking guns, dark secrets aplenty in YouTube-Viacom filings

At least one of the upcoming episodes of The Daily Show promises some fun. Can’t wait for January 18.


Online Help and Computer-Based Training using DotNetNuke

January 12, 2012

A project that I am working on deals with DotNetNuke 6 as online help and/or Computer-based Training software (CBT) for an existing web application.

Both the application and DotNetNuke manage registered users and their privileges, and DNN handles the content management for the online help contents.

Note that a couple of years ago I wrote about Wikis for online help, but a Wiki (typically) does not allow for user-specific or role-specific content to be displayed, and was found as insufficient for this scenario.

The solution that we came up with was that both applications are synchronized via a custom Web Service that (mainly) matches the logins of both applications and logs application access.

Each application needed to be extended by a hyperlink mechanism that calculates the web address of the corresponding page in the other application (usually the landing page with some parameters), nicknamed “jumper” in the chart below, and the landing page itself which performs a login based on a session ID in the URL string, and redirects to the application or content page, also encoded in a URL parameter.

The DotNetNuke modules were developed using the DotNetNuke Module Development Template on CodePlex.


Follow

Get every new post delivered to your Inbox.