ASP.NET – Overposting/Mass Assignment Model Binding Security

imageThis little post is just a reminder that while Model Binding in ASP.NET is very cool, you should be aware of the properties (and semantics of those properties) that your object has, and whether or not your HTML form includes all your properties, or omits some.

OK, that’s a complex – and perhaps poorly written – sentence. Let me back up.

Let’s say you have this horrible class. Relax, yes, it’s horrible. It’s an example. It’ll make sense in a moment.

public class Person
{
public int ID { get; set; }
public string First { get; set; }
public string Last { get; set; }
public bool IsAdmin { get; set; }
}

Then you’ve got an HTML Form in your view that lets folks create a Person. That form has text boxes/fields for First, and Last. ID is handled by the database on creation, and IsAdmin is a property that the user doesn’t need to know about. Whatever. It’s secret and internal. It could be Comment.IsApproved or Product.Discount. You get the idea.

Then you have a PeopleController that takes in a Person via a POST:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(Person person)
{
if (ModelState.IsValid)
{
_context.Add(person);
await _context.SaveChangesAsync();
return RedirectToAction("Index");
}
return View(person);
}

If a theoretical EvilUser found out that Person had an “IsAdmin” property, they could “overpost” and add a field to the HTTP POST and set IsAdmin=true. There’s nothing in the code here to prevent that. ModelBinding makes your code simpler by handling the “left side -> right side” boring code of the past. That was all that code where you did myObject.Prop = Request.Form[“something”]. You had lines and lines of code digging around in the QueryString or Form POST.

Model Binding gets rid of that and looks at the properties of the object and lines them up with HTTP Form POST name/value pairs of the same names.

NOTE: Just a friendly reminder that none of this “magic” is magic or is secret. You can even write your own custom model binders if you like.

The point here is that folks need to be aware of the layers of abstraction when you use them. Yes, it’s convenient, but it’s hiding something from you, so you should know the side effects.

How do we fix the problem? Well, a few ways. You can mark the property as [ReadOnly]. More commonly, you can use a BindAttribute on the method parameters and just include (whitelist) the properties you want to allow for binding:

public async Task<IActionResult> Create([Bind("First,Last")] Person person)

Or, the correct answer. Don’t let models that look like this get anywhere near the user. This is the case for ViewModels. Make a model that looks like the View. Then do the work. You can make the work easier with something like AutoMapper.

Some folks find ViewModels to be too cumbersome for basic stuff. That’s valid. There are those that are “All ViewModels All The Time,” but I’m more practical. Use what works, use what’s appropriate, but know what’s happening underneath so you don’t get some scriptkiddie overposting to your app and a bit getting flipped in your Model as a side effect.

Use ViewModels when possible or reasonable, and when not, always whitelist your binding if the model doesn’t line up one to one (1:1) with your HTML Form.

What are your thoughts?


Sponsor: Check out JetBrains Rider: a new cross-platform .NET IDE. Edit, refactor, test, build and debug ASP.NET, .NET Framework, .NET Core, or Unity applications. Learn more and get access to early builds!


© 2017 Scott Hanselman. All rights reserved.
     

imageThis little post is just a reminder that while Model Binding in ASP.NET is very cool, you should be aware of the properties (and semantics of those properties) that your object has, and whether or not your HTML form includes all your properties, or omits some.

OK, that's a complex - and perhaps poorly written - sentence. Let me back up.

Let's say you have this horrible class. Relax, yes, it's horrible. It's an example. It'll make sense in a moment.

public class Person

{
public int ID { get; set; }
public string First { get; set; }
public string Last { get; set; }
public bool IsAdmin { get; set; }
}

Then you've got an HTML Form in your view that lets folks create a Person. That form has text boxes/fields for First, and Last. ID is handled by the database on creation, and IsAdmin is a property that the user doesn't need to know about. Whatever. It's secret and internal. It could be Comment.IsApproved or Product.Discount. You get the idea.

Then you have a PeopleController that takes in a Person via a POST:

[HttpPost]

[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(Person person)
{
if (ModelState.IsValid)
{
_context.Add(person);
await _context.SaveChangesAsync();
return RedirectToAction("Index");
}
return View(person);
}

If a theoretical EvilUser found out that Person had an "IsAdmin" property, they could "overpost" and add a field to the HTTP POST and set IsAdmin=true. There's nothing in the code here to prevent that. ModelBinding makes your code simpler by handling the "left side -> right side" boring code of the past. That was all that code where you did myObject.Prop = Request.Form["something"]. You had lines and lines of code digging around in the QueryString or Form POST.

Model Binding gets rid of that and looks at the properties of the object and lines them up with HTTP Form POST name/value pairs of the same names.

NOTE: Just a friendly reminder that none of this "magic" is magic or is secret. You can even write your own custom model binders if you like.

The point here is that folks need to be aware of the layers of abstraction when you use them. Yes, it's convenient, but it's hiding something from you, so you should know the side effects.

How do we fix the problem? Well, a few ways. You can mark the property as [ReadOnly]. More commonly, you can use a BindAttribute on the method parameters and just include (whitelist) the properties you want to allow for binding:

public async Task<IActionResult> Create([Bind("First,Last")] Person person)

Or, the correct answer. Don't let models that look like this get anywhere near the user. This is the case for ViewModels. Make a model that looks like the View. Then do the work. You can make the work easier with something like AutoMapper.

Some folks find ViewModels to be too cumbersome for basic stuff. That's valid. There are those that are "All ViewModels All The Time," but I'm more practical. Use what works, use what's appropriate, but know what's happening underneath so you don't get some scriptkiddie overposting to your app and a bit getting flipped in your Model as a side effect.

Use ViewModels when possible or reasonable, and when not, always whitelist your binding if the model doesn't line up one to one (1:1) with your HTML Form.

What are your thoughts?


Sponsor: Check out JetBrains Rider: a new cross-platform .NET IDE. Edit, refactor, test, build and debug ASP.NET, .NET Framework, .NET Core, or Unity applications. Learn more and get access to early builds!



© 2017 Scott Hanselman. All rights reserved.
     

Options for CSS and JS Bundling and Minification with ASP.NET Core

Maria and I were updating the NerdDinner sample app (not done yet, but soon) and were looking at various ways to do bundling and minification of the JSS and CS. There’s runtime bundling on ASP.NET 4.x but in recent years web developers have used tools like Grunt or Gulp to orchestrate a client-side build process to squish their assets. The key is to find a balance that gives you easy access to development versions of JS/CSS assets when at dev time, while making it “zero work” to put minified stuff into production. Additionally, some devs don’t need the Grunt/Gulp/npm overhead while others absolutely do. So how do you find balance? Here’s how it works.

I’m in Visual Studio 2017 and I go File | New Project | ASP.NET Core Web App. Bundling isn’t on by default but the configuration you need IS included by default. It’s just minutes to enable and it’s quite nice.

In my Solution Explorer is a “bundleconfig.json” like this:

// Configure bundling and minification for the project.
// More info at https://go.microsoft.com/fwlink/?LinkId=808241
[
{
"outputFileName": "wwwroot/css/site.min.css",
// An array of relative input file paths. Globbing patterns supported
"inputFiles": [
"wwwroot/css/site.css"
]
},
{
"outputFileName": "wwwroot/js/site.min.js",
"inputFiles": [
"wwwroot/js/site.js"
],
// Optionally specify minification options
"minify": {
"enabled": true,
"renameLocals": true
},
// Optionally generate .map file
"sourceMap": false
}
]

Pretty simple. Ins and outs. At the top of the VS editor you’ll see this yellow prompt. VS knows you’re in a bundleconfig.json and in order to use it effectively in VS you grab a small extension. To be clear, it’s NOT required. It just makes it easier. The source is at https://github.com/madskristensen/BundlerMinifier. Slip this UI section if you just want Build-time bundling.

BundleConfig.json

If getting a prompt like this bugs you, you can turn all prompting off here:

Tools Options HTML Advanced Identify Helpful Extensions

Look at your Solution Explorer. See under site.css and site.js? There are associated minified versions of those files. They aren’t really “under” them. They are next to them on the disk, but this hierarchy is a nice way to see that they are associated, and that one generates the other.

Right click on your project and you’ll see this Bundler & Minifier menu:

Bundler and Minifier Menu

You can manually update your Bundles with this item as well as see settings and have bundling show up in the Task Runner Explorer.

Build Time Minification

The VSIX (VS extension) gives you the small menu and some UI hooks, but if you want to have your bundles updated at build time (useful if you don’t use VS!) then you’ll want to add a NuGet package called BuildBundlerMinifier.

You can add this NuGet package SEVERAL ways. Which is awesome.

  • Add it from the Manage NuGet Packages menu
  • Add it from the command line via “dotnet add package BuildBundlerMinifier”
    • Note that this adds it to your csproj without you having to edit it! It’s like “nuget install” but adds references to projects!  The dotnet CLI is lovely.
  • If you have the VSIX installed, just right-click the bundleconfig.json and click “Enable bundle on build…” and you’ll get the NuGet package.
    Enable bundle on build

Now bundling will run on build…

c:\WebApplication8\WebApplication8>dotnet build
Microsoft (R) Build Engine version 15
Copyright (C) Microsoft Corporation. All rights reserved.

Bundler: Begin processing bundleconfig.json
Bundler: Done processing bundleconfig.json
WebApplication8 -> c:\WebApplication8\bin\Debug\netcoreapp1.1\WebApplication8.dll

Build succeeded.
0 Warning(s)
0 Error(s)

…even from the command line with “dotnet build.” It’s all integrated.

This is nice for VS Code or users of other editors. Here’s how it would work entirely from the command prompt:

$ dotnet new mvc
$ dotnet add package BuildBundlerMinifier
$ dotnet restore
$ dotnet run

Advanced: Using Gulp to handle Bundling/Minifying

If you outgrow this bundler or just like Gulp, you can right click and Convert to Gulp!

Convert to Gulp

Now you’ll get a gulpfile.js that uses the bundleconfig.json and you’ve got full control:

gulpfile.js

And during the conversion you’ll get the npm packages you need to do the work automatically:

npm and bower

I’ve found this to be a good balance that can get quickly productive with a project that gets bundling without npm/node, but I can easily grow to a larger, more npm/bower/gulp-driven front-end developer-friendly app.


Sponsor: Did you know VSTS can integrate closely with Octopus Deploy? Join Damian Brady and Brian A. Randell as they show you how to automate deployments from VSTS to Octopus Deploy, and demo the new VSTS Octopus Deploy dashboard widget. Register now!


© 2017 Scott Hanselman. All rights reserved.
     

Maria and I were updating the NerdDinner sample app (not done yet, but soon) and were looking at various ways to do bundling and minification of the JSS and CS. There's runtime bundling on ASP.NET 4.x but in recent years web developers have used tools like Grunt or Gulp to orchestrate a client-side build process to squish their assets. The key is to find a balance that gives you easy access to development versions of JS/CSS assets when at dev time, while making it "zero work" to put minified stuff into production. Additionally, some devs don't need the Grunt/Gulp/npm overhead while others absolutely do. So how do you find balance? Here's how it works.

I'm in Visual Studio 2017 and I go File | New Project | ASP.NET Core Web App. Bundling isn't on by default but the configuration you need IS included by default. It's just minutes to enable and it's quite nice.

In my Solution Explorer is a "bundleconfig.json" like this:

// Configure bundling and minification for the project.

// More info at https://go.microsoft.com/fwlink/?LinkId=808241
[
{
"outputFileName": "wwwroot/css/site.min.css",
// An array of relative input file paths. Globbing patterns supported
"inputFiles": [
"wwwroot/css/site.css"
]
},
{
"outputFileName": "wwwroot/js/site.min.js",
"inputFiles": [
"wwwroot/js/site.js"
],
// Optionally specify minification options
"minify": {
"enabled": true,
"renameLocals": true
},
// Optionally generate .map file
"sourceMap": false
}
]

Pretty simple. Ins and outs. At the top of the VS editor you'll see this yellow prompt. VS knows you're in a bundleconfig.json and in order to use it effectively in VS you grab a small extension. To be clear, it's NOT required. It just makes it easier. The source is at https://github.com/madskristensen/BundlerMinifier. Slip this UI section if you just want Build-time bundling.

BundleConfig.json

If getting a prompt like this bugs you, you can turn all prompting off here:

Tools Options HTML Advanced Identify Helpful Extensions

Look at your Solution Explorer. See under site.css and site.js? There are associated minified versions of those files. They aren't really "under" them. They are next to them on the disk, but this hierarchy is a nice way to see that they are associated, and that one generates the other.

Right click on your project and you'll see this Bundler & Minifier menu:

Bundler and Minifier Menu

You can manually update your Bundles with this item as well as see settings and have bundling show up in the Task Runner Explorer.

Build Time Minification

The VSIX (VS extension) gives you the small menu and some UI hooks, but if you want to have your bundles updated at build time (useful if you don't use VS!) then you'll want to add a NuGet package called BuildBundlerMinifier.

You can add this NuGet package SEVERAL ways. Which is awesome.

  • Add it from the Manage NuGet Packages menu
  • Add it from the command line via "dotnet add package BuildBundlerMinifier"
    • Note that this adds it to your csproj without you having to edit it! It's like "nuget install" but adds references to projects!  The dotnet CLI is lovely.
  • If you have the VSIX installed, just right-click the bundleconfig.json and click "Enable bundle on build..." and you'll get the NuGet package.
    Enable bundle on build

Now bundling will run on build...

c:\WebApplication8\WebApplication8>dotnet build

Microsoft (R) Build Engine version 15
Copyright (C) Microsoft Corporation. All rights reserved.

Bundler: Begin processing bundleconfig.json
Bundler: Done processing bundleconfig.json
WebApplication8 -> c:\WebApplication8\bin\Debug\netcoreapp1.1\WebApplication8.dll

Build succeeded.
0 Warning(s)
0 Error(s)

...even from the command line with "dotnet build." It's all integrated.

This is nice for VS Code or users of other editors. Here's how it would work entirely from the command prompt:

$ dotnet new mvc

$ dotnet add package BuildBundlerMinifier
$ dotnet restore
$ dotnet run

Advanced: Using Gulp to handle Bundling/Minifying

If you outgrow this bundler or just like Gulp, you can right click and Convert to Gulp!

Convert to Gulp

Now you'll get a gulpfile.js that uses the bundleconfig.json and you've got full control:

gulpfile.js

And during the conversion you'll get the npm packages you need to do the work automatically:

npm and bower

I've found this to be a good balance that can get quickly productive with a project that gets bundling without npm/node, but I can easily grow to a larger, more npm/bower/gulp-driven front-end developer-friendly app.


Sponsor: Did you know VSTS can integrate closely with Octopus Deploy? Join Damian Brady and Brian A. Randell as they show you how to automate deployments from VSTS to Octopus Deploy, and demo the new VSTS Octopus Deploy dashboard widget. Register now!


© 2017 Scott Hanselman. All rights reserved.
     

ZEIT now deployments of open source ASP.NET Core web apps with Docker

ZEIT is a new cloud service and “now” is the name of their deployment tool. ZEIT World is their DNS service. If you head over to https://zeit.co/ you’ll see a somewhat cryptic animated gif that shows how almost impossibly simple it is to deploy a web app with ZEIT now.

ZEIT works with .NET Core and ASP.NET

You can make a folder, put an index.html (for example) in it and just run “now.” You’ll automatically get a website with an autogenerated name and it’ll be live. It’s probably the fastest and easiest deploy I’ve ever seen. Remember when Heroku (then Azure, then literally everyone) started using git for deployment? Clearly being able to type “now” and just get a web site on the public internet was the next step. (Next someone will make “up” which will then get replaced with just pressing ENTER on an empty line! 😉 )

Jokes aside, now is clean and easy. I appreciate their organizational willpower to make an elegant and simple command line tool. I suspect it’s harder than it looks to keep things simple.

All of their examples use JavaScript and node.js, but they also support Docker, which means they support open source ASP.NET Core on .NET Core! But do they know they do? 😉 Let’s find out.

And more importantly, how easy is it? Can I take a site from concept to production in minutes? Darn tootin’ I can.

First, make a quick ASP.NET Core app. I’ll use the MVC template with Bootstrap.

C:\Users\scott\zeitdotnet>dotnet new mvc
Content generation time: 419.5337 ms
The template "ASP.NET Core Web App" created successfully.

I’ll do a quick dotnet restore to get the packages for my project.

C:\Users\scott\zeitdotnet>dotnet restore
Restoring packages for C:\Users\scott\zeitdotnet\zeitdotnet.csproj...
Generating MSBuild file C:\Users\scott\zeitdotnet\obj\zeitdotnet.csproj.nuget.g.props.
Generating MSBuild file C:\Users\scott\zeitdotnet\obj\zeitdotnet.csproj.nuget.g.targets.
Writing lock file to disk. Path: C:\Users\scott\zeitdotnet\obj\project.assets.json
Restore completed in 2.93 sec for C:\Users\scott\zeitdotnet\zeitdotnet.csproj.

NuGet Config files used:
C:\Users\scott\AppData\Roaming\NuGet\NuGet.Config
C:\Program Files (x86)\NuGet\Config\Microsoft.VisualStudio.Offline.config

Feeds used:
https://api.nuget.org/v3/index.json
C:\LocalNuGet
C:\Program Files (x86)\Microsoft SDKs\NuGetPackages\

Now I need to add a Dockerfile. I’ll make one in the root that looks like this:

FROM microsoft/aspnetcore
LABEL name="zeitdotnet"
ENTRYPOINT ["dotnet", "zeitdotnet.dll"]
ARG source=.
WORKDIR /app
EXPOSE 80
COPY $source .

Note that I could have ZEIT build my app for me if I used the aspnetcore Dockerfile that includes the .NET Core SDK, but that would not only make my deployment longer, it would also make my docker images a LOT larger. I want to include JUST the .NET Core runtime in my image, so I’ll build and publish locally.

ZEIT now is going to need to see my Dockerfile, and since I want my app to include the binaries (I don’t want to ship my source in the Docker image up to ZEIT) I need to mark my Dockerfile as “Content” and make sure it’s copied to the publish folder when my app is built and published.

<ItemGroup>
  <None Remove="Dockerfile" />
</ItemGroup>
<ItemGroup>
  <Content Include="Dockerfile">
    <CopyToOutputDirectory>Always</CopyToOutputDirectory>
  </Content>
</ItemGroup>

I’ll add this my project’s csproj file. If I was using Visual Studio, this is the same as right clicking on the Properties of the Dockerfile, setting it to Content and then “Always Copy to Output Directory.”

Now I’ll just build and publish to a folder with one command:

C:\Users\scott\zeitdotnet>dotnet publish
Microsoft (R) Build Engine version 15.1.548.43366
Copyright (C) Microsoft Corporation. All rights reserved.

zeitdotnet -> C:\Users\scott\zeitdotnet\bin\Debug\netcoreapp1.1\zeitdotnet.dll

And finally, from the .\bin\Debug\netcoreapp1.1\ folder I run “now.” (Note that I’ve installed now and signed up for their service, of course.)

C:\Users\scott\zeitdotnet\bin\Debug\netcoreapp1.1\publish>now
> Deploying ~\zeitdotnet\bin\Debug\netcoreapp1.1\publish
> Ready! https://zeitdotnet-gmhcxevqkf.now.sh (copied to clipboard) [3s]
> Upload [====================] 100% 0.0s
> Sync complete (196.18kB) [2s]
> Initializing…
> Building
> ▲ docker build
> ---> 035a0a1401c3
> Removing intermediate container 289b9e4ce5d9
> Step 6 : EXPOSE 80
> ---> Running in efb817308333
> ---> fbac2aaa3039
> Removing intermediate container efb817308333
> Step 7 : COPY $source .
> ---> ff009cfc48ea
> Removing intermediate container 8d650c1867cd
> Successfully built ff009cfc48ea
> ▲ Storing image
> ▲ Deploying image
> Deployment complete!

Now has put the generated URL in my clipboard (during deployment you’ll get redirected to a lovely status page) and when it’s deployed I can visit my live site. But, that URL is not what I want. I want to use a custom URL.

I can take one of my domains and set it up with ZEIT World’s DNS but I like DNSimple (ref).

I can add my domain as an external one after adding a TXT record to my DNS to verify I own it. Then I setup a CNAME to point my subdomain to alias.zeit.co.

C:\Users\scott\Desktop\zeitdotnet>now alias https://zeitdotnet-gmhcxevqkf.now.sh http://zeitdotnet.hanselman.com
> zeitdotnet.hanselman.com is a custom domain.
> Verifying the DNS settings for zeitdotnet.hanselman.com (see https://zeit.world for help)
> Verification OK!
> Provisioning certificate for zeitdotnet.hanselman.com
> Success! Alias created:
https://zeitdotnet.hanselman.com now points to https://zeitdotnet-gmhcxevqkf.now.sh [copied to clipboard]

And that’s it. It even has a nice SSL certificate that they applied for me. It doesn’t terminate to SSL all the way into the docker container’s Kestral web server, but for most things that aren’t banking it’ll be just fine.

All in all, a lovely experience. Here’s my Hello World ASP.NE Core app running in ZEIT and deployed with now  at http://zeitdotnet.hanselman.com (if you are visiting this long after this was published, this sample MAY be gone.)

I am still learning about this (this whole exercise was about 30 total minutes and asking Glenn Condron a docker question) so I’m not clear how this would work in a large multi-container deployment, but as long as your site is immutable (don’t write to the container’s local disk!) ZEIT says it will scale your single containers. Perhaps docker-compose support is coming?


Sponsor: Did you know VSTS can integrate closely with Octopus Deploy? Join Damian Brady and Brian A. Randell as they show you how to automate deployments from VSTS to Octopus Deploy, and demo the new VSTS Octopus Deploy dashboard widget. Register now!


© 2017 Scott Hanselman. All rights reserved.
     

ZEIT is a new cloud service and "now" is the name of their deployment tool. ZEIT World is their DNS service. If you head over to https://zeit.co/ you'll see a somewhat cryptic animated gif that shows how almost impossibly simple it is to deploy a web app with ZEIT now.

ZEIT works with .NET Core and ASP.NET

You can make a folder, put an index.html (for example) in it and just run "now." You'll automatically get a website with an autogenerated name and it'll be live. It's probably the fastest and easiest deploy I've ever seen. Remember when Heroku (then Azure, then literally everyone) started using git for deployment? Clearly being able to type "now" and just get a web site on the public internet was the next step. (Next someone will make "up" which will then get replaced with just pressing ENTER on an empty line! ;) )

Jokes aside, now is clean and easy. I appreciate their organizational willpower to make an elegant and simple command line tool. I suspect it's harder than it looks to keep things simple.

All of their examples use JavaScript and node.js, but they also support Docker, which means they support open source ASP.NET Core on .NET Core! But do they know they do? ;) Let's find out.

And more importantly, how easy is it? Can I take a site from concept to production in minutes? Darn tootin' I can.

First, make a quick ASP.NET Core app. I'll use the MVC template with Bootstrap.

C:\Users\scott\zeitdotnet>dotnet new mvc

Content generation time: 419.5337 ms
The template "ASP.NET Core Web App" created successfully.

I'll do a quick dotnet restore to get the packages for my project.

C:\Users\scott\zeitdotnet>dotnet restore

Restoring packages for C:\Users\scott\zeitdotnet\zeitdotnet.csproj...
Generating MSBuild file C:\Users\scott\zeitdotnet\obj\zeitdotnet.csproj.nuget.g.props.
Generating MSBuild file C:\Users\scott\zeitdotnet\obj\zeitdotnet.csproj.nuget.g.targets.
Writing lock file to disk. Path: C:\Users\scott\zeitdotnet\obj\project.assets.json
Restore completed in 2.93 sec for C:\Users\scott\zeitdotnet\zeitdotnet.csproj.

NuGet Config files used:
C:\Users\scott\AppData\Roaming\NuGet\NuGet.Config
C:\Program Files (x86)\NuGet\Config\Microsoft.VisualStudio.Offline.config

Feeds used:
https://api.nuget.org/v3/index.json
C:\LocalNuGet
C:\Program Files (x86)\Microsoft SDKs\NuGetPackages\

Now I need to add a Dockerfile. I'll make one in the root that looks like this:

FROM microsoft/aspnetcore

LABEL name="zeitdotnet"
ENTRYPOINT ["dotnet", "zeitdotnet.dll"]
ARG source=.
WORKDIR /app
EXPOSE 80
COPY $source .

Note that I could have ZEIT build my app for me if I used the aspnetcore Dockerfile that includes the .NET Core SDK, but that would not only make my deployment longer, it would also make my docker images a LOT larger. I want to include JUST the .NET Core runtime in my image, so I'll build and publish locally.

ZEIT now is going to need to see my Dockerfile, and since I want my app to include the binaries (I don't want to ship my source in the Docker image up to ZEIT) I need to mark my Dockerfile as "Content" and make sure it's copied to the publish folder when my app is built and published.

<ItemGroup>
  <None Remove="Dockerfile" />
</ItemGroup>
<ItemGroup>
  <Content Include="Dockerfile">
    <CopyToOutputDirectory>Always</CopyToOutputDirectory>
  </Content>
</ItemGroup>
I'll add this my project's csproj file. If I was using Visual Studio, this is the same as right clicking on the Properties of the Dockerfile, setting it to Content and then "Always Copy to Output Directory."

Now I'll just build and publish to a folder with one command:

C:\Users\scott\zeitdotnet>dotnet publish

Microsoft (R) Build Engine version 15.1.548.43366
Copyright (C) Microsoft Corporation. All rights reserved.

zeitdotnet -> C:\Users\scott\zeitdotnet\bin\Debug\netcoreapp1.1\zeitdotnet.dll

And finally, from the .\bin\Debug\netcoreapp1.1\ folder I run "now." (Note that I've installed now and signed up for their service, of course.)

C:\Users\scott\zeitdotnet\bin\Debug\netcoreapp1.1\publish>now

> Deploying ~\zeitdotnet\bin\Debug\netcoreapp1.1\publish
> Ready! https://zeitdotnet-gmhcxevqkf.now.sh (copied to clipboard) [3s]
> Upload [====================] 100% 0.0s
> Sync complete (196.18kB) [2s]
> Initializing…
> Building
> ▲ docker build
> ---> 035a0a1401c3
> Removing intermediate container 289b9e4ce5d9
> Step 6 : EXPOSE 80
> ---> Running in efb817308333
> ---> fbac2aaa3039
> Removing intermediate container efb817308333
> Step 7 : COPY $source .
> ---> ff009cfc48ea
> Removing intermediate container 8d650c1867cd
> Successfully built ff009cfc48ea
> ▲ Storing image
> ▲ Deploying image
> Deployment complete!

Now has put the generated URL in my clipboard (during deployment you'll get redirected to a lovely status page) and when it's deployed I can visit my live site. But, that URL is not what I want. I want to use a custom URL.

I can take one of my domains and set it up with ZEIT World's DNS but I like DNSimple (ref).

I can add my domain as an external one after adding a TXT record to my DNS to verify I own it. Then I setup a CNAME to point my subdomain to alias.zeit.co.

C:\Users\scott\Desktop\zeitdotnet>now alias https://zeitdotnet-gmhcxevqkf.now.sh http://zeitdotnet.hanselman.com

> zeitdotnet.hanselman.com is a custom domain.
> Verifying the DNS settings for zeitdotnet.hanselman.com (see https://zeit.world for help)
> Verification OK!
> Provisioning certificate for zeitdotnet.hanselman.com
> Success! Alias created:
https://zeitdotnet.hanselman.com now points to https://zeitdotnet-gmhcxevqkf.now.sh [copied to clipboard]

And that's it. It even has a nice SSL certificate that they applied for me. It doesn't terminate to SSL all the way into the docker container's Kestral web server, but for most things that aren't banking it'll be just fine.

All in all, a lovely experience. Here's my Hello World ASP.NE Core app running in ZEIT and deployed with now  at http://zeitdotnet.hanselman.com (if you are visiting this long after this was published, this sample MAY be gone.)

I am still learning about this (this whole exercise was about 30 total minutes and asking Glenn Condron a docker question) so I'm not clear how this would work in a large multi-container deployment, but as long as your site is immutable (don't write to the container's local disk!) ZEIT says it will scale your single containers. Perhaps docker-compose support is coming?


Sponsor: Did you know VSTS can integrate closely with Octopus Deploy? Join Damian Brady and Brian A. Randell as they show you how to automate deployments from VSTS to Octopus Deploy, and demo the new VSTS Octopus Deploy dashboard widget. Register now!



© 2017 Scott Hanselman. All rights reserved.
     

Three FREE Training Courses on ASP.NET Core from Microsoft Virtual Academy

This time last year we did a Microsoft Virtual Academy class on what was then called “ASP.NET 5.” It made sense to call it 5 since 5 > 4.6, right? But since then ASP.NET 5 has become .NET Core 1.0 and ASP.NET Core 1.0. It’s 1.0 because it’s smaller, newer, and different. As the .NET “full” framework marches on, on Windows, .NET Core is cross-platform and for the cloud.

Command line concepts like dnx, dnu, and dnvm have been unified into a single “dotnet” driver. You can download .NET Core at http://dot.net and along with http://code.visualstudio.com you can get a web site up and running in 10 minutes on Windows, Mac, or many flavors of Linux.

So, we’ve decided to update and refresh our Microsoft Virtual Academy. In fact, we’ve done three days of training. Introduction, Intermediate, and Cross-Platform and all three days are now available! We just released training for ASP.NET Core 1.0 Cross-Platform that shows Mac, Ubuntu, and Docker!

Head over to Microsoft Virtual Academy and watch our new, free “Introduction to ASP.NET Core 1.0.” It’s a great relaxed pace if you’ve been out of the game for a bit, or you’re a seasoned .NET “Full” developer who has avoided learning .NET Core thus far. If you don’t know the C# language yet, check out our online C# tutorial first, then watch the video.

Introduction to ASP.NET Core 1.0

Join experts Scott Hanselman and Maria Naggaga, and find out how to build .NET Core applications on any operating system. Bring your web development expertise and roll up your sleeves, for this first in a three-part series.

image

Intermediate ASP.NET Core 1.0

Want a deeper dive into ASP.NET Core 1.0? Build on what you learned in Introduction to ASP.NET Core 1.0, and explore this new technology even further, as Scott Hanselman, Jeff Fritz, and Rowan Miller offer an in-depth, intermediate-level look at ASP.NET Core 1.0.

Intermediate ASP.NET Core 1.0

ASP.NET Core 1.0 Cross-Platform

Ready to build and deploy ASP.NET Core 1.0 apps? Join experts Scott Hanselman, Maria Naggaga, and Glenn Condron, and see how to do just that using Mac and Linux. Revisit content from the Introduction to ASP.NET Core 1.0 course, but using a Mac and Linux.

image

Do us a favor when you watch these, rate them (5 stars!) and SHARE them on your social networks.

NOTE: There’s a LOT of quality free courseware for learning .NET Core and ASP.NET Core. We’ve put the best at http://asp.net/free-courses and I encourage you to check them out!

Hope you have as much fun with these courses as we had creating them!


Sponsor: Do you deploy the same application multiple times for each of your end customers? The team at Octopus have taken the pain out of multi-tenant deployments. Check out their latest 3.4 release


© 2016 Scott Hanselman. All rights reserved.
     

This time last year we did a Microsoft Virtual Academy class on what was then called "ASP.NET 5." It made sense to call it 5 since 5 > 4.6, right? But since then ASP.NET 5 has become .NET Core 1.0 and ASP.NET Core 1.0. It's 1.0 because it's smaller, newer, and different. As the .NET "full" framework marches on, on Windows, .NET Core is cross-platform and for the cloud.

Command line concepts like dnx, dnu, and dnvm have been unified into a single "dotnet" driver. You can download .NET Core at http://dot.net and along with http://code.visualstudio.com you can get a web site up and running in 10 minutes on Windows, Mac, or many flavors of Linux.

So, we've decided to update and refresh our Microsoft Virtual Academy. In fact, we've done three days of training. Introduction, Intermediate, and Cross-Platform and all three days are now available! We just released training for ASP.NET Core 1.0 Cross-Platform that shows Mac, Ubuntu, and Docker!

Head over to Microsoft Virtual Academy and watch our new, free "Introduction to ASP.NET Core 1.0." It's a great relaxed pace if you've been out of the game for a bit, or you're a seasoned .NET "Full" developer who has avoided learning .NET Core thus far. If you don't know the C# language yet, check out our online C# tutorial first, then watch the video.

Introduction to ASP.NET Core 1.0

Join experts Scott Hanselman and Maria Naggaga, and find out how to build .NET Core applications on any operating system. Bring your web development expertise and roll up your sleeves, for this first in a three-part series.

image

Intermediate ASP.NET Core 1.0

Want a deeper dive into ASP.NET Core 1.0? Build on what you learned in Introduction to ASP.NET Core 1.0, and explore this new technology even further, as Scott Hanselman, Jeff Fritz, and Rowan Miller offer an in-depth, intermediate-level look at ASP.NET Core 1.0.

Intermediate ASP.NET Core 1.0

ASP.NET Core 1.0 Cross-Platform

Ready to build and deploy ASP.NET Core 1.0 apps? Join experts Scott Hanselman, Maria Naggaga, and Glenn Condron, and see how to do just that using Mac and Linux. Revisit content from the Introduction to ASP.NET Core 1.0 course, but using a Mac and Linux.

image

Do us a favor when you watch these, rate them (5 stars!) and SHARE them on your social networks.

NOTE: There's a LOT of quality free courseware for learning .NET Core and ASP.NET Core. We've put the best at http://asp.net/free-courses and I encourage you to check them out!

Hope you have as much fun with these courses as we had creating them!


Sponsor: Do you deploy the same application multiple times for each of your end customers? The team at Octopus have taken the pain out of multi-tenant deployments. Check out their latest 3.4 release



© 2016 Scott Hanselman. All rights reserved.
     

Three FREE Training Courses on ASP.NET Core from Microsoft Virtual Academy

This time last year we did a Microsoft Virtual Academy class on what was then called “ASP.NET 5.” It made sense to call it 5 since 5 > 4.6, right? But since then ASP.NET 5 has become .NET Core 1.0 and ASP.NET Core 1.0. It’s 1.0 because it’s smaller, newer, and different. As the .NET “full” framework marches on, on Windows, .NET Core is cross-platform and for the cloud.

Command line concepts like dnx, dnu, and dnvm have been unified into a single “dotnet” driver. You can download .NET Core at http://dot.net and along with http://code.visualstudio.com you can get a web site up and running in 10 minutes on Windows, Mac, or many flavors of Linux.

So, we’ve decided to update and refresh our Microsoft Virtual Academy. In fact, we’ve done three days of training. Introduction, Intermediate, and Cross-Platform and all three days are now available! We just released training for ASP.NET Core 1.0 Cross-Platform that shows Mac, Ubuntu, and Docker!

Head over to Microsoft Virtual Academy and watch our new, free “Introduction to ASP.NET Core 1.0.” It’s a great relaxed pace if you’ve been out of the game for a bit, or you’re a seasoned .NET “Full” developer who has avoided learning .NET Core thus far. If you don’t know the C# language yet, check out our online C# tutorial first, then watch the video.

Introduction to ASP.NET Core 1.0

Join experts Scott Hanselman and Maria Naggaga, and find out how to build .NET Core applications on any operating system. Bring your web development expertise and roll up your sleeves, for this first in a three-part series.

image

Intermediate ASP.NET Core 1.0

Want a deeper dive into ASP.NET Core 1.0? Build on what you learned in Introduction to ASP.NET Core 1.0, and explore this new technology even further, as Scott Hanselman, Jeff Fritz, and Rowan Miller offer an in-depth, intermediate-level look at ASP.NET Core 1.0.

Intermediate ASP.NET Core 1.0

ASP.NET Core 1.0 Cross-Platform

Ready to build and deploy ASP.NET Core 1.0 apps? Join experts Scott Hanselman, Maria Naggaga, and Glenn Condron, and see how to do just that using Mac and Linux. Revisit content from the Introduction to ASP.NET Core 1.0 course, but using a Mac and Linux.

image

Do us a favor when you watch these, rate them (5 stars!) and SHARE them on your social networks.

NOTE: There’s a LOT of quality free courseware for learning .NET Core and ASP.NET Core. We’ve put the best at http://asp.net/free-courses and I encourage you to check them out!

Hope you have as much fun with these courses as we had creating them!


Sponsor: Do you deploy the same application multiple times for each of your end customers? The team at Octopus have taken the pain out of multi-tenant deployments. Check out their latest 3.4 release


© 2016 Scott Hanselman. All rights reserved.
     

This time last year we did a Microsoft Virtual Academy class on what was then called "ASP.NET 5." It made sense to call it 5 since 5 > 4.6, right? But since then ASP.NET 5 has become .NET Core 1.0 and ASP.NET Core 1.0. It's 1.0 because it's smaller, newer, and different. As the .NET "full" framework marches on, on Windows, .NET Core is cross-platform and for the cloud.

Command line concepts like dnx, dnu, and dnvm have been unified into a single "dotnet" driver. You can download .NET Core at http://dot.net and along with http://code.visualstudio.com you can get a web site up and running in 10 minutes on Windows, Mac, or many flavors of Linux.

So, we've decided to update and refresh our Microsoft Virtual Academy. In fact, we've done three days of training. Introduction, Intermediate, and Cross-Platform and all three days are now available! We just released training for ASP.NET Core 1.0 Cross-Platform that shows Mac, Ubuntu, and Docker!

Head over to Microsoft Virtual Academy and watch our new, free "Introduction to ASP.NET Core 1.0." It's a great relaxed pace if you've been out of the game for a bit, or you're a seasoned .NET "Full" developer who has avoided learning .NET Core thus far. If you don't know the C# language yet, check out our online C# tutorial first, then watch the video.

Introduction to ASP.NET Core 1.0

Join experts Scott Hanselman and Maria Naggaga, and find out how to build .NET Core applications on any operating system. Bring your web development expertise and roll up your sleeves, for this first in a three-part series.

image

Intermediate ASP.NET Core 1.0

Want a deeper dive into ASP.NET Core 1.0? Build on what you learned in Introduction to ASP.NET Core 1.0, and explore this new technology even further, as Scott Hanselman, Jeff Fritz, and Rowan Miller offer an in-depth, intermediate-level look at ASP.NET Core 1.0.

Intermediate ASP.NET Core 1.0

ASP.NET Core 1.0 Cross-Platform

Ready to build and deploy ASP.NET Core 1.0 apps? Join experts Scott Hanselman, Maria Naggaga, and Glenn Condron, and see how to do just that using Mac and Linux. Revisit content from the Introduction to ASP.NET Core 1.0 course, but using a Mac and Linux.

image

Do us a favor when you watch these, rate them (5 stars!) and SHARE them on your social networks.

NOTE: There's a LOT of quality free courseware for learning .NET Core and ASP.NET Core. We've put the best at http://asp.net/free-courses and I encourage you to check them out!

Hope you have as much fun with these courses as we had creating them!


Sponsor: Do you deploy the same application multiple times for each of your end customers? The team at Octopus have taken the pain out of multi-tenant deployments. Check out their latest 3.4 release



© 2016 Scott Hanselman. All rights reserved.
     

Free Intermediate ASP.NET Core 1.0 Training on Microsoft Virtual Academy

At the end of October I announced that Maria from my team and I published a Microsoft Virtual Academy on ASP.NET Core. This Free ASP.NET Core 1.0 Training is up on Microsoft Virtual Academy now for you to watch and enjoy! I hope you like it, we worked very hard to bring it to you.

Again, start with Introduction to ASP.NET Core 1.0, and explore this new technology even further in Intermediate ASP.NET Core 1.0.

Intermediate ASP.NET Core 1.0

Intermediate ASP.NET Core 1.0

We’ve just launched Day 2, the Intermediate day. If the first is 100 level, this is 200 level. In this day, Jeff Fritz and I build on what we learned with Maria in Day 1. We’re also joined by Rowan Miller and Maria later in the day as we explore topics like:

  • Tag Helpers
  • Authentication
  • Custom Middleware
  • Dependency Injection
  • Web APIs
  • Single Page Apps
  • Entity Framework Core and Database Access
  • Publishing and Deployment

In a few weeks (maybe sooner) we’ll publish Day 3 which we’ll do exclusively on Macs and Linux machines. We’ll talk about Cross-Platform concerns and Containers.

NOTE: There’s a LOT of quality free courseware for learning .NET Core and ASP.NET Core. We’ve put the best at http://asp.net/free-courses and I encourage you to check them out!

Also, please help me out by adding a few stars there under Ratings. We’re new. 😉


Sponsor: Do you deploy the same application multiple times for each of your end customers? The team at Octopus have taken the pain out of multi-tenant deployments. Check out their latest 3.4 release


© 2016 Scott Hanselman. All rights reserved.
     

At the end of October I announced that Maria from my team and I published a Microsoft Virtual Academy on ASP.NET Core. This Free ASP.NET Core 1.0 Training is up on Microsoft Virtual Academy now for you to watch and enjoy! I hope you like it, we worked very hard to bring it to you.

Again, start with Introduction to ASP.NET Core 1.0, and explore this new technology even further in Intermediate ASP.NET Core 1.0.

Intermediate ASP.NET Core 1.0

Intermediate ASP.NET Core 1.0

We've just launched Day 2, the Intermediate day. If the first is 100 level, this is 200 level. In this day, Jeff Fritz and I build on what we learned with Maria in Day 1. We're also joined by Rowan Miller and Maria later in the day as we explore topics like:

  • Tag Helpers
  • Authentication
  • Custom Middleware
  • Dependency Injection
  • Web APIs
  • Single Page Apps
  • Entity Framework Core and Database Access
  • Publishing and Deployment

In a few weeks (maybe sooner) we'll publish Day 3 which we'll do exclusively on Macs and Linux machines. We'll talk about Cross-Platform concerns and Containers.

NOTE: There's a LOT of quality free courseware for learning .NET Core and ASP.NET Core. We've put the best at http://asp.net/free-courses and I encourage you to check them out!

Also, please help me out by adding a few stars there under Ratings. We're new. ;)


Sponsor: Do you deploy the same application multiple times for each of your end customers? The team at Octopus have taken the pain out of multi-tenant deployments. Check out their latest 3.4 release


© 2016 Scott Hanselman. All rights reserved.
     

Exploring Wyam – a .NET Static Site Content Generator

It’s a bit of a renaissance out there when it comes to Static Site Generators. There’s Jekyll and GitBook, Hugo and Hexo. Middleman and Pelican, Brunch and Octopress. There’s dozens, if not hundreds of static site content generators, and “long tail is long.”

Wyam is a great .NET based open source static site generator

Static Generators a nice for sites that DO get updated with dynamic content, but just not updated every few minutes. That means a Static Site Generator can be great for documentation, blogs, your brochure-ware home page, product catalogs, resumes, and lots more. Why install WordPress when you don’t need to hit a database or generate HTML on every page view? Why not generate your site only when it changes?

I recently heard about a .NET Core-based open source generator called Wyam and wanted to check it out.

Wyam is a simple to use, highly modular, and extremely configurable static content generator that can be used to generate web sites, produce documentation, create ebooks, and much more.

Wyam is a module system with a pipeline that you can configure and chain processes together however you like. You can generate HTML from Markdown, from Razor, even XSLT2 – anything you like, really. Wyam also integrates nicely into your continuous build systems like Cake and others, so you can also get the Nuget Tools package for Wyam.

There’s a few ways to get Wyam but I downloaded the setup.exe from GitHub Releases. You can also just get a ZIP and download it to any folder. When I ran the setup.exe it flashed (I didn’t see a dialog, but it’s beta so I’ll chalk it up to that) and it installed to C:\Users\scott\AppData\Local\Wyam with what looked like the Squirrel installer from GitHub and Paul Betts.

Wyam has a number of nice features that .NET Folks will find useful.

Let’s see what I can do with http://wyam.io in just a few minutes!

Scaffolding a Blog

Wyam has a similar command line syntax as dotnet.exe and it uses “recipes” so I can say –recipe Blog and I’ll get:

C:\Users\scott\Desktop\wyamtest>wyam new --recipe Blog
Wyam version 0.14.1-beta

,@@@@@ /@\ @@@@@
@@@@@@ @@@@@| $@@@@@h
$@@@@@ ,@@@@@@@ g@@@@@P
]@@@@@M g@@@@@@@ g@@@@@P
$@@@@@ @@@@@@@@@ g@@@@@P
j@@@@@ g@@@@@@@@@p ,@@@@@@@
$@@@@@g@@@@@@@@B@@@@@@@@@@@P
`$@@@@@@@@@@@` ]@@@@@@@@@`
$@@@@@@@P` ?$@@@@@P
`^`` *P*`
**NEW**
Scaffold directory C:/Users/scott/Desktop/wyamtest/input does not exist and will be created
Installing NuGet packages
NuGet packages installed in 101813 ms
Recursively loading assemblies
Assemblies loaded in 2349 ms
Cataloging classes
Classes cataloged in 277 ms

One could imagine recipes for product catalogs, little league sites, etc. You can make your own custom recipes as well.

I’ll make a config.wyam file with this inside:

Settings.Host = "test.hanselman.com";
GlobalMetadata["Title"] = "Scott Hanselman";
GlobalMetadata["Description"] = "The personal wyam-made blog of Scott Hanselman";
GlobalMetadata["Intro"] = "Hi, welcome to my blog!";

Then I’ll run wyam with:

C:\Users\scott\Desktop\wyamtest>wyam -r Blog
Wyam version 0.14.1-beta
**BUILD**
Loading configuration from file:///C:/Users/scott/Desktop/wyamtest/config.wyam
Installing NuGet packages
NuGet packages installed in 30059 ms
Recursively loading assemblies
Assemblies loaded in 368 ms
Cataloging classes
Classes cataloged in 406 ms
Evaluating configuration script
Evaluated configuration script in 2594 ms
Root path:
file:///C:/Users/scott/Desktop/wyamtest
Input path(s):
file:///C:/Users/scott/.nuget/packages/Wyam.Blog.CleanBlog.0.14.1-beta/content
theme
input
Output path:
output
Cleaning output path output
Cleaned output directory
Executing 7 pipelines
Executing pipeline "Pages" (1/7) with 8 child module(s)
Executed pipeline "Pages" (1/7) in 221 ms resulting in 13 output document(s)
Executing pipeline "RawPosts" (2/7) with 7 child module(s)
Executed pipeline "RawPosts" (2/7) in 18 ms resulting in 1 output document(s)
Executing pipeline "Tags" (3/7) with 10 child module(s)
Executed pipeline "Tags" (3/7) in 1578 ms resulting in 1 output document(s)
Executing pipeline "Posts" (4/7) with 6 child module(s)
Executed pipeline "Posts" (4/7) in 620 ms resulting in 1 output document(s)
Executing pipeline "Feed" (5/7) with 3 child module(s)
Executed pipeline "Feed" (5/7) in 134 ms resulting in 2 output document(s)
Executing pipeline "RenderPages" (6/7) with 3 child module(s)
Executed pipeline "RenderPages" (6/7) in 333 ms resulting in 4 output document(s)
Executing pipeline "Resources" (7/7) with 1 child module(s)
Executed pipeline "Resources" (7/7) in 19 ms resulting in 14 output document(s)
Executed 7/7 pipelines in 2936 ms

I can also run it with -t for different themes, like “wyam -r Blog -t Phantom”:

Wyam supports themes

As with most Static Site Generators I can start with a markdown file like “first-post.md” and included name value pairs of metadata at the top:

Title: First Post
Published: 2016-01-01
Tags: Introduction
---
This is my first post!

If I’m working on my site a lot, I could run Wyam with the -w (WATCH) switch and then edit my posts in Visual Studio Code and Wyam will WATCH the input folder and automatically run over and over, regenerating the site each time I change the inputs! A nice little touch, indeed.

There’s a lot of cool examples at https://github.com/Wyamio/Wyam/tree/develop/examples that show you how to generate RSS, do pagination, use Razor but still generate statically, as well as mixing Razor for layouts and Markdown for posts.

The AdventureTime sample is fairly sophisticated (be sure to read the comments in the config.wyam for gotcha) example that includes a custom Pipeline, use of Yaml for front matter, and mixes markdown and Razor.

There’s also a ton of modules you can use to extend the build however you like. For example, you could have source images be large and then auto-generate thumbnails like this:

Pipelines.Add("Images",
ReadFiles("*").Where(x => x.Contains("images\\") && new[] { ".jpg", ".jpeg", ".gif", ".png"}.Contains(Path.GetExtension(x))),
Image()
.SetJpegQuality(100).Resize(400,209).SetSuffix("-thumb"),
WriteFiles("*")
);

There’s a TON of options. You could even use Excel as the source data for your site, generate CSVs from the Excel OOXML and then generate your site from those CSVs. Sounds crazy, but if you run a small business or non-profit you could quickly make a nice workflow for someone to take control of their own site!

GOTCHA: When generating a site locally your initial reaction may be to open the /output folder and open the index.html in your local browser. You MAY be disappointed with you use a static site generator. Often they generate absolute paths for CSS and Javascript so you’ll see a lousy version of your website locally. Either change your templates to generate relative paths OR use a staging site and look at your sites live online. Even better, use the Wyam “preview web server” and run Wyam with a “-p” argument and then visit http://localhost:5080 to see your actual site as it will show up online.

Wyam looks like a really interesting start to a great open source project. It’s got a lot of code, good docs, and it’s easy to get started. It also has a bunch of advanced features that would enable me to easily embed static site generation in a dynamic app. From the comments, it seems that Dave Glick is doing most of the work himself. I’m sure he’d appreciate you reaching out and helping with some issues.

As always, don’t just send a PR without talking and working with the maintainers of your favorite open source projects. Also, ask if they have issues that are friendly to http://www.firsttimersonly.com.


Sponsor: Big thanks to Redgate! Help your team write better, shareable SQL faster. Discover how your whole team can write better, shareable SQL faster with a free trial of SQL Prompt. Write, refactor and share SQL effortlessly, try it now!


© 2016 Scott Hanselman. All rights reserved.
     

It's a bit of a renaissance out there when it comes to Static Site Generators. There's Jekyll and GitBook, Hugo and Hexo. Middleman and Pelican, Brunch and Octopress. There's dozens, if not hundreds of static site content generators, and "long tail is long."

Wyam is a great .NET based open source static site generator

Static Generators a nice for sites that DO get updated with dynamic content, but just not updated every few minutes. That means a Static Site Generator can be great for documentation, blogs, your brochure-ware home page, product catalogs, resumes, and lots more. Why install WordPress when you don't need to hit a database or generate HTML on every page view? Why not generate your site only when it changes?

I recently heard about a .NET Core-based open source generator called Wyam and wanted to check it out.

Wyam is a simple to use, highly modular, and extremely configurable static content generator that can be used to generate web sites, produce documentation, create ebooks, and much more.

Wyam is a module system with a pipeline that you can configure and chain processes together however you like. You can generate HTML from Markdown, from Razor, even XSLT2 - anything you like, really. Wyam also integrates nicely into your continuous build systems like Cake and others, so you can also get the Nuget Tools package for Wyam.

There's a few ways to get Wyam but I downloaded the setup.exe from GitHub Releases. You can also just get a ZIP and download it to any folder. When I ran the setup.exe it flashed (I didn't see a dialog, but it's beta so I'll chalk it up to that) and it installed to C:\Users\scott\AppData\Local\Wyam with what looked like the Squirrel installer from GitHub and Paul Betts.

Wyam has a number of nice features that .NET Folks will find useful.

Let's see what I can do with http://wyam.io in just a few minutes!

Scaffolding a Blog

Wyam has a similar command line syntax as dotnet.exe and it uses "recipes" so I can say --recipe Blog and I'll get:

C:\Users\scott\Desktop\wyamtest>wyam new --recipe Blog

Wyam version 0.14.1-beta

,@@@@@ /@\ @@@@@
@@@@@@ @@@@@| $@@@@@h
$@@@@@ ,@@@@@@@ g@@@@@P
]@@@@@M g@@@@@@@ g@@@@@P
$@@@@@ @@@@@@@@@ g@@@@@P
j@@@@@ g@@@@@@@@@p ,@@@@@@@
$@@@@@g@@@@@@@@B@@@@@@@@@@@P
`$@@@@@@@@@@@` ]@@@@@@@@@`
$@@@@@@@P` ?$@@@@@P
`^`` *P*`
**NEW**
Scaffold directory C:/Users/scott/Desktop/wyamtest/input does not exist and will be created
Installing NuGet packages
NuGet packages installed in 101813 ms
Recursively loading assemblies
Assemblies loaded in 2349 ms
Cataloging classes
Classes cataloged in 277 ms

One could imagine recipes for product catalogs, little league sites, etc. You can make your own custom recipes as well.

I'll make a config.wyam file with this inside:

Settings.Host = "test.hanselman.com";

GlobalMetadata["Title"] = "Scott Hanselman";
GlobalMetadata["Description"] = "The personal wyam-made blog of Scott Hanselman";
GlobalMetadata["Intro"] = "Hi, welcome to my blog!";

Then I'll run wyam with:

C:\Users\scott\Desktop\wyamtest>wyam -r Blog

Wyam version 0.14.1-beta
**BUILD**
Loading configuration from file:///C:/Users/scott/Desktop/wyamtest/config.wyam
Installing NuGet packages
NuGet packages installed in 30059 ms
Recursively loading assemblies
Assemblies loaded in 368 ms
Cataloging classes
Classes cataloged in 406 ms
Evaluating configuration script
Evaluated configuration script in 2594 ms
Root path:
file:///C:/Users/scott/Desktop/wyamtest
Input path(s):
file:///C:/Users/scott/.nuget/packages/Wyam.Blog.CleanBlog.0.14.1-beta/content
theme
input
Output path:
output
Cleaning output path output
Cleaned output directory
Executing 7 pipelines
Executing pipeline "Pages" (1/7) with 8 child module(s)
Executed pipeline "Pages" (1/7) in 221 ms resulting in 13 output document(s)
Executing pipeline "RawPosts" (2/7) with 7 child module(s)
Executed pipeline "RawPosts" (2/7) in 18 ms resulting in 1 output document(s)
Executing pipeline "Tags" (3/7) with 10 child module(s)
Executed pipeline "Tags" (3/7) in 1578 ms resulting in 1 output document(s)
Executing pipeline "Posts" (4/7) with 6 child module(s)
Executed pipeline "Posts" (4/7) in 620 ms resulting in 1 output document(s)
Executing pipeline "Feed" (5/7) with 3 child module(s)
Executed pipeline "Feed" (5/7) in 134 ms resulting in 2 output document(s)
Executing pipeline "RenderPages" (6/7) with 3 child module(s)
Executed pipeline "RenderPages" (6/7) in 333 ms resulting in 4 output document(s)
Executing pipeline "Resources" (7/7) with 1 child module(s)
Executed pipeline "Resources" (7/7) in 19 ms resulting in 14 output document(s)
Executed 7/7 pipelines in 2936 ms

I can also run it with -t for different themes, like "wyam -r Blog -t Phantom":

Wyam supports themes

As with most Static Site Generators I can start with a markdown file like "first-post.md" and included name value pairs of metadata at the top:

Title: First Post

Published: 2016-01-01
Tags: Introduction
---
This is my first post!

If I'm working on my site a lot, I could run Wyam with the -w (WATCH) switch and then edit my posts in Visual Studio Code and Wyam will WATCH the input folder and automatically run over and over, regenerating the site each time I change the inputs! A nice little touch, indeed.

There's a lot of cool examples at https://github.com/Wyamio/Wyam/tree/develop/examples that show you how to generate RSS, do pagination, use Razor but still generate statically, as well as mixing Razor for layouts and Markdown for posts.

The AdventureTime sample is fairly sophisticated (be sure to read the comments in the config.wyam for gotcha) example that includes a custom Pipeline, use of Yaml for front matter, and mixes markdown and Razor.

There's also a ton of modules you can use to extend the build however you like. For example, you could have source images be large and then auto-generate thumbnails like this:

Pipelines.Add("Images",

ReadFiles("*").Where(x => x.Contains("images\\") && new[] { ".jpg", ".jpeg", ".gif", ".png"}.Contains(Path.GetExtension(x))),
Image()
.SetJpegQuality(100).Resize(400,209).SetSuffix("-thumb"),
WriteFiles("*")
);

There's a TON of options. You could even use Excel as the source data for your site, generate CSVs from the Excel OOXML and then generate your site from those CSVs. Sounds crazy, but if you run a small business or non-profit you could quickly make a nice workflow for someone to take control of their own site!

GOTCHA: When generating a site locally your initial reaction may be to open the /output folder and open the index.html in your local browser. You MAY be disappointed with you use a static site generator. Often they generate absolute paths for CSS and Javascript so you'll see a lousy version of your website locally. Either change your templates to generate relative paths OR use a staging site and look at your sites live online. Even better, use the Wyam "preview web server" and run Wyam with a "-p" argument and then visit http://localhost:5080 to see your actual site as it will show up online.

Wyam looks like a really interesting start to a great open source project. It's got a lot of code, good docs, and it's easy to get started. It also has a bunch of advanced features that would enable me to easily embed static site generation in a dynamic app. From the comments, it seems that Dave Glick is doing most of the work himself. I'm sure he'd appreciate you reaching out and helping with some issues.

As always, don't just send a PR without talking and working with the maintainers of your favorite open source projects. Also, ask if they have issues that are friendly to http://www.firsttimersonly.com.


Sponsor: Big thanks to Redgate! Help your team write better, shareable SQL faster. Discover how your whole team can write better, shareable SQL faster with a free trial of SQL Prompt. Write, refactor and share SQL effortlessly, try it now!


© 2016 Scott Hanselman. All rights reserved.
     

Exploring Wyam – a .NET Static Site Content Generator

It’s a bit of a renaissance out there when it comes to Static Site Generators. There’s Jekyll and GitBook, Hugo and Hexo. Middleman and Pelican, Brunch and Octopress. There’s dozens, if not hundreds of static site content generators, and “long tail is long.”

Wyam is a great .NET based open source static site generator

Static Generators a nice for sites that DO get updated with dynamic content, but just not updated every few minutes. That means a Static Site Generator can be great for documentation, blogs, your brochure-ware home page, product catalogs, resumes, and lots more. Why install WordPress when you don’t need to hit a database or generate HTML on every page view? Why not generate your site only when it changes?

I recently heard about a .NET Core-based open source generator called Wyam and wanted to check it out.

Wyam is a simple to use, highly modular, and extremely configurable static content generator that can be used to generate web sites, produce documentation, create ebooks, and much more.

Wyam is a module system with a pipeline that you can configure and chain processes together however you like. You can generate HTML from Markdown, from Razor, even XSLT2 – anything you like, really. Wyam also integrates nicely into your continuous build systems like Cake and others, so you can also get the Nuget Tools package for Wyam.

There’s a few ways to get Wyam but I downloaded the setup.exe from GitHub Releases. You can also just get a ZIP and download it to any folder. When I ran the setup.exe it flashed (I didn’t see a dialog, but it’s beta so I’ll chalk it up to that) and it installed to C:\Users\scott\AppData\Local\Wyam with what looked like the Squirrel installer from GitHub and Paul Betts.

Wyam has a number of nice features that .NET Folks will find useful.

Let’s see what I can do with http://wyam.io in just a few minutes!

Scaffolding a Blog

Wyam has a similar command line syntax as dotnet.exe and it uses “recipes” so I can say –recipe Blog and I’ll get:

C:\Users\scott\Desktop\wyamtest>wyam new --recipe Blog
Wyam version 0.14.1-beta

,@@@@@ /@\ @@@@@
@@@@@@ @@@@@| $@@@@@h
$@@@@@ ,@@@@@@@ g@@@@@P
]@@@@@M g@@@@@@@ g@@@@@P
$@@@@@ @@@@@@@@@ g@@@@@P
j@@@@@ g@@@@@@@@@p ,@@@@@@@
$@@@@@g@@@@@@@@B@@@@@@@@@@@P
`$@@@@@@@@@@@` ]@@@@@@@@@`
$@@@@@@@P` ?$@@@@@P
`^`` *P*`
**NEW**
Scaffold directory C:/Users/scott/Desktop/wyamtest/input does not exist and will be created
Installing NuGet packages
NuGet packages installed in 101813 ms
Recursively loading assemblies
Assemblies loaded in 2349 ms
Cataloging classes
Classes cataloged in 277 ms

One could imagine recipes for product catalogs, little league sites, etc. You can make your own custom recipes as well.

I’ll make a config.wyam file with this inside:

Settings.Host = "test.hanselman.com";
GlobalMetadata["Title"] = "Scott Hanselman";
GlobalMetadata["Description"] = "The personal wyam-made blog of Scott Hanselman";
GlobalMetadata["Intro"] = "Hi, welcome to my blog!";

Then I’ll run wyam with:

C:\Users\scott\Desktop\wyamtest>wyam -r Blog
Wyam version 0.14.1-beta
**BUILD**
Loading configuration from file:///C:/Users/scott/Desktop/wyamtest/config.wyam
Installing NuGet packages
NuGet packages installed in 30059 ms
Recursively loading assemblies
Assemblies loaded in 368 ms
Cataloging classes
Classes cataloged in 406 ms
Evaluating configuration script
Evaluated configuration script in 2594 ms
Root path:
file:///C:/Users/scott/Desktop/wyamtest
Input path(s):
file:///C:/Users/scott/.nuget/packages/Wyam.Blog.CleanBlog.0.14.1-beta/content
theme
input
Output path:
output
Cleaning output path output
Cleaned output directory
Executing 7 pipelines
Executing pipeline "Pages" (1/7) with 8 child module(s)
Executed pipeline "Pages" (1/7) in 221 ms resulting in 13 output document(s)
Executing pipeline "RawPosts" (2/7) with 7 child module(s)
Executed pipeline "RawPosts" (2/7) in 18 ms resulting in 1 output document(s)
Executing pipeline "Tags" (3/7) with 10 child module(s)
Executed pipeline "Tags" (3/7) in 1578 ms resulting in 1 output document(s)
Executing pipeline "Posts" (4/7) with 6 child module(s)
Executed pipeline "Posts" (4/7) in 620 ms resulting in 1 output document(s)
Executing pipeline "Feed" (5/7) with 3 child module(s)
Executed pipeline "Feed" (5/7) in 134 ms resulting in 2 output document(s)
Executing pipeline "RenderPages" (6/7) with 3 child module(s)
Executed pipeline "RenderPages" (6/7) in 333 ms resulting in 4 output document(s)
Executing pipeline "Resources" (7/7) with 1 child module(s)
Executed pipeline "Resources" (7/7) in 19 ms resulting in 14 output document(s)
Executed 7/7 pipelines in 2936 ms

I can also run it with -t for different themes, like “wyam -r Blog -t Phantom”:

Wyam supports themes

As with most Static Site Generators I can start with a markdown file like “first-post.md” and included name value pairs of metadata at the top:

Title: First Post
Published: 2016-01-01
Tags: Introduction
---
This is my first post!

If I’m working on my site a lot, I could run Wyam with the -w (WATCH) switch and then edit my posts in Visual Studio Code and Wyam will WATCH the input folder and automatically run over and over, regenerating the site each time I change the inputs! A nice little touch, indeed.

There’s a lot of cool examples at https://github.com/Wyamio/Wyam/tree/develop/examples that show you how to generate RSS, do pagination, use Razor but still generate statically, as well as mixing Razor for layouts and Markdown for posts.

The AdventureTime sample is fairly sophisticated (be sure to read the comments in the config.wyam for gotcha) example that includes a custom Pipeline, use of Yaml for front matter, and mixes markdown and Razor.

There’s also a ton of modules you can use to extend the build however you like. For example, you could have source images be large and then auto-generate thumbnails like this:

Pipelines.Add("Images",
ReadFiles("*").Where(x => x.Contains("images\\") && new[] { ".jpg", ".jpeg", ".gif", ".png"}.Contains(Path.GetExtension(x))),
Image()
.SetJpegQuality(100).Resize(400,209).SetSuffix("-thumb"),
WriteFiles("*")
);

There’s a TON of options. You could even use Excel as the source data for your site, generate CSVs from the Excel OOXML and then generate your site from those CSVs. Sounds crazy, but if you run a small business or non-profit you could quickly make a nice workflow for someone to take control of their own site!

GOTCHA: When generating a site locally your initial reaction may be to open the /output folder and open the index.html in your local browser. You MAY be disappointed with you use a static site generator. Often they generate absolute paths for CSS and Javascript so you’ll see a lousy version of your website locally. Either change your templates to generate relative paths OR use a staging site and look at your sites live online. Even better, use the Wyam “preview web server” and run Wyam with a “-p” argument and then visit http://localhost:5080 to see your actual site as it will show up online.

Wyam looks like a really interesting start to a great open source project. It’s got a lot of code, good docs, and it’s easy to get started. It also has a bunch of advanced features that would enable me to easily embed static site generation in a dynamic app. From the comments, it seems that Dave Glick is doing most of the work himself. I’m sure he’d appreciate you reaching out and helping with some issues.

As always, don’t just send a PR without talking and working with the maintainers of your favorite open source projects. Also, ask if they have issues that are friendly to http://www.firsttimersonly.com.


Sponsor: Big thanks to Redgate! Help your team write better, shareable SQL faster. Discover how your whole team can write better, shareable SQL faster with a free trial of SQL Prompt. Write, refactor and share SQL effortlessly, try it now!


© 2016 Scott Hanselman. All rights reserved.
     

It's a bit of a renaissance out there when it comes to Static Site Generators. There's Jekyll and GitBook, Hugo and Hexo. Middleman and Pelican, Brunch and Octopress. There's dozens, if not hundreds of static site content generators, and "long tail is long."

Wyam is a great .NET based open source static site generator

Static Generators a nice for sites that DO get updated with dynamic content, but just not updated every few minutes. That means a Static Site Generator can be great for documentation, blogs, your brochure-ware home page, product catalogs, resumes, and lots more. Why install WordPress when you don't need to hit a database or generate HTML on every page view? Why not generate your site only when it changes?

I recently heard about a .NET Core-based open source generator called Wyam and wanted to check it out.

Wyam is a simple to use, highly modular, and extremely configurable static content generator that can be used to generate web sites, produce documentation, create ebooks, and much more.

Wyam is a module system with a pipeline that you can configure and chain processes together however you like. You can generate HTML from Markdown, from Razor, even XSLT2 - anything you like, really. Wyam also integrates nicely into your continuous build systems like Cake and others, so you can also get the Nuget Tools package for Wyam.

There's a few ways to get Wyam but I downloaded the setup.exe from GitHub Releases. You can also just get a ZIP and download it to any folder. When I ran the setup.exe it flashed (I didn't see a dialog, but it's beta so I'll chalk it up to that) and it installed to C:\Users\scott\AppData\Local\Wyam with what looked like the Squirrel installer from GitHub and Paul Betts.

Wyam has a number of nice features that .NET Folks will find useful.

Let's see what I can do with http://wyam.io in just a few minutes!

Scaffolding a Blog

Wyam has a similar command line syntax as dotnet.exe and it uses "recipes" so I can say --recipe Blog and I'll get:

C:\Users\scott\Desktop\wyamtest>wyam new --recipe Blog

Wyam version 0.14.1-beta

,@@@@@ /@\ @@@@@
@@@@@@ @@@@@| $@@@@@h
$@@@@@ ,@@@@@@@ g@@@@@P
]@@@@@M g@@@@@@@ g@@@@@P
$@@@@@ @@@@@@@@@ g@@@@@P
j@@@@@ g@@@@@@@@@p ,@@@@@@@
$@@@@@g@@@@@@@@B@@@@@@@@@@@P
`$@@@@@@@@@@@` ]@@@@@@@@@`
$@@@@@@@P` ?$@@@@@P
`^`` *P*`
**NEW**
Scaffold directory C:/Users/scott/Desktop/wyamtest/input does not exist and will be created
Installing NuGet packages
NuGet packages installed in 101813 ms
Recursively loading assemblies
Assemblies loaded in 2349 ms
Cataloging classes
Classes cataloged in 277 ms

One could imagine recipes for product catalogs, little league sites, etc. You can make your own custom recipes as well.

I'll make a config.wyam file with this inside:

Settings.Host = "test.hanselman.com";

GlobalMetadata["Title"] = "Scott Hanselman";
GlobalMetadata["Description"] = "The personal wyam-made blog of Scott Hanselman";
GlobalMetadata["Intro"] = "Hi, welcome to my blog!";

Then I'll run wyam with:

C:\Users\scott\Desktop\wyamtest>wyam -r Blog

Wyam version 0.14.1-beta
**BUILD**
Loading configuration from file:///C:/Users/scott/Desktop/wyamtest/config.wyam
Installing NuGet packages
NuGet packages installed in 30059 ms
Recursively loading assemblies
Assemblies loaded in 368 ms
Cataloging classes
Classes cataloged in 406 ms
Evaluating configuration script
Evaluated configuration script in 2594 ms
Root path:
file:///C:/Users/scott/Desktop/wyamtest
Input path(s):
file:///C:/Users/scott/.nuget/packages/Wyam.Blog.CleanBlog.0.14.1-beta/content
theme
input
Output path:
output
Cleaning output path output
Cleaned output directory
Executing 7 pipelines
Executing pipeline "Pages" (1/7) with 8 child module(s)
Executed pipeline "Pages" (1/7) in 221 ms resulting in 13 output document(s)
Executing pipeline "RawPosts" (2/7) with 7 child module(s)
Executed pipeline "RawPosts" (2/7) in 18 ms resulting in 1 output document(s)
Executing pipeline "Tags" (3/7) with 10 child module(s)
Executed pipeline "Tags" (3/7) in 1578 ms resulting in 1 output document(s)
Executing pipeline "Posts" (4/7) with 6 child module(s)
Executed pipeline "Posts" (4/7) in 620 ms resulting in 1 output document(s)
Executing pipeline "Feed" (5/7) with 3 child module(s)
Executed pipeline "Feed" (5/7) in 134 ms resulting in 2 output document(s)
Executing pipeline "RenderPages" (6/7) with 3 child module(s)
Executed pipeline "RenderPages" (6/7) in 333 ms resulting in 4 output document(s)
Executing pipeline "Resources" (7/7) with 1 child module(s)
Executed pipeline "Resources" (7/7) in 19 ms resulting in 14 output document(s)
Executed 7/7 pipelines in 2936 ms

I can also run it with -t for different themes, like "wyam -r Blog -t Phantom":

Wyam supports themes

As with most Static Site Generators I can start with a markdown file like "first-post.md" and included name value pairs of metadata at the top:

Title: First Post

Published: 2016-01-01
Tags: Introduction
---
This is my first post!

If I'm working on my site a lot, I could run Wyam with the -w (WATCH) switch and then edit my posts in Visual Studio Code and Wyam will WATCH the input folder and automatically run over and over, regenerating the site each time I change the inputs! A nice little touch, indeed.

There's a lot of cool examples at https://github.com/Wyamio/Wyam/tree/develop/examples that show you how to generate RSS, do pagination, use Razor but still generate statically, as well as mixing Razor for layouts and Markdown for posts.

The AdventureTime sample is fairly sophisticated (be sure to read the comments in the config.wyam for gotcha) example that includes a custom Pipeline, use of Yaml for front matter, and mixes markdown and Razor.

There's also a ton of modules you can use to extend the build however you like. For example, you could have source images be large and then auto-generate thumbnails like this:

Pipelines.Add("Images",

ReadFiles("*").Where(x => x.Contains("images\\") && new[] { ".jpg", ".jpeg", ".gif", ".png"}.Contains(Path.GetExtension(x))),
Image()
.SetJpegQuality(100).Resize(400,209).SetSuffix("-thumb"),
WriteFiles("*")
);

There's a TON of options. You could even use Excel as the source data for your site, generate CSVs from the Excel OOXML and then generate your site from those CSVs. Sounds crazy, but if you run a small business or non-profit you could quickly make a nice workflow for someone to take control of their own site!

GOTCHA: When generating a site locally your initial reaction may be to open the /output folder and open the index.html in your local browser. You MAY be disappointed with you use a static site generator. Often they generate absolute paths for CSS and Javascript so you'll see a lousy version of your website locally. Either change your templates to generate relative paths OR use a staging site and look at your sites live online. Even better, use the Wyam "preview web server" and run Wyam with a "-p" argument and then visit http://localhost:5080 to see your actual site as it will show up online.

Wyam looks like a really interesting start to a great open source project. It's got a lot of code, good docs, and it's easy to get started. It also has a bunch of advanced features that would enable me to easily embed static site generation in a dynamic app. From the comments, it seems that Dave Glick is doing most of the work himself. I'm sure he'd appreciate you reaching out and helping with some issues.

As always, don't just send a PR without talking and working with the maintainers of your favorite open source projects. Also, ask if they have issues that are friendly to http://www.firsttimersonly.com.


Sponsor: Big thanks to Redgate! Help your team write better, shareable SQL faster. Discover how your whole team can write better, shareable SQL faster with a free trial of SQL Prompt. Write, refactor and share SQL effortlessly, try it now!


© 2016 Scott Hanselman. All rights reserved.
     

Publishing ASP.NET Core 1.1 applications to Azure using git deploy

I took an ASP.NET Core 1.0 application and updated its package references to ASP.NET 1.1 today. I also updated to my SDK to the Current (not the LTS – Long Term Support version). Everything worked great building and running locally, but then I made a new Web App in Azure and did a quick git deploy.

Deploying ASP.NET Core 1.1 to Azure

Basically:

c:\aspnetcore11app> azure site create "aspnetcore11test" --location "West US" --git
c:\aspnetcore11app> git add .
c:\aspnetcore11app> git commit -m "initial"
c:\aspnetcore11app> git push azure master

Then I watched the logs go by. You can watch them at the command line or from within the Azure Portal under “Log Stream.”

The deployment failed when Azure was building the app and got this error:

Build started 11/25/2016 6:51:54 AM.
2016-11-25T06:51:55         1>Project "D:\home\site\repository\aspnet1.1.xproj" on node 1 (Publish target(s)).
2016-11-25T06:51:55         1>D:\home\site\repository\aspnet1.1.xproj(7,3): error MSB4019: The imported project "D:\Program Files (x86)\dotnet\sdk\1.0.0-preview3-004056\Extensions\Microsoft\VisualStudio\v14.0\DotNet\Microsoft.DotNet.Props" was not found. Confirm that the path in the <Import> declaration is correct, and that the file exists on disk.
2016-11-25T06:51:55         1>Done Building Project "D:\home\site\repository\aspnet1.1.xproj" (Publish target(s)) -- FAILED.
2016-11-25T06:51:55    

See where it says “1.0.0-preview3-004056” in there? Looks like Azure Web Apps has some build that isn’t the one that I have. Theirs has the new csproj/msbuild stuff and I’m staying a few steps back waiting for things to bake.

Remember that unless you specify the SDK version, .NET Core will use whatever is the latest one on the box.

Well, what do I have locally?

C:\aspnetcore11app>dotnet --version
1.0.0-preview2-1-003177

OK, then that’s what I need to use so I’ll make a global.json at the root of my project, then move my code into a folder under “src” for example.

{
"projects": [ "src", "test" ],
"sdk": {
"version": "1.0.0-preview2-1-003177"
}
}

Here I’m “pinning” the same SDK version. This will tell Azure (or you, if I gave you the code) to use this SDK version when building.

Now I’ll redeploy with a git add, commit, and push. It works.

I think this should be easier, but I’m not sure how it should be easier. Does this mean that everyone should have a global.json with a preferred version? If you have no preferred version should Azure give a smarter error if it has an incompatible newer one?

The learning here for me is that not having a global.json basically says “*.*” to any cloud build servers and you’ll get whatever latest SDK they have. It could stop working any day.


Sponsor: Big thanks to Octopus Deploy! Do you deploy the same application multiple times for each of your end customers? The team at Octopus have taken the pain out of multi-tenant deployments. Check out their latest 3.4 release!


© 2016 Scott Hanselman. All rights reserved.
     

I took an ASP.NET Core 1.0 application and updated its package references to ASP.NET 1.1 today. I also updated to my SDK to the Current (not the LTS - Long Term Support version). Everything worked great building and running locally, but then I made a new Web App in Azure and did a quick git deploy.

Deploying ASP.NET Core 1.1 to Azure

Basically:

c:\aspnetcore11app> azure site create "aspnetcore11test" --location "West US" --git

c:\aspnetcore11app> git add .
c:\aspnetcore11app> git commit -m "initial"
c:\aspnetcore11app> git push azure master

Then I watched the logs go by. You can watch them at the command line or from within the Azure Portal under "Log Stream."

The deployment failed when Azure was building the app and got this error:

Build started 11/25/2016 6:51:54 AM.
2016-11-25T06:51:55         1>Project "D:\home\site\repository\aspnet1.1.xproj" on node 1 (Publish target(s)).
2016-11-25T06:51:55         1>D:\home\site\repository\aspnet1.1.xproj(7,3): error MSB4019: The imported project "D:\Program Files (x86)\dotnet\sdk\1.0.0-preview3-004056\Extensions\Microsoft\VisualStudio\v14.0\DotNet\Microsoft.DotNet.Props" was not found. Confirm that the path in the <Import> declaration is correct, and that the file exists on disk.
2016-11-25T06:51:55         1>Done Building Project "D:\home\site\repository\aspnet1.1.xproj" (Publish target(s)) -- FAILED.
2016-11-25T06:51:55    

See where it says "1.0.0-preview3-004056" in there? Looks like Azure Web Apps has some build that isn't the one that I have. Theirs has the new csproj/msbuild stuff and I'm staying a few steps back waiting for things to bake.

Remember that unless you specify the SDK version, .NET Core will use whatever is the latest one on the box.

Well, what do I have locally?

C:\aspnetcore11app>dotnet --version

1.0.0-preview2-1-003177

OK, then that's what I need to use so I'll make a global.json at the root of my project, then move my code into a folder under "src" for example.

{

"projects": [ "src", "test" ],
"sdk": {
"version": "1.0.0-preview2-1-003177"
}
}

Here I'm "pinning" the same SDK version. This will tell Azure (or you, if I gave you the code) to use this SDK version when building.

Now I'll redeploy with a git add, commit, and push. It works.

I think this should be easier, but I'm not sure how it should be easier. Does this mean that everyone should have a global.json with a preferred version? If you have no preferred version should Azure give a smarter error if it has an incompatible newer one?

The learning here for me is that not having a global.json basically says "*.*" to any cloud build servers and you'll get whatever latest SDK they have. It could stop working any day.


Sponsor: Big thanks to Octopus Deploy! Do you deploy the same application multiple times for each of your end customers? The team at Octopus have taken the pain out of multi-tenant deployments. Check out their latest 3.4 release!



© 2016 Scott Hanselman. All rights reserved.
     

Free ASP.NET Core 1.0 Training on Microsoft Virtual Academy

This time last year we did a Microsoft Virtual Academy class on what was then called “ASP.NET 5.” It made sense to call it 5 since 5 > 4.6, right? But since then ASP.NET 5 has become .NET Core 1.0 and ASP.NET Core 1.0. It’s 1.0 because it’s smaller, newer, and different. As the .NET “full” framework marches on, on Windows, .NET Core is cross-platform and for the cloud.

Command line concepts like dnx, dnu, and dnvm have been unified into a single “dotnet” driver. You can download .NET Core at http://dot.net and along with http://code.visualstudio.com you can get a web site up and running in 10 minutes on Windows, Mac, or many flavors of Linux.

So, we’ve decided to update and refresh our Microsoft Virtual Academy. In fact, we’ve done three days of training. Introduction, Intermediate, and Cross-Platform. The introduction day is out and it’s free! We’ll be releasing the new two days of training very soon.

NOTE: There’s a LOT of quality free courseware for learning .NET Core and ASP.NET Core. We’ve put the best at http://asp.net/free-courses and I encourage you to check them out!

Head over to Microsoft Virtual Academy and watch our new, free “Introduction to ASP.NET Core 1.0.” It’s a great relaxed pace if you’ve been out of the game for a bit, or you’re a seasoned .NET “Full” developer who has avoided learning .NET Core thus far. If you don’t know the C# language yet, check out our online C# tutorial first, then watch the video.

image

And help me out by adding a few stars there under Ratings. We’re new. 😉


Sponsor: Do you deploy the same application multiple times for each of your end customers? The team at Octopus have taken the pain out of multi-tenant deployments. Check out their latest 3.4 release!


© 2016 Scott Hanselman. All rights reserved.
     

This time last year we did a Microsoft Virtual Academy class on what was then called "ASP.NET 5." It made sense to call it 5 since 5 > 4.6, right? But since then ASP.NET 5 has become .NET Core 1.0 and ASP.NET Core 1.0. It's 1.0 because it's smaller, newer, and different. As the .NET "full" framework marches on, on Windows, .NET Core is cross-platform and for the cloud.

Command line concepts like dnx, dnu, and dnvm have been unified into a single "dotnet" driver. You can download .NET Core at http://dot.net and along with http://code.visualstudio.com you can get a web site up and running in 10 minutes on Windows, Mac, or many flavors of Linux.

So, we've decided to update and refresh our Microsoft Virtual Academy. In fact, we've done three days of training. Introduction, Intermediate, and Cross-Platform. The introduction day is out and it's free! We'll be releasing the new two days of training very soon.

NOTE: There's a LOT of quality free courseware for learning .NET Core and ASP.NET Core. We've put the best at http://asp.net/free-courses and I encourage you to check them out!

Head over to Microsoft Virtual Academy and watch our new, free "Introduction to ASP.NET Core 1.0." It's a great relaxed pace if you've been out of the game for a bit, or you're a seasoned .NET "Full" developer who has avoided learning .NET Core thus far. If you don't know the C# language yet, check out our online C# tutorial first, then watch the video.

image

And help me out by adding a few stars there under Ratings. We're new. ;)


Sponsor: Do you deploy the same application multiple times for each of your end customers? The team at Octopus have taken the pain out of multi-tenant deployments. Check out their latest 3.4 release!



© 2016 Scott Hanselman. All rights reserved.