<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:a10="http://www.w3.org/2005/Atom" version="2.0"><channel><title>AppHarbor Blog</title><link>http://feeds.feedburner.com/appharbor</link><description>Where .NET apps grow and prosper</description><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/appharbor" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="appharbor" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">appharbor</feedburner:emailServiceId><feedburner:feedburnerHostname xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">http://feedburner.google.com</feedburner:feedburnerHostname><item><link>http://blog.appharbor.com/2013/05/20/announcing-spdy-support</link><title>Announcing SPDY support</title><description>&lt;p&gt;&lt;img src="/Resources/Images/appharbor-com-spdy.png" alt="appharbor.com spdy support" style="border: 1px solid #aaa;"&gt;&lt;/p&gt;

&lt;p&gt;Today we're announcing SPDY protocol support for your AppHarbor applications. SPDY is an experimental protocol pioneered by Google which is designed to minimize latency of web pages. It is available immediately on all shared and dedicated load balancers in the US and EU regions. Among other things it allows for efficient use of available bandwidth by multiplexing concurrent streams over a single TCP connection and compressing HTTP headers. Here's an example of SPDY in action from last year's Google I/O:&lt;/p&gt;

&lt;iframe width="640" height="360" src="https://www.youtube.com/embed/zN5MYf8FtN0?start=2140" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;The performance benefits that can be realized with SPDY of course depends on your application and user demographic. If your web pages include many resources (javascript, css, images etc) served directly from your domain you'll likely see some pretty significant performance improvements in supported browsers. For instance, SPDY can eliminate the need for CSS sprites as all images can be downloaded in parallel. If you use a CDN the performance benefits will be limited as the resources fetched externally won't be served through SPDY (unless the CDN supports it). You'll also need to use HTTPS since SPDY relies on SSL. &lt;a href="http://support.appharbor.com/kb/tips-and-tricks/ssl-and-certificates"&gt;AppHarbor offer piggyback, SNI and IP-based SSL&lt;/a&gt; to help you with that.&lt;/p&gt;

&lt;p&gt;Chrome and newer versions of Firefox and Opera supports SPDY and it &lt;a href="http://winsupersite.com/windows-8/blue-s-clues-spdy-support-ie-11"&gt;seems like Internet Explorer 11 will support it too&lt;/a&gt;. AppHarbor supports &lt;a href="http://www.chromium.org/spdy/spdy-protocol/spdy-protocol-draft2"&gt;draft 2 of the SPDY protocol&lt;/a&gt;. We also recommend reading the &lt;a href="http://www.chromium.org/spdy/spdy-whitepaper"&gt;SPDY white paper&lt;/a&gt; and &lt;a href="http://blog.cloudflare.com/introducing-spdy"&gt;this CloudFlare blog post&lt;/a&gt; to learn more about SPDY.&lt;/p&gt;

&lt;p&gt;&lt;img src="/Resources/Images/spdy-button-enable.png" alt="Enable SPDY button" style="border: 1px solid #aaa;"&gt;&lt;/p&gt;

&lt;p&gt;To enable SPDY on an existing application simply click the button on your application's settings page. SPDY is enabled by default on all new applications. Since the protocol and the nginx implementation we use are still considered experimental it'll continue to be configurable for a while.&lt;/p&gt;

&lt;p&gt;You can &lt;a href="http://spdycheck.org/"&gt;test your application on SPDYCheck.org&lt;/a&gt; or you can install the SPDY indicator for &lt;a href="https://chrome.google.com/webstore/detail/spdy-indicator/mpbpobfflnpcgagjijhmgnchggcjblin"&gt;Chrome&lt;/a&gt; or &lt;a href="https://addons.mozilla.org/en-us/firefox/addon/spdy-indicator/"&gt;Firefox&lt;/a&gt; to confirm that SPDY is enabled.&lt;/p&gt;
</description></item><item><link>http://blog.appharbor.com/2013/04/16/cloudinary-now-available</link><title>Cloudinary add-on now available</title><description>&lt;p&gt;&lt;img src="http://blog.appharbor.com/Resources/Images/cloudinary-logo.png" alt="Cloudinary" /&gt;&lt;/p&gt;

&lt;p&gt;We've just added &lt;a href="https://appharbor.com/addons/cloudinary"&gt;Cloudinary to the add-on catalog&lt;/a&gt;. Cloudinary makes working with images in the cloud a breeze and offers a wide array of image manipulation services. They also have a .NET SDK available making it easy for AppHarbor customers to take advantage of their services.&lt;/p&gt;

&lt;p&gt;Working with images can be a hassle and we know some of you already use Cloudinary to take the pain out of transforming images. We're excited to offer easy integration with this simple and flexible service and hope you'll find it useful for your applications. Cloudinary has &lt;a href="http://cloudinary.com/documentation/appharbor_integration"&gt;published thorough documentation and samples showing how to use the add-on with AppHarbor&lt;/a&gt; - make sure to take a look when you try it out.&lt;/p&gt;
</description></item><item><link>http://blog.appharbor.com/2013/03/13/introducing-vertical-scaling-make-your-workers-better-faster-and-stronger</link><title>Introducing Vertical Scaling - Make Your Workers Better, Faster and Stronger</title><description>&lt;p&gt;Today we're introducing vertical scaling of workers, so you can get web and background workers with more resources. You can now get workers with two, three and four times the limits of a normal worker unit. We’ve tested this feature for the last couple of months with some large customers and the results have been great.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://blog.appharbor.com/Resources/Images/worker-size-box.png" alt="New Relic screenshot of AppHarbor after scaling vertically" /&gt;&lt;/p&gt;

&lt;p&gt;An application is scaled on &lt;a href="https://appharbor.com/pricing"&gt;the app’s subscription page&lt;/a&gt;. When you scale your workers vertically you’ll get better response times, request throughput, application stability and ultimately an improved user experience. Scaling vertically also allows you to deploy larger and more complex applications on AppHarbor.&lt;/p&gt;

&lt;p&gt;Vertical scaling can do wonders for your apps, but we still want to encourage developers to design apps that are ready for horizontal scaling. The principles &lt;a href="http://www.12factor.net/"&gt;outlined in “The 12 Factor App”&lt;/a&gt; by &lt;a href="https://twitter.com/hirodusk"&gt;Adam Wiggins&lt;/a&gt; are excellent guidelines to archive that (among other things), and if you haven’t read it already we strongly recommend it.&lt;/p&gt;

&lt;p&gt;The impact of vertical scaling depends on how resource intensive the app is. Here is a screenshot from New Relic showing how appharbor.com performed after tripling each worker's resource allocation:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://blog.appharbor.com/Resources/Images/ah-scaled-vertically-new-relic-screenshot.png" alt="New Relic screenshot of AppHarbor after scaling vertically" /&gt;&lt;/p&gt;

&lt;p&gt;About 80-100ms (~40%) was cut of the average response time, and notice that the New Relic apdex score is greatly improved. In the meanwhile the request throughput was doubled. You can &lt;a href="https://appharbor.com/pricing"&gt;try for yourself&lt;/a&gt;, and see how vertical scaling makes your apps perform better.&lt;/p&gt;

&lt;p&gt;Some scenarios where this feature is particularly useful:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You've exhausted the resources of a single worker unit but can’t scale horizontally.&lt;/li&gt;
&lt;li&gt;You have already scaled out to multiple workers, and need to handle even more requests.&lt;/li&gt;
&lt;li&gt;You want to improve page load times.&lt;/li&gt;
&lt;li&gt;You have CPU/RAM intensive web or background workers.&lt;/li&gt;
&lt;li&gt;You need to scale more to more than 20 regular web or background workers.&lt;/li&gt;
&lt;li&gt;You application requires many concurrent connections and a higher request queue limit - for example for apps that extensively uses WebSocket and long-polling.&lt;/li&gt;
&lt;li&gt;Background workers - redundancy might not be as critical here and a single, large worker will often perform significantly better.&lt;/li&gt;
&lt;li&gt;Each of your background workers runs a large number of processes. With vertical scaling you get fewer, larger workers that can better run many processes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Remember that all prices on AppHarbor are prorated and you only pay for the time you have a resource provisioned, not for the entire month - so you can scale your app vertically as well as horizontally cheaply and when you need it.&lt;/p&gt;

&lt;p&gt;With today’s release we’re also changing the plans a little - the plans now include “worker units” rather than “workers”. This means that pricing remains the same, but you can use the worker units to scale both up and out. For instance if you’re on the Yacht plan, which includes 4 worker units, you can now scale to two workers with two worker units allocated for each - or 1 large worker with 4 worker units.&lt;/p&gt;

&lt;p&gt;We’re very excited to make this feature available immediately. It’s a powerful and flexible addition to AppHarbor’s “scaling toolbox”. We welcome any and all feedback so we can continue to it improve it, and if you need help or advice on how to scale your app you’re more than welcome to &lt;a href="https://support.appharbor.com"&gt;reach out&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now go &lt;a href="https://appharbor.com/pricing"&gt;scale those apps&lt;/a&gt;.&lt;/p&gt;
</description></item><item><link>http://blog.appharbor.com/2013/02/22/hosted-graphite-now-in-add-on-catalog</link><title>Hosted Graphite now in add-on catalog</title><description>&lt;p&gt;&lt;img src="http://blog.appharbor.com/Resources/Images/hg_full.png" alt="Hosted Graphite Logo" /&gt;&lt;/p&gt;

&lt;p&gt;Today we're welcoming the &lt;a href="https://appharbor.com/addons/hostedgraphite"&gt;Hosted Graphite add-on&lt;/a&gt;. Hosted Graphite offers simple, cloud-based &lt;a href="http://graphite.wikidot.com/"&gt;Graphite&lt;/a&gt; hosting to support real-time metrics from your applications.&lt;/p&gt;

&lt;p&gt;A &lt;a href="https://github.com/ragnard/Graphite.NET"&gt;Graphite.NET client library is available here&lt;/a&gt; and is can be installed using &lt;a href="http://nuget.org/packages/Graphite.NET/"&gt;the NuGet package too&lt;/a&gt;. Provision the add-on and configure the client to start sending metrics:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var apiKey = ConfigurationManager.AppSettings.Get("HOSTEDGRAPHITE_APIKEY");
using (var client = new GraphiteTcpClient("carbon.hostedgraphite.com",
    port: 2003, keyPrefix: string.Format("{0}", apiKey)))
{
    client.Send("users", users.Count());
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Metrics can also be &lt;a href="http://docs.hostedgraphite.com/languageguide/lg_dotnet.html#sending-a-metric-via-udp"&gt;sent via UDP&lt;/a&gt; and you can read more about &lt;a href="http://docs.hostedgraphite.com/"&gt;it in the documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://blog.appharbor.com/Resources/Images/hg_sample_dashboard.png" alt="Sample Hosted Graphite dashboard" /&gt;&lt;/p&gt;

&lt;p&gt;Have fun!&lt;/p&gt;
</description></item><item><link>http://blog.appharbor.com/2013/02/19/websocket-support-for-net-and-node-js-apps</link><title>WebSocket support for .NET and node.js apps</title><description>&lt;p&gt;&lt;img src="http://blog.appharbor.com/Resources/images/html5-badge.png" alt="HTML5 badge" /&gt;
&lt;img src="http://blog.appharbor.com/Resources/images/html5-connectivity.png" alt="HTML5 connectivity" /&gt;&lt;/p&gt;

&lt;p&gt;We're happy to finally introduce (experimental) WebSocket support today. You can now select the "Beta" region when creating an application to try our latest environment, and we hope you'll help us test it with your own .NET and node.js apps.&lt;/p&gt;

&lt;p&gt;The "Beta" region runs Windows Server 2012 application instances in the US (AWS US-EAST) with IIS8, &lt;a href="http://nodejs.org/"&gt;node.js (0.8.20)&lt;/a&gt; and &lt;a href="https://github.com/tjanczuk/iisnode"&gt;iisnode (0.2.3)&lt;/a&gt; and is otherwise identical to the current environment. Along with nginx this allows you to leverage WebSockets for your .NET and node.js apps.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://blog.appharbor.com/Resources/images/beta-region.png" alt="Create beta region app" /&gt;&lt;/p&gt;

&lt;p&gt;We're still ironing out some kinks before we're ready to fully migrate to WS2012 and IIS8 and the &lt;a href="http://trac.nginx.org/nginx/changeset/5073/nginx"&gt;WebSocket-enabled version of nginx&lt;/a&gt; was just released - so it will be a little while before we feel confident about migrating all apps. With the new region you can try how your applications actually work before we make the move to the updated environment. It will be updated frequently and is generally less available than our regular US and EU regions, so make sure not to use it for your production apps.&lt;/p&gt;

&lt;p&gt;Here are a couple of sample apps using WebSockets on AppHarbor:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://jabbrwebsocket.apphb.com"&gt;JabbR chat app clone based on SignalR&lt;/a&gt; - just create a pair of test credentials when trying it: You can use the JabbR repository as-is, just provision a SQL Server database, set the connection string "Alias" to "Jabbr" and make sure to enable file system write access on the application. Source code &lt;a href="https://github.com/davidfowl/JabbR"&gt;is available here&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://websocket.apphb.com"&gt;Node.js app using Socket.IO&lt;/a&gt;: Very simply websocket sample using iisnode. &lt;a href="https://github.com/appharbor/node-socketio-sample"&gt;Source code available here&lt;/a&gt;. Note that you currently need to configure the app with a &lt;a href="https://github.com/appharbor/node-socketio-sample/blob/master/web.config"&gt;&lt;code&gt;web.config&lt;/code&gt;&lt;/a&gt; file and may have to disable view precompilation under "Settings". More about &lt;a href="http://blog.appharbor.com/2012/01/19/announcing-node-js-support"&gt;node.js on AppHarbor here&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's it! Take it for a spin and we look forward to your feedback.&lt;/p&gt;
</description></item><item><link>http://blog.appharbor.com/2013/02/05/welcoming-the-loader-io-add-on</link><title>Loader.IO add-on now available</title><description>&lt;p&gt;Today we've added the &lt;a href="https://appharbor.com/addons/loaderio"&gt;loader.io add-on&lt;/a&gt; to the add-on catalog. Loader.io allows you to test and measure web application performance under load. With loader.io you can among other things run tests with up to 10,000 concurrent connections with SSL support. And it's free!&lt;/p&gt;

&lt;p&gt;&lt;img src="http://blog.appharbor.com/Resources/Images/loaderio-logo.png" alt="Loader.IO logo" /&gt;&lt;/p&gt;

&lt;p&gt;Get started by installing the add-on from the catalog and go to the loader.io admin page. Before you can use it you need to configure either your application or DNS, so your ownership can be established. You can read more details on Loader.io when you create tests.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://blog.appharbor.com/Resources/Images/loaderio-results.png" alt="Loader.IO logo" /&gt;&lt;/p&gt;

&lt;p&gt;Loader.io is a new product from &lt;a href="http://labs.sendgrid.com/"&gt;SendGrid labs&lt;/a&gt;, a group under SendGrid, the e-mail platform, which is &lt;a href="https://appharbor.com/addons/sendgrid"&gt;also available in the add-on catalog&lt;/a&gt;. SendGrid Labs aims to "help developers be more successful by providing technologies and services we've identified as pain points while focusing on building and scaling our engineering organization as we've grown as a company" says Mike Rowan, VP R&amp;amp;D for SendGrid.&lt;/p&gt;

&lt;p&gt;We're excited to have the loader.io add-on available and are looking forward to see what comes out of SendGrid Labs in the future.&lt;/p&gt;
</description></item><item><link>http://blog.appharbor.com/2013/02/01/cloudbird-launches-rtm</link><title>CloudBird RTM</title><description>&lt;p&gt;&lt;img src="http://blog.appharbor.com/Resources/Images/cloudbird.png" alt="CloudBird" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.cloudbird.net/"&gt;CloudBird, the cloud RavenDB service&lt;/a&gt; recently &lt;a href="http://www.cloudbird.net/blog/129/cloudbird-launch-now-with-ravendb-2-0-support"&gt;"peeled off the beta label"&lt;/a&gt; and now welcome production applications to use their service.&lt;/p&gt;

&lt;p&gt;Andrew Smith from CloudBird commented on the launch:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;We're delighted to launch our CloudBird AddOn in the EU, offering production-ready RavenDB hosting in the cloud. We're launching with full support for RavenDB 2.0 and the ability to easily upgrade existing 1.0 databases.&lt;/p&gt;
  
  &lt;p&gt;We have a variety of plans to suit your storage, performance and replication requirements starting at just $9.99 a month, as well as a free Starter plan to get your project off the ground.&lt;/p&gt;
  
  &lt;p&gt;We perform twice-daily internal backups for all databases and most plans also offer the ability to do hourly incremental exports to your own Amazon S3 bucket.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It's great to see more providers for &lt;a href="http://ravendb.net/"&gt;RavenDB&lt;/a&gt; and we're happy to have the &lt;a href="https://appharbor.com/addons/cloudbird"&gt;CloudBird service available in our add-on catalog&lt;/a&gt;. We wish them all the best with the launch!&lt;/p&gt;
</description></item><item><link>http://blog.appharbor.com/2013/01/30/visual-studio-git-integration</link><title>Visual Studio Git Integration</title><description>&lt;p&gt;&lt;a href="http://blogs.msdn.com/b/bharry/archive/2013/01/30/git-init-vs.aspx"&gt;Microsoft today announced&lt;/a&gt; that they'll be supporting Git in Visual Studio and Team Foundation Server. We care a lot about Git and providing a great user experience to developers, so we think it's great that Microsoft is adding first class support for Git in Visual Studio. Many developers have asked us for a way to deploy directly from Visual Studio, and this is one way to do it.&lt;/p&gt;

&lt;p&gt;Luckily Microsoft has provided a CTP for VS 2012 so you can try it right away. A couple of steps are necessary to get started, but it's all covered in the beginning of &lt;a href="http://blogs.msdn.com/b/visualstudioalm/archive/2013/01/30/getting-started-with-git-in-visual-studio-and-team-foundation-service.aspx"&gt;this tutorial&lt;/a&gt;. Also make sure to read &lt;a href="http://www.hanselman.com/blog/GitSupportForVisualStudioGitTFSAndVSPutIntoContext.aspx"&gt;Scott Hanselman's blog post about the integration&lt;/a&gt;. In this post we'll just cover a couple of steps necessary to set the integration up with AppHarbor and share a few initial impressions.&lt;/p&gt;

&lt;p&gt;Adding your AppHarbor repository is straight forward: If you have already set up a a remote AppHarbor/GitHub/Bitbucket repository in your local Git repository it should work without any further configuration. If not you simply need to copy the "Repository URL" from your application on AppHarbor. Then go to the "Connect" page in the VS Git tool, select "Clone" and paste the URL underneath:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://blog.appharbor.com/Resources/Images/vs-git-connect-nav.png" alt="Go to the Connect screen" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src="http://blog.appharbor.com/Resources/Images/vs-git-clone-repo.png" alt="Add repository" /&gt;&lt;/p&gt;

&lt;p&gt;You're now set and can start using Visual Studio to deploy to AppHarbor.&lt;/p&gt;

&lt;p&gt;Our first experience with the integration is that it seems to work pretty well and is stable. It doesn't allow developers to do too much Git magic/harm and generally applies some sensible defaults (auto-crlf on by default, .gitignore file). You can store your credentials the first time you connect to your AppHarbor repository, so you'll only have to write your password once which is very convenient. The default Visual Studio merge tool is well-integrated (and arguably better than the default "Git Gui") and will likely make more Windows developers feel comfortable about resolving Git merge conflicts.&lt;/p&gt;

&lt;p&gt;Git integration for Visual Studio is a big step in the right direction and a very welcome addition to our favorite IDE. We're excited that git support on Windows is evolving at a rapid clip, and if you haven't already we recommend that you also &lt;a href="http://windows.github.com/"&gt;check out GitHub for Windows&lt;/a&gt;.&lt;/p&gt;
</description></item><item><link>http://blog.appharbor.com/2013/01/10/asynchronous-browser-uploads-to-s3-and-gcs-using-cors-aspnet-mvc</link><title>Browser uploads to AWS S3 and Google Cloud Storage using CORS and ASP.NET MVC</title><description>&lt;p&gt;Ever-increasing requirements to application scalability and availability often requires applications to be deployed to multiple machines. Many cloud hosting providers, such as AppHarbor, even encourage developers to write apps that are mostly stateless and designed to scale horizontally.&lt;/p&gt;

&lt;p&gt;This poses challenges when building applications that interacts with files: Files that are uploaded to a web service needs to be available to all instances that needs to serve them. This is difficult to archive if the files are written to the local file system of the instance that the file is uploaded to, which is also why we and other hosts restrict file system write access by default.&lt;/p&gt;

&lt;p&gt;Amazon S3 and Google Cloud Storage supports &lt;a href="http://en.wikipedia.org/wiki/Cross-origin_resource_sharing"&gt;CORS&lt;/a&gt; (Cross-origin resource sharing), which allows us to work with files in a flexible, asynchronous manner and provide our users with a better experience. In this post we'll show how to leverage CORS and the direct upload options available, and introduce a small new .NET library, &lt;a href="https://github.com/appharbor/nupload"&gt;Nupload&lt;/a&gt;, that makes working with GCS, S3, CORS and ASP.NET MVC even easier.&lt;/p&gt;

&lt;p&gt;We'll walk through 5 steps to upload and serve files:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Configuring CORS on S3 and GCS&lt;/li&gt;
&lt;li&gt;Server side form and signature generation.&lt;/li&gt;
&lt;li&gt;Asynchronous, CORS-enabled upload of files directly to S3 or GCS using Javascript.&lt;/li&gt;
&lt;li&gt;Notifying our application about successful uploads.&lt;/li&gt;
&lt;li&gt;Server side signing of URLs to serve private content to a client.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The source code is available on &lt;a href="https://github.com/appharbor/nupload"&gt;GitHub&lt;/a&gt; and includes a sample application - the sample application is also deployed to AppHarbor [so you can &lt;a href="http://corssample.apphb.com"&gt;go and play with it right away&lt;/a&gt;. In this blog post we'll use the code in the sample application, but you can also just download the sample project and try it out for yourself. You'll need to set your own AWS or GCS credentials and configure the CORS policy of your bucket.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://corssample.apphb.com"&gt;&lt;img src="http://blog.appharbor.com/resources/images/cors-sample-app-screenshot.png" alt="Cors sample application" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before diving into the code lets walk through the configuration of CORS policies on AWS and GCS respectively.&lt;/p&gt;

&lt;h2&gt;Step 1: Configuring CORS policy&lt;/h2&gt;

&lt;p&gt;Below are a couple of samples for CORS configuration. Please note that in both cases you'd likely want to set the allowed origin parameters to something more restrictive than "*" - like the domain name of your application.&lt;/p&gt;

&lt;h3&gt;AWS configuration:&lt;/h3&gt;

&lt;p&gt;Go to the AWS S3 management console, create a bucket and click the "Add CORS configuration" button. The CORS configuration can look similar to this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;
&amp;lt;CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"&amp;gt;
    &amp;lt;CORSRule&amp;gt;
        &amp;lt;AllowedOrigin&amp;gt;*&amp;lt;/AllowedOrigin&amp;gt;
        &amp;lt;AllowedMethod&amp;gt;GET&amp;lt;/AllowedMethod&amp;gt;
        &amp;lt;AllowedMethod&amp;gt;POST&amp;lt;/AllowedMethod&amp;gt;
        &amp;lt;AllowedMethod&amp;gt;PUT&amp;lt;/AllowedMethod&amp;gt;
        &amp;lt;MaxAgeSeconds&amp;gt;3000&amp;lt;/MaxAgeSeconds&amp;gt;
        &amp;lt;AllowedHeader&amp;gt;*&amp;lt;/AllowedHeader&amp;gt;
    &amp;lt;/CORSRule&amp;gt;
&amp;lt;/CORSConfiguration&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;For security reasons we also recommend that you use AWS IAM to generate credentials that are only allowed to perform the bucket operations you need them for.&lt;/p&gt;

&lt;h3&gt;GCS configuration:&lt;/h3&gt;

&lt;p&gt;Use the &lt;a href="https://developers.google.com/storage/docs/gsutil"&gt;gsutil tool&lt;/a&gt; to configure your bucket with a CORS configuration like so:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;gsutil setcors corsconfig.xml gs://corssample
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Where "corssample" is the name of your GCS bucket and corsconfig.xml contains something like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;
&amp;lt;CorsConfig&amp;gt;
    &amp;lt;Cors&amp;gt;
        &amp;lt;Origins&amp;gt;
            &amp;lt;Origin&amp;gt;*&amp;lt;/Origin&amp;gt;
        &amp;lt;/Origins&amp;gt;
        &amp;lt;Methods&amp;gt;
            &amp;lt;Method&amp;gt;GET&amp;lt;/Method&amp;gt;
            &amp;lt;Method&amp;gt;HEAD&amp;lt;/Method&amp;gt;
            &amp;lt;Method&amp;gt;POST&amp;lt;/Method&amp;gt;
            &amp;lt;Method&amp;gt;DELETE&amp;lt;/Method&amp;gt;
            &amp;lt;Method&amp;gt;PUT&amp;lt;/Method&amp;gt;
        &amp;lt;/Methods&amp;gt;
        &amp;lt;ResponseHeaders&amp;gt;
            &amp;lt;ResponseHeader&amp;gt;*&amp;lt;/ResponseHeader&amp;gt;
        &amp;lt;/ResponseHeaders&amp;gt;
        &amp;lt;MaxAgeSec&amp;gt;10&amp;lt;/MaxAgeSec&amp;gt;
    &amp;lt;/Cors&amp;gt;
&amp;lt;/CorsConfig&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With this in place we're ready to upload files to our bucket using Nupload, ASP.NET MVC (2 or later supported out of the box) and CORS.&lt;/p&gt;

&lt;h2&gt;Step 2: Server side form and signature generation&lt;/h2&gt;

&lt;p&gt;S3 and GCS both work by POSTing files using a signature for authentication. The signature ensures that even though the clients have access to certain configuration fields, they won't be able to modify them. We need to do sign our signatures with private keys, so for security reasons this is best handled on the server side.&lt;/p&gt;

&lt;p&gt;First we can install the Nupload library in our MVC web project. MVC2 and forward is supported out of the box, but it can easily be extended to other web application types. &lt;a href="http://nuget.org/packages/Nupload/1.0.1"&gt;Nupload is available as a NuGet package&lt;/a&gt; which can easily be installed:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt; Install-Package Nupload
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Using Nupload we can now configure the client uploads to our cloud storage provider like so:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public ActionResult Create()
{
    var randomStringGenerator = new RandomStringGenerator();
    var objectKey = string.Format("uploads/{0}/${{filename}}", randomStringGenerator.GenerateString(16));
    var bucket = "corssample";

    var maxFileSize = 512 * 1024 * 1024;
    var objectConfiguration = new AmazonS3ObjectConfiguration(objectKey, AmazonS3CannedAcl.Private, maxFileSize);

    var credentials = new AmazonCredentials(
                    ConfigurationManager.AppSettings.Get("amazon.access_key_id"),
                    ConfigurationManager.AppSettings.Get("amazon.secret_access_key"));

    var uploadConfiguration = new AmazonS3UploadConfiguration(credentials, bucket, objectConfiguration);

    return View(uploadConfiguration);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here an &lt;a href="https://github.com/appharbor/nupload/blob/master/Nupload/AmazonS3UploadConfiguration.cs"&gt;AmazonS3UploadConfiguration&lt;/a&gt; object, which implement the IObjectConfiguration interface) is passed to the view. Object access settings are configured and can be set to any of the &lt;a href="http://docs.amazonwebservices.com/AmazonS3/latest/dev/ACLOverview.html#CannedACL"&gt;S3 Canned ACL grants&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you prefer using GCS we've also included a &lt;a href="https://github.com/appharbor/nupload/blob/master/Nupload/GoogleCloudStorageUploadConfiguration.cs"&gt;GoogleCloudStorageUploadConfiguration&lt;/a&gt; implementation in Nupload, but you're free to add your own implementation to suit your requirements.&lt;/p&gt;

&lt;p&gt;By using the upload configuration that is passed from the controller to our view, we can now implement the upload form in the "New" painting view:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@using Dupload

@using (Html.BeginAsyncUploadForm(new Uri(Url.Action("create"), UriKind.Relative), Model,
    new { id = "fileupload", data_as = "imageUrl" })) {

    &amp;lt;input id="file" multiple="multiple" name="file" type="file" /&amp;gt;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;BeginAsyncUploadForm&lt;/code&gt; HtmlHelper extension method is included as part of the Nupload package. It takes care of extracting and writing all the required form attributes and fields based on our upload configuration. The first argument is the application's "callback URL", which will be set to the &lt;code&gt;data-post&lt;/code&gt; attribute. The &lt;code&gt;data_as&lt;/code&gt; attribute is also set for use later on.&lt;/p&gt;

&lt;p&gt;This will render HTML similar to this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;form accept-charset="utf-8" action="https://corssample.s3.amazonaws.com/" data-as="imageUrl" data-post="/Paintings/create" enctype="multipart/form-data" id="fileupload" method="post"&amp;gt;
    &amp;lt;input id="key" name="key" type="hidden" value="uploads/osqSbYGNNWJXH4Go/${filename}"&amp;gt;
    &amp;lt;input id="acl" name="acl" type="hidden" value="private"&amp;gt;
    &amp;lt;input id="policy" name="policy" type="hidden" value="eyJleHBpcmF0aW9uIjoiMjAxabY0xMi0xMVQwMjo0MDo0NVoq$LCJjb25kaXRpb25zIjpbWyJzdGFydHMtd2l0aCIsIiRrZXkiLCIiXSxbInN0YXJ0cy121XRoIiwiJGNvbnRlbnQtdHlwZSIsIiJdLFsic3RhcnRzLXdpdGgiLCIkYWNsIiwicHJpdmF0ZSJdLFsiY29udGVudC1sZW5ndGgtcmFuZ2UiLDAsNTM2ODtwOTEyXSx7InN1Y2Nlc3NfYWN0aW9uX3N0YXR1cyI6IjIwMSa9LssiYnVja2V0IjoiY29yc3NhbXBsZSJ9LHsiYWNsIjoicHJpdmF0ZSJ9XX0="&amp;gt;
    &amp;lt;input id="signature" name="signature" type="hidden" value="P/cuc28kR4gc/sLeK1U7XS3gmGd4="&amp;gt;
    &amp;lt;input id="content-type" name="content-type" type="hidden" value="application/octet-stream"&amp;gt;
    &amp;lt;input id="AWSAccessKeyId" name="AWSAccessKeyId" type="hidden" value="AKIAJMTMMPVNWB73LE4A"&amp;gt;
    &amp;lt;input id="success_action_status" name="success_action_status" type="hidden" value="201"&amp;gt;
    &amp;lt;input id="file" multiple="multiple" name="file" type="file"&amp;gt;
&amp;lt;/form&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We're now ready to implement the client side logic that'll upload files to our storage provider.&lt;/p&gt;

&lt;h2&gt;Step 3: Uploading files from the client&lt;/h2&gt;

&lt;p&gt;Files can be uploaded in a number of ways and in this example we'll use the jQuery FileUpload plugin. Here is some of the javascript included in the &lt;a href="https://github.com/appharbor/nupload/tree/master/CorsSample"&gt;sample project&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$('#fileupload').fileupload({
    dataType: "xml",
    add: function (e, data) {
        var file, types;
        types = /(\.|\/)(gif|jpe?g|png)$/i;
        file = data.files[0];
        if (types.test(file.type) || types.test(file.name)) {
            data.context = $(tmpl("template-upload", file));
            $('#fileupload').append(data.context);
            data.form.find('#content-type').val(file.type);

            return data.submit();
        } else {
            return alert("" + file.name + " is not a gif, jpeg, or png image file");
        }
    },
    done: function (e, data) {
        var content, domain, file, path, to;
        file = data.files[0];
        to = $('#fileupload').data('post');
        content = {};

        var location = $(data.result).find("Location")[0].textContent;
        content[$('#fileupload').data('as')] = decodeURIComponent(location);
        $.post(to, content, function (data, statusText, xhr) {
            $.get(xhr.getResponseHeader("location"), function (painting) {
                $("#uploadedPaintings").append($(tmpl("template-painting", painting)));
            });
        });
        if (data.context) {
            return data.context.remove();
        }
    },
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Let's go through some of the steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When files are added the "add" callback is invoked. In this case we're testing the file ending, but you can of course put any validation logic you like here.&lt;/li&gt;
&lt;li&gt;If the file type is valid we set the "content-type" form field to the actual mime type of the file. By default the content-type field is set to &lt;code&gt;application/octet-stream&lt;/code&gt;, but we want to set the specific content type so the cloud storage provider can use it for serving content.&lt;/li&gt;
&lt;li&gt;Finally the form is submitted and the upload is initiated.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Step 4: Notifying our application about the uploaded files&lt;/h2&gt;

&lt;p&gt;When the files have been uploaded we want to notify our application about it. That is also handled by the javascript above:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;done&lt;/code&gt; callback is invoked when the upload finishes. At this point we use the response from our storage provider to get the exact file URL. We then POST a request to the &lt;code&gt;data-post&lt;/code&gt; (callback) URL. The parameter name for the object URL is set to the value of the &lt;code&gt;data-as&lt;/code&gt; attribute, in this case "imageUrl".&lt;/li&gt;
&lt;li&gt;Finally a javascript template is rendered to show the user the new file.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The controller action that takes this request could look similar to this (assuming the Painting model has an ImageUrl parameter):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[HttpPost]
public ActionResult Create(Painting painting)
{
    if (ModelState.IsValid)
    {
        var imageUri = new Uri(painting.ImageUrl);
        painting.Name = Server.UrlDecode(imageUri.Segments.Last());

        _databaseContext.Paintings.Add(painting);
        _databaseContext.SaveChanges();

        Response.RedirectLocation = Url.Action("details", new { id = painting.Id });
        return new HttpStatusCodeResult((int)HttpStatusCode.Created);
    }

    return View(painting);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We simply set the URL decoded name of the Painting object, save it to the database and redirect the client to the "Details" action.&lt;/p&gt;

&lt;p&gt;Our application now knows about the new Painting that was uploaded, and it can be served directly from the cloud storage provider by specifying the image url. In case you want to modify files (like creating thumbnails) we recommend that you do this asynchronously, for instance by using &lt;a href="http://support.appharbor.com/kb/getting-started/background-workers"&gt;AppHarbor's background workers&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;Step 5: Authorizing file downloads&lt;/h2&gt;

&lt;p&gt;In a lot of cases we don't want files to be publicly accessible. We want to restrict access only to authorized users. As you may have noticed we actually set the access grant to "Private" in step 2, which means that only the bucket owner has access to the file. This also means that although a client can upload files like we saw in step 3, he cannot retrieve it afterwards even with the URL. This gives us much of the same access control that we'd have if we stored the files locally.&lt;/p&gt;

&lt;p&gt;We can authorize access to private files in our bucket by using signed URLs. Signed URLs allows us to give our clients a URL with a signature parameter, which authorizes access to the resource given a signature expiration and a method. We've included "URL signers" for AWS and GCS in Dupload, which can be used like so:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public ActionResult Details(int id)
{
    var painting = _databaseContext.Paintings.Find(id);

    var credentials = new AmazonCredentials(
                    ConfigurationManager.AppSettings.Get("amazon.access_key_id"),
                    ConfigurationManager.AppSettings.Get("amazon.secret_access_key"));
    var urlSigner = new AmazonS3UrlSigner(credentials);
    var signedUrl = urlSigner.GetSignedUrl(new Uri(painting.ImageUrl), TimeSpan.FromMinutes(20));

    return Json(new
    {
        id = painting.Id,
        signedUrl = signedUrl,
        name = painting.Name
    },
    JsonRequestBehavior.AllowGet);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will give us a signed URL, which will be valid for 20 minutes which should be plenty of time to retrieve an image.&lt;/p&gt;

&lt;p&gt;In the example application we use the returned JSON object from the &lt;code&gt;Details&lt;/code&gt; action to render our template. The template can look like so:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;script id="template-painting" type="text/x-tmpl"&amp;gt;
    &amp;lt;div class="painting"&amp;gt;
        &amp;lt;img src="{%=o.signedUrl %}" alt="{%=o.name %}"&amp;gt;
        &amp;lt;span&amp;gt;{%= o.name %}&amp;lt;/span&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That's it. The application can now handle uploads to Amazon S3 using CORS, notify our application about the new file upload and afterwards serve it using a signed URL.&lt;/p&gt;

&lt;p&gt;We hope you'll find good use of the Nupload library and please feel free to contribute with anything you think is missing. We can also recommend watching &lt;a href="http://railscasts.com/episodes/383-uploading-to-amazon-s3"&gt;this railscasts episode&lt;/a&gt; if you'd like to learn more about uploading to Amazon S3.&lt;/p&gt;
</description></item><item><link>http://blog.appharbor.com/2012/11/20/elephantsql-now-in-add-on-catalog</link><title>ElephantSQL now in add-on catalog</title><description>&lt;p&gt;We have a new add-on ready for you: &lt;a href="https://appharbor.com/addons/elephantsql"&gt;ElephantSQL&lt;/a&gt; – cloud-hosted PostgreSQL as-a-service.&lt;/p&gt;

&lt;p&gt;PostgreSQL is a stable, mature and high-performance open source RDMS and the guys at ElephantSQL have done a great job of packaging that into an awesome service.&lt;/p&gt;

&lt;p&gt;We have updated our &lt;a href="https://github.com/appharbor/PostgreSQL-Sample-MVC-Application"&gt;PostgreSQL-NHibernate example MVC app&lt;/a&gt; to also work with ElephantSQL and there's additional &lt;a href="http://www.elephantsql.com/docs/appharbor.html"&gt;.NET sample code and documentation on the ElephantSQL website&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;ElephantSQL has a free plan to get you started, &lt;a href="https://appharbor.com/addons/elephantsql"&gt;try it out&lt;/a&gt; right now!&lt;/p&gt;

&lt;p&gt;&lt;img src="http://blog.appharbor.com/resources/images/elephant_sql.png" alt="ElephantSQL logo" /&gt;&lt;/p&gt;
</description></item></channel></rss>
