├── .gitignore ├── content └── dotnet-template-azure-iot-edge-module │ └── CSharp │ ├── appsettings.Development.json │ ├── Program.cs │ ├── appsettings.json │ ├── Properties │ └── launchSettingsTEMPLATE..json │ ├── .gitignore │ ├── SampleModule.csproj │ ├── README.md │ ├── .template.config │ └── template.json │ └── ModuleBackgroundService.cs ├── CONTRIBUTING.md ├── Test ├── Test.csproj └── Test.cs ├── Microsoft.Azure.IoT.Edge.Module.nuspec ├── LICENSE ├── IotEdgeModuleTemplate.sln ├── SECURITY.md ├── CHANGELOG.md ├── azure-pipelines.yml └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | obj/ 3 | *.nupkg 4 | .vscode 5 | .vs/ -------------------------------------------------------------------------------- /content/dotnet-template-azure-iot-edge-module/CSharp/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.Hosting.Lifetime": "Information" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /content/dotnet-template-azure-iot-edge-module/CSharp/Program.cs: -------------------------------------------------------------------------------- 1 | using SampleModule; 2 | 3 | IHost host = Host.CreateDefaultBuilder(args) 4 | .ConfigureServices(services =>services.AddHostedService()) 5 | .Build(); 6 | 7 | host.Run(); -------------------------------------------------------------------------------- /content/dotnet-template-azure-iot-edge-module/CSharp/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.Hosting.Lifetime": "Information" 6 | }, 7 | "Console": { 8 | "FormatterName": "systemd" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /content/dotnet-template-azure-iot-edge-module/CSharp/Properties/launchSettingsTEMPLATE..json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "SampleModule": { 4 | "commandName": "Project", 5 | "environmentVariables": { 6 | "IotHubConnectionString": "" 7 | } 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Prerequisites 2 | * Latest [.NET Core SDK](https://www.microsoft.com/net/download/windows/) 3 | 4 | ## Setup 5 | 1. Fork and clone the repository 6 | 2. Install the .NET Core SDK 7 | 3. Install the template `dotnet new -i .\content\dotnet-template-azure-iot-edge-module\` 8 | 4. Use the template to scaffold `dotnet new aziotedgemodule -n ` 9 | 10 | ## Test 11 | Make sure you have run `dotnet test` before submitting Pull Requests. -------------------------------------------------------------------------------- /content/dotnet-template-azure-iot-edge-module/CSharp/.gitignore: -------------------------------------------------------------------------------- 1 | # .NET Core 2 | project.lock.json 3 | project.fragment.lock.json 4 | artifacts/ 5 | **/Properties/launchSettings.json 6 | 7 | *_i.c 8 | *_p.c 9 | *_i.h 10 | *.ilk 11 | *.meta 12 | *.obj 13 | *.pch 14 | *.pdb 15 | *.pgc 16 | *.pgd 17 | *.rsp 18 | *.sbr 19 | *.tlb 20 | *.tli 21 | *.tlh 22 | *.tmp 23 | *.tmp_proj 24 | *.log 25 | *.vspscc 26 | *.vssscc 27 | .builds 28 | *.pidb 29 | *.svclog 30 | *.scc 31 | .vs 32 | 33 | [Bb]in/ 34 | [Oo]bj/ -------------------------------------------------------------------------------- /content/dotnet-template-azure-iot-edge-module/CSharp/SampleModule.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net8.0 4 | enable 5 | enable 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Test/Test.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | all 13 | runtime; build; native; contentfiles; analyzers; buildtransitive 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /content/dotnet-template-azure-iot-edge-module/CSharp/README.md: -------------------------------------------------------------------------------- 1 | # IoT Edge Module Template for .NET 8 2 | 3 | This project leverages the latest dotnet features to create docker images without using a `Dockerfile`. See more details in https://github.com/dotnet/sdk-container-builds 4 | 5 | ## Create the docker image 6 | 7 | ``` 8 | dotnet publish --os linux --arch x64 -c Release /t:PublishContainer 9 | ``` 10 | 11 | ## Debug 12 | 13 | The `Properties\launchSettings.TEMPLATE.json` shows how to add an environment variable to debug. Rename the file to remove `TEMPLATE` and update the module connection string. 14 | 15 | ## Publish to a container registry 16 | 17 | The created image can be re-tagged to match your target container registry, or you build with the MSBuild property `ContainerRegistry` to produce the image for your registry 18 | -------------------------------------------------------------------------------- /Microsoft.Azure.IoT.Edge.Module.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Microsoft.Azure.IoT.Edge.Module 5 | 8.0.0 6 | Azure IoT Edge Module 7 | Microsoft 8 | microsoft, nugetazureiotedge 9 | Scaffolding tool to setup azure iot edge module development environment. 10 | false 11 | en-US 12 | http://github.com/azure/dotnet-template-azure-iot-edge-module/ 13 | https://github.com/Azure/dotnet-template-azure-iot-edge-module/blob/master/LICENSE 14 | http://go.microsoft.com/fwlink/?LinkID=288890 15 | © Microsoft Corporation. All rights reserved. 16 | azure iot edge dotnet template 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) .NET Foundation and Contributors 4 | 5 | All rights reserved. 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. -------------------------------------------------------------------------------- /IotEdgeModuleTemplate.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.8.34004.107 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleModule", "content\dotnet-template-azure-iot-edge-module\CSharp\SampleModule.csproj", "{076FF2B0-9939-48A5-A2A6-B2003637A744}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test", "Test\Test.csproj", "{2EA37308-0FBE-4C6D-B532-3671D33ED2BB}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {076FF2B0-9939-48A5-A2A6-B2003637A744}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {076FF2B0-9939-48A5-A2A6-B2003637A744}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {076FF2B0-9939-48A5-A2A6-B2003637A744}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {076FF2B0-9939-48A5-A2A6-B2003637A744}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {2EA37308-0FBE-4C6D-B532-3671D33ED2BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {2EA37308-0FBE-4C6D-B532-3671D33ED2BB}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {2EA37308-0FBE-4C6D-B532-3671D33ED2BB}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {2EA37308-0FBE-4C6D-B532-3671D33ED2BB}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {04A15845-D8E7-4F71-95F8-8B58F9FC5627} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /content/dotnet-template-azure-iot-edge-module/CSharp/.template.config/template.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/template", 3 | "author": "Microsoft", 4 | "classifications": [ 5 | "Console" 6 | ], 7 | "name": "Azure IoT Edge Module", 8 | "identity": "Azure.IoT.Edge.Module.CSharp", 9 | "groupIdentity": "Azure.IoT.Edge.Module", 10 | "shortName": "aziotedgemodule", 11 | "tags": { 12 | "language": "C#", 13 | "type": "project" 14 | }, 15 | "sourceName": "SampleModule", 16 | "preferNameDirectory": true, 17 | "primaryOutputs": [ 18 | { 19 | "path": "." 20 | } 21 | ], 22 | "symbols": { 23 | "skipRestore": { 24 | "type": "parameter", 25 | "datatype": "bool", 26 | "defaultValue": "false" 27 | }, 28 | "repository": { 29 | "type": "parameter", 30 | "defaultValue": "/", 31 | "replaces": "" 32 | } 33 | }, 34 | "sources": [ 35 | { 36 | "exclude": [ 37 | ".template.config/*", 38 | "bin/**/*", 39 | "obj/**/*" 40 | ] 41 | } 42 | ], 43 | "postActions": [ 44 | { 45 | "condition": "(!skipRestore)", 46 | "description": "Restore NuGet packages required by this project.", 47 | "manualInstructions": [ 48 | { 49 | "text": "Run 'dotnet restore'" 50 | } 51 | ], 52 | "actionId": "210D431B-A78B-4D2F-B762-4ED3E3EA9025", 53 | "continueOnError": true 54 | } 55 | ] 56 | } 57 | -------------------------------------------------------------------------------- /content/dotnet-template-azure-iot-edge-module/CSharp/ModuleBackgroundService.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Azure.Devices.Client; 2 | using Microsoft.Azure.Devices.Client.Transport.Mqtt; 3 | using System.Text; 4 | 5 | namespace SampleModule; 6 | 7 | internal class ModuleBackgroundService : BackgroundService 8 | { 9 | private int _counter; 10 | private ModuleClient? _moduleClient; 11 | private CancellationToken _cancellationToken; 12 | private readonly ILogger _logger; 13 | 14 | public ModuleBackgroundService(ILogger logger) => _logger = logger; 15 | 16 | protected override async Task ExecuteAsync(CancellationToken cancellationToken) 17 | { 18 | _cancellationToken = cancellationToken; 19 | MqttTransportSettings mqttSetting = new(TransportType.Mqtt_Tcp_Only); 20 | ITransportSettings[] settings = { mqttSetting }; 21 | 22 | // Open a connection to the Edge runtime 23 | _moduleClient = await ModuleClient.CreateFromEnvironmentAsync(settings); 24 | 25 | // Reconnect is not implented because we'll let docker restart the process when the connection is lost 26 | _moduleClient.SetConnectionStatusChangesHandler((status, reason) => 27 | _logger.LogWarning("Connection changed: Status: {status} Reason: {reason}", status, reason)); 28 | 29 | await _moduleClient.OpenAsync(cancellationToken); 30 | 31 | _logger.LogInformation("IoT Hub module client initialized."); 32 | 33 | // Register callback to be called when a message is received by the module 34 | await _moduleClient.SetInputMessageHandlerAsync("input1", ProcessMessageAsync, null, cancellationToken); 35 | } 36 | 37 | async Task ProcessMessageAsync(Message message, object userContext) 38 | { 39 | int counterValue = Interlocked.Increment(ref _counter); 40 | 41 | byte[] messageBytes = message.GetBytes(); 42 | string messageString = Encoding.UTF8.GetString(messageBytes); 43 | _logger.LogInformation("Received message: {counterValue}, Body: [{messageString}]", counterValue, messageString); 44 | 45 | if (!string.IsNullOrEmpty(messageString)) 46 | { 47 | using Message pipeMessage = new(messageBytes); 48 | foreach (KeyValuePair prop in message.Properties) 49 | { 50 | pipeMessage.Properties.Add(prop.Key, prop.Value); 51 | } 52 | await _moduleClient!.SendEventAsync("output1", pipeMessage, _cancellationToken); 53 | 54 | _logger.LogInformation("Received message sent"); 55 | } 56 | return MessageResponse.Completed; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Security 4 | 5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). 6 | 7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below. 8 | 9 | ## Reporting Security Issues 10 | 11 | **Please do not report security vulnerabilities through public GitHub issues.** 12 | 13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report). 14 | 15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). 16 | 17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). 18 | 19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: 20 | 21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) 22 | * Full paths of source file(s) related to the manifestation of the issue 23 | * The location of the affected source code (tag/branch/commit or direct URL) 24 | * Any special configuration required to reproduce the issue 25 | * Step-by-step instructions to reproduce the issue 26 | * Proof-of-concept or exploit code (if possible) 27 | * Impact of the issue, including how an attacker might exploit the issue 28 | 29 | This information will help us triage your report more quickly. 30 | 31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs. 32 | 33 | ## Preferred Languages 34 | 35 | We prefer all communications to be in English. 36 | 37 | ## Policy 38 | 39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd). 40 | 41 | 42 | -------------------------------------------------------------------------------- /Test/Test.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Linq; 6 | using Xunit; 7 | 8 | namespace Test 9 | { 10 | public class DotNetFixture : IDisposable 11 | { 12 | private static string RelativeTemplatePath = @"../../../../content/dotnet-template-azure-iot-edge-module/"; 13 | public DotNetFixture() 14 | { 15 | Process.Start("dotnet", "new -i " + RelativeTemplatePath).WaitForExit(); 16 | } 17 | 18 | public void Dispose() 19 | { 20 | Console.WriteLine("DotNetFixture: Disposing DotnetFixture"); 21 | 22 | // uninstall does not work now according to dotnet issue 23 | // issue link: https://github.com/dotnet/templating/issues/1226 24 | Process.Start("dotnet", "new -u " + RelativeTemplatePath).WaitForExit(); 25 | } 26 | } 27 | 28 | public class Test : IClassFixture 29 | { 30 | private DotNetFixture fixture; 31 | private const string CSharp = "C#"; 32 | private const string ArchLinux64 = "linux64"; 33 | private const string ArchWindowsNano = "windowsNano"; 34 | 35 | public Test(DotNetFixture fixture) 36 | { 37 | this.fixture = fixture; 38 | } 39 | 40 | private static string BeforeEach(string lang, string repository, bool skipRestore = false) 41 | { 42 | var scaffoldName = Path.GetRandomFileName().Replace(".", "").ToString(); 43 | var command = "new aziotedgemodule -n " + scaffoldName + " -lang " + lang + " -s " + skipRestore + " -r " + repository; 44 | Process.Start("dotnet", command).WaitForExit(); 45 | return scaffoldName; 46 | } 47 | 48 | [Theory] 49 | [InlineData(CSharp, true)] 50 | public void TestArchitecture(string lang, bool skipRestore) 51 | { 52 | var repository = "test.azurecr.io/test"; 53 | var scaffoldName = BeforeEach(lang, repository, skipRestore); 54 | var filesToCheck = new List { ".gitignore" }; 55 | 56 | if (skipRestore) 57 | { 58 | Assert.True(!Directory.Exists(Path.Combine(scaffoldName, "obj"))); 59 | } 60 | else 61 | { 62 | Assert.True(Directory.Exists(Path.Combine(scaffoldName, "obj"))); 63 | } 64 | 65 | if (lang == CSharp) 66 | { 67 | filesToCheck.AddRange(new List { "Program.cs", scaffoldName + ".csproj"}); 68 | } 69 | 70 | foreach (var file in filesToCheck) 71 | { 72 | Assert.True(File.Exists(Path.Combine(scaffoldName, file))); 73 | } 74 | 75 | Directory.Delete(scaffoldName, true); 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | [![Nuget](https://img.shields.io/nuget/v/Microsoft.Azure.IoT.Edge.Module.svg)](https://www.nuget.org/packages/Microsoft.Azure.IoT.Edge.Module/) 4 | 5 | 6 | ### 8.0.0 (2024-04-22) 7 | 8 | * [Updated] Updates template to target dotnet8 9 | 10 | ### 7.0.1 (2023-12-12) 11 | 12 | * [Updated] Updates template to target dotnet7 13 | 14 | ### 3.2.0 (2022-11-29) 15 | * [Updated] Update template to target dotnet6 16 | * [Updated] Template based on the Worker template, using BackgroundService base class 17 | * [Removed] F# Template 18 | 19 | ### 3.1.1 (2021-09-01) 20 | * [Updated] Updated the nuget template json to match the schema 21 | 22 | ### 3.1.0 (2020-04-07) 23 | * [Updated] Add arm64v8 and arm64v8.debug dockerfiles 24 | * [Updated] Upgrade .Net Core SDK to 3.1 25 | 26 | ### 2.7.0 (2019-12-20) 27 | * [Updated] Pull base image from Microsoft Container Registry 28 | 29 | ### 2.6.0 (2019-11-01) 30 | * [Added] Add .dockerignore to ignore bin and obj folder 31 | 32 | ### 2.5.0 (2019-03-05) 33 | * [Added] Add arm32v7.debug dockerfile 34 | 35 | ### 2.4.0 (2018-12-18) 36 | * [Updated] Update Windows base image for Windows 10 Version 1809 37 | * [Updated] Switch back to MQTT as default transport 38 | 39 | ### 2.3.0 (2018-10-29) 40 | * [Added] Add contextPath in module.json 41 | * [Added] Add AzureIoTEdgeModule project capability for csproj 42 | * [Updated] Use 1.* for Microsoft.Azure.Devices.Client 43 | 44 | ### 2.2.0 (2018-09-11) 45 | * [Updated] Update Microsoft.Azure.Devices.Client dependency to 1.18.0 for CSharp Template 46 | * [Updated] Update target framework to dotnet 2.1 47 | 48 | ### 2.1.0 (2018-07-26) 49 | * [Updated] Update the sample code to use amqp instead of mqtt 50 | 51 | ### 2.0.0 (2018-06-27) 52 | * [Updated] Update Microsoft.Azure.Devices.Client dependency to 1.17.0 for CSharp Template 53 | * [Updated] Update the sample code to use module client instead of device client 54 | 55 | ### 1.4.0 (2018-04-27) 56 | * [Updated] Use unprivileged user in amd64 and amd32v7 Dockerfiles 57 | 58 | ### 1.3.1 (2018-03-29) 59 | * [Updated] Cache vsdbg in first layer in Docker file to speed up docker image rebuild time. 60 | 61 | ### 1.3.0 (2018-03-27) 62 | * [Updated] Update folder structure to put docker files under project root 63 | * [Added] Add module.json file into project root 64 | 65 | ### 1.2.0 (2017-12-22) 66 | * [Fixed] Users get no hint with building Windows image against Docker Linux container 67 | * [Added] Add support to scaffold Azure IoT Edge Custom Module in FSharp 68 | 69 | ### 1.1.0 (2017-12-06) 70 | * [Fixed] Docker image hint in deployment.json is not clear enough 71 | 72 | ### 1.0.1 (2017-11-15) 73 | * [Added] Add support to scaffold Azure IoT Edge Custom Module in CSharp 74 | * [Added] Add support to scaffold only Azure IoT Edge deployment manifest 75 | * [Added] Add support to scaffold targeting only linux-x64 or windows-nano architecture 76 | * [Added] Add ready-to-use Azure IoT Edge Custom Module template 77 | -------------------------------------------------------------------------------- /azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | pr: 2 | - master 3 | trigger: 4 | branches: 5 | include: 6 | - master 7 | - refs/tags/v* 8 | 9 | pool: 10 | name: Azure-IoT-EdgeExperience-1ES-Hosted-Linux 11 | demands: 12 | - ImageOverride -equals MMSUbuntu18.04TLS 13 | 14 | steps: 15 | - task: UseDotNet@2 16 | displayName: 'Install .NET 8 SDK' 17 | inputs: 18 | version: 8.x 19 | 20 | - task: UseDotNet@2 21 | displayName: 'Install .NET 6 SDK' 22 | inputs: 23 | version: 6.x 24 | 25 | - task: NuGetToolInstaller@1 26 | inputs: 27 | versionSpec: 28 | 29 | - task: DotNetCoreCLI@2 30 | inputs: 31 | command: 'test' 32 | projects: 'Test/Test.csproj' 33 | 34 | - task: NuGetCommand@2 35 | inputs: 36 | command: 'pack' 37 | packagesToPack: 'Microsoft.Azure.IoT.Edge.Module.nuspec' 38 | packDestination: '$(Build.ArtifactStagingDirectory)' 39 | versioningScheme: 'off' 40 | 41 | - task: AzureArtifacts.manifest-generator-task.manifest-generator-task.ManifestGeneratorTask@0 42 | displayName: 'SBOM Generation Task' 43 | inputs: 44 | BuildDropPath: '$(Build.ArtifactStagingDirectory)' 45 | 46 | - task: Bash@3 47 | inputs: 48 | targetType: 'inline' 49 | script: | 50 | if [[ $(Build.SourceBranch) =~ ^refs/tags/v?[0-9]+\.[0-9]+\.[0-9]+$ ]]; then 51 | echo "##vso[task.setvariable variable=NUGET_PUBLISH_FLAG;]true" 52 | fi 53 | 54 | - task: UseDotNet@2 55 | displayName: 'Install .NET 2.1 SDK' 56 | inputs: 57 | version: '2.1.x' 58 | 59 | - task: EsrpCodeSigning@3 60 | inputs: 61 | ConnectedServiceName: 'template-aziotedge-pmc-v4-prod' 62 | FolderPath: '$(Build.ArtifactStagingDirectory)' 63 | Pattern: '*.nupkg' 64 | signConfigType: 'inlineSignParams' 65 | inlineOperation: | 66 | [ 67 | { 68 | "keyCode": "CP-401405", 69 | "operationSetCode": "NuGetSign", 70 | "parameters": [ ], 71 | "toolName": "sign", 72 | "toolVersion": "1.0" 73 | }, 74 | { 75 | "keyCode": "CP-401405", 76 | "operationSetCode": "NuGetVerify", 77 | "parameters": [ ], 78 | "toolName": "sign", 79 | "toolVersion": "1.0" 80 | } 81 | ] 82 | SessionTimeout: '20' 83 | MaxConcurrency: '50' 84 | MaxRetryAttempts: '5' 85 | 86 | - task: PowerShell@2 87 | condition: and(succeeded(), eq(variables['NUGET_PUBLISH_FLAG'], 'true')) 88 | inputs: 89 | targetType: 'inline' 90 | script: | 91 | $PACKAGEVERSION = $([xml]$(Get-Content Microsoft.Azure.IoT.Edge.Module.nuspec) | ForEach-Object package).metadata.version; 92 | Write-Host "##vso[task.setvariable variable=PACKAGEVERSION;]$PACKAGEVERSION" 93 | pwsh: true 94 | 95 | - task: PublishBuildArtifacts@1 96 | inputs: 97 | PathtoPublish: '$(Build.ArtifactStagingDirectory)' 98 | ArtifactName: 'drop' 99 | publishLocation: 'Container' 100 | 101 | - task: GitHubRelease@0 102 | condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/')) 103 | inputs: 104 | gitHubConnection: 'github.com_marianan' 105 | repositoryName: '$(Build.Repository.Name)' 106 | action: 'create' 107 | target: '$(Build.SourceVersion)' 108 | tagSource: 'manual' 109 | tag: '$(Build.SourceBranch)' 110 | releaseNotesSource: 'input' 111 | assets: '$(Build.ArtifactStagingDirectory)/*.nupkg' 112 | isPreRelease: true 113 | addChangeLog: false 114 | 115 | - task: Bash@3 116 | condition: and(succeeded(), eq(variables['NUGET_PUBLISH_FLAG'], 'true')) 117 | inputs: 118 | targetType: 'inline' 119 | script: | 120 | wget https://aka.ms/downloadazcopy-v10-linux 121 | tar -xvf downloadazcopy-v10-linux 122 | sudo cp ./azcopy_linux_amd64_*/azcopy /usr/bin/ 123 | 124 | - task: Bash@3 125 | displayName: 'Upload to Blob' 126 | condition: and(succeeded(), eq(variables['NUGET_PUBLISH_FLAG'], 'true')) 127 | inputs: 128 | targetType: 'inline' 129 | script: | 130 | export AZCOPY_SPA_CLIENT_SECRET=$(AZURESDKPARTNERDROPS-SERVICE-PRINCIPAL-KEY) 131 | azcopy login --service-principal --application-id $(APPID) 132 | azcopy copy "$(Build.ArtifactStagingDirectory)/Microsoft.Azure.IoT.Edge.Module.$(PACKAGEVERSION).nupkg" "https://azuresdkpartnerdrops.blob.core.windows.net/drops/azure-iot-edge-tools-templates-module/dotnet/$(PACKAGEVERSION)/Microsoft.Azure.IoT.Edge.Module.$(PACKAGEVERSION).nupkg" 133 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # dotnet-template-azure-iot-edge-module 2 | 3 | [![Nuget](https://img.shields.io/nuget/v/Microsoft.Azure.IoT.Edge.Module.svg)](https://www.nuget.org/packages/Microsoft.Azure.IoT.Edge.Module/) 4 | 5 | > dotnet template to do scaffolding for Azure IoT Edge module development. 6 | 7 | This README will introduce how to install the dotnet template and then create Azure IoT Edge module with the template step by step. 8 | The template will set up all necessary files for you to focus on functionality programming. 9 | 10 | ## Get Started 11 | 12 | Make sure you have [.NET 8.0 SDK](https://dotnet.microsoft.com/en-us/download/dotnet/8.0) installed. 13 | 14 | Run `dotnet` command to install the template: 15 | 16 | ```bash 17 | dotnet new install Microsoft.Azure.IoT.Edge.Module 18 | ``` 19 | You could find the template with short name *aziotedgemodule* in output: 20 | 21 | ``` 22 | Templates Short Name Language Tags 23 | --------------------------------------------------------------------------------------------------------------- 24 | Console Application console [C#], F#, VB Common/Console 25 | Class library classlib [C#], F#, VB Common/Library 26 | Azure IoT Edge Module aziotedgemodule [C#] Console 27 | Contoso Sample 06 sample06 [C#], F# Console 28 | Unit Test Project mstest [C#], F#, VB Test/MSTest 29 | xUnit Test Project xunit [C#], F#, VB Test/xUnit 30 | ASP.NET Core Empty web [C#] Web/Empty 31 | ASP.NET Core Web App (Model-View-Controller) mvc [C#], F# Web/MVC 32 | ASP.NET Core Web App (Razor Pages) razor [C#] Web/MVC/Razor Pages 33 | ASP.NET Core with Angular angular [C#] Web/MVC/SPA 34 | ASP.NET Core with React.js react [C#] Web/MVC/SPA 35 | ASP.NET Core with React.js and Redux reactredux [C#] Web/MVC/SPA 36 | ASP.NET Core Web API webapi [C#] Web/WebAPI 37 | Nuget Config nugetconfig Config 38 | Web Config webconfig Config 39 | Solution File sln Solution 40 | Razor Page page Web/ASP.NET 41 | MVC ViewImports viewimports Web/ASP.NET 42 | MVC ViewStart viewstart Web/ASP.NET 43 | ``` 44 | 45 | Check out the template details: 46 | ``` 47 | PS C:\> dotnet new aziotedgemodule --help 48 | Azure IoT Edge Module (C#) 49 | Author: Microsoft 50 | 51 | Usage: 52 | dotnet new aziotedgemodule [options] [template options] 53 | 54 | Options: 55 | -n, --name The name for the output being created. If no name is specified, the name of the output 56 | directory is used. 57 | -o, --output Location to place the generated output. 58 | --dry-run Displays a summary of what would happen if the given command line were run if it would result 59 | in a template creation. 60 | --force Forces content to be generated even if it would change existing files. 61 | --no-update-check Disables checking for the template package updates when instantiating a template. 62 | --project The project that should be used for context evaluation. 63 | -lang, --language Specifies the template language to instantiate. 64 | --type Specifies the template type to instantiate. 65 | 66 | Template options: 67 | -s, --skipRestore Type: bool 68 | Default: false 69 | -r, --repository Type: string 70 | Default: / 71 | 72 | ``` 73 | 74 | ``` 75 | dotnet new aziotedgemodule -o 76 | ``` 77 | 78 | 79 | ## Support 80 | The team monitors the issue section on regular basis and will try to assist with troubleshooting or questions related IoT Edge tools on a best effort basis. 81 | 82 | A few tips before opening an issue. Try to generalize the problem as much as possible. Examples include 83 | - Removing 3rd party components 84 | - Reproduce the issue with provided deployment manifest used 85 | - Specify whether issue is reproducible on physical device or simulated device or both 86 | Also, Consider consulting on the [docker docs channel](https://github.com/docker/docker.github.io) for general docker questions. 87 | --------------------------------------------------------------------------------