| Comments

Yay! .NET Core 3.0 is now available!  You now are migrating your apps and want to get it to your favorite cloud hosting solution.  But they may not have it quite ready yet and you are still eager to deploy to production.  No worries, we have a solution for you.

As our documentation explains on different deployment models we have for .NET Core apps (simplified);

  • Framework-dependent (FDD): you are expecting the required framework to be where you are deploying…you are just deploying your code.
  • Self-contained (SCD) : you are packaging the required libraries and runtimes needed for your code to run, not expecting any shared runtime on your endpoint.
  • Framework-dependent executable (FDE): similar to FDD, but packaged as an executable, but expects a shared runtime to exist where you are deploying

Ideally your favorite cloud host provider will have your desired runtime available to you in their PaaS offerings.  But we’ve already established you are eager and want to get your new app there sooner.  No worries, then SCD is for you.  So how do you do that?  Here’s some helpful hints to get you going.

Producing the bits for SCD deployment is a part of the ‘publish’ pipeline to get the fully functional bits in all the right formats/places for you.  Here’s how you get it going in a few different environments.  First, though all of these require the understanding of runtime identifier values, or RID as we affectionately call it.  RIDs identify the target platform where the app will run.  You can see a list of all possible values in the RID catalog.  Understanding your value is key first.  For this, I’m going to deploy to Azure App Service for Linux and going to use linux-64 as my RID in all samples below.  This would vary based on what/where you are deploying.  I am also assuming in my samples that I’m executing these commands where they know the context of where my csproj file exists.  You can, of course, specify the path to your project files explicitly.

dotnet CLI

From the dotnet CLI you would first want to build and then publish using the RID.  Why build?  Well, it’s valuable to ensure your building against the RID that you will publish.  Catch any build errors in advance, ya know?  So from the CLI:

dotnet build -r linux-x64
dotnet publish --self-contained -r linux-x64

The key here is the ‘-r’ and ‘--self-contained’ arguments.  I’m using ‘-r’ but you can also use ‘--runtime’ for the long form.  What this will produce (unless you specified a different output argument) is a folder with your RID and then the publish folder within that.  So for me above in my project directory it would be in \bin\release\netcoreapp3.0\linux-x64\publish and everything in that \publish is what is needed for SCD. 

Using the CLI is the basic you can do.  Now it’s on your own to push the bits where they need to be, specify startup commands, etc.  But better, you can use some tools that build on top of this CLI goodness.

Azure DevOps 

Let’s first talk about DevOps.  You should be using this.  No let’s be real clear – USE CI/CD!!! “But I’m only myself as a developer!” So what, you should still use this.  I’m a believer now and it is so simple to set up and you then just worry about committing your code and your DevOps flow/pipelines take care of build/test/publish/release for you…it’s awesome.  With that out of the way, let’s show you how to do it in Azure DevOps. 

Honestly, if you haven’t gotten the hang of CI/CD you really should spend the time in one day and get your project configured.  Whether it is Azure DevOps, GitHub Actions, AppVeyor, Jenkins, whatever, you will be better off.  Azure DevOps is basically free and you’ll be happier once you’ve got it done.  You owe it to yourself.  But don’t worry, I explain the other ways below too.

In your pipeline you would add the .NET Core task and configure it for publish (assuming you also have the build/test).  This task basically calls the CLI so you put the same arguments as we just went through.  Here is my task in part one:

Screenshot of Azure DevOps pipeline showing publish arguments

Observe the ‘Zip Published Projects’ – I enabled this because this is what will be used for Azure App Service deploy next.

SPECIAL NOTE: When using the ‘Use .NET Core’ task in Azure DevOps, I recommend using the major.minor.x pattern to specify the version, so in this case 3.0.x.  This will ensure you get the latest patch updates for your specified major.minor version.  For self-contained this is smart since you are bringing the platform runtime with you and not getting auto-updates from the platform.

Then you want to deploy it, and for me to Azure App Service, I add the Azure App Service Deploy task and configure it using my published bits from the previous step.  Notice I’m still specifying the Runtime Stack value (even though at the time of this writing I need to use SCD) and specifying the startup command as the folder path to my app.

Screenshot of Azure DevOps pipeline showing deployment

And that’s it…now when I commit a change, these pipelines run and build/publish/deploy my app to my cloud provider without me having to worry if they have the runtime available yet or not.  You should be able to do this with Azure, AWS, wherever, and still use Azure DevOps to manage your workflow (or GitHub Actions).

Oh you’re a YAML person?  Sorry about that…here’s basically what it looks like using Azure DevOps tasks:

steps:
    # task for publish CLI command
    - task: [email protected]
    displayName: Publish
    inputs:
    command: publish
    publishWebProjects: True
    arguments: '--configuration $(BuildConfiguration) --output $(build.artifactstagingdirectory) --self-contained -r linux-x64'
    zipAfterPublish: True

    #task for deploy to Azure App Service
    - task: [email protected]
    displayName: 'Azure App Service Deploy: tacticview'
    inputs:
    azureSubscription: 'Azure-Microsoft'
    appType: webAppLinux
    WebAppName: tacticview
    deployToSlotOrASE: true
    ResourceGroupName: 'timheuer-linuxappsvc'
    SlotName: staging
    RuntimeStack: 'DOTNETCORE|3.0'
    StartupCommand: /home/site/wwwroot/TacticView
    

So there you have it for Azure DevOps!

GitHub Actions

For GitHub Actions, it is very similar to Azure DevOps using the CLI.  Here’s the relevant snippet for those steps (minus the deploy part):

name: ASP.NET Core CI

    on: [push]

    jobs:
    build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/[email protected]
    - name: Setup .NET Core
    uses: actions/[email protected]
    with:
    dotnet-version: 2.2.108
    - name: Build with dotnet
    run: dotnet build --configuration Release
    - name: Publish with dotnet
    run: dotnet build --configuration Release -r linux-x64 --self-contained

    

You would them want to add the deploy pieces in GitHub Actions and you can follow along with that from Abel’s blog post.

Visual Studio

I STRONGLY recommend you adopt a full CI/CD workflow for all your projects.  This has gotten so simple for most cases that it would be a shame not to do that.  But we do also provide means in Visual Studio tools to publish as well.  In your ASP.NET Core application if you right-click and choose Publish, you’ll see the options.  You first create a publish profile which walks you through where you want to publish.  I won’t show that part because it can be different depending on your selection.  But once complete you’ll be presented with this view:

Screenshot of Visual Studio showing deployment mode option

In that view you click on the area highlighted that is labeled Deployment Mode and will be presented with the dialog to change:

Screenshot of Visual Studio showing deployment mode and target runtime options

Once those two things are changed, then when you click Publish it will use the self-contained version of your app and push to whichever endpoint you chose.  And you are done for Visual Studio.

VS Code

What about if you use Visual Studio Code, VS Code?  With the latest release of the Azure App Service extension, .NET projects got better support for deploying to Azure App Service.  The default flow for this is simpler and doesn’t assume you want to deploy using SCD, so you have to do a bit more setup.  When you have a C# project in VS Code you should get prompted (and you should accept) the option to add assets to your project.

Screenshot of Visual Studio Code dialog requesting to add assets

This adds a .vscode foler with a tasks.json file in it that looks like this:

{
    "version": "2.0.0",
    "tasks": [
    {
    "label": "build",
    "command": "dotnet",
    "type": "process",
    "args": [
    "build",
    "${workspaceFolder}/testwebdeploy.csproj",
    "/property:GenerateFullPaths=true",
    "/consoleloggerparameters:NoSummary"
    ],
    "problemMatcher": "$msCompile"
    },
    {
    "label": "publish",
    "command": "dotnet",
    "type": "process",
    "args": [
    "publish",
    "${workspaceFolder}/testwebdeploy.csproj",
    "/property:GenerateFullPaths=true",
    "/consoleloggerparameters:NoSummary"
    ],
    "problemMatcher": "$msCompile"
    },
    {
    "label": "watch",
    "command": "dotnet",
    "type": "process",
    "args": [
    "watch",
    "run",
    "${workspaceFolder}/testwebdeploy.csproj",
    "/property:GenerateFullPaths=true",
    "/consoleloggerparameters:NoSummary"
    ],
    "problemMatcher": "$msCompile"
    }
    ]
    }
    

Note lines 17-24 which show the CLI commands we’ve already been talking about here.  So these you’d have to change to add arguments.  For brevity I’m only showing the modified publish lines here to what you would need:

{
    "label": "publish",
    "command": "dotnet",
    "type": "process",
    "args": [
    "publish",
    "${workspaceFolder}",
    "--configuration",
    "Release",
    "/property:GenerateFullPaths=true",
    "/consoleloggerparameters:NoSummary",
    "--runtime",
    "linux-x64",
    "--output",
    "bin/release/netcoreapp3.0/publish",
    "--self-contained",
    ],
    "problemMatcher": "$msCompile",
    "dependsOn": "clean"
    }
    

But that’s not it.  Remember when we talked about how the CLI publishes to a /netcoreapp3.0/<RID>/publish folder?  You’ll need to know that for the Azure App Service deploy.  Notice I added an explicit output argument here.  Why?  Well laziness for one.  The App Service Extension when you deploy will also add a settings.json file in your .vscode folder that looks like this:

{
    "appService.preDeployTask": "publish",
    "appService.deploySubpath": "bin/Release/netcoreapp3.0/publish"
    }
    

Notice the appService.deploySubpath argument?  Well I just didn’t want to change that to /linuxx64/publish.  Either way, you could have changed the argument here or in tasks.json but the bottom line is they need to match paths so the extension knows what you want to publish!  With these two complete, when you choose to publish using the extension you’ll be publishing a self-contained app to your provisioned Azure App Service instance.

I hope this helps get an idea of the different ways you can publish and how to use the SCD option.  Realistically you don’t need to use this in cloud environments which support your framework version.  In fact, as soon as they do support your version, go back in to your DevOps flow and remove the SCD argument and kick off a new release…no need to change code in your project or use your dev tools…another benefit of using DevOps – you can even do it from your phone!

Thanks for reading this far!

| Comments

I run my site on Subtext which has been around for 6+ years in some form (Subtext is a fork of .Text from way back).  As a part of the framework, there was initially built-in capabilities for tracking referral traffic.  On each view of the application, it would tick a referral note and you could see this in the statistics view of the admin pages.

As the standards (for lack of a better term) of tracking Page Views, Referrals, etc. moved to more proven/consistent reporting like Google Analytics (or other platforms) these type of platform tracking became worthless to me.  I never checked them because, frankly, I didn’t believe them anyway.  The problem is that Subtext is still tracking this information for me and taking up valuable little bytes in my database.

For Subtext, specifically, contributors have created scripts and maintenance pages to help manage some of these referrals that may not matter to folks and are just taking up space.  I am one of those people.  In my recent migration to SQL Azure I wanted to take advantage of 100MB pricing.  Surely my blog was not bigger than that.  To my surprise my blog was 650MB in size. 

What!?

I hadn’t run my database maintenance script in a while and decided to run that which purges the referral tracking.  It got down to 35MB.  Yeah baby.  In fact this topic has been discussed on a few times on the Subtext developer mailing list and even tracking as a issue for the project.  In the meantime I wanted to solve it myself for my blog.

In Subtext there is a stored proc that runs to get some of the entry tracking data called subtext_TrackEntry.  Within that proc is where it looks to see if it is a referral and adds that data.  I simply altered my proc on my end to be like this (keeping in the old function just so that I know what I did in case I needed to revert back):

   1: ALTER PROCEDURE [dbo].[subtext_TrackEntry]
   2: @EntryID INT, @BlogId INT, @Url NVARCHAR (255)=NULL, @IsWeb BIT
   3: WITH EXECUTE AS CALLER
   4: AS
   5: -- Removing the referral tracking
   6: -- if(@Url is not NULL AND @IsWeb = 1)
   7: -- BEGIN
   8: --    EXEC [dbo].[subtext_InsertReferral] @EntryID, @BlogId, @Url
   9: -- END
  10: EXEC [dbo].[subtext_InsertEntryViewCount] @EntryID, @BlogId, @IsWeb

Now I’m no longer tracking referrals because my analytics package is doing that for me already.  My database is now representative of things that matter to me, rather than things I just want to clean up.  If you are a Subtext user and never knew that referral logging was wasting your database (and you are using an analytic package to track that anyway), then I hope this helps! 

| Comments

One of the nice little additions to the data client services in Silverlight 2 is the removal of the need to drop out of Visual Studio to do some proxy code generation.  Prior to Silverlight 2 release, if you wanted to consume an ADO.NET Data Service (the artist formerly known as Astoria), you had to drop into a command line and execute something like:

   1: datasvcutil.exe /out:"MyDataService.cs" /uri:"http://foo.com/MyDataServiceEndpoint.svc"

While that isn’t difficult, it just wasn’t convenient as a developer productivity workflow.  I mean who wants to have to click and type more than you have to, right?  After all, ADO.NET Data Service (alright forget it, I’m calling it Astoria) endpoints are services right?  And Visual Studio does have this thing called Add Service Reference?

Alas, now we don’t have to use a command-line anymore.  With Silverlight 2 and Visual Studio tools, you now can use the service reference capability I’d like to show you a screenshot, but it’s not like the dialog window is any different than other service references, so I’ll save me and you the bandwidth.  But try it out.  Take your project, add a reference to your Astoria service.

| Comments

Well, I wish I was going to this event: ReMIX UK!  For one, it would be starting the day of my birthday and would be a great birthday treat!  Secondly, I would be able to meet up with my fellow escamoles chaps and maybe take in some local cuisine instead.

If you are in the UK, or for some reason really wanted to see the current value of the US dollar, make sure you head to ReMIX UK!  The lineup is pretty incredible when you look at it…here’s some Microsoft favorites:

I also saw on the agenda for the 2 day event that Tim Sneath and Jesse Liberty were listed, so it should be even richer (pun intented) content.  In addition it looks like some great stuff on the designer and creative strategy side of the business as well.  I’m sure there will be enough Silverlight stuff there to keep you going as well as WPF, ASP.NET and others!

By the way, I listed Dr. Neil above as one of my Microsoft favorites.  He’s actually one of our Regional Directors.  If you have never met Dr. Neil…do so.  He’s a great guy, very intelligent and fun to be around.  Ask him about how he manages developer teams and the ‘check-in’ metaphor for people, not just code.  Seriously, he would be a not miss either.

I wish I could travel across the pond for this one, but I’ll be hopefully approximately 25 meters under water in some area of Mexico celebrating with friends.  Have fun though!

| Comments

Stephen WaltherAre you poking around with the latest ASP.NET MVC (Model-View-Controller) bits?  If so, hopefully you are already aware of the resources available to you and the fact that Phil Haack is one of the program manager’s leading those efforts, and Scott Hanselman has been providing the community with some resources to jump start your learning.

Well, another member has just joined the ranks on the team I work for.  Stephen Walther, pictured here in his best book-cover pose ;-), has joined the team.  He actually joined earlier this month, but I’m just now getting around to welcoming him to our team and checking out the stuff he’s been doing.  He’s been on a great clip lately and I’ve been reading his latest 11 tips on ASP.NET MVC on his blog.  I’m really glad to have him on our team as I think we’ve got some great resources for ASP.NET, AJAX, MVC, Silverlight and Windows Client.

If you are messing around with the ASP.NET MVC framework, check out his site and subscribe.  We’ll be seeing a lot more of Stephen soon and I’m sure your ideas will be welcome to him as well!