MSBuild and VisualStudioVersion

Lately I have built up our deployment scripts to get them to be a bit more bullet-proof. I have also been creating some new web-based tooling to automate other tasks. I recently created a new web-tool using MVC 4, WebAPI and WCF. I needed to deploy to our test server, and I realized that I did not have MVC 4 and .NET 4.5 installed.

Then it dawned on me – this tool would probably go on our www server too, and that runs Server 2003 – so no .NET 4.5.

I changed up the projects no problem, but it wasn’t that simple. When I built, I ran into an error regarding the version of Microsoft.WebApplication.targets being used. I started digging in the csproj, and I found this bit:

<PropertyGroup>
  <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">
    10.0
  </VisualStudioVersion>
  <VSToolsPath Condition="'$(VSToolsPath)' == ''">
    $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\
      v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\
  WebApplications\Microsoft.WebApplication.targets"
  Condition="'$(VSToolsPath)' != ''" />

I banged my head a bit because, from the looks of it, the version is explicitly set to 10.0, but my error kept referencing 11.0? What gives?!? Then I found this post. The important piece for me was this:

To simplify this statement, the .sln file will build with specifying VisualStudioVersion to the value of the version of VS which created the .sln file.

I made the switch to VS 2012 a few months ago, and my co-worker and I were just talking about SLN files and some showing the “10” icon while others showed the “11”. I told him, “I am not sure why that is? But I do know that there is version-specific details in the SLN.” Isn’t it funny how the timing on some things can be so uncanny?

So, the workaround referenced within that post was the solution I needed:

msbuild.exe Web.csproj /p:VisualStudioVersion=10.0

All fixed!

WebAPI and JSON Serialization

I was getting this crazy “k__BackingField” crap, and quickly found this pablissimo.com post. It links to a post about changing the JSON serializer. Unfortunately, JSON.net is already used, so I am not sure why I was getting the crazy JSON garbage. [DataContract] and [DataMember] did the trick, but I am still left wondering why I had to go here? Oh well, I guess it is better to be explicit anyway, right?

On a semi-related note, I found this post on JSON casing with JsonMediaTypeFormatter. Pretty cool stuff…

Bootstrap Add-Ons

There is a great, big list of badass for Bootstrap over at bootstraphero.

Some of my favories:

I’ll also be checking out those WordPress themes…

Trolliminator!

I am a big soccer fan, and I love my MLS. I frequent the site and read up on all the articles. Unfortunately, there are a few faces that are always trolling in the comments. I really don’t even care to read what they have to say, as it doesn’t contribute to the discussion. I decided I’d do something about it.

Trolliminator!

Introducing the Trolliminator! bookmarklet.

javascript: (function () {
  var trolls = [
		'troll', // <-- add troll names here
	];
 
    var el = document.createElement('div'),
        b = document.getElementsByTagName('body')[0];
    otherlib = false, msg = '';
    el.style.position = 'fixed';
    el.style.height = '32px';
    el.style.width = '220px';
    el.style.marginLeft = '-110px';
    el.style.top = '0';
    el.style.left = '50%';
    el.style.padding = '5px 10px 5px 10px';
    el.style.zIndex = 1001;
    el.style.fontSize = '12px';
    el.style.color = '#222';
    el.style.backgroundColor = '#f99';
    if (typeof jQuery != 'undefined') {
        msg = 'This page already using jQuery v' + jQuery.fn.jquery;
        return showMsg();
    } else if (typeof $ == 'function') {
        otherlib = true;
    }
    function getScript(url, success) {
        var script = document.createElement('script');
        script.src = url;
        var head = document.getElementsByTagName('head')[0],
            done = false;
        script.onload = script.onreadystatechange = function () {
            if (!done && (!this.readyState || this.readyState == 'loaded' 
|| this.readyState == 'complete')) {
                done = true;
                success();
            }
        };
        head.appendChild(script);
    }
    getScript('http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js', 
function () {
        if (typeof jQuery == 'undefined') {
            msg = 'Sorry, but jQuery wasn\'t able to load';
        } else {
            msg = 'This page is now jQuerified with v' + jQuery.fn.jquery;
            if (otherlib) {
                msg += ' and noConflict(). Use $jq(), not $().';
            }
        }
        return showMsg();
    });
 
    function showMsg() {
        el.innerHTML = msg;
        b.appendChild(el);
        window.setTimeout(function () {
            if (typeof jQuery == 'undefined') {
                b.removeChild(el);
            } else {
                jQuery(el).fadeOut('slow', function () {
                    jQuery(this).remove();
                });
                if (otherlib) {
                    $jq = jQuery.noConflict();
                }
                trolliminator();
            }
        }, 2500);
    }
 
    function trolliminator() {
    	var $ = jQuery;
    	var matchCounter = 0;
    	$.each(trolls, function(index, value) {
    		$('.gig-comments-comment-username').filter(function() {
    			var match = $(this).text() == value;
    			if (match) {
    				var table = $(this).closest('table');
    				table.hide();
    				table.parent().append(
$('<div>').css({ 'color':'#666', 'font-style':'italic' })
.html('Trolliminated!'));
    				matchCounter++;
    				return match;
    			}
    		});
    	});
    	$('<div>').css({ 
'position':'fixed', 'right':'0', 'bottom':'0', 
'padding':'5px', 'font-weight':'bold', 
'color':'#090', 'z-index':'99999' })
.html(matchCounter + ' trolls eliminated').appendTo('body');
    }
})();

To use it:

  1. Edit the “trolls” using comma-separated, single-quoted names
  2. Save it as a bookmarklet
  3. Hit it up prior to reading any article

It removes posts for matching “trolls” and replaces them with a “Trolliminated!” message. It also puts a counter down in the bottom-right corner. I started to develop a Chrome extension, but I ran into a little trouble and, to be honest, I did not want to put much effort into blocking the trolls – that is just another way they are fed.
🙂

MLSSoccer.com uses Gigya, so this should technically work with any other site that uses Gigya comments.

Cool CSS gradient text effect in Webkit

.textfade {
  background: 
    -webkit-gradient(linear,left top,right top,from(#0060F3),to(#00339A));
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
}

“Borrowed” from Polygon

This makes some pretty cool gradient-filled text!

* If you aren’t using a Webkit browser, then the above is an image to show you what you are missing

Here Be Dragons

Probably just as interesting was the hoops I had to jump through to get something to show up to illustrate how it looks in Webkit browsers for non-Webkit browsers. Only an image would do, so I needed to do some CSS trickery. First, the Firefox-only CSS:

@-moz-document url-prefix() {
  .textfade {
    background: url(/wp-content/uploads/2013/03/gradient-text.png) 
      left top no-repeat;
    width: 590px;
    height: 27px;
    text-indent: -99999em;
  }
  q { display: none; }
}

The Firefox-only CSS was made easy by the Firefox-specific plugin syntax.

Now, for the IE-specific stuff:

<!--[if IE]>
<script>document.documentElement.className='ie10';</script>
<![endif]-->
<script>
if(Function('/*@cc_on return 10===document.documentMode@*/')()){
  document.documentElement.className='ie10';
}
</script>
.ie10 .textfade {
  background: url(/wp-content/uploads/2013/03/gradient-text.png) 
    left top no-repeat;
  width: 590px;
  height: 27px;
  text-indent: -99999em;
}
.ie10 q { display: none; }

The IE stuff was (as expected) much more difficult. Conditional comments make most of it easy, but with IE 10 not supporting them, that made it tricky. So, you need to perform a little js check and attach a classname tot he document as a nice work-around. I decided to use this same thing in the conditional comments too, that way I only needed to make 1 CSS change for all IE browsers.

Since IE forced me into using js to do the conditional comments checking, I really could have just went full-js and it probably would have been easier. I thought this was interesting, however, and I was striving for a strictly CSS solution. Alas, IE comes along to screw things up (as usual) and I was unable to create the solution I was looking for. The tricks are still cool.
🙂

Select2 and Chosen

I was looking at my options for including an image in a select list – why is this not easier?

Anyway, I found some good Stackoverflow Q & A’s, and one mentions Select2. This is a pretty slicklooking jQuery extension, and it is based on another really cool plugin, Chosen.

The Select2 site uses Bootstrap, and the more I see examples in Bootstrap the more I <3 Bootstrap! I have discussed moving our company site over to Bootstrap to take advantage of the goodness that it offers (especially responsive UI) and the Select2 would be a great addition.

So much to do and so little time… 🙂

Powershell Cookbook

I have been working on a LOT of automation scripting, and for whatever reason whenever I did this int he past I always used batch files – I guess I was just used to it? Whatever…

I got smart (finally) and started using Powershell and I have been able to do some pretty cool automation (post with scripts incoming). Powershell has a quirky syntax, and I have been doing lots of googling. I just ran across the Powershell Cookbook. Pretty good stuff…

What a PITA!

frustration300x300

I got the seemingly ever-present message to upgrade WP, so I stupidly did. Then I could no longer log in!?! It kept saying my password was incorrect. I could not send myself a password reset because the mail server isn’t configured. Great.

After much searching and a lot of wasted time, I finally was able to manually change my password. The following pages came in very handy:

The MySQL Workbench tools were also invaluable, as it was much easier to download/install than to setup phpMyAdmin.

I am really hoping that this was in fact related to the install. I’d hate to think that somehow my blog login was compromised. It seems a bit too coincidental though, so it most likely was something upgrade-related. I’ll have to check out my other accounts though…

Lorem Pixel

LoremPixel.comClick the refresh icon to update the sample image
refresh-icon16x16

LoremPixel.com – the Lorem Ipsum of images.

This, lorem ipsum and Twitter Bootstrap and you can whip up a pretty good mockup/prototype.

Instruction for use, taken directly from the lorem pixel homepage:

Placeholder Images for every case. Webdesign or Print. It’s simple and absolutely free! Just put the custom url in your code like this:
<img src="http://lorempixel.com/400/200" />
to get your FPO / dummy image.

http://lorempixel.com/400/200 to get a random picture of 400 x 200 pixels
http://lorempixel.com/g/400/200 to get a random gray picture of 400 x 200 pixels
http://lorempixel.com/400/200/sports to get a random picture of the sports category
http://lorempixel.com/400/200/sports/1 to get picture no. 1/10 from the sports category
http://lorempixel.com/400/200/sports/Dummy-Text …with a custom text on the random Picture
http://lorempixel.com/400/200/sports/1/Dummy-Text …with a custom text on the selected Picture