How to read optional attributes in XML with default values

When we are reading data from XML data sources, it is very common that when a value is not given for an attribute or an element, we have to use a default value instead. Having to check for the existence of the node each and every time we are reading a value can be annoying and clutter the code. To address this issue I have made a few useful extension method that you can use copy and use in your code. These are written on top of XAttribute class, but you can write similar methods for other types and APIs pretty much the same way.

public static class XmlExtentions
{
    public static string ValueOrDefault(this XAttribute attr)
    {
        return ValueOrDefault(attr, string.Empty);
    }
    public static string ValueOrDefault(this XAttribute attr, string defaultValue)
    {
        return attr == null ? defaultValue : attr.Value;
    }

    public static T ValueOrDefault<T>(this XAttribute attr, T defaultValue) where T : struct
    {
        if (attr == null) { return defaultValue; }
        var value = attr.Value;
        var convertedValue = typeof(T).IsEnum ? Enum.Parse(typeof(T), value) : Convert.ChangeType(value, typeof(T));
        if (convertedValue == null) { return defaultValue; }
        return (T) convertedValue;
    }

    public static T ValueOrDefault<T>(this XAttribute attr, Func<T> defaultDelegate) where T : struct
    {
        if (attr == null) { return defaultDelegate(); }
        var convertedValue = Convert.ChangeType(attr.Value, typeof(T));
        if (convertedValue == null) { return defaultDelegate(); }
        return (T)convertedValue;
    }
}

Once you get it in place. It is pretty easy to use. Assume that we have the following XML document:

<Configuration>
    <Search Enabled="True" RankingAlghorithm="BS77" LowMark="1000" HighMark="2000">
        <Source Name="Orders" Type="WebService" />
        <Source Name="Products" Type="REST" />
    </Search>
<Configuration>

As is shown below, you can read any type of values exactly the same way.

// reading a bool
var isEnabled = sourceNode.Attribute("Enabled").ValueOrDefault(false);

// reading a string
var scopeName = sourceNode.Attribute("Name").ValueOrDefault("Default");

// reading a string and using empty string (string.Empty) as default value
var scopeName = sourceNode.Attribute("Name").ValueOrDefault();

// reading an enum
var sourceType = sourceNode.Attribute("Type").ValueOrDefault(SearchSources.Html);

// reading an integer
var lowMark = sourceNode.Attribute("LowMark").ValueOrDefault(100);

// Using a delegate to provide the default value
var highMark = sourceNode.Attribute("HighMark").ValueOrDefault(()=> App.GetUserSetting("Search.HighMark"));
How to read optional attributes in XML with default values

Disabling Security warning for Attach to process in Visual Studio 2010, 2013 and 2015

You probably have already suffered from the pain of having to click one more time when attaching visual studio’s debugger to a process. As developers we all have the obsession to be more productive and everything that comes in the way is a bummer. I should have shared this little secret before, but … I forgot.

You know this message box, right?

attach-security-warning1

Now when a colleague sent me a link to a blog post that explains how to change a registry key to disable the security warning in Visual Studio when attaching to processes, I decided to write a little “.reg” file to make it even easier for you. This warning is there to warn you when you are attaching the debugger to a process and that process is (that are running with different accounts than the one running Visual Studio)  The reg file works for Visual Studio 2010, 2013 and 2015 no matter which edition. You can view / download it from here:

Disabling Security warning for Attach to process in Visual Studio 2010, 2013 and 2015

Connecting WebParts programmatically in SharePoint

Let’s start by an example.

Example

In this blog post, I’m going to assume we have a webpart that displays a contact list and another one that displays a map with the possibility to pinpoint an address. To keep things simple I assume the address is merely a string.

public class Map : WebPart
{

}

public ContactList : WebPart
{
    [Personalizable]
    string SelectedAddress { get; set; }
}

To connect these webparts, we typically do the following four steps:

  • Write an interface to contain the information we need to transfer (i.e. Address)
  • Implement the interface in the provider webpart (i.e Map)
  • Write a callback method in the provider webpart to return the address.
  • Write another callback method in the consumer webpart to receive the address.
public interface IAddressConnection {
    string SelectedAddress { get; set; }
}

public class Map : WebPart
{
    [ConnectionConsumer(&quot;Pinpoint address&quot;, &quot;Address&quot;)]
    public void ConsumeAddress(ISelectedAddress address)
    {
        // Set the map extent and display a pinpoint.
    }
}

public ContactList : WebPart, IAddressConnection
{
    [Personalizable]
    public string SelectedAddress { get; set; }

    [ConnectionProvider(&quot;Selected address&quot;, &quot;Address&quot;)]
    public ISelectedAddress ProviderAddress()
    {
        return this;
    }
}

ConnectWebParts()

In order to connect two webparts, you need an instance of each webpart plus the WebPartManager (to be precise the SPLimitedWebPartManager) for the page they are hosted in and of course you need to know which of their connection points you are going to connect.

Let’s say you already have the WebPartManager and the two webparts at hand. In that case you can use the following method. Note that T is the interface these two webparts share.

public void ConnectWebParts(WebPartManager webPartManager, WebPart consumer, WebPart provider)
{
    var consumerConnection =
        webPartManager.GetConsumerConnectionPoints(consumer)
            .Cast&lt;ConsumerConnectionPoint&gt;()
            .FirstOrDefault(c =&gt; c.InterfaceType == typeof(T));
    var providerConnection =
        webPartManager.GetProviderConnectionPoints(provider)
            .Cast&lt;ProviderConnectionPoint&gt;()
            .FirstOrDefault(c =&gt; c.InterfaceType == typeof(T));
    webPartManager.ConnectWebParts(provider, providerConnection, consumer, consumerConnection);
}

The above method assumes that these webpart only have one connection point of type T, which makes sense most of the time, but in case your webpart have multiple connection points of the same interface.

By using ConnectWebParts method, we can easily connect the Map to the Contacts webpart.

ConnectWebParts&lt;IAddressConnection&gt;(webPartManager, map, contacts)

But, how to get the WebPartManager and instances of the webparts? you might ask. These webparts might be used in any page, but you definitely know on which page you are going to connect them. By having a reference to the page you can instantiate a WebPartManager and with that you can find you webparts too. If you are doing this in the code-behind of the page or a control (or webpart) in the page, you can do as following:

var webPartManager = WebPartManager.GetCurrentWebPartManager(this) // or this.Page if we are in a control.
var consumer =
    webPartManager.WebParts.Cast&lt;WebPart&gt;()
        .FirstOrDefault(w =&gt; w.GetType() == typeof(Map));
var provider =
    webPartManager.WebParts.Cast&lt;WebPart&gt;()
        .FirstOrDefault(w =&gt; w.GetType() == typeof(Contacts));
ConnectWebParts&lt;IAddressConnection&gt;(webPartManager, consumer, provider)

What if the code is not running in the page? Then you need to get an instance of the page. Let’s use SPLimitedWebPartManager this time.

using (var site = new SPSite(&quot;http://mydomain/mysite&quot;))
{
    var file = site.RootWeb.GetFile(&quot;myfolder/mypage.aspx&quot;);
    var webPartManager = file.GetLimitedWebPartManager(PersonalizationScope.Shared);
    var consumer =
        webPartManager.WebParts.Cast&lt;WebPart&gt;()
            .FirstOrDefault(w =&gt; w.GetType() == typeof(Map));
    var provider =
        webPartManager.WebParts.Cast&lt;WebPart&gt;()
            .FirstOrDefault(w =&gt; w.GetType() == typeof(Contacts));
    ConnectWebParts&lt;IAddressConnection&gt;(webPartManager, consumer, provider)
}

Please note that you might need to checkout the page, publish and approve it if versioning or approval workflow has been enabled on the library that contains the page.

I hope you find it useful. By the way, don’t forget the null checks!

Connecting WebParts programmatically in SharePoint

How to install/update Atom, Sublime, VSCode and Brackets packages behind corporate proxy (NTLM)

Many developers these days are using these fancy new cross-platform text editors that are lightweight and fast to reduce the workflow of writing and testing code. I’m mostly talking about web developers here. If you are new in this world I suggest you give the followings a shot as after days of researching and trying I think currently they are the bests:

Now back to the subject. Many of these text editors support proxy servers, but none of them that I have tried support NTLM for authentication and if your corporate proxy is using NTLM they simply cannot connect to it. Or lets say not directly! Actually the only solution I have found is to use a software called CNTLM that can act as a proxy server itself and behind the scene it can connect to another proxy server that is using NTLM. The good news is this software is open-source, very lightweight and independent of any external library (written in C) and can take care of all the complexity of NTLM. In fact You can easily setup CNTLM to allow any application that does not support NTLM authentication to connect to the internet. Atom is based on NodeJS (most of them are) so you’ll be able to apply what you will learn hear to other similar text editors as well.

Configure CNTLM to use your corporate proxy

  1. CNTLM is an opensource software and you need to download its latest version from SourceForge website here.
  2. Now you need to install it by running the installation package. There is not much to worry about. it just adds a few shortcuts to your start menu and copies the file under “Program Files (x86)“.
  3. All the settings of CNTLM are stored in Program Files (x86)\Cntlm\cntlm.ini, and you can open this file from Start Menu > Cntlm > cntlm.ini
  4. The cntlm.ini file is quite self descriptive. You just need to add the following lines in this file:
Username    your-username
Domain      your-domain-name
Password    your-password-or-leave-empty
Proxy       proxy-ip-or-hostname:port
Proxy       another-proxy-ip-or-hostname:port
Listen      3128

you can add as many Proxy lines as you want, Cntlm will try them one by one until it can find one that works.

Please note that the address of your proxy will be "localhost:3128" by default but you can change it to any desired port that is not currently being used by another program. You just need to change the value in front of Listen setting. I have highlighted the line so you never miss it.

  1. Star the proxy server by  heading to Start Menu > Cntlm > “Start Cntlm Authentication Proxy”
  2. Test your shiny new proxy by using your favorite browser.

Configure Atom to use Cntlm as proxy server

  1. Start Atom by heading to Start Menu > All Programs > GitHub, Inc > Atom
  2. Go to File > Settings or press Ctrl+Comma. Click on “Open Config Folder” button in the left pane of the Settings tab. It will open and show all the content of the setting folder in Atom.
  3. Click and open .apmrc file located under the root setting folder (.atom folder) and add the following lines:
http-proxy=http://localhost:port-number-to-be-used-by-Cntlm
https-proxy=http://localhost:port-number-to-be-used-by-Cntlm
strict-ssl=false
registry=http://registry.npmjs.org/

The last line (that I have highlighted) tells npm to use the http address instead of the default https address. This is because I noticed that Cntl might have some problems with https addresses. This issue might be solved later and you might not need it in the future.

  1. Restart Atom and enjoy using your favorite packages.

A little bonus

By running the following command you can tell many other programs to use your new little proxy server by default. Unfortunately not every program supports it.

netsh winhttp set proxy localhost:3128 "localhost,127.0.0.*"

How to install/update Atom, Sublime, VSCode and Brackets packages behind corporate proxy (NTLM)

Automating SharePoint Deployments (aka Continues Integration) by PowerShell

SharePoint has an infrastructure for packaging, deploying, and upgrading with its own meta language (XAML), but often our requirements during deployment and maintenance goes beyond what’s possible in SharePoint’s out-of-the-box IMHO it’s the case with every software that provides such facilities. Fortunately SharePoint relies on PowerShell, a scripting language meant for automating administrative tasks. Since I’m a fan of good tools to get rid of non-creative tasks, long ago I decided to build an extendable script that can take care of main scenarios and can be used in a production environment and also takes care of common pitfalls along the way. The part of the script that takes care of deploying / retracting the package is based on this blog post.

The script uses a clean and understandable XML file to let you control the process without modifying the code. The XML file consists of 3 main segments BeforeDeploy, Deploy and AfterDeploy. You just need to put tasks inside these main nodes in whatever order you like and if the script does not understand a task it simply ignores it. This gives you the possibility to use the same XML file for your other configurations without any need to create a separate one. Let’s look at an example.

<Deployment>
  <BeforeDeploy>
    <Provision>
      <Website Description="Home" Template="CMSPUBLISHING#0" Title="Home" Url="http://dev/myapp/en/home"/>
      <Website Description="Products" Template="CMSPUBLISHING#0" Title="Products" Url="http://dev/epro/en/products"/>
      <Website Description="Support" Template="CMSPUBLISHING#0" Title="Support" Url="http://dev/epro/en/support"/>
    </Provision>
    <Features>
      <deactivate Description="MyApp.Support.Pages" Id="2aa7ea41-6b01-45d4-87e0-a8194ea246fb" Url="http://dev/myapp/en/support"/>
      <activate Description="MyApp.Products.Pages" Id="2aa7ea41-6b01-45d4-87e0-a8194ea246fb" Url="http://dev/myapp/en/products"/>
      <deactivate Description="MyApp.Home.Pages" Id="2aa7ea41-6b01-45d4-87e0-a8194ea246fb" Url="http://dev/myapp/en/home"/>
      <deactivate Description="MyApp.PageLayouts" Id="f21423d1-0052-456f-b727-aa7268fa4e52" Url="http://dev/myapp"/>
      <deactivate Description="MyApp.ContentTypes" Id="807d55b5-77fc-423c-bae3-aedd861a96c4" Url="http://dev/myapp"/>
      <deactivate Description="MyApp.SessionSharing" Id="93a36eb1-5948-44ed-82a4-642bc1a4132b" Url="http://dev/"/>
      <deactivate Description="MyApp.UrlRewrite" Id="1f8cdfca-c7a6-4f11-8520-b02459b79479" Url="http://dev/"/>
      <deactivate Description="MyApp.BCS" Id="4d3288a9-ce52-4a0e-af83-b0ff78e1d40e"/>
    </Features>
  </BeforeDeploy>
  <Deploy>
    <Solutions>
      <Solution Force="true" Path="C:\CODE\MyApp\Package\MyApp.wsp" UpgradeExisting="false">
        <WebApplications>
          <WebApplication>http://dev/</WebApplication>
        </WebApplications>
      </Solution>
    </Solutions>
  </Deploy>
  <AfterDeploy>
    <Features>
      <activate Description="MyApp.BCS" Id="4d3288a9-ce52-4a0e-af83-b0ff78e1d40e"/>
      <activate Description="MyApp.UrlRewrite" Id="1f8cdfca-c7a6-4f11-8520-b02459b79479" Url="http://dev/"/>
      <activate Description="MyApp.SessionSharing" Id="93a36eb1-5948-44ed-82a4-642bc1a4132b" Url="http://dev/"/>
      <activate Description="MyApp.ContentTypes" Id="807d55b5-77fc-423c-bae3-aedd861a96c4" Url="http://dev/myapp"/>
      <activate Description="MyApp.PageLayouts" Id="f21423d1-0052-456f-b727-aa7268fa4e52" Url="http://dev/myapp"/>
      <activate Description="MyApp.Home.Pages" Id="2aa7ea41-6b01-45d4-87e0-a8194ea246fb" Url="http://dev/myapp/en/home"/>
      <activate Description="MyApp.Products.Pages" Id="2aa7ea41-6b01-45d4-87e0-a8194ea246fb" Url="http://dev/myapp/en/products"/>
      <activate Description="MyApp.Support.Pages" Id="2aa7ea41-6b01-45d4-87e0-a8194ea246fb" Url="http://dev/myapp/en/support"/>
    </Features>
  <AfterDeploy>
    <IIS>
      <Recycle AppPool="MyApp - Service"/>
      <Recycle AppPool="SharePoint - DEV"/>
    </IIS>
    <WarmUp Url="http://dev/myapp/en/home/pages/welcome.aspx" />
    <WarmUp Url="http://dev/myapp/en/support/pages/welcome.aspx" />
    <WarmUp Url="http://dev/myapp/en/products/pages/welcome.aspx" />
    <TimerJobs>
      <Start JobName="Variations Propagate Page Job Definition" WebApp="http://dev" WaitForCompletion="false"/>
    </TimerJobs>
  </AfterDeploy>
</Deployment>

The above XML tells the script to provision a hierarchy of websites, then deactivate some features and then deploy the solution (which will also retract and remove the solution if it is previously deployed) after the deployment is done, it activates features, recycle two application pools and warms up the SharePoint web application by requesting a few pages and at the end starts a timer job. Please note that the order of different elements in the XML file defines the order of the tasks to be run. You can save the XML in a file with arbitrary name and call it like so:

Deploy-SPSolutions c:\solutions.xml -Log "c:\install.log"

You can download the latest version of Deploy-SPSolutions (SharePoint CI) script from GitHub You will also find some samples there.

Automating SharePoint Deployments (aka Continues Integration) by PowerShell

How to enable three finger drag-n-drop in Windows 10 on a macbook

In my previous post we saw how easy it is to update a Boot Camp Windows installed on a MacBook to Windows 10, and how you can easily install the latest version of your Windows drivers provided by Apple. In this post I am going to focus on a different issue that annoys all of us who regularly switch back and forth between Windows and OSX, (you guessed it) Trackpad gestures and more specifically three finger drag-n-drop.

One of the features you’ll miss when you switch from OSX to Windows is the ability to drag with three fingers. You can still enable One-Finger-Dragging in the Boot Camp Control Panel (you need to double-click on its icon displayed beside the clock in your taskbar). You just need to go to the Trackpad tab and enable it:

Boot Camp Control Panel - TrackPad - One Finger Dragging

It’s better than nothing, but it’s not good enough, I know. What if we had three finger dragging and all those cool gestures in Windows 10? Is it hidden somewhere? No, it’s not these options are simply not provided by Apple in it’s Trackpad driver for Windows, but don’t be discouraged you still have one possibility at this moment. Some smart guys have developed a free driver called TrackPad++ that makes it possible to have all those gestures and three finger dragging plus many more and it’s free! It’s actually a wrapper around Apple’s native driver.

The real three finger dragging

Basically you need to download and install two small software. The first one changes a setting in Windows registry to let you install unsigned drivers and the second one is the driver itself. Obviously the developers of a free driver cannot afford to pay a fortune to Microsoft on a yearly basis to review and sign their driver! After you install both software you can uninstall the first one without any issue if you don’t like it😉

Here are the links to these two software:

  1. Power Plan Assistant 3.2a
  2. TrackPad++

Take a look at their website for more information and instructions. Don’t be fooled by a not so beautiful UI in their app, it works like a charm and there is no annoying popup, ad or anything like that! You might even like to keep the first app as well, it will give you some extra options around power management, keyboard’s backlight, etc.

How to enable three finger drag-n-drop in Windows 10 on a macbook

Upgrading from Windows 7 or 8 on Macbook’s Boot Camp to Windows 10

I decided to share my experience of upgrading to Windows 10 so that in case any of you out there who are thinking about upgrading your BootCamp hosted windows to the latest version can be prepared before hand.

Don’t panic!

First of all know in advanced that the upgrade process went smoothly and you’ll still be able to boot either to your OSX or Windows by holding the option (alt) key during startup, so go ahead get busy while reading this.

Where to start? Download, Windows Update or Download

Technically you have two options. First option is to upgrade through Windows Update channel:

picture is taken from here: http://arstechnica.com/information-technology/2015/07/windows-10-is-on-windows-update-now-the-free-upgrades-start-today/

And the second option is to download the installation image and mount it (right click and select Mount in File Explorer) or write it to a DVD. Microsoft has provided a tool called Windows 10 Media Creation Tool. The 32bit edition can be found here and the 64bit edition can be found here. Another option is to directly download the ISO file from this page if you are currently viewing this page in a Mac. MSDN subscribers can download through their MSDN subscriber downloads page.

You can pick the edition you want I leave the researching to you, but it’s more likely that you stay with the similar edition you currently have on your machine.

Setup process

There’s not much to say here. The process couldn’t be easier, everything is done automatically and after the last restart (yes there are a few) you’ll need to pick your wireless if your computer is not connected through a wired link and that’t it. If you are interested in more pictures and description head here.

The after math

So far the experience was not different that a normal PC, but after you log in to your brand new Windows, you’ll discover that not all features of your touchpad is working and because not all the drivers are installed automatically and you’ll have to reinstall all the BootCamp drivers again. You might (like me) think about downloading the drivers manually but according to Apple you won’t get the latest even if you download “Boot Camp Support Software 5.1.5640” you need to download the latest drivers by using Boot Camp Assistant that is already preinstalled in your OSX, it will give you an option to copy all you need to a USB Flash Drive. Then you can reboot to your Windows drive and install the driver package and everything will be back to normal.

Well, that’s about it. How was your experience during and after installation? don’t hesitate to share with in the comments.

Upgrading from Windows 7 or 8 on Macbook’s Boot Camp to Windows 10