Quantcast
Channel: Scott Hanselman's Blog
Viewing all 1148 articles
Browse latest View live

Introducing Windows Azure WebJobs

$
0
0

I'm currently running 16 web sites on Windows Azure. I have a few Virtual Machines, but I prefer to run things using "platform as a service" where I don't have to sweat the underlying Virtual Machine. That means, while I know I can run a Virtual Machine and put "cron" jobs on it, I'm less likely to because I don't want to mess with VMs or Worker Roles.

There are a few ways to run stuff on Azure, first, there's IAAS (Infrastructure as a Service) which is VMs. Then there's Cloud Applications (Cloud Services) where you can run anything in an Azure-managed VM. It's still a VM, but you have a lot of choice and can run Worker Roles and background stuff. However, there's a lot of ceremony if you just want to run your small "job" either on a regular basis or via a trigger.

image

Looking at this differently, platform as a service is like having your hotel room fixed up daily, while VMs is more like managing a house yourself.

image

As someone who likes to torch a hotel room as much as the next person, this is why I like Azure Web Sites (PAAS). You just deploy, and it's done. The VM is invisible and the site is always up.

However, there's not yet been a good solution under web sites for doing regular jobs and batch work in the background. Now Azure Web Sites support a thing  called "Azure WebJobs" to solve this problem simply.

Scaling a Command Line application with Azure WebJobs

When I want to do something simple - like resize some images - I'll either write a script or a small .NET application. Things do get complex though when you want to take something simple and do it n times. Scaling a command line app to the cloud often involves a lot of yak shaving.

Let's say I want to take this function that works fine at the command line and run it in the cloud at scale.

public static void SquishNewlyUploadedPNGs(Stream input, Stream output)
{
var quantizer = new WuQuantizer();
using (var bitmap = new Bitmap(input))
{
using (var quantized = quantizer.QuantizeImage(bitmap))
{
quantized.Save(output, ImageFormat.Png);
}
}
}

WebJobs aims to make developing, running, and scaling this easier. They are built into Azure Websites and run in the same VM as your Web Sites.

Here's some typical scenarios that would be great for the Windows Azure WebJobs SDK:

  • Image processing or other CPU-intensive work.
  • Queue processing.
  • RSS aggregation.
  • File maintenance, such as aggregating or cleaning up log files. 
  • Other long-running tasks that you want to run in a background thread, such as sending emails.

WebJobs are invoked in two different ways, either they are triggered or they are continuously running. Triggered jobs happen on a schedule or when some event happens and Continuous jobs basically run a while loop.

WebJobs are deployed by copying them to the right place in the file-system (or using a designated API which will do the same). The following file types are accepted as runnable scripts that can be used as a job:

  • .dll, .exe - .NET assemblies compiled with the WebJobs SDK
  • .cmd, .bat, .exe (using windows cmd)
  • .sh (using bash)
  • .php (using php)
  • .py (using python)
  • .js (using node)

After you deploy your WebJobs from the portal, you can start and stop jobs, delete them, upload jobs as ZIP files, etc. You've got full control.

A good thing to point out, though, is that Azure WebJobs are more than just scheduled scripts, you can also create WebJobs as .NET projects written in C# or whatever.

Making a WebJob out of a command line app with the Windows Azure WebJobs SDK

WebJobs can effectively take some command line C# application with a function and turn it into a scalable WebJob. I spoke about this over the last few years in presentations when it was codenamed "SimpleBatch." This lets you write a simple console app to, say, resize an image, then move it up to the cloud and resize millions. Jobs can be triggered by the appearance of new items on an Azure Queue, or by new binary Blobs showing up in Azure Storage.

NOTE: You don't have to use the WebJobs SDK with the WebJobs feature of Windows Azure Web Sites. As noted earlier, the WebJobs feature enables you to upload and run any executable or script, whether or not it uses the WebJobs SDK framework.

I wanted to make a Web Job that would losslessly squish PNGs as I upload them to Azure storage. When new PNGs show up, the job should automatically run on these new PNGs. This is easy as a Command Line app using the nQuant open source library as in the code above.

Now I'll add the WebJobs SDK NuGet package (it's prerelease) and Microsoft.WindowsAzure.Jobs namespace, then add [BlobInput] and [BlobOutput] attributes, then start the JobHost() from Main. That's it.

using Microsoft.WindowsAzure.Jobs;
using nQuant;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
JobHost host = new JobHost();
host.RunAndBlock();
}

public static void SquishNewlyUploadedPNGs(
[BlobInput("input/{name}")] Stream input,
[BlobOutput("output/{name}")] Stream output)
{
var quantizer = new WuQuantizer();
using (var bitmap = new Bitmap(input))
{
using (var quantized = quantizer.QuantizeImage(bitmap))
{
quantized.Save(output, ImageFormat.Png);
}
}

}
}
}

CONTEXT: Let's just step back and process this for a second. All I had to too was spin up the JobHost and set up a few attributes. Minimal ceremony for maximum results. My console app is now processing information from Azure blob storage without ever referencing the Azure Blob Storage API!

The function is automatically called when a new blob (in my case, a new PNG) shows up in the input container in storage and the Stream parameters are automatically
"bound" (like Model Binding) for me by the WebJobs SDK.

To deploy, I zip up my app and upload it from the WebJobs section of my existing Azure Website in the Portal.

image

Here it is in the Portal.

image

I'm setting mine to continuous, but it can also run on a detailed schedule:

12schdmonthsonpartweekdaysoccurences

I need my WebJob to be told about what Azure Storage account it's going to use, so from my Azure Web Site under the Connection Strings section I set up two strings, one for the AzureJobsRuntime (for logging) and one for AzureJobsData (what I'm accessing). 

image

For what I'm doing they are the same. The connection strings look like this:

DefaultEndpointsProtocol=https;AccountName=hanselstorage;AccountKey=3exLzmagickey

The key here came from Manage Access Keys in my storage account, here:

image

In my "Hanselstorage" Storage Container I made two areas, input and output. You can name yours whatever. You can also process from Queues, etc.

image

Now, going back to the code, look at the parameters to the Attributes I'm using:

public static void SquishNewlyUploadedPNGs(           
[BlobInput("input/{name}")] Stream input,
[BlobOutput("output/{name}")] Stream output)

There's the strings "input" and "output" pointing to specific containers in my Storage account. Again, the actual storage account (Hanselstorage) is part of the connection string. That lets you reuse WebJobs in multiple sites, just by changing the connection strings.

There is a link to get to the Azure Web Jobs Dashboard to the right of your job, but the format for the URL to access is this: https://YOURSITE.scm.azurewebsites.net/azurejobs. You'll need to enter your same credentials you've used for Azure deployment.

Once you've uploaded your job, you'll see the registered function(s) here:

image

I've installed the Azure SDK and can access my storage live within Visual Studio. You can also try 3rd party apps like Cloudberry Explorer. Here I've uploaded a file called scottha.png into the input container.

image

After a few minutes the SDK will process the new blob (Queues are faster, but blobs are checked every 10 minutes), the job will run and either succeed or fail. If your app throws an exception you'll actually see it in the Invocation Details part of the site.

image

Here's a successful one. You can see it worked (it squished) because of the number of input bytes and the number of output bytes.

image

You can see the full output of what happens in a WebJob within this Dashboard, or check the log files directly via FTP. For me, I can explore my output container in Azure Storage and download or use the now-squished images. Again, this can be used for any large job whether it be processing images, OCR, log file analysis, SQL server cleanup, whatever you can think of.

Azure WebJobs is in preview, so there will be bugs, changing documentation and updates to the SDK but the general idea is there and it's solid. I think you'll dig it.

Related Links


Sponsor: Big thanks to combitfor sponsoring the blog feed this week! Enjoy feature-rich report designing: Discover the reporting tool of choice for thousands of developers. List & Label is an award-winning component with a royalty-free report designer. Free trial!



© 2014 Scott Hanselman. All rights reserved.
     

Why isn't People-Centric UI Design taking off?

$
0
0

NOTE: This post is just speculation and brainstorming. I'm not a UX expert by any means, although I have worked in UI testing labs, run A/B tests, yada yada yada. I dabble. Also, I work for Microsoft, but on the Web and in Open Source. I use an iPhone. Those facts don't affect my ramblings here.

Screenshot from my Windows 3.1 Virtual MachineiPhone screenshot from Flickr User philozopher used under CC

I'm just a little disappointed that 30 years later (longer of course, if you consider Xerox Alto and before, but you get the idea) and we're still all looking at grids of icons. But not just icons, icons are great. It's that the icons still represent applications. Even on my iPhone or iPad I can't have an icon that represents a document. The closest I can get is to add a URL from Mobile Safari.

After Windows 3.1, Microsoft made a big deal about trying to say that Windows was a "document-centric operating system." OS/2 Warp did similarly, except object-centric, which was rather too meta for the average business user. Bear with me here, this is old news, but it was a big deal while we were living it. They kept pushing it up through Windows 98.

This document-centric approach is reflected in a number of Windows 98 features. For example, you can place new blank documents on the Desktop or in any folder window. You can access documents via the Documents menu on the Start menu. You can click a file icon and have its associated application open it, and you can define actions to be taken on a file and display those actions as options in the context menu

Today on the desktop we take all this for granted. Ubuntu, OS X, Windows all know (for the most part) how a document was created and let us open documents in associated programs. iOS is starting to get similar document-centric abilities, although it appears Open In is limited to 10 apps.

In Windows Phone and Windows 8+ I can pin People to the Start Screen. It's a killer feature that no one talks about. In fact, Nokia recently tweeted a screenshot of a 1080p Windows Phone (I've been testing the this last month myself) and I think they made a mistake here. Rather than pinning People, Faces, Groups, Friends, Family, Co-Workers, etc, they shrunk down a bunch of ordinarily good looking icons to their most unflattering to see how many they could fit on the screen.

(Plus they have 19 Updates pending, which I just find annoying.)

Here's mine next to theirs, just to contrast. Now, far be it from me to tell someone how to personalize their phone, I'm just trying to show that it doesn't have to be cartoonish.

What I'm really interested inis why do we, as humans, find App Centric interfaces more intuitive than People Centric ones?

Be5xQ4aCMAABrmy wp_ss_20140127_0006

The "story" around People Centric is that you don't think "go to twitter and tweet my friend" or "go to Skype and call my friend," instead you click a picture of your friend and then contact them in any possible way using any enlisted app from there.

For example, if I search my Windows machine for "Scott Guthrie" I get this (Scott is lousy about keeping his pictures up to date.)

image

You can see from here I can Email, Call, Facebook, Skype (if he had Skype), or get a map to his house. All his actual accounts, Twitter, Facebook, etc are linked into one Scott Guthrie Person.

Screenshot (56)

It works great on the phone, where I'm more likely to do more than just email. Note at the bottom there's a chain with a number showing that my wife has 6 accounts (Google, Hotmail, Facebook, Skype, etc) that are all linked into one Contact.

image

Folks that use Windows Phone mostly know about these features, and the hardcore users I know pin people to Start. On the desktop, though, I never see this. I wonder why. I am surprised that in a people focused world of social networks that elevating our friends, family and loved ones to be at least peers with notepad.exe would have happened by now.

What do you think, Dear Reader? Have you given this some thought in your interfaces?


Sponsor: Thanks to Red Gate for sponsoring Blog Feed this week! Want Easy release management? Deploy your SQL Server databases in a single, repeatable process with Red Gate's Deployment Manager. There's a free Starter edition, so get started now!



© 2014 Scott Hanselman. All rights reserved.
     

Here's 10 things I did before I wrote this blog post title. What happened next will shock you.

$
0
0

What a crap title, eh? Just the worst. But this kind of linkbait garbage is rampant on our internet - that's yours and my internet, people - and we're promoting their chicanery by spreading their links.

This came to a head for me yesterday when a video started going viral on the social web AGAIN. I say AGAIN because it was the same darn video from 5 years ago, just with a new title. Seriously, a totally unrelated "viral" site made up a new title, called it an article, then embedded the video with their ads everywhere, then (I presume) went to their bosses and say "my stuff generated x PV (page views) this week."

Step 4. PROFIT

I partially blame BuzzFeed, but every once in a while they have a decent article. Upworthy is another, disguising their stealing with an "inspirational spin." One that is the worst is ViralNova - find them yourself, no link from me. Sites like these started this style of hanging headline:

  • It Might Seem Like A Normal Temple From The Outside. But Go Inside And… AHHHH!
  • This Is The Most Unique Sunrise You’ll Ever See. Guaranteed.
  • A 12 Year-Old Boy Wrote The Perfect Advice To Understand Women. This Is Priceless.
  • You’ll Have No Idea What You’re Seeing In These 20 Photos. But Look A Little Closer…

How is this a business? Apparently mining for Page Views is more profitable than mining for Bitcoin.

And now this madness is spreading to CNN. That's supposed to be a real news site, folks.

These are custom designed to prey on our base human need to always be seeing new crap. It's drug pushing.

Many sites declare their content "curated" and pull it (most often without explicit permission) from elsewhere. They pull so much from the original site that there's usually no reason to visit the original site! One article recently had 20 high resolution pictures lifted from elsewhere. Buried in the the post it said "via so-in-so" so I visited there, if only to give my page view to the original author and some how cleanse myself. I counted the photos while I was there. There where 20 images. They had reblogged them all.

These are entire "media companies" that have turned reblogging into an art. Reblogging is not journalism. It's not even nice. It's not appreciated, it's not appropriate, and it's not kind.

When you blog, think about what it really means to curate. Consider the Curator's Code. When you use something, give attribution or a hat tip. Confused or not sure if you should use something, ask. Just email them, explain what you want to do, and ask.

There's even Chrome extensions like @snipeyhead's "Downworthy" that will replace the text in headlines like these with more appropriate text.

Please, don't start a multimillion pageview media conglomerate based on copy-pasting other people's hard work combined with deceptive copywriting.

Reject them. I reject them. Will the beginning of the end start on the Dark and Evil Side of the Internet or will it sneak up on us slowly with harmless titles like "The 26 Craziest Crimes That Involve Taco Bell." OMG! I have to click.

image


Sponsor: Thanks to Red Gate for sponsoring Blog Feed this week! Want Easy release management? Deploy your SQL Server databases in a single, repeatable process with Red Gate's Deployment Manager. There's a free Starter edition, so get started now!



© 2014 Scott Hanselman. All rights reserved.
     

Fixed: The Synology NAS with Plex Server and mismatched version numbers

$
0
0

I am a HUGE fan of Plex. Plex is a server you run combined with both a great HTML5 web app and some awesome native clients. Plex has clients for iOS, Windows Store, Windows Phone, and on and on. Best yet, the Plex Server can run not only on your spare computers, but also NAS (Network Attached Storage) devices like Synology, Netgear, Drobo, and more.

Last year, Plex came to the Synology DiskStation. I have a Synology 1511+ NAS and run everything on it from Minecraft Servers to Plex to using it as a giant 5TB NAS to storing my Time Machine backups and Windows 8 File History. I also run CrashPlan headless on my Synology.

Synology has an ersatz App Store that allows you to easily install all sorts of stuff to your Synology NAS, like phpBB, Plex, Git, and more.

Plex installed on Synology

However, I personally (and others) have found this feed of packages to be either updated not very often, or when it is updated, versions don't line up.

If I can be slightly critical of Plex for a moment, they are fairly aggressive about keeping their client and server protocol versions in line. This means if you aren't keeping your Plex Server reasonably up to date, one day you'll startup your iPad Plex app or Windows Plex app and be told that server version is too old. It's a little jarring.

The issue for me happens when I go to the Synology to update and there's no new update. So the client is saying "you need version x+2" and all I see on the Synology feed is version x.

Plex example on a Microsoft Surface RT with Windows 8

Here's the gotcha, and why I'm writing this up for you. You can use the Manual Install option (as seen in the top picture) then visit https://plex.tv/downloads and manually upload the .SPK file for Plex to your Synology server.

If you don't uninstall Plex first - that's the one that you install from Synology's feed originally - then you can get yourself into some very weird versioning situations where Plex thinks one version is running and the Synology thinks another as seen in the screenshot below.

Plex Version Numbers not lining up

This has been discussed in the forums for almost a year now with no clear answer or solution.

Again, here's what I did:

  • Uninstall Plex from the Synology Package Manager
  • Download Plex from https://plex.tv/downloads
  • Use Manual Install to install the new SPK to Synology

I hope this helps someone. Be sure to check out Plex, it's a joy.


Sponsor: Big Thanks to Aspose for sponsoring the blog this week! Aspose.Total for .NET has all the APIs you need to create, manipulate and convert Microsoft Office documents and a host of other file formats in your applications. Curious? Start a free trial today.



© 2014 Scott Hanselman. All rights reserved.
     

Deploying TWO websites to Windows Azure from one Git Repository

$
0
0

Deploying to Windows Azure is very easy from Git. I use the Azure Cross-Platform Command Line (open source on github, written in node) that I get from npm via "npm install azure-cli --g" to make the sites.

When you make a new site with the Azure command line, you'll usually do this:

azure site create --location "West US" MyFirstSite --git

And the tool will not only make the site, but also add a git remote for you, something like https://username@MyFirstSite.scm.azurewebsites.net:443/MyFirstSite.git. When you push to that git remote, Azure deploys the site. You can git push sites with PHP, node, ASP.NET, and Python.

Two Deployments in Azure using Git

You may have multiple remotes with your git repository, of course:

C:\MyCode>git remote show
azure
origin

When you push a folder with code to Azure via Git, unless you're pushing binaries, Azure is going to compile the whole thing for you when it gets pushed. It will restore npm modules or restore NuGet packages, and then build and deploy your app.

If your repository has a lot of .NET projects, you usually only want one project to be the actual deployed website, so you can add a .deployment file to specify which project contains website you're git deploying:

[config]
project = WebProject/MyFirstSiteWebProject.csproj

However, in lieu of a .deployment file, you can also set an application configuration setting with the Azure Portal to to the same thing.

Setting Kudu Projects with Config options

Or, of course, set the configuration values for each site using the Azure Command Line:

c:\MyCode>azure site config add Project=WebProject/MyFirstSiteWebProject.csproj [sitename]

What's nice about setting the "Project" setting via site configuration rather than via a .deployment file is that you can now push the same git repository containing two different web sites to two remote Azure web sites. Each Azure website should have a different project setting and will end up deploying the two different sites.

Git Deploying from one Repo to two separate Azure Web Sites

I do this by setting the git remotes manually like this, using the correct git remote URLs I get from the Azure Portal:

C:\MyCode> git remote add azureweb1 https://scott@website1.scm.azurewebsites.net:443/website1.git
C:\MyCode> git remote add azureweb2 https://scott@website2.scm.azurewebsites.net:443/website2.git
C:\MyCode> git remote show
azureweb1
azureweb2
origin
C:\MyCode> git push azureweb1 master

I have a number of solutions with two or more web sites, or in one case, a web site I want separate from my web api, and I deploy them just like this.

Hope this helps!


Sponsor: Big Thanks to Aspose for sponsoring the blog this week! Aspose.Total for .NET has all the APIs you need to create, manipulate and convert Microsoft Office documents and a host of other file formats in your applications. Curious? Start a free trial today.



© 2014 Scott Hanselman. All rights reserved.
     

HTTP PUT or DELETE not allowed? Use X-HTTP-Method-Override for your REST Service with ASP.NET Web API

$
0
0

I got an email today where someone had built a REST(ful/ish) API with ASP.NET Web API that had a customer who was against the idea of using GET, POST, PUT, and DELETE, and insisted that they only use GET and POST.

Sometimes this is because of a browser or client limitaton, sometimes it's a really tense corporate firewall. They wanted to know what they could do.

One thing you can do is to "tunnel" HTTP Methods inside another HTTP Header. Basically you have a header that says "No, seriously, I know I got here via a POST, but use this one instead." You would still POST, but then you'd have "X-HTTP-Method-Override:PUT" as a header.

Here is a PUT in the Postman REST client:

image

So that's:

PUT /api/Person/4 HTTP/1.1
Host: localhost:10320
Content-Type: application/json
Cache-Control: no-cache

And here's the same PUT, except as a POST plus an X-HTTP-Method-Override header.

image

Raw, that's like this:

POST /api/Person/4 HTTP/1.1
Host: localhost:10320
Content-Type: application/json
X-HTTP-Method-Override: PUT
Cache-Control: no-cache

Now, how do you get ASP.NET Web API to respect this new way to route things? You may have a Web API Controller like this:

public IEnumerable<Person> Get() { }

// GET api/person/5
public Person Get(int id) { }

// POST api/person
public void Post([FromBody]Person value) { }

// PUT api/person/5
public void Put(int id, [FromBody]Person value) { }

// DELETE api/person/5
public void Delete(int id) { }

And you likely don't want to change it. Make a MethodOverrideHandler like this one. You can add the code yourself, get it from a NuGet package, or use one from the WebAPIContrib project. It's up to you.

public class MethodOverrideHandler : DelegatingHandler
{
readonly string[] _methods = { "DELETE", "HEAD", "PUT" };
const string _header = "X-HTTP-Method-Override";

protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
// Check for HTTP POST with the X-HTTP-Method-Override header.
if (request.Method == HttpMethod.Post && request.Headers.Contains(_header))
{
// Check if the header value is in our methods list.
var method = request.Headers.GetValues(_header).FirstOrDefault();
if (_methods.Contains(method, StringComparer.InvariantCultureIgnoreCase))
{
// Change the request method.
request.Method = new HttpMethod(method);
}
}
return base.SendAsync(request, cancellationToken);
}
}

You see it checks if it's a post, looks for the extra header, then changes the request's Method property after the message has been received, but before it's been sent through the pipeline. It'll show up on the right method just as if a PUT had been sent, because from its perspective, a PUT was sent.

You need to register this new MethodOverrideHandler in your WebApiConfig like this, just by adding to the MessageHandlers collection, next to the rest of the configuration and routing code.

public static void Register(HttpConfiguration config)
{
config.MessageHandlers.Add(new MethodOverrideHandler());

//OTHER REGULAR STUFF HERE

// Web API routes
config.MapHttpAttributeRoutes();

config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}

On the client side, you can keep sending a post with your .ajax call in jQuery, for example, just make sure the override header in there.

$.ajax({
url: "http://localhost:10320/api/Person/4",
type: "POST",
data: JSON.stringify(whatever),
headers: {
"Content-Type": "application/json",
"X-HTTP-Method-Override": "PUT" },
})

That's the general idea, enjoy!


Sponsor: Big Thanks to Aspose for sponsoring the blog this week! Aspose.Total for .NET has all the APIs you need to create, manipulate and convert Microsoft Office documents and a host of other file formats in your applications. Curious? Start a free trial today.



© 2014 Scott Hanselman. All rights reserved.
     

Building Modern Web Apps with ASP.NET - A new day of free ASP.NET Training for 2014

$
0
0
Scott Hunter and Scott Hanselman talking about What's New in VS2013

Last year, about this time, a bunch of us sat down in a studio to give a full day of tutorials and discussion on "Building Web Apps with ASP.NET." All those videos are online and have lots of good content like:

We headed over to the Microsoft Virtual Academy Studios again just this last week for another full day of discussion, training, as well as a glimpse into the possible future of .NET. Between these two days of videos you'll get a real sense of what's possible and real advice on how to build your next web application.

Today we've got 7 all-new segments for you, each recorded live at the MS Studios.

These videos are featuring folks like Scott Hunter, Levi Broderick, Rowan Miller, Pranav Rastogi, Mads Kristensen, and Louis DeJardin. No marketing folks, just actual developers that work on ASP.NET every day.

ScottHu and ScottHa talking about VS20131: What's New in Visual Studio 2013 for Web Developers - Learn about the latest features in Visual Studio 2013, including dozens of tips and tricks.

image2: Upgrading Applications - Get a deep dive on how to upgrade your older applications to ASP.NET 4.5 and later.

image3: ASP.NET Identity - Explore the new ASP.NET Identity system. Learn how to migrate your existing membership data to the new Identity system and how to integrate with other membership systems.

image4: Web Essentials and the Client Side - Discover how to build modern client-side applications, more simply and quickly, with a host of new features, tips, and tricks in Web Essentials for Visual Studio.

image5: Entity Framework - Have you been using Entity Framework for data access in your web app? In this advanced demo-heavy session, learn the latest features of Entity Framework 6 and get sneak previews of what's coming in version 6.1.

image6: The "Katana" Project - Hear the latest on "Project Katana," the Microsoft implementation of Open Web Interface for .NET. It's a glimpse of the future for cloud-optimizing your ASP.NET applications.

image7: ASP.NET "Project Helios" - Discover "Project Helios," a prototype representing the re-thinking of the core of ASP.NET. Take a look at the future of web development, with a modular, lightweight OWIN host that runs on Internet Information Services (IIS).

Also be sure to explore the new series "Get Started with Windows Azure today" featuring content from ScottGu himself for a full 90 minutes!

image

I hope you have as much fun watching them as we did filming them.


Sponsor: Big Thanks to Aspose for sponsoring the blog this week! Aspose.Total for .NET has all the APIs you need to create, manipulate and convert Microsoft Office documents and a host of other file formats in your applications. Curious? Start a free trial today.


© 2014 Scott Hanselman. All rights reserved.
     

Checklist: What NOT to do in ASP.NET

$
0
0

Damian Edwards at NDC 2013 talking about ASP.NETAbout a year ago we thought it would be a good idea to do a talk on "What not to do in ASP.NET?" - basically an anti-patterns talks. We kept seeing folks falling into the same traps and wanted to be prescriptive as there's aspects to ASP.NET that are 10 years old and don't apply to today's internet, but there are also new aspects to ASP.NET that are only a year old, and perhaps haven't soaked into the zeitgeist quite yet.

Damian Edwards gave his version of this talk at NDC 2013 and you can watch the video here if you like, it's very entertaining.

We took the information we gathered from people like Damian, Levi Broderick and others, and Tom FitzMacken put together a whitepaper on the topic. It's not complete, but it covers some of the most common "gotchas" folks run into.

Here are the areas we call out in the whitepaper so far, with highlights below from me.

I hope this helps someone out!


Sponsor: Big Thanks to Aspose for sponsoring the blog this week! Aspose.Total for .NET has all the APIs you need to create, manipulate and convert Microsoft Office documents and a host of other file formats in your applications. Curious? Start a free trial today.



© 2014 Scott Hanselman. All rights reserved.
     

If you had to start over, what technologies would you learn in 2014?

$
0
0

I got an email recently from a long-time programmer who had to step out of the game for a little while. They basically had a hiatus from programming due to situations out of their control, but now are looking at getting back in.

They asked, quoting from the email:

If you had to “start over,” what are the technologies, languages, paradigms and platforms I need to be up-to-date and mastering in my new world of 2014?

It’s daunting if not downright scary.  I can *learn* anything, and do - quickly.  I feel like I’ve been sooooo out of the loop, it’s not even funny.

Programming Books used under Wikimedia CommonsI think we can all relate to feeling like this. I've talked about this before in my post "I'm a phony" about imposter syndrome. Technology is changing so fast it's hard to be a "professional" at anything. Ultimately, we're all amateurs.

To the root question, though, what technologies would I learn?

This question comes up a lot. I tell people this. Learn one language you can build large systems with AND also learn JavaScript. For me, that's C# and JavaScript. For someone else, the "systems" language might be Erlang, or Groovy, or Ruby, or Java, or Scala. That language matters less to me. Your goal is to be able to write applications for the web, as well as write other systems.

Pick a language that feels right

Learn a language that has a community behind it and that has been a part of building successful systems. Learn a language that lets you create the kinds of systems you want to create. For me, I picked C# because I can write web apps, Windows apps, Mac apps, iPhone apps, Windows Phone apps, SmartWatch apps, and tiny embedded apps, but above all because I enjoy writing C#.

There are many other languages that have a wonderfully rich breadth of power and expressiveness. Python is one, Java is another, and JavaScript and node can even control robots. Pick a language with personality and breadth, and learn that language the hard way, by doing. Read lots of code and lots of books. Pick a language that fits your brain and helps you learn how to think, and when you do think, think about abstractions'.

Write while you learn your new language. Write about what you discover, what works, what doesn't. Write even though no one may be reading; you may find that they are reading. Join your new language's community and go to its user groups. Remember not to have ego, you are not your code.

Bet on the Web

There's lots of talk about App Stores these days. Everyone has them and they are clearly where the money is made. But today's (2014's) App Stores are still broken. Updates are a hassle, even when they are automatic. Apps (on all platforms) get stuck in broken updating states and have to be reinstalled, updates are often huge and rarely use smart patching and deltas. App Stores can become weed-filled gardens if they aren't attended to.

The web persists, though. We have issues like net neutrality to work out, and walled gardens like Facebook, our standards orgs are stuck in committee, and we get a new identity subsystem every few years, but the web is winning. The web will persist and the web will win. That's why I suggest you learn JavaScript. (Learn HTML5 and CSS3 also and learn to create and consume JSON services.) JavaScript is the virtual machine that we all have installed and JavaScript is the language of the web. (For some, JavaScript is Assembly Language.) It's not going anywhere, so that why you should learn it.

Aim to be able to create web sites, web apps, and rich connected apps and systems. Also aim to know a language that lets you write applications that you can put in the App Store for any of a billion connected devices.

That's my advice to someone starting over in 2014.


Sponsor: Big Thanks to Aspose for sponsoring the blog this week! Aspose.Total for .NET has all the APIs you need to create, manipulate and convert Microsoft Office documents and a host of other file formats in your applications. Curious? Start a free trial today.



© 2014 Scott Hanselman. All rights reserved.
     

Download Wrappers and Unwanted Software are pure evil

$
0
0

Call it Adware, Malware, Spyware, Crapware, it's simply unwanted. Every non-technical relative I've ever talked to has toolbars they apparently can't see, apps running in the background, browser home pages set to Russian Google clones, and they have no idea how it got that way.

Here's how they get that way.

You go to download something reasonable. I wanted to download a Skype Recorder, so I went here. (Yes, I linked here to the URL because they don't need Google Juice from me.)

CLICK THE GREEN BUTTON YOU WANT TO

OK at this point I'm screwed. The green button CLEARLY desperately wants me to click on it. I totally ignore the tiny "Direct Download Link" below the friendly button. I have no idea what that glyph icon means, but it's pointing down, so that must mean download.

Welcome to the Download.com installer! How helpful!

image

More green buttons, awesome. Let's go!

CLICK IT!!!

Pre-selected Express installation? Super helpful, I love that. Ah, and next to it there's text in the same font size and color that I totally won't read that says:

Install Search Protect to set [CHANGE] my home page and [TOTALLY MESS UP] default search to Conduit Search [THAT I HAVE NEVER HEARD OF AND NEITHER DO YOU] and [NOW THIS IS AUDACIOUS...]prevent attempts to change my browser settings.

In other words, we, Download.com, are going to totally change the way you use you computer and browser the way and prevent you from easily changing it back. We're going to do it now, when you press Next, and oh, by the way, we have Admin on your computer because just a moment ago you pressed YES on the Windows Warning that we could mess things up, because everyone ignores that.

Or, you can click Custom, because non-technical relative ALWAYS clicks Custom. NO. They don't. Technical people ALWAYS press Custom. ALWAYS. Always. Other people? Never.

MOAR GREEN BUTTONS

Ah, nice, when I press Custom it's set to...wait for it...the same stuff that was gonna happen if you pressed Express.

AND WE ARE ONLY ON STEP 2. What ever happened to clicking just once and getting what I needed?

YOU WILL NEVER READ THE EULA!

OMG "It communicates several times a day with servers to check for new offers and change ads on my computer?" I totally want that. Thanks Green Button!

I'm sure that if I press Decline here that it will mess up my installation of the original thing I wanted to install...I have forgotten what that was, but I'll just keep going.

PAY NO ATTENTION TO THE MAN BEHIND THE EULA

Weird. I thought I was already here. I'm sure I want this also.

ZOMG THERE ARE THREE EULAS

Huh. Does my Mouse not work? I'll click it again. Backing up my files without asking seems legit.

NOT DONE YET

Install Now? What have we been doing all this time?

I am disappointed in us, Internet, that this is a business. Someone wrote this, for their job, directed by their middle manager, who was directed by their rich boss. There was a meeting (there's always a meeting) where it was discussed on how we could most effectively fool non-technical relatives into installing crap.

These are Dark UI Patterns.

A Dark Pattern is a type of user interface that appears to have been carefully crafted to trick users into doing things, such as buying insurance with their purchase or signing up for recurring bills.

This isn't cool and it needs to stop. I won't be visiting Download.com anymore.

I'll only install software from Vendors I trust, like Oracle...

Thanks Ask Toolbar!

Gosh, maybe I need to install that "Crap Cleaner" everyone talks about so I can remove these unwanted toolbars.

Crapware Inception

Ok, forgot it. I'll just stick with the official Windows Updates because I'm sure I want all those.

Seems legit.

So, um. Yeah.

Dumbledore Welp

Sound off in the comments.



© 2014 Scott Hanselman. All rights reserved.
     

How do we know if mobile apps are secure?

$
0
0

You know how we're always telling out non-technical non-gender-specific spouses and parents to be safe and careful online? You know how we teach non-technical friends about the little lock in the browser and making sure that their bank's little lock turned green?

Well, we know that HTTPS and SSL don't imply trust, they imply (some) privacy. But we have some cues, at least, and after many years while a good trustable UI isn't there, at least web browsers TRY to expose information for technical security decisions. Plus, bad guys can't spell.

image

But what about mobile apps?

I download a new 99 cent app and perhaps it wants a name and password. What standard UI is there to assure me that the transmission is secure? Do I just assume?

What about my big reliable secure bank? Their banking app is secure, right? If they use SSL, that's cool, right? Well, are they sure who they are talking too?

OActive Labs researcher Ariel Sancheztested 40 mobile banking apps from the "top 60 most influential banks in the world."

40% of the audited apps did not validate the authenticity of SSL certificates presented. This makes them susceptible to man-in-the-middle (MiTM) attacks.

Many of the apps (90%) contained several non-SSL links throughout the application. This allows an attacker to intercept the traffic and inject arbitrary JavaScript/HTML code in an attempt to create a fake login prompt or similar scam.

If I use an app to log into another service, what assurance is there that they aren't storing my password in cleartext? 

It is easy to make mistakes such as storing user data (passwords/usernames) incorrectly on the device, in the vast majority of cases credentials get stored either unencrypted or have been encoded using methods such as base64 encoding (or others) and are rather trivial to reverse,” says Andy Swift, mobile security researcher from penetration testing firm Hut3.

I mean, if Starbucks developers can't get it right (they stored your password in the clear, on your device) then how can some random Jane or Joe Developer? What about cleartext transmission?

"This mistake extends to sending data too, if developers rely on the device too much it becomes quite easy to forget altogether about the transmission of the data. Such data can be easily extracted and may include authentication tokens, raw authentication data or personal data. At the end of the day if not investigated, the end user has no idea what data the application is accessing and sending to a server somewhere." - Andy Swift

I think that it's time for operating systems and SDKs to start imposing much more stringent best practices. Perhaps we really do need to move to an HTTPS Everywhere Internet as the Electronic Frontier Foundation suggests.

Transmission security doesn't mean that bad actors and malware can't find their way into App Stores, however. Researchers have been able to develop, submit, and have approved bad apps in the iOS App Store. I'm sure other stores have the same problems.

The NSA has a 37 page guide on how to secure your (iOS5) mobile device if you're an NSA employee, and it mostly consists of two things: Check "secure or SSL" for everything and disable everything else.

What do you think? Should App Stores put locks or certification badges on "secure apps" or apps that have passed a special review? Should a mobile OS impose a sandbox and reject outgoing non-SSL traffic for a certain class of apps? Is it too hard to code up SSL validation checks? '

Whose problem is this? I'm pretty sure it's not my Dad's.


Sponsor: Big thanks to Red Gate for sponsoring the blog feed this week! Easy release management: Deploy your SQL Server databases in a single, repeatable process with Red Gate’s Deployment Manager. There’s a free Starter edition, so get started now!



© 2014 Scott Hanselman. All rights reserved.
     

Distributed Automated Browser Testing with Selenium and BrowserStack

$
0
0

imageI'm a huge fan of BrowserStack. They are a cloud-based browser testing service that lets you remote into effectively any browser version on any version of any operating system. They've even got Visual Studio integration so you can just hit F5, choose the browser you want, and start debugging.

COUPON: BrowserStack is a service (a cloud of machines do the work) but you can get 3 months free from the IE folks at Modern.ie. To be clear: I'm not affiliated with either of these folks, just letting you know that it's cool. I do personally have a BrowserStack subscription that I pay for.

I've long been a proponent of integration testing websites by putting the browser on a string, like a puppet. I used Watir (Web Application Testing in Ruby) almost 10 (!) years ago, and write WatirMaker (and later WatirRecorder) to make that easier.

I also spent time with Selenium as early as 2007, although it was a very different Selenium than it is today. I also interviewed Jim Evans from the Selenium Team on my podcast.

BrowserStack as a Selenium Cloud with RemoteDriver

Selenium today uses a "Selenium Server" and a "WebDriver." WebDrivers are language-specific bindings to drive a browser - to put strings on your browser and control it.

Now, there's dozens of choices to make and dozens of ways you can get Selenium working. With much respect due to the Selenium team, the docs on their main page spend a LOT of time talking about different versions, older versions, history of the project, and there's no real "Getting Started FAQ" with stuff like "I'm a Windows person, get this and this and that." Or "I'm on a Mac and like Ruby, just get this and this." There is a fairly extensive Wiki, though, but it's still a lot of terms to understand.

Do expect to spend a few hours exploring and messing up, but do know that there's a few dozen ways to be successful with Selenium, which is part of its charm.

First, you can write tests in whatever language you like. So, C#/NUnit, or Ruby, or Python, for example.

You can download "drivers" for a browser and run them directly, having them listen a port, and make them available to yourself or others in your company.

When writing tests, you can ask for browsers ("drivers") directly by asking for them from your test language of choice, like instantiating a "ChromeDriver" or an "IEDriver."

But, you can also launch a more general-purpose server that will present itself as a "WebDriver," then you give it a list of the capabilities you want and it will then find and drive a browser for you. This is what BrowserStack's cloud does. You can also set these up inside your own company, although it's a bit of a hassle.

There's 8 different OSes. 20 mobile devices, 300 browser/version combos. For the free automated trial you get 100 minutes of "drive time" free. Also, it's half the price if you only want desktop browsers.

The Web Interface for BrowserStack showing the tests I've run

I like to use Python for Selenium Tests, for some odd reason. Again, you can use whatever you like. Doesn't matter.

If you don't have Python...

Your Python code might look like this. Here I'm using BrowserStack's cloud and asking for IE7 on Windows XP.

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities

desired_cap = {'os': 'Windows',
'os_version': 'xp',
'browser': 'IE',
'browser_version': '7.0',
'browserstack.debug': 'true' }

driver = webdriver.Remote(
command_executor='http://hanselman:mysecretkey@hub.browserstack.com:80/wd/hub',
desired_capabilities=desired_cap)

driver.get("http://www.google.com")
if not "Google" in driver.title:
raise Exception("Unable to load google page!")
elem = driver.find_element_by_name("q")
elem.send_keys("Hanselman")
elem.submit()
print driver.title
driver.quit()

Note I have "browserstack.debug" on, so I can actually go to the BrowserStack site and see screenshots of each step!

Screenshot of BrowserStack automatically typing Hanselman into Google on IE7 on XP

Here's the next step...

The results of the Google Search for Hanselman

Details on how this automation works are all up at https://www.browserstack.com/automate. Again you can use any language you want. Here's the same thing in C#:

using System;
using OpenQA.Selenium;
using OpenQA.Selenium.Remote;

namespace SeleniumTest {
class Program {
static void Main(string[] args) {
IWebDriver driver;
DesiredCapabilities capability = DesiredCapabilities.Firefox();
capability.SetCapability("browserstack.user", "hanselman");
capability.SetCapability("browserstack.key", "superfancypantssecretapikey");

driver = new RemoteWebDriver(
new Uri("http://hub.browserstack.com/wd/hub/"), capability
);
driver.Navigate().GoToUrl("http://www.google.com/ncr");
Console.WriteLine(driver.Title);

IWebElement query = driver.FindElement(By.Name("q"));
query.SendKeys("hanselman");
query.Submit();
Console.WriteLine(driver.Title);

driver.Quit();
}
}
}

If your site is only available at localhost, you can make a temporary tunnel and make is accessible to BrowserStack, as well. If you've got Chrome or Firefox, there are extensions to make this even easier.

I hope you check out both BrowserStack and Selenium, and perhaps consider how you're testing your site today (humans who click?) and if you could be more effective with different tools?


Sponsor: Big thanks to Red Gate for sponsoring the blog feed this week! Easy release management: Deploy your SQL Server databases in a single, repeatable process with Red Gate’s Deployment Manager. There’s a free Starter edition, so get started now!



© 2014 Scott Hanselman. All rights reserved.
     

Microsoft killed my Pappy

$
0
0

Photo by Frank Swift used under Creative CommonsI was talking to a young (<25) Front End Developer recently who actively hated Microsoft. Sometimes I meet folks that are actively pissed or sometimes ambivalent. But this dude was pissed.

The ones I find the most interesting are the "Microsoft killed my Pappy" people, angry with generational anger. My elders hated Microsoft so I hate them. Why? Because, you wronged me.

"You killed my pappy," said the youth, "and my pappy's pappy. And his pappy's pappy. And my brothers Jethro, Hank, Hoss, Red, Peregrine, Marsh, Junior, Dizzy, Luke, Peregrine, George and all the others. I'm callin' you out, lawman."

One person said that he was still mad about the Microsoft Anti-Trust thing. "Hey, 10 years ago Microsoft did this..." That was initiated in 1998 for actions in 1994. That's 20 years ago.  And for bundling a browser in the operating system that couldn't be uninstalled or easily replaced? Sure, no operating systems do that in 2014. I wonder if I can swap out Chrome from Chrome OS or Mobile Safari in iOS. Point is, it's common now.

This "generational technology pain" seems to persist long after the root causes have died. Do I hate Japan for World War II? My 6 year old wanted to know this as he's learning world history. I said, "No, we're cool with Japan. We've done some good stuff together." And he was like, "Cool." 

I realize that you, Dear Reader, are a thoughtful and respectful lot, the Internet tends to be a bit of a motley crew. I fully expect the comments to be on fire later. But know this, I didn't work for The Man when all this went down, and I was as outraged as you were 20 years ago (assuming you were alive). But now, I've been here pushing open source and the open web for over 5 years and things are VERY different. I know you all have stories about how you were wronged, but we all have those about various companies. You're pissed about IE6, about FoxPro, about Silverlight, heck, maybe VB6. Sure, I hear you. I'm pissed about DESQView and my Newton, and Snow Leopard not running on my PowerPC. At some point you let go, and you start again with fresh eyes.

Embrace, Extend, Hugs?

We're putting source on GitHub, many groups are using Git with TFS internally for projects, we've open sourced (not just source-opened) huge parts of .NET and are still pushing. We've open sourced Azure hardware specs, opening SDKs, and we're making systems more pluggable than ever. Frankly, we're bending over backwards to NOT be dicks about stuff, at the very least in my corner of the company. Could we do better? ALWAYS. Are we pure evil? Nah.

Is Microsoft circa 2014 worse than Google, Apple, or Facebook? We're not nearly as organized as we'd need to be to be as evil as you might think we are.

Moreover, I think that Microsoft is very aware of perceptions and is actively trying to counter them by actually being open. I'd say we're more concerned than a Google or Apple about how folks perceive us.

I don't speak for Microsoft, I'm not a mouthpiece or a marketer. Sure, I promote the stuff I work on, because some of it is damn cool stuff. I'm a programmer with a blog who likes to speak on technology. But I am not my employer.

That said, I will quote myself (again, opinion, don't fire me) from my own Hacker News comment regarding the direction we're going:

It's worth noting that under Satya [Ed: And ScottGu] (in my org, Cloud and Enterprise) we open sourced ASP.NET, use 50+ OSS libraries in Visual Studio, have all the Azure cloud SDKs on GitHub, and on and on. We made Portable Libraries happen and now share code between iOS, Android, and Windows. This is not your grandfather's MSFT, and now the dude who helped us (Azure) change things in a fundamentally non-MSFT and totally awesome way is in charge. I'm stoked - big things coming, I think.

Sure, we do stupid stuff sometimes, usually because someone in one org isn't talking to another org, or some marketing vendor overreaches, every big company makes these mistakes.

But I like the direction we're heading. I work here to fix stuff. Some folks complain, some tweet complaints, I'm here to fix it. If it was a lost cause, I'd quit, as I truly don't need the job that badly. I'm happy to be a small part of a small part of pushing us. I will push until I can't push anymore.

I said, find a new reason to hate Microsoft. I didn't kill your Pappy, son.

* Photo by Frank Swift used under Creative Commons


Sponsor: Big thanks to Red Gate for sponsoring the blog feed this week! Easy release management: Deploy your SQL Server databases in a single, repeatable process with Red Gate’s Deployment Manager. There’s a free Starter edition, so get started now!



© 2014 Scott Hanselman. All rights reserved.
     

Announcing the new Roslyn-powered .NET Framework Reference Source

$
0
0

.NET Framework Reference Source SiteIn 2007 ScottGu's team announced they were releasing the .NET Framework source code for reference. Just a little later, Microsoft made it possible to step through the .NET Framework Source code while debugging. This was announced to much fanfare, and for a while, it was very cool. It wasn't "Open Source" but it's definitely "Source Opened."

However, as time passed, the original Reference Source website for the .NET Framework sucked for a number of reasons, mostly because it wasn't updated often enough.

Fast forward to today...we're back and the .NET team is launching the fresh new and updated.NET Reference Sourcesite with a Roslyn-powered index!

The new beta site is at http://referencesource-beta.microsoft.com and it'll move over to replace the existing http://referencesource.microsoft.com site soon.

It's easy to browse the code, but if you'd prefer you can also download the .NET Framework source in a ZIP from the download link at the top of the site.

The Roslyn-powered .NET Reference Source browser

There's some very cool .NET-related stuff happening this year, and you'll be hearing about it all soon. The new "Roslyn" compiler-as-a-service replacements for the C# and VB compilers have had the "Big Switch" flipped. We're now getting an amazing totally-rewritten managed compiler that can enable features that weren't possible when .NET started over a decade ago.

Today there's a new team working on the .NET Reference Source, and Roslyn let the team generate a complete syntactic and semantic index of the .NET Framework Sources.

From the team: The version of the framework that we currently have indexed is .NET framework version 4.5.1.  If this is something that folks agree is useful, our ongoing commitment towards this feature is to update this every major release i.e. an update for 4.5.2 and so on.  

This is a crucial feature, IMHO, and they are recommitted to making it happen, and most importantly, keeping it fresh and updated. They are also thinking about maybe using the Monaco editor for the site as well.

Be sure to explore the browser and click on everything, as there's a lot more there than just "search box and results."

Here's a few cool things you can do with the URLS on the new site that you should explore. I like being able to reference a line number in the URL for tweeting or IM'ing.

There's also a lot of flexibility in the search:

You can also actually click on types directly within the editor and find where they are referenced in the code.

clip_image002

They will switch the beta site at http://referencesource-beta.microsoft.com/ to take over the existing Reference Source site soon. Until then, use the Feedback link on the site and email the team directly! They are listening and actively working on this site.

The next thing the team is working on, and they are very close, is getting .NET Source Stepping (meaning you can just F11 into the .NET source code) to again work reliably when debugging, no matter what patch version you have of the .NET Framework on your local machine. Look for that in a few days on the .NET Team Blog.

BONUS: Community Visual Studio Extension

Here's an exciting bonus. Community member and fabulous coder Schabse Laks has created a Visual Studio extension for VS2010, 2012, and 2013! This extension sends calls to Go To Definition (or pressing F12 on a symbol) directly to the code online (when it's .NET Framework code, not yours).

You can download this companion "Ref12" Visual Studio Extension now! Just Goto Definition on any .NET type we have source for and it'll launch your default browser so you can explore the .NET Framework source yourself! Thanks Schabse!

.NET Reference Source Code Licensing Clarified

Finally, the licensing before was originally the very straightforward Microsoft Reference Source License,  but then started to get other caveats tacked on like "don't look at this if you aren't using Windows" until it wasn't really the MS-RSL at all.

They've changed that stuff. They're back to the straight MS-RSL which is easy to read and clear. This means that folks can now look at this Reference Source and not have to gouge their eyes out afterwards. Which is great!

We all hope you like the new site and the team looks forward to your comments!


Sponsor: Big thanks to Red Gate for sponsoring the blog feed this week! Easy release management: Deploy your SQL Server databases in a single, repeatable process with Red Gate’s Deployment Manager. There’s a free Starter edition, so get started now!



© 2014 Scott Hanselman. All rights reserved.
     

When is it stealing?

$
0
0

Image by Duncan Hill, used under Creative Commons from http://flic.kr/p/7YkGurAnything you put on the internet is gonna get stolen. It's preferable if it gets shared or linked to but often it gets copied and copied again.

RSS is magical but it makes it even easier to programmatically syndicate (copy) content. Search around and you'll likely find complete copies of your entire blog mirrored in other countries'.

There's so many websites (now "media empires") that have taken aggregation to the extreme, giving it the more palatable name "content curation." Now, to be clear, I respect the work involved in curation. Sites like http://dumbesttweets.com require work and attribute creators. But taking a post, copying unique content, even paraphrasing, and then including a small link just isn't kind. Forget about the legality of it, remembering IANAL, but it's just poor netiquette to not to ask permission before using non-Creative Commons content.

Every week or two I get an email from some large aggregation site that says "We'd love to reprint your post...it'll get you more readers." The few times I've done this they've gotten 50,000 views and I've gotten 300 referral views. Likely because the "originally appeared on Hanselman.com" link a the bottom is in 4 point font.

Sites like ViralNova and BuzzFeed are effectively reblogging and embedding machines powered by linkbait copyrighters. "What happened next will shock you."

Even if you make a piece of software, someone may just wrap/embed your installer with their own installer and build a whole business around it.

Narrating your blog posts

Today It was pointed out to me that a nearly 7 year old (and not very good) blog post of mine had be narrated - effectively turned into a podcast - by a startup called Umano. BTW, it's more than a little ironic that my post wasn't even mine. It's an excerpt - published with permission - of my friend Patrick Cauldwell's larger post.

I've used the Umano developer tools and embedded the narrated version here.

First, let me just say that this is essentially a great idea. It's the opposite of transcribing a podcast. It's creating podcasts from existing content using professional narrators, not just text to speech. This could be great for not just the visually impaired but also for anyone who wants to catch up on blogs while commuting.

Where did the Content come from?

Here's a screenshot of the post on Umano's site. You can see my name "Hanselman" is there, but it's not a link. The headline is a link, but you'd never know until you hovered over it. There's really no easy way to tell where, when, and how this content came about. I think that Umano could easily redesign this site to put the content owner front and center.

image

Podcasts and audio snippets from blog posts? Great idea, except I wrote the script for this podcast. If I wrote the script and they did the narration, then this must be a partnership, right?

However, if we look at Umano's own Terms of Use:

SoThree claims no ownership or control over any of the content you post to the Service ("Your User Content"). You or a third party licensor, as appropriate, retain all copyright, patent, and trademark rights to any of the content you post on or through the Service. You are responsible for protecting those rights.

Ok, they don't own the content.

By posting Your User Content on or through the Service, you grant SoThree a universal, non-exclusive, royalty-free license to reproduce, adapt, distribute and publish such content through the Service and for the purpose of promoting SoThree and its services.

I'm pretty sure I haven't granted them a universal license to my content as I didn't submit this link. On their home page they say that "you tell us what articles should be voiced." The community submits links, sometimes to content they are a fan of, but don't own, then Umano narrates it.

You may not aggregate, copy, or duplicate any SoThree Content.

Wait, but I can't copy their content? Their content that was generated from my content.

Does this mean I can get a book from the library and narrate it? Turn it into a podcast?

I am told by Umano's twitter account that I'm the first person to object to their content being copied without permission.

I certainly don't think Umano is are malicious. Umano is perhaps naive, if they think can narrate blogs without someone speaking up. That said, their narrators are top notch and their site and app are both attractive and usable. Frankly, I'd be happy if they narrated my whole blog (or at least the good stuff and not the lousy decade-old stuff) and made a podcast feed of my blog like their competitor Castify. But I'd like Umano to do it with me.

Sites like this should ask creators first and their business model should be based on partnerships with content creators, not assumptions. Stitcher has the right idea. I've submitted my content to them and entered into a partnership. They didn't just suck my podcasts in and make a radio station.

Even a single email from Umano like "hey, we would love to narrate your blog, click here and sign this little form" would have be sufficient. 

Narrate first, ask questions later? Michael Dunbar nails it with this tweet:

This is an easily solved problem, and it's not just a problem with Umano. This applies to all businesses and startups that rely on content created by others. I think it's important to honor attribution. This isn't about money or even copyright, although those things do apply. Rather, this is about netiquette. When you're building a business model, build it around partnerships and transparency, not assumptions around fair use and copyright. Aask first.

What are your thoughts, Dear Reader?

(If they narrate this one, I'll update the post and complete the circle. ;) )

Related Links



© 2014 Scott Hanselman. All rights reserved.
     

Hanselman's Newsletter of Wonderful Things: January 21st, 2014

$
0
0

I have a "whenever I get around to doing it" Newsletter of Wonderful Things. Why a newsletter? I dunno. It seems more personal somehow. Fight me.

You can view all the previous newsletters here. You can sign up here to the Newsletter of Wonderful Things or just wait and get them some weeks later on the blog, which hopefully you have subscribed to. If you're signed up via email, you'll get all the goodness FIRST. I also encourage you to subscribe to my blog. You can also have all my blog posts delivered via email if you like.

Here's the Newsletter from January. Subscribers get the new one first. ;) 


Thanks again for signing up for this experiment. Here's some interesting things I've come upon this week. If you forwarded this (or if it was forwarded to you) a reminder: You can sign up at http://hanselman.com/newsletter and the archive of all previous Newsletters is here.

Remember, you get the newsletter here first. This one will be posted to the blog as an archive in a few weeks.

Scott Hanselman

(BTW, since you *love* email you can subscribe to my blog via email here: http://feeds.hanselman.com/ScottHanselman DO IT!)

P.P.S. You know you can forward this to your friends, right?


Sponsor: Big thanks to ComponentOne, a division of GrapeCity, for sponsoring the blog this week. Their widely popular .NET control suite, Studio Enterprise contains hundreds of data and UI controls such as grids, charts and reports that offer the functionality, features and support you need for current and future application development. Download your trial today!



© 2014 Scott Hanselman. All rights reserved.
     

NuGet Package of the Week: FluentAutomation for automated testing of Web Applications

$
0
0

FluentAutomation starting a testLast week I was exploring today's varied choices we have for Automated Browser Testing. There's headless WebKit "browsers" like PhantomJS and cloud powered multi-browser testing tools like BrowserStack and SauceLabs.

Selenium is kind of the gold standard and offers not only a lot of "drivers" but also a lot of language bindings with which drive a browser. Sometimes browsers update so fast there can be some version incompatibilities with Selenium, but for the most part it works great once you've settled in.

One option I've been looking at is FluentAutomation. It's a fluent automation API that supports Selenium as well as WatiN along with all their flavors and drivers. Since Fluient supports Selenium, that means you can use the Selenium ChromeDriver, IEDriver, Remote Web Driver or even the headless PhantomJS. FluentAutomation is on GitHub, of course, as well as on NuGet.

FluentAutomation has great (and growing) documentation and has adopted and interesting fluent style for it's API.

Now, not everyone likes a "fluent" API so it may take a while to get used to. Often you'll be doing things over many lines when it's really just one line, for example, this is one line:

I.Open("http://automation.apphb.com/forms")
.Select("Motorcycles").From(".liveExample tr select:eq(0)")
.Select(2).From(".liveExample tr select:eq(1)")
.Enter(6).In(".liveExample td.quantity input:eq(0)")
.Expect
.Text("$197.72").In(".liveExample tr span:eq(1)")
.Value(6).In(".liveExample td.quantity input:eq(0)");

Notice the method chaining as well as the use of CSS selectors.

FluentAutomation also has the cool concept of a PageObject to take your potentially brittle scripts and give them more structure. PageObjects group your actions, expectations, and assertions and let you reuse code when a page appears in multiple tests.

For example you could have a high level test (this is XUnit, but you can use whatever you want):

public class SampleTest : FluentTest {
public SampleTest() {
SeleniumWebDriver.Bootstrap(SeleniumWebDriver.Browser.Chrome);
}

[Fact]
public void SearchForFluentAutomation() {
new BingSearchPage(this)
.Go()
.Search("FluentAutomation")
.FindResultUrl("http://fluent.stirno.com/blog/FluentAutomation-scriptcs/");
}
}

Then you can have separate PageObjects that have your own public methods specific to that page, as well as assertions you can reuse.

public class BingSearchPage : PageObject<BingSearchPage> {
public BingSearchPage(FluentTest test) : base(test) {
Url = "http://bing.com/";
At = () => I.Expect.Exists(SearchInput);
}

public BingSearchResultsPage Search(string searchText) {
I.Enter(searchText).In(SearchInput);
I.Press("{ENTER}");
return this.Switch<BingSearchResultsPage>();
}

private const string SearchInput = "input[title='Enter your search term']";
}

public class BingSearchResultsPage : PageObject<BingSearchResultsPage> {
public BingSearchResultsPage(FluentTest test) : base(test) {
At = () => I.Expect.Exists(SearchResultsContainer);
}

public BingSearchResultsPage FindResultUrl(string url) {
I.Expect.Exists(string.Format(ResultUrlLink, url));
return this;
}

private const string SearchResultsContainer = "#b_results";
private const string ResultUrlLink = "a[href='{0}']";
}

You don't have to be all structure and OO if you don't want. You can just as easily write scripts with FluentAutomation and head in a different direction.

FluentAutomation along with ScriptCS = Automating your Browser with C# Script

I've usually used Python with my Selenium scripts. I like being able to just make a text file and start scripting, then run, debug, continue, all from the command line. It feels simple and lightweight. Creating a DLL and running Unit Tests in C# usually comes later, as I can move faster with a "scripting language."

You can do that with ScriptsCS as it gives you project-less C# that effectively is C# as scripting language. Combine this with FluentAutomation and you've potentially got the best of both worlds.

To install, first you need the Windows apt-get open source equivalent, the oddly-named and -spelled Chocolatey. Then you get ScriptCS and the packages for FluentAutomation.

  • Install Chocolatey - one line installation here
  • Run "cinst ScriptCS" from your command line to use Chocolatey to install ScriptCS
  • Now, get the ScriptCS script packages for FluentAutomation like this:
    • scriptcs -install FluentAutomation.SeleniumWebDriver
    • scriptcs -install ScriptCs.FluentAutomation

Now, as a quick test, create a folder and put a text file called start.csx in it with just these contents:

var Test = Require<F14N>()
.Init<FluentAutomation.SeleniumWebDriver>()
.Bootstrap("Chrome")
.Config(settings => {
// Easy access to FluentAutomation.Settings values
settings.DefaultWaitUntilTimeout = TimeSpan.FromSeconds(1);
});

Test.Run("Hello Google", I => {
I.Open(http://google.com);
});

Notice how there's no namespace, no classes, no main. It's just a script, except it's using C#. You can change the "Chrome" to "IE" or "Firefox" as well, to play around.

Random: I love this Selenium feature, exposed by FluentAutomation...take screenshot!

// Take Screenshot
I.TakeScreenshot("LoginScreen");

If you don't want ScriptCS, while it can act as a REPL itself, there is also the start of a dedicated FluentAutomation REPL (read–eval–print loop). This is basically a command prompt that lets you explore you app interactively and facilitates building your scripts. You can get the Repl as a Chocolatey package as well and just "cinst FluentAutomation.Repl"

You've got LOTS of choices in the world of automated testing. There's so many choices that there's just no good excuse. Pick a library, pick a language, and start automating your web app today.

Related Links


Sponsor: Big thanks to ComponentOne, a division of GrapeCity, for sponsoring the blog this week. Their widely popular .NET control suite, Studio Enterprise contains hundreds of data and UI controls such as grids, charts and reports that offer the functionality, features and support you need for current and future application development. Download your trial today!



© 2014 Scott Hanselman. All rights reserved.
     

Review: A tale of three Lenovo Laptops - X1 Carbon Touch, ThinkPad Yoga, IdeaPad Yoga 2 Pro

$
0
0
ThinkPad Yoga, X1 Carbon Touch, and Yoga 2 Pro all together

I'm a big Lenovo fan and have used Thinkpads nearly exclusively since my first T60p. I'm using an first-gen X1 Carbon Touch as my main on the go machine these days. I've also tried using a Lenovo Yoga 2 Pro but had a little trouble with its extremely high-dpi display, although the build quality of the hardware is amazing.

I'm also trying out a loaner of a ThinkPad Yoga. What's the difference between the ThinkPad Yoga and the regular Yoga or Yoga 2 Pro? I think of the ThinkPad line, and this Yoga, as a business laptop. It has a TPM which is essential for Bitlocker encryption and VPN/DirectAccess without a Smartcard. Both very similar specs otherwise aside from the Yoga 2 Pro's super-high-res 3200x1800 screen.

Battery life on all these is reasonable, but not truly all-day long epic. You can get 6 hours on any of them, you just need to be thoughtful about what you are doing. Turn down brightness, use power plans smartly, and you're cool.

Frankly, the battery life Haswell brought us hasn't been as life-changing as has been the "RapidCharge" feature on the X1 Carbon Touch. A 30 min layover at an airport can get me almost 80% of my battery back. THAT is a feature that has changed how I work.

Lenovo ThinkPad Yoga

Yoga means the laptop is also a convertible and bends into a tent or a tablet. This is the consumer Yoga. My Mom and my wife both chose and use this model, coincidentally.

  • The ThinkPad Yoga has your choice of processor from a 4th Gen Intel i3 up to a to an i7-4600U at 3.3GHz.
  • You can get the rather low-res touch-enabled 1366x768 screen or the near-deal touch and pen (with a pen you can store in the device!) 1920x1080 screen. Get the 1080p one, I say.
  • This one uses mini-HDMI for its video out.

Lenovo IdeaPad Yoga 2 Pro

The Yoga 2 Pro has more options to build out but does top out on the processor side earlier.

  • The Yoga 2 Pro can also to up to an i7-4500U at 1.8Ghz.
  • It has a fantastic 13.3" QHD+ 32001800 screen.
  • Micro HDMI video output.
    • This was and remains the one totally unacceptable spec for me. As I present a lot, this connector is useless. It's too small, too weak, too unreliable, and too wonky. It only took three presentations before it broke. I don't blame Lenovo, I blame the connector and its spec. If you aren't going to use video out, don't sweat it at all. But if you are presenting daily, NEVER buy a laptop with micro HDMI. It will let you down.

Lenovo ThinkPad X1 Carbon Touch

I own and love the first generation X1. I'd really like to get my hands on the new one and its controversial keyboard and compare the two.

The X1 isn't a Yoga and while it does bend to flat and it does have a great touch-screen, it is NOT a tablet.

  • The X1 has goes from 4th Gen Intel i3 up to a to an i7-4600U at 3.3GHz.
  • Mine has a 1600x900 screen but you can now get up to QHD 2560x1440. This isn't as high as the Yoga 2 but when setting Windows at 150% it works nicely. If you have decent eyes you can avoid any high-dpi issues and just run at 100%.
  • The Mini DP Connector is great. I've never had an issue connecting to a projector with this laptop.

Things you need to consider if you travel

We can talk specs all day and you can dig into them if you like. Needless to say, they are fast, they have SSDs and you can get up to 8gig of RAM. Here's some things you may not have thought about when looking at an Ultrabook.

All Lenovo laptops are thin and light

These are all small and all around 3lbs. The Yoga 2 Pro is the sleekest and the most outwardly attractive. The X1 is a close second with its tapered nose. The ThinkPad Yoga is boxy and reliable looking.

  • What kind of Video Output does it have?
    • You won't get full-sized VGA on 90% of Ultrabooks. It'll be either HDMI, Micro-HDMI (a nightmare), or MiniDP (Mini Display Port.) When in doubt, go MiniDP all the way.
  • USB3 vs. USB2
    • Most Ultrabooks have one USB3 connector and one that's USB2. The USB3 one is almost always blue, that's how you can tell. Think about what your requirements are what if you'll need a nice USB adapter. I recommend combination USB3 hubs with included Ethernet. I own one and love it.
  • Will you dock your laptop a lot?
    • If so, consider the new OneLink dock from Lenovo. It's in the ThinkPad line of laptops, so that's the ThinkPad Yoga or the 2nd Gen X1 Carbon Touch. That means one connector gets you power, USB along with 6 (!) ports, 4 of which are USB3. You'll also get DisplayPort up to 2560x1600 and a DVI-I connector.
    • I own the original USB3 dock which uses USB3 and DisplayLink technology to run up to two additional monitors. The video is compressed and you have to plug in both a USB3 connector and the power. It works, and I'm happy with it, but OneLink is a clear improvement.

Keyboards

I have always loved ThinkPad keyboards. The W520 workhorse has the best laptop keyboard ever, to this day, IMHO. The first generation X1 Carbon Touch is a close second.

X1 Carbon Touch Keyboard

The ThinkPad Yoga's keyboard is good, but a few changes like the removal of the insert button from the top row as well as the de-emphasis of the function keys did slow me down for a few days.

The Yoga also changes the TrackPad a little by making in larger, clickier, and removes the physical buttons for folks who like "The Nub" for their mousing. Note that the buttons are still there, they are just integrated into the top of the TrackPad so your muscle memory doesn't need to change.

ThinkPad Yoga Keyboard

The Yoga 2 Pro keyboard keys don't have the subtle concave shape that the ThinkPad line is known for. The keyboard is nearly flat. It also seemed to show hand grease a little more, although clearly a cloth solves that problem quickly. As a fast touch-typist I'm a little slower on this keyboard but it's certainly

Yoga 2 Pro Keyboard

Resolutions

I just love 1080p on a 13.3" screen. It's just large enough that it feels roomy but not so big that it's squinty. This collection of three laptops straddles that ideal, though. My wife doesn't see the difference and works on the 768 or 900 machines with no complaint. The has a retina one and doesn't appreciate it (or notice its screen). I prefer 1080 or 1800 if I'm doing multiple window website debugging. At 1800p the pixels just disappear.

1366x768 you can see the pixels

1600x900 is a nice compromise

3200x1800 is insane. No pixels to be seen.

My Wish List for the Ultimate Lenovo Ultrabook

This is simple.

  • Micro-HDMI is a failed connector. The industry needs to accept this and stop using it.
    • There is only full-sized HDMI or ideally, MiniDP.  Mini Display Port, in my experience, always works and works well. Adapters are many and plentiful and I always feel comfortable going to a conference with a MiniDP laptop as I know they can handle it.
  • I want more RAM. Always. Give me a 12 gig Ultrabook, please, Lenovo. That said, these machines have happily run VS, Outlook and two Virtual Machines without complaint.
  • Anything over 1080p at 13"+ is the sweet spot resolution for me. Retina is nice but Windows 8.1 isn't quite there yet on the desktop. Soon I hope.
  • A 256 gig SSD is the ideal size for me. 128 is a little cramped for a developer.
  • #MOARYOGA - The whole Yoga hinge is brilliant.

Give me an X1 Yoga with the fastest i7, 256G SSD, a Mini DP connector, and a screen that is anything over 1080p and we're cool. You can...

Shut up and take my money

Today, I'm happy using the X1 Carbon Touch until I see the new X1. But I really recommend any of these devices if the tech specs and connectors meet your requirements.

Related Links


Sponsor: Big thanks to ComponentOne, a division of GrapeCity, for sponsoring the blog this week. Their widely popular .NET control suite, Studio Enterprise contains hundreds of data and UI controls such as grids, charts and reports that offer the functionality, features and support you need for current and future application development. Download your trial today!



© 2014 Scott Hanselman. All rights reserved.
     

Back to Basics: Assert your assumptions and diff your source code

$
0
0

I've done a whole series of "Back to Basics" posts that I encourage you to check out. Sometimes I'll do a post as a result of a reader emailing me for help and this is one such post.

A person emailed me with an ASP.NET app was behaving differently on his computer vs. another developer's computer.

On his machine when he hit a protected page foo.aspx?returnurl=http://mymachine.domain.com

he would get a FORM element like this:

<form action="foo.aspx?returnurl=http://mymachine.domain.com">

but on everyone else's machines their HTML was:

<form action="foo.aspx">

They debugging and were frustrated and eventually reached out. They said:

1. there's nothing going on in the aspx of login.aspx that would append the querystring.

2. there's nothing going on in the code-behind of the aspx that manipulates Form.Action or messes with the Page.Render in any way.

So, I'm stumped, because the querystring is included on my machine, but not on others. I've tried comparing IIS components, web.config differences, application pool runtime type, machine.config differences, possible differences in Modules for IIS (IISrewrite), but nothing is giving me love. 

I suggested that they assert assumptions and start diffing everything. You can see in the last paragraph that they're comparing stuff but I think you really have to diff everything.

When something "works here but not there" my answer is always, what has changed? What's different? If the answer is "nothing is different" I'm just gonna say it again:

"What's different?"

What are some things we can check?

  • Code
    • Do you know what's on disk?
    • Do you know what ended up in memory? These are different things.
  • Configuration
    • There's local and machine-wide config to check
  • Network Traffic
    • This is often overlooked. The Internet is not a black box, but you'd be surprised how few people hook up a packet sniffer or even just Fiddler to look at HTTP traffic.
    • I've talked to developers who have said "well, that's under SSL so I can't see it." Oh, my friend, if you only knew.

I had them do a sniff and see if there was a difference in HTTP traffic. My assumption was that the HTTP_REFERER HTTP header was different and there was some code that was causing the page to render differently.

We went back and forth over a few days and my reader became frustrated and just added this line in their app's Page_Load:

this.Form.Action = Request.Url.ToString();

Here they are basically reasserting the Form action by pulling it from the URL. It's gross and it's a hack. It's a Band-Aid on Cancer.

They then started looking at the source for ASP.NET proper and then decided to disassemble the code that was running on the other person's machine. They then started to assert their assumptions.

Is the code running what's on disk? For a compiled language, do the binaries reflect the source?

They looked in Temporary ASP.NET files at the compiled ASPX markup pages and found this.

//ExternalSource("D:\WebApplications\Foo\login.aspx",27)
__ctrl.Method = "post";

//ExternalSource("D:\WebApplications\Foo\login.aspx",27)
__ctrl.Action = "login.aspx";

What? Why is someone setting the FORM Action manually? And there's a line number.

They had diff compared all the source code but not the markup/views/html.

Their markup:

<form id="Form1" method="post" runat="server">

Other person's markup:

<form id="Form1" method="post" runat="server" action="Login.aspx">

The other person had hard-coded the action in their source markup. They'd been diffing everything but the markup.

When you are comparing two code-bases, make sure to compare everything or you might just lose a day or two like this person.

Thanks to my reader for sharing this and letting me in on this debugging adventure.

Related Links:


Sponsor: Big thanks to Red Gate for sponsoring the blog feed this week. Check out the Free Starter Edition of their release management tool! Deploy your SQL Server databases, .NET apps and services in a single, repeatable process with Red Gate’s Deployment Manager. Get started now with the free Starter Edition.



© 2014 Scott Hanselman. All rights reserved.
     

Exploring FAKE, an F# Build System for all of .NET

$
0
0

I've been orbiting around F# - but not really jumping in - for a while now. In fact, I looked at F# in 2008 almost 6 years ago and more recently talked to Richard Minerich and Phillip Trelford on Hanselminutes Podcast #311 "Why F#?"

Last week I looked at using ScriptCS, literally C# as a Scripting language, to drive browser automation. Today I'm exploring a make system called FAKE. It's F# Make, a build automation system similar to Make (which is 38 years old next month!) or Rake (which uses Ruby).

Fake is a Domain Specific Language that you can use without knowing F#, but if and when you outgrow it you can keep heading down the F# road. In all cases you've got all of .NET at your command.

Here's their Hello World example, a basic deploy script:

#r "tools/FAKE/tools/FakeLib.dll" // include Fake lib
open Fake


Target "Test" (fun _ ->
trace "Testing stuff..."
)

Target "Deploy" (fun _ ->
trace "Deploy stuff..."
)

"Test" // define the dependencies
==> "Deploy"

Run "Deploy"

Note that Deploy depends on Test.

FAKE uses F# but you can use it go build whatever. These are some C# OSS projects that use FAKE to build themselves:

FAKE isn't new, it's actually been around for 4 years with 55 contributors so far! It works not only on .NET but also on Linux and Mac under Mono - it works everywhere. Because it's all .NET you can use it on your Continuous Integration Servers like TeamCity or Travis CI.

image

Getting Started with FAKE

Check out their Calculator sample, a .NET project you'll extend to build itself with FAKE. Just download the zip, unblock it, and unzip. Then run build.bat from a developer command prompt.

The build.net is a bootstrapper. It could be powershell or a shell script if you like, of course.

@echo off
cls
"tools\nuget\nuget.exe""install""FAKE""-OutputDirectory""tools""-ExcludeVersion""tools\FAKE\tools\Fake.exe" build.fsx
pause

This batch file uses NuGet to get FAKE, just as npm install restores node_modules, or gem gets ruby libraries. Then it calls Fake on the build.fsx file. Follow their Getting Started instructions to slowly expand the responsibilities of the build.fsx file.

FAKE has a lot of Helpers in their API documentation. Hundreds, and there's a whole community making others that you can call upon. For example, the built in FileHelper has things like CleanDir to remove files and subdirs.

Here we Clean before we build by making Clean a dependency of Default. BuildDir here is a property that's shared.

// include Fake lib
#r "tools/FAKE/tools/FakeLib.dll"
open Fake

// Properties
let buildDir = "./build/"

// Targets
Target "Clean" (fun _ ->
CleanDir buildDir
)

Target "Default" (fun _ ->
trace "Hello World from FAKE"
)

// Dependencies
"Clean"
==> "Default"

// start build
RunTargetOrDefault "Default"

Jumping to the end of the tutorial, the syntax gets a little more tricky, butu once you get the |> format, it makes sense.

Some cool things to note and file away as interesting at in the script below.

  • the use of !! to include files
  • the use of -- to exclude a file spec after a !! operator
  • Zip is built-in as a helper and zips up the results of the build.
  • the options passed into NUnit
  • The dependency chain
  • #r for referencing .NET DLLs
// include Fake lib
#r "tools/FAKE/tools/FakeLib.dll"
open Fake

RestorePackages()

// Properties
let buildDir = "./build/"
let testDir = "./test/"
let deployDir = "./deploy/"

// version info
let version = "0.2" // or retrieve from CI server

// Targets
Target "Clean" (fun _ ->
CleanDirs [buildDir; testDir; deployDir]
)

Target "BuildApp" (fun _ ->
!! "src/app/**/*.csproj"
|> MSBuildRelease buildDir "Build"
|> Log "AppBuild-Output: "
)

Target "BuildTest" (fun _ ->
!! "src/test/**/*.csproj"
|> MSBuildDebug testDir "Build"
|> Log "TestBuild-Output: "
)

Target "Test" (fun _ ->
!! (testDir + "/NUnit.Test.*.dll")
|> NUnit (fun p ->
{p with
DisableShadowCopy = true;
OutputFile = testDir + "TestResults.xml" })
)

Target "Zip" (fun _ ->
!! (buildDir + "/**/*.*")
-- "*.zip"
|> Zip buildDir (deployDir + "Calculator." + version + ".zip")
)

Target "Default" (fun _ ->
trace "Hello World from FAKE"
)

// Dependencies
"Clean"
==> "BuildApp"
==> "BuildTest"
==> "Test"
==> "Zip"
==> "Default"

// start build
RunTargetOrDefault "Default"

You can do virtually anything and there's a great community out there to help.

Here's a more complex dependency chain with an optional parameter:

// Build order
"Clean"
==> "BuildApp"
==> "BuildTest"
==> "FxCop"
==> "NUnitTest"
=?> ("xUnitTest",hasBuildParam "xUnitTest") // runs the target only if FAKE was called with parameter xUnitTest
==> "Deploy"

There's a rich FAKE world out there with support for Octopus Deploy, all Unit Test systems, Xamarin's xpkg format and much more. Thanks to Steffan Forkmann for helping me explore this. ;)

Related Links


Sponsor: Big thanks to Red Gate for sponsoring the blog feed this week. Check out the Free Starter Edition of their release management tool! Deploy your SQL Server databases, .NET apps and services in a single, repeatable process with Red Gate’s Deployment Manager. Get started now with the free Starter Edition.



© 2014 Scott Hanselman. All rights reserved.
     
Viewing all 1148 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>