Monday, September 8, 2014

Serializing private fields with JSON.NET and GetSerializableMembers

JSON.NET can handle serializing and deserializing private fields, but you have to tell it to do so.

In the past, you had to set the DefaultMembersSearchFlags property of the ContractResolver of your settings. But this property is now marked obsolete. The documentation/Intellisense tells you to override GetSerializableMembers instead.

But I've found there's just one extra step involved.

First thing to do is to create your own class that inherits from DefaultContractResolver and override the GetSerializableMembers method:

protected override List<MemberInfo> GetSerializableMembers(Type objectType)
{
    var result = base.GetSerializableMembers(objectType);

    if (objectType == typeof(MyClass))
    {    
        var memberInfo = objectType.GetMember("_myField", 
                BindingFlags.NonPublic | BindingFlags.Instance).Single();
        result.Add(memberInfo);
    }

    return result;
}

This will make sure JSON.NET serializes the private field, but it didn't seem to deserialize it in my case. The solution is to also override the CreateProperties method and set the property as... Readeable.

Curiously enough, you have to set the property as Readable, not Writeable. If anyone knows why, feel free to let me know (I have no time now to check the source).

Anyway, this is more or less what my code looks like now:

protected override IList<jsonproperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
    var properties = base.CreateProperties(type, memberSerialization);

    if (type == typeof(MyClass))
    {
        var property = properties.Single(x => 
                 x.PropertyName == "_myField" 
                 && x.DeclaringType == member.DeclaringType);
        property.Readable = true;
    }
    
    return properties;
}

Thursday, September 4, 2014

Seeing more code in Visual Studio and adding a Command to a Menu in a Toolbar

I spend most of my time in Visual Studio. My work time, that is, although it probably takes up a big portion of my overall life too... ouch!

I like to have a clean Visual Studio, void of toolbars, icons, panels,.... I'll summon them when I need them, but most of them I rarely need. I keep a strip at the bottom (collapsed) with things like Output, Error List, Unit Tests, etc. This is the one on my work-PC (not my personal PC, I wouldn't choose to work with TFS :)


To the right, I have my Solution Explorer and Properties (and at work, Team Explorer). At the top, only the main menu, no toolbars:



This allows for a clean working space, maximizing your view on what you actually work on most: the code. It reduces noise, reduces the need for splitting lines of code over multiple lines, and it pushes you to learn keyboard shortcuts, by which you increase your productivity/speed.

There's one toolbar that I've added to the right, with some things I need now and then. It's a customized toolbar so it only has the commands I need. And it's to the right, because my screen is wider than it is high, and I want to be able to see as much code as possible. Putting it to the right is less "invasive" than if I were to put it at the top.

For the buttons, I've even declared my own shortcuts (i.e. Source Control Explorer maps to ctrl+alt+shift+S). You can do this via Tools > Customize > Keyboard... Search for "View.TfsSourceControlExplorer".

It's a little harder to add a command to a menu. You can see there's a Configuration item, where I can change the active Configuration of the solution:


(To my knowledge, there's no shortcut for this, and even if there was, you need some way of seeing the active configuration)

So, adding this to such a toolbar is not that intuitive. What's more, you want to add this Command ("Solution Configurations") to a Menu inside your Toolbar. Just adding it to the Toolbar will hide it when docked left or right.

To add a Command to a Menu inside a Toolbar, first create a new Toolbar. Go to Tools > Customize and click "New...". Give it a name and then go to the Commands tab.

In the Commands tab, select the "Toolbar" radio button and select your new Toolbar from the list. Add a new menu and click the "Modify Selection" button to give it a name. The Menu inside your new Toolbar actually is a new Toolbar in itself. So select that one:


Now click "Add Command" and select (in my case) Build > Solution Configurations:
Now, dock the Toolbar to the right, and you have the result:
It's not very intuitive that the Menu inside your Toolbar lists as a new Toolbar. But once you learn to customize your Visual Studio for your needs, and for maximizing screen real estate for code, you can begin working more efficiëntly.

Friday, July 18, 2014

Angular and ASP.NET MVC: when to use which golden hammer

In my previous post, I outlined how to use ASP.NET MVC and Angular together, making certain views pure MVC and others Angular.

When I first used Angular this way, I was so happy, I went the full Angular way making requests from Angular for my data. Essentially, something like this:
$http({
    method: 'GET',
    url: '/api/rest/'
}).success(function (data, status, headers, config) {
    vm.names = data;
}).error(function (data, status, headers, config) {
              
});

This is code inside my customers.js. It's just a call to my RestController.cs (a WebAPI controller). In my customers.html template, I have a simple:
<li ng-repeat="name in vm.names">{{name}}</li>

But now, we're making two requests for something that the server could have added to our HTML anyway. This would be different if we could add a customer on the overview page, but because adding is done on a separate page, this data is actually static (from the viewpoint of the browser).

So can we keep using Angular, but let the server dynamically add anything to the page that it can? Luckily yes, and this is where, to me, we hit the sweet spot of SPAs: making the web application feel responsive thanks to Angular, but making it performant and limiting request thanks to ASP.NET.

Here's how.

Add a new (MVC) controller and a view. Make the controller return the view with the necessary data, taking care to add Angular attributes where necessary. Something like this:
@model IEnumerable<string>

<section id="dashboard-view" class="mainbar" data-ng-controller="customersmvc as vm">
    <h1>{{vm.title}}</h1>

    <a href="/Angular/#/customers/create">Create new customer</a>

    <p>
        The title of this view is rendered via Angular, whereas the customer names are added to
        the HTML on the server.
    </p>

    <div>
        <ul>
            @foreach (var name in Model)
            {
                <li>@name</li>
            }
        </ul>
    </div>

</section>

This page now combines Angular and ASP.NET MVC. This can be handy for data that is "dynamic" in the sense that it comes from a database, differs per user, etc but won't change once it's rendered in the browser.

For data that will change in the browser, you can still leverage Angular.

One final thing to take a look at is that ASP.NET MVC will set the Layout of the view you are loading. This is done in the _ViewStart.cshtml file. Of course, you want to keep this for pages loaded normally via ASP.NET MVC, but not for the ones loaded by Angular.

If we would keep this for the pages loaded by Angular, we would get our navigation, footer, etc. twice. You can easily avoid this by adding the following to the view:

@{Layout = null;}

So that's basically how I've combined ASP.NET MVC and Angular. Let me know if you've found a better or different way, or if you have any comments or questions.

Wednesday, July 16, 2014

Angular and ASP.NET MVC: now I've got two golden hammers!

Angular is a great tool, but it took me some time to find a way to combine it elegantly with ASP.NET MVC. This is basically how I did it.

First, create a new ASP.NET MVC application. Next, install the Angular package via NuGet. Now for the customization.

The objective is to use the normal ASP.NET MVC navigation, unless for certain URLs, when we'll let Angular take over.

So http://www.example.com/Account/Login would be handled by ASP.NET ("ASP.NET-mode"), but http://www.example.com/#/Customers would be handled by Angular ("Angular-mode"). Of course, it's ASP.NET serving us the Customers page, but after that, we want to use Angular for data-binding, navigation, routing, the forms, etc.

Add a new Controller with one method, Index(), that returns View(). Standard ASP.NET up until now. I named mine AngularController.

Next, add a View in the corresponding folder (in my case: /Angular/Index.cshtml). In this view, set up your main Angular view. Something like:
@{
    ViewBag.Title = "Index";
}

<div ng-app="app">
    <div ng-controller="main as vm">
        <div ng-view class="shuffle-animation"></div>
    </div>
</div>

@section scripts {
    @Scripts.Render("~/bundles/angular")
}

So when we're in "Angular-mode", we want ASP.NET MVC to include our Angular scripts. The angular bundle looks something like this (in /App_Start/BundleConfig.cs):
bundles.Add(new Bundle("~/bundles/angular").Include(
                      "~/Scripts/angular.js",
                      "~/Scripts/angular-animate.js",
                      "~/Scripts/angular-route.js",
                      "~/Scripts/angular-sanitize.js",
                      "~/Scripts/app/app.js",
                      "~/Scripts/app/config.js",
                      "~/Scripts/app/main.js",
                      "~/Scripts/app/customers/customers.js"));

The reason I'm not using a ScriptBundle is because we don't want ASP.NET to minify the Angular scripts. This causes errors because Angular sometimes depends on function arguments to be specific strings. You can read more on that here.

For now, minification isn't important, but in a production-environment, you would want to use the minified Angular scripts.

In app.js, config.js and main.js, I've put the necessary code to get Angular running. The most important part is the getRoutes function in config.js:
function getRoutes() {
    return [
        {
            url: '/customers',
            templateUrl: '/Scripts/app/customers/customers.html'
        }
    ];
}

Finally, the customers.html and customers.js contain my Angular logic and HTML markup for this specific page. This now allows you to navigate to http://localhost:1748/Angular/#/ (your portnumber may vary of course).

There you have it. ASP.NET MVC is serving the HTML page that includes references to Angular scripts and templates, the browser downloads all that, and then Angular wires it all together!

(Of course, you might want to configure ASP.NET to use a different URL for the AngularController)

Adding this to your navigation is as simple as adding this tag to your _Layout.cshtml file:
<li><a href="https://www.blogger.com/Angular/#/customers">Customers</a></li>

Don't forget the hash.

Now lets add a second page. This will make the difference between what I've been calling "ASP.NET-mode" and "Angular-mode" more clear.

Add a new html file and a new javascript file to the /Scripts/app/customers/ folder, add the route to config.js and add the javascript file to the Angular bundle in BundleConfig.cs. The link in my case would now be:
<a href="https://www.blogger.com/Angular/#/customers/create">Create new customer</a>

Now, when you run the app, navigating from /Angular/#/customers to, say, /Account/Login will load the entire new page. But navigating from /Angular/#/customers to /Anguler/#/customers/create stays within Angular, and just loads the new template, "staying inside" your SPA. You can sort of notice it because loading a new page "inside" the SPA feels faster.

So we've effectively combined classic ASP.NET MVC with Angular, allowing us to choose where we want/need which.

You can check out the source code in my GitHub repository. I've taken care to make every commit a logical step in the process.

Monday, June 16, 2014

Techorama 2014: Nik Molnar on GitHub

At Techorama, some sessions really sprung out. I took some notes and pictures (tip for the Windows Phoners: Office Lens) so I could share what I learnt.

Nik Molnar gave a great session on extending GitHub (see his slides on GitHub). He showed some of the great tools that add functionality to GitHub. If you don't already have a GitHub account or work with Git, I cannot over-recommend getting started with it.

Here are some things he shared, though very incomplete. Be sure to check out the rest or, even better, attend one of his talks if you can.

Printing

Gitprint is a simple idea that could be of great use. Go to a markdown file on GitHub and change the 'hub' in the url to 'print'. Presto! A printable PDF version of the file. You can also do this from the repository root and Gitprint will take the README.MD file.

Markdown

Speaking of Markdown. If you haven't already learned it, do so right away. It's increasingly the markup language of developers collaborating.
A handy tool for Markdown is MarkdownPad. It allows you to see the results on the fly and it offers a choice of the different Markdown flavors.
Something I learnt about Markdown is that apart from the usual readme.md file, GitHub also recognizes a contributing.md file. The readme file will be displayed in your repository root, but the contributing file will be shown to anyone that wants to create an issue. An example of such a file can be found in the Angular repository. Notice the link on the 'guidelines for contributing' when you want to create an issue.
And finally, if you're into Markdown and mindmapping, check out Memofon.com.

HuBoard

HuBoard is a task board that lists the issues of a GitHub repository and syncs between GitHub and HuBoard. When you drag a task to the done column, the issue is closed. Quite neat.

5 minute fork

5minfork.com is similar to gitprint.com. If your repository has an index.html file in the root, replace https://github.com/ with http://5minfork.com (lose the -s in the protocol) and a fork will be created and hosted. For example, https://github.com/petermorlion/pwa has an index.html. Go to http://5minfork.com/petermorlion/pwa to see it live. Of course, this is a simple example. But for more complex applications, this could be handy to see how it works when not on your local machine (think Angular, Durandal, etc).

etc etc etc

There was lots more: Emoji Cheat Sheet, Expandinizr, userscripts.org, Octokit, asciiflow, Web Sequence Diagrams, and more. Once again, check out the session in its entirety.


Wednesday, June 11, 2014

Techorama 2014: databases (Grant Fritchey)

I'm not a database guy. In fact, it's one of the aspects of programming I least like. So it surprised some of my colleagues when I told them I was attending a session at Techorama aimed at DBAs.

But the description struck a chord with me. Grant Fritchey gave a session named "Solving the Database Deployment Problem".

In my short career, I've only seen one place where database deployment was done correctly. And it was my first employer. Every change to the SQL database had to be put in a .sql file. The file went into source control. All these scripts could be executed multiple times on our local development sandbox (our own PC, no connections to servers). Essentially, you could rebuild the database time and again and start messing about from scratch.

These scripts were also executed on the build server, staging server, and finally production servers. We used RoundhouseE for database versioning and it all went more or less automatic and it was a blast!

Other companies seem to struggle with their database (although they won't admit the arcane and tedious wizardry that is easy-once-you-know-how-it's-done is struggling). Scripts need to be executed manually, versioning is done inside the script file, database compares are done, etc.

That's why I took a picture of what I believe was Grant's best slide:



First of all, treat it as code. That means (among others) putting it in source control. Too often, databases are still managed like we did in the nineties (well not we, as I was still on my skateboard back then, oblivious of the coolness of programming).

And automate! Don't waste developer's or DBA's precious time with tedious monkey jobs. Invest in an automated solution.


One question I asked him was if he had experience with NoSQL databases and automating that. NoSQL databases don't always have an easy way of creating scripts for updates and putting that into source control.

While Grant did have experience with NoSQL databases, they had a product (can't remember which) that did support scripts.

Although it should be feasable to have your application run some code on startup, and check/update the database if necessary. Sort of like Code First Migrations and MigrateDatabaseToLatestVersion in Entity Framework.

Not part of the Techorama session, but this slide deck Grant recently uploaded covers the session in more detail. And be sure to check out this extensive resource on the subject.


Tuesday, June 10, 2014

Use CDNs, but have a fallback mechanism

At Techorama 2014, Nik Molnar mentioned very shortly that you should use CDNs. CDNs, or Content Delivery Networks (or Distribution), are public repositories of javascript libraries, css files, images, etc that anyone can reference.

There are lots of CDNs out there. A popular one is Google Hosted Libraries. You'll find Angular, jQuery, jQuery UI, etc.

The main advantage of using a CDN is performance. There's a good chance that people who visit your site will already have visited a site referencing the same libraries/files. If these were hosted on a the same CDN that you are referencing, your browser will fetch the file from its own cache. That's one less HTTP request, and increased speed in loading the file.

An added bonus is that it doesn't use up your bandwidth :)

One thing Nik mentioned very briefly was to have a fallback mechanism in case the CDN doesn't respond. However, he didn't go into how this works.

A CDN that is down shouldn't happen (often), but knowing the internet, it will. If your site is a low profile, small throwaway test-site, there's no problem. If your site is more crucial and has lots of visitors, it pays to have this fallback, as it's very simple.

Instead of just referencing the CDN like this:

<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>


You can check for the existence of a variable the library defines. If it doesn't exist, load the local version of the file:

<script>
    window.jQuery 
    || document.write('<script src="js/libs/jquery-2.1.1.min.js"><script>')
</script>