TortoiseSVN Checkout from localhost:port Results in “‘svn://localhost:port/path’ isn’t in the same repository as ‘svn:localhost/path'”

January 31, 2012

Connecting to a SVN repository via PuTTY, I configured an SSH tunnel from local port 3690 to remote-server:3690.

I tried to check out a remote directory, but received the message (in Repository Browser and during Check out)

‘svn://localhost:3690/some/path’ isn’t in the same repository as ‘svn://localhost/some/path’

I quickly found this bug report relating to TortoiseSVN client version 1.6 (I had Tortoise SVN 1.6.8).

After upgrading to version 1.7, check out succeeded.


C# Wishlist: Methods returning Anonymous Types

January 29, 2012

Anonymous Types were introduced in .Net 3.5, and I believe the motivation was to support the Linq Select() method which implicitly creates new types based on existing types (i.e. database-based classes) in statements like

var productQuery = 
    from prod in products
    select new { prod.Color, prod.Price };

This statement creates a strongly-typed read-only variable (productQuery) and an anonymous type with the properties Color and Price, based on the Product definition generated by the database OR mapper.

However, as stated in the linked article, these types cannot be passed as parameters or declared as return types of methods or delegates, unless variables of these types are cast to object.

In my opinion, however, the restriction on return types could easily be remove if some requirements are met. Just imagine two methods like these:

public var GetProducts()
{
    var productQuery = 
        from prod in products
        select new { prod.Color, prod.Price };
    return productQuery.ToList();
}

public var GetProduct(int productId)
{
    var productQuery = 
        products
        .Where(prod => prod.productId)
        .Select(prod => new { prod.Color, prod.Price })
        .FirstOrDefault(); 
    return productQuery;
}

As with the Linq examples, these examples are again shortcuts avoiding explicit type declarations. The result is still strictly typed, but some restrictions remain:

  • if more than 1 return statement occurs, all return statements need to declare the same properties of the return type
  • no return statement may explicitly return null
  • the accessibility level of the returned type is the same as that of the declaring method

The question of returning anonymous types is usually regarded a closely related to Tuples introduced in .Net 4.0. The major drawback of tuples, as I see it, is that the Tuple’s properties are named Item1, Item2, etc without any possibility to give them useful or sensible names, other than declaring your on class. The feature seems confusing and already raised some questions on SO.

Tuples and anonymous return types allow another food for thought: the request to have syntactic support for tuples just as sketched by Miguel de Icaza in Mono (I don’t know whether it is included in released code). His example in C# is

(user, password, host, port, path) = ParseUri (url);

calling a method

Tuple<string, string, string, int, string> ParseUri (string url);

Using anonymous types, the method might as well be declared as

var ParseUri(string url)
{
    return new { User = "...", Password = "...", 
        Host = "www.example.com", Port = 80, Path = "/..." };
}

and invoked by

var parsedUri = ParseUrl("http://www.example.com/");

One can easily see that these methods (tuples and anonymous types) could be used interchangeably.

Personally, I find the tuple notation using round parens (as in Perl, Python) untypical for C#, which uses curly braces { } for structured data.

 


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);
    }
}


Follow

Get every new post delivered to your Inbox.

Join 66 other followers