Deploying ASP.NET Core along with a WebJob to App Service

Recently I have been working on a project in ASP.NET Core and DotVVM accompanied by a WebJob using Azure WebJob SDK. The idea behind publishing was that whenever I push code to the repository (VSTS in my case), App Service would pull the code, build it and deploy it automatically (this is achieved by setting up Continuous Deployment). This method works just great for ASP.NET Core application, however when accompanied by a WebJob, things weren’t as smooth as I was expecting them to be.

When you deploy a regular ASP.NET application with a WebJob, a special package is used in the main project (Microsoft.Web.WebJobs.Publish), which causes the WebJobs contained within the project to be built and put into their respective directories.

In the main application’s .csproj file, special targets are imported which in combination with the configuration file provide the necessary information for the build process to build the jobs and place them to correct WebJob directories.

However this method isn’t compatible with ASP.NET Core at the moment and while there is work in progress on enabling it to work together directly, you have to do it on your own.

Brief introduction to Git publishing to App Service

So what happens on the background when you deploy your code to App Service? When change is triggered and the repository is downloaded, Kudu (the engine behind App Service) tries to figure out what type of project you are deploying. It is done by various methods like checking for presence of .sln files and their content (you can look into it yourself here). Once the project type is figured out, a build script is assembled from templates (which can be found here). That build script is then run in the downloaded project and results in successful deployment (or fail :)).

Sample script, which gets generated for ASP.NET Core project can be found below:

deploy.cmd

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

@if"%SCM_TRACE_LEVEL%"NEQ"4"@echo off

::----------------------

::KUDU Deployment Script

::Version:1.0.12

::----------------------

::Prerequisites

::-------------

::Verify node.js installed

where node2>nul>nul

IF%ERRORLEVEL%NEQ0(

echo Missing node.js executable,please install node.js,ifalready installed make sure it can be reached from current environment.

Whenever you deploy a project, the generated build script is saved to D:\home\site\deployments\tools as deploy.cmd. From there you can download it and make modifications to it.

So like you probably understood from the statement above, the script can be completely customized. In order to do so, you have to let Kudu know that you will be using a custom deployment script by creating a file in the project root called .deployment and putting the following content into it (much more information about deployment scripts can be found in Kudu’s docs):

.deployment

1

2

[config]

command=deploy.cmd

Once done, you also need to create the deploy.cmd file in the root (or specify its path). You can start with copying the contents of the pregenerated file (D:\home\site\deployments\tools\deploy.cmd). After that, you have to change it, so that the WebJob project gets built and put into correct folder. It is very simple and quite common sense:

You just put this piece of code to your deploy.cmd, right after section 2.1 Build and publish, change the paths, names and done. Next you can do that for every other WebJob you have in your project.

The output path %DEPLOYMENT_TEMP%\App_Data\Jobs\Continuous\ applies to all cases when you are using the WebJobs SDK. If you need to deploy a triggered job, you would be using Triggered directory instead of Continuous (more info can be found in the docs).

I also found it quite handy to include run.cmd script with my WebJob to make sure that the correct executable is used when the job is run or triggered instead of relying on .exe detection.