Visual Studio 2013 Hidden Gems

by Oliver 17. October 2014 23:13

This post is one of several summarizing some of the sessions I attended during the .NET Developer Days conference in October 2014. Check out the rest of them.

Here are my notes from a whole day of sessions diving deep into Visual Studio and its possibilities, lead by Kate Gregory:

Window positioning

When drag'n'dropping windows you can drop them in any place you like, even in a place where VS suggests to dock it to another window group, by holding down the CTRL key and then releasing the mouse button.

Using the Start Page

image Probably 3% of all developers use it but it's gotten better over the years. You can now pin projects to it so they won't fall of the most recently used list, you can remove unneeded projects by right clicking or open its folder if you forgot where you keep it.

Also, the start age hides itself once you open a project or a file so you don't have to close it by hand anymore.

Navigating Code

If you want to go to the definition of a symbol just get your cursor on it and press F12 which is the shortcut for Go To Definition. That will open the file that contains the definition of given symbol. Now, if you want to drill down into a deeper hierarchy and don't care for the intermediate definitions, give Alt+F12 a try – it's the shortcut for Peek Definition and it will open the definition of the given symbol in an iframe type of window right inside the code you're looking at. You can then use that window to follow further definitions without leaving the current point of interest. [Can't find that menu item in the Express edition, though.]

Also, give bookmarks a try! There's a bookmark manager where you can give your bookmarks a name, group them into folders and the like. Quite helpful to quickly find your way around a large codebase or for presentations.

Finding things

imageThere's great inline find window by now in VS that you can control from your keyboard in no time. Use Ctrl+F to open it with the word prefilled that your cursor is currently on or use Ctrl+F3 to search for the next occurrence of the word your cursor is on. This little tool is really worth getting to know well because it can save you a lot of time when looking for stuff or replacing it.

imageHave you noticed the search text box at the top of the Solution Explorer? There's even a shortcut to get there so you don't have to take your hand off the keyboard.

Be prepared to find even more search boxes here and there, e.g. the Error List has one, too!

Application Lifecycle Management (ALM)

Visual Studio Online is a new one-stop solution for hosting projects and collaborating on them in the cloud. It basically offers cloud-based TFS instances. The basic plan is free for up to 5 users in a project with an unlimited number of stakeholders, who are allowed view burndown charts, backlogs, Kanban, and task boards, and may even create new Work Items. It supports, of course, TFVC but also Git for source control.

In Visual Studio, use the Team Explorer window to work with your remote TFS, e.g. your Visual Studio Online account, but you can choose to manage your project through a web browser just as well. There's powerful work item editor available online, have a look and take a minute to grasp what all it offers:

image

I'd call it impressive.

There's really a ton of features here, and no doubt there are other tools out there to do the same thing. What really cuts it for me:

  1. Visual Studio Online is free for up to 5 users and an unlimited number of stakeholders.
  2. The integration with Visual Studio is seamless. [You can do pretty much all of the management work either in VS or online.]

Sign out of VisualStudio.com

image If you're logged into VisualStudio.com you can log out by opening the drop-down menu next to your login name, choosing "Account settings…" and there clicking "Sign out". Beware that you have to be logged in with a Microsoft account if you want to use the Express version for longer than 30 days.

Debugging

I'll just put stuff into a list here for better readability:

  1. Have you  met the Autos window? Seems not to be included in the Express version but when hitting a breakpoint it offers insight into all variables used on the current line, the previous line and after exiting a function, shows its return value even if you didn't assign to any variable!
  2. The Locals window captures the values of all variables defined in the current scope without the need to add them to the Watch window.
  3. Press the CTRL key to temporarily hide the variable inspector popup window: image -> hidden-in-vs-debug
  4. Pin values from the above window so you'll keep their values in view – even during the next debugging session!
  5. Set your cursor on a line of code and choose Run To Cursor from the context menu to continue running your code up until the line with the cursor. Wow!
  6. Or choose Set Next Statement to skip all code from the current breakpoint onwards and jump to the selected line. Wow²!
  7. Edit + Continue is also great but works only in 32-bit mode :-|
  8. IntelliTrace (in the Ultimate edition) allows you to capture execution traces of your software on a client machine and debug (through replaying) the same set of instructions inside your local VS – Kate Gregory called it Time Travel Debugging ;-)

That's it from the first day. Happy developing!

.NET Developer Days in Wroclaw

by Oliver 15. October 2014 19:39

I'm currently attending the first .NET Developer Days conference in Wrocław, Poland, and will put up a few posts with my notes from some of the sessions I was able to attend.
The conference took place from 14.10. to 16.10.2014 in the Wrocław Stadium.

Here's a list of all posts (I'll update the links as soon as I finish a given post):

There's already been a lot of input and the third day is still ahead of me! I hope I'll be able to update the above list soon.

Happy Coding!

Getting Started With Meteor On Windows – Or Not

by Oliver 2. October 2014 18:30

Recently, we at teamaton decided to take a break from Camping.Info and discoverize to dive into something new. We wanted to breathe some fresh air, open our eyes and minds for a world outside of our day-to-day development stack of ASP.NET.

During the process we also wanted to check out some tools, frameworks, environments that we'd heard of or read about but hadn't found the time to really take a closer look at.

One of these was Meteor.

What's Meteor about

The elevator pitch on meteor.com reads like this:

Meteor is an open-source platform for building top-quality web apps in a fraction of the time, whether you're an expert developer or just getting started.

I really encourage you, dear Reader, to check out the Meteor site and take a look at what's waiting for you. I really liked what I found there: Pure JavaScript. Live page updates. Hot Code Pushes. Fully self-contained application bundles. And more. That's stuff, .NET developers aren't used to.

Setting up Meteor on Windows

[Note: Before proceeding, please have a look at Meteor's Supported Platforms page just to make sure you're not missing out on anything new.]

This part took me about 2h to get right, so I took notes to save my colleagues or anyone else interested some precious time. I basically followed this comprehensive guide (and I encourage you to do the same) but made a few adjustments.

[A word of warning: Running my first out of the box sample failed and that's where I stopped.]

  1. Install Git and add C:\Program Files (x86)\Git\bin to your PATH variable
  2. Download and install VirtualBox > 4.3.12 from here: https://www.virtualbox.org/wiki/Downloads
  3. Download and install Vagrant >= 1.6.3 from here: http://www.vagrantup.com/downloads.html
  4. Install the ChefDK from here: http://downloads.getchef.com/chef-dk/windows/
  5. Now start a command line and run:
    vagrant plugin install vagrant-berkshelf --plugin-version ">= 2.0.1"
    vagrant plugin install vagrant-vbguest
    vagrant plugin install vagrant-omnibus
  6. Create C:\vagrant and cd into it, then call:
    git clone git://github.com/shoebappa/vagrant-meteor-windows.git meteor
  7. Edit C:\vagrant\meteor\Vagrantfile to use a new virtual machine image (the old one wouldn't work with Meteor's current version): 
    1. In line 8, set: config.vm.box = "trusty64"
    2. In line 10, set: config.vm.box_url = "http://cloud-images.ubuntu.com/vagrant/trusty/current/trusty-server-cloudimg-amd64-vagrant-disk1.box"
    3. In Iine 36, use a different name for your first app
  8. Go to C:\vagrant\meteor and initiate Vagrant (will take a while):
    vagrant up
  9. Now start your app by:
    cd C:\vagrant\meteor
    vagrant ssh
    cd /vagrant/mymeteorapp
    mrt run

Running the app threw a NullReferenceException (or something alike) at me that was triggered from somewhere inside a javascript file – I don't remember exactly where. I tried fiddling around with it for another hour or so, especially when I read that Meteorite (mrt) is no longer needed with Meteor versions >= 0.9.0. But without success.

What to do now?

I shied away from it but you might just feel like setting up a dev environment on a Linux OS and simply running the few lines from the Meteor home page:

 $ curl https://install.meteor.com/ | sh

It seems to simple to be true.

But wait! Official Windows support is coming to Meteor – sometime in the near or farther future. So please check if the future isn't already here!

What we did

We went to grab Angular.js and haven't looked back.

Happy coding!

Sending DateTime Instances From a .NET Server to a JavaScript Client and vice-versa

by Oliver 20. September 2014 21:47

At teamaton we're currently developing our own Time Tracking tool that we'll be using instead of KeepTempo as soon as it's good enough. We even plan on making it accessible to the public later but that's a different story.

We chose Angular.js to develop the frontend and now want to synchronize our time tracking records with our ASP.NET WebAPI backend. One property of such a record is the date and time it was created at, createdUtc. Let's look at how we can send those date-time values to the server and back again.

Some Background on Date and DateTime

JavaScript Date instances are seeded at 01/01/1970 00:00:00 and can be instantiated by passing to the Date() constructor the number of milliseconds that have passed since that moment in time. Date.now() will directly output this number, at the moment of writing these words it returned the value 1 411 240 284 042. This value is what all other representations of a given Date instance will be based on.

In .NET we have the DateTime type and its seed value is 01/01/0001 00:00:00. Internally, DateTime instances count time in Ticks, where one tick equals 100 nanoseconds, i.e. 0.000 000 1 seconds, thus delivering a theoretical precision of 10000 times that of the JavaScript equivalent. When writing these words, the current number of Ticks of DateTime.Now was 635 468 449 058 588 764 (I use LINQPad to execute C# code snippets).

How to Convert JavaScript Date to .NET DateTime

So how do we convert those values into each other?

If we decide to send the number of milliseconds in a given JavaScript Date instance to our .NET server we can reconstruct an equivalent DateTime instance by seeding it with 01/01/1970 and just adding the milliseconds we got from the client to it:

  1. Record.CreatedUtc = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(milliseconds);

Going the other way, we actually need to get hold of a TimeSpan instance which has the property TotalMilliseconds that gives us what we want. We'll do that by substracting a DateTime instance representing the 01/01/1970 from the DateTime instance we want to send to the client:

  1. (Record.CreatedUtc - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds

The code looks a bit ugly because we take care to work with UTC dates so that our code will run the same for clients and servers around the world. It's a very good idea to work with UTC dates internally and only convert them to local dates when you want to display them somewhere.

… or Just Use Date Strings

There's another way to transfer date objects between JavaScript and your server: using a standardized string representation that both sides will be able to generate and parse.

In JavaScript you would use Date.toISOString() and in .NET DateTime.ToString("O") (see the MSDN for the O format string).

Happy coding!

SSL Certificate Jungle – Multiple Domains, Wildcards, and Both

by Oliver 10. September 2014 22:05

Recently, we've decided to add https:// support to Camping.Info. Since we've been running our application servers behind an NGINX reverse proxy for a while now, the natural choice in our setup was to terminate the secured connections at the NGINX server which has CPU usage values somewhere between 1% and 5%. This is also call SSL offloading and will allow us to keep all the SSL setup and potential runtime overhead off of our application servers.

Certificate Options

On Camping.Info, we serve almost all static content from the domain images-camping.info. Since we want to secure the whole site, we need to have valid ssl certificates for images-camping.info and all subdomains of camping.info.

Using Separate Certificates

The first solution to the problem would be using one SSL certificate for images-camping.info and one (wildcard) certificate for *.camping.info that would secure all subdomains of camping.info. If we wanted to secure camping.info itself as well, we would need a third certificate just for that one domain, because wildcard certificates do not cover the parent domain without a subdomain.

Using a SAN (or UCC) Certificate

Subject Alternative Names (SAN) can help in this situation. The subjectAltName field of an SSL certificate can contain many domain names that will be secured by that certificate. In our scenario we could have put images-camping.info, camping.info, www.camping.info, en.camping.info, and the other over 25 subdomains in there. Unfortunately, that would complicate things for the use of new subdomains in the future which would be missing from the list. A wildcard certificate really seems like the natural choice when you have more than 5 subdomains to secure or are expecting to have more of them in the near future.

Using a Wildcard Certificate with SANs

It turns out that wildcard certificates can well be combined with the usage of the subjectAltName field. Most CAs make you pay quite a lot for this combination, but we've also found a quite affordable offer on www.startssl.com.

Multiple SSL Certificates on a Single NGINX Instance – Beware

Choosing the first certificate option, i.e. using at least two certificates we now need to install both of them on our NGINX reverse proxy server.

This blog post on how to install multiple SSL certificates on NGINX is a very good read – but be sure to read the comments as well. It turns out that the Server Name Indication (SNI) extension to the TLS protocol that allows you to do so will lock out clients that don't support SNI. The most prominent example of such a client is any version of Internet Explorer running on Windows XP, and even though Microsoft has ended support of XP almost half a year ago, we're still seeing 11% of our Windows users running XP accounting for 6% of our total traffic – a number we cannot ignore.

Wanting to use separate SSL certificates on one NGINX instance we would need two different IP addresses pointing to that same server so that each certificate could respond to requests on one of those addresses. This would both complicate our setup and incur higher monthly infrastructural costs that we'd gladly avoid.

Installing a Single SSL Certificate on NGINX

The option we finally chose is to use a wildcard SAN certificate where we'd enter images-camping.info, camping.info and *.camping.info as the different subject alternative names. Installing that into NGINX is straight-forward if you know how.

Happy SSL'ing!

Turn Off / Remove Ads in Skype's Chat Window On a Windows OS

by Oliver 19. August 2014 21:37

I've got quite annoyed by seeing the same ad in my Skype chat window and today I simply had enough of it. Going to Google lead me to this Youtube video which shows how to block ads in Skype by denying access to https://apps.skype.com/ in Internet Explorer. Here's a screen shot, just follow the steps below and you're done:

  1. Open Internet Options
  2. Switch to the Security tab
  3. Select Restricted Sites
  4. Click the Sites button
  5. Type https://apps.skype.com/ into the text box
  6. Click Add
  7. Click Close
  8. Click OK

For those changes to take effect in Skype you need to leave your chat window e.g. by clicking on your profile in the upper left corner. Now, when you open a chat window no ads will show.

disable-skype-ads-on-windows

There are other ways to stop Skype from showing ads, and here's a really thorough post on that topic.

Happy Skype'ing!

Pieces of C# – long and short

by Oliver 9. August 2014 12:52

Today, I found this dusty piece of code in our code base:

Stone-age version
  1. public string GetIframeIds()
  2. {
  3.     var result = new StringBuilder();
  4.     var first = true;
  5.     foreach (var iframe in _iframes)
  6.     {
  7.         if (!first) result.Append(',');
  8.         else first = false;
  9.         result.Append("'" + iframe.ClientID + "'");
  10.     }
  11.     return result.ToString();
  12. }

… and just had to rewrite it to this:

Updated version
  1. public string GetIframeIds()
  2. {
  3.     return string.Join(",", _iframes.Select(ifr => "'" + ifr.ClientID + "'"));
  4. }

I couldn't bear but run some micro-performance test on these code snippets since StringBuilder is usually quite fast. I ran each of the snippets with an _iframes length of 30 in a loop of 10.000 iterations and yes, the first version is faster with 215ms vs. 360ms. But then, in production I run that code block only once per request, not 10.000 times as in the test. Spending 21ns or 36ns in that method won't make any significant difference, especially when looking at request execution times of beyond 100ms.

Why should you or I care?

The second code block is arguably easier to read, quicker to write, and harder to get wrong.

Happy coding!

Remove The Padding From The Google Map API v3 fitBounds() Method

by Oliver 4. July 2014 21:56

In our customizable web portal platform discoverize we offer searching for results using a Google Map. In a recent iteration, we were trying to improve the overall map usage experience, and one thing we wanted to do was to zoom into the map as far as possible for all results to still appear on the map.

map.fitBounds(map.getBounds()); – does not do what you would like it to

The natural choice to achieve that would be to use the fitBounds method on the Map object with the bounding rectangle for the coordinates of all results. Unfortunately, though, Google chose to add a non-configurable 45px margin around that bounding box so that in a lot of cases the map appears to be zoomed out too far for what would be possible. That's why map.fitBounds(map.getBounds()); will zoom the map out!

Zoom in if you can

After a bit of searching I found a workaround on this Google Groups thread: map.fitBounds(map.getBounds()) zooms out map. The idea behind the solution provided there is to check whether the bounds to fit on the map wouldn't still fit using a higher zoom level and if yes, apply that zoom level. Since I had some problems with the code from the thread I reworked it slightly and now have this:

function myFitBounds(myMap, bounds) {
    myMap.fitBounds(bounds); // calling fitBounds() here to center the map for the bounds

    var overlayHelper = new google.maps.OverlayView();
    overlayHelper.draw = function () {
        if (!this.ready) {
            var extraZoom = getExtraZoom(this.getProjection(), bounds, myMap.getBounds());
            if (extraZoom > 0) {
                myMap.setZoom(myMap.getZoom() + extraZoom);
            }
            this.ready = true;
            google.maps.event.trigger(this, 'ready');
        }
    };
    overlayHelper.setMap(myMap);
}

function getExtraZoom(projection, expectedBounds, actualBounds) {

    // in: LatLngBounds bounds -> out: height and width as a Point
    function getSizeInPixels(bounds) {
        var sw = projection.fromLatLngToContainerPixel(bounds.getSouthWest());
        var ne = projection.fromLatLngToContainerPixel(bounds.getNorthEast());
        return new google.maps.Point(Math.abs(sw.y - ne.y), Math.abs(sw.x - ne.x));
    }

    var expectedSize = getSizeInPixels(expectedBounds),
        actualSize = getSizeInPixels(actualBounds);

    if (Math.floor(expectedSize.x) == 0 || Math.floor(expectedSize.y) == 0) {
        return 0;
    }

    var qx = actualSize.x / expectedSize.x;
    var qy = actualSize.y / expectedSize.y;
    var min = Math.min(qx, qy);

    if (min < 1) {
        return 0;
    }

    return Math.floor(Math.log(min) / Math.LN2 /* = log2(min) */);
}

Replace map.fitBounds(bounds) with myFitBounds(map, bounds)

That's all you have to do to zoom in as far as possible while keeping your bounds on the map.

Happy coding!

Learning Powershell

by Oliver 30. May 2014 21:34

Today, I finally decided that I want to get to grips with PowerShell and have it available in my toolbox for those everyday developer tasks. For a fresh start, I wanted to make sure I'm running the latest and greatest of PowerShell, but how do I find out which version I have installed?

What version am I running?

Just fire up a PowerShell instance and type $psversiontable or $host.version:

PS C:\Windows\system32> $psversiontable

Name                           Value
----                           -----
PSVersion                      4.0
WSManStackVersion              3.0
SerializationVersion           1.1.0.1
CLRVersion                     4.0.30319.18444
BuildVersion                   6.3.9600.16406
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0}
PSRemotingProtocolVersion      2.2

PS C:\Windows\system32> $host.version

Major  Minor  Build  Revision
-----  -----  -----  --------
4      0      -1     -1

Actually, when I ran this I didn't have the 4.0 version installed yet. So where did I get it?

How to install Powershell 4.0 (the newest version as of mid 2014)?

Go here and choose the right link for you: How to Install Windows PowerShell 4.0. That's it.

Make use of great tooling: use the ISE

Last but not least, especially for those of you who like me are just getting started, make sure you're using the great Integrated Scripting Environment (ISE) that comes bundled with PowerShell:

image

Now, get scripting!

Delete a Large Number of Rows from a Table in SQL Server

by Oliver 28. May 2014 12:09

Recently, we had to make some space available in one of our SQL Express instances that was getting close to its 10 GB limit of stored data, so I set out to delete some old data from two of our largest tables. One contained about half a million rows, the other a bit over 21 million.

Simple Deletion Would Take… Forever

The simplest sql statement to delete all rows that were created before 2012 would be the following:

  1. DELETE FROM [dbo].[Message] WHERE DateCreated < '20120101'

I can't even tell you how long this took because at 14 minutes I just cancelled the query execution (which took another 7 minutes to finish). This was the table with less than 500,000 rows where we wanted to delete a bit more than 200,000 rows.

Break Delete Operation Into Chunks

Searching for a solution to the problem, I came across this blog post on breaking large delete operations into chunks. It shows in good detail how the simple version above behaves against running a loop of a few tens of thousand deletes per iteration. An interesting aspect I hadn't thought of at that point was the transaction log growth that can become a problem with large delete operations. Running a loop allows you to do a log backup (in full recovery mode) or a checkpoint (in simple mode) at the end of each iteration so that the log will grow much more slowly.

Unfortunately, though, this didn't help with the execution time of the delete itself, as you can also see from the graphs presented in above post.

Disable Those Indexes!

It turns out, our [Message] table had six non-clustered indexes on them which all had to be written to for every row that was deleted. Even if those operations are fast, their processing time will add up over a few hundred thousand iterations. So let's turn them off! In fact, let's turn only those off that won't be used during out delete query. [We have one index on the DateCreated column which will be helpful during execution.]

This stackoverflow answer shows how to create some dynamic SQL to disable all non-clustered indexex in a database. I've modified it slightly to disable only indexes of a given table:

Disable/Enable Table Indexes
  1. DECLARE @table AS VARCHAR(MAX) = 'Message';
  2. DECLARE @sqlDisable AS VARCHAR(MAX) = '';
  3. DECLARE @sqlEnable AS VARCHAR(MAX) = '';
  4.  
  5. SELECT
  6.     @sqlDisable = @sqlDisable + 'ALTER INDEX ' + idx.name + ' ON '
  7.                     + obj.name + ' DISABLE;' + CHAR(13) + CHAR(10),
  8.     @sqlEnable = @sqlEnable + 'ALTER INDEX ' + idx.name + ' ON '
  9.                     + obj.name + ' REBUILD;' + CHAR(13) + CHAR(10)
  10. FROM sys.indexes idx
  11. JOIN sys.objects obj
  12.     ON idx.object_id = obj.object_id
  13. WHERE idx.type_desc = 'NONCLUSTERED'
  14.     AND obj.type_desc = 'USER_TABLE'
  15.     AND obj.name = @table;
  16.  
  17. RAISERROR(@sqlDisable, 0, 1) WITH NOWAIT;
  18. RAISERROR(@sqlEnable, 0, 1) WITH NOWAIT;
  19. --EXEC(@sqlDisable);
  20. --EXEC(@sqlEnable);

Now, with those indexes disabled, the simple delete operation took a lot less than a minute! Even in the case of our 21 million rows table, deleting 7 million rows took only 1:02 on my machine. Of course, after deleting the unwanted rows, you need to re-enable the indexes again which took another minute, but all in all I'm happy with the result.

Copy Data to New Table and Drop Old Table

One other way of deleting rows that I've used in combination with changing the table schema at the same time is the following:

  • use a temporary table into which you copy all the rows you want to keep (the schema of which I modified to meet our new needs)
  • delete the original table
  • rename the temporary table to the original table's name
  • recreate all indexes you had defined before

This is basically what SSMS generates for you when you change the schema of a table, except for the indexes – you have to recreate them yourself.

As you can imagine, this approach becomes faster and creates smaller transaction log footprint with a growing amount of data to delete. It won't have any benefit if you delete less than half of the table's rows.

Choose the right tool for the job

There are quite a few other approaches and tips out there on how to speed up your deletion process. It depends a lot on your concrete situation which of those will actually help you get your deletion job done faster. I had to experiment quite a bit to find the sweet spot but now that I've seen a few approaches I'm able to take a better decision in the future.

About Oliver

shades-of-orange.com code blog logo I build web applications using ASP.NET and have a passion for jQuery. Enjoy MVC 4 and Orchard CMS, and I do TDD whenever I can. I like clean code. Love to spend time with my wife and our daughter.

About Anton

shades-of-orange.com code blog logo I'm a software developer at teamaton. I code in c# and work with mvc, orchard, specflow, coypu and nhibernate. I enjoy beach volleyball, board games and Coke.