{"id":71,"date":"2025-01-03T18:56:56","date_gmt":"2025-01-03T18:56:56","guid":{"rendered":"https:\/\/www.ivanjurina.com\/?p=71"},"modified":"2025-01-03T19:09:21","modified_gmt":"2025-01-03T19:09:21","slug":"generating-net-web-api-microservices-from-template","status":"publish","type":"post","link":"https:\/\/www.ivanjurina.com\/index.php\/2025\/01\/03\/generating-net-web-api-microservices-from-template\/","title":{"rendered":"Generating .NET Web API Microservices from Template"},"content":{"rendered":"\n<p>Inspired by a colleague&#8217;s efficient approach to standardizing microservices, I created a bash script template generator for .NET Web API projects. The script creates a standardized architecture with controllers, services, repositories, and data models, setting up Entity Framework Core and Swagger UI in the process.<\/p>\n\n\n\n<p>With a single command:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">bashCopy<code>.\/create-api.sh ProjectName<\/code><\/pre>\n\n\n\n<p>You get a complete microservice structure following clean architecture principles. The template includes a layered design, basic User entity implementation, and an in-memory database for rapid development.<\/p>\n\n\n\n<p>This approach ensures all microservices follow the same structure, making maintenance and cross-service development more straightforward for team members.<\/p>\n\n\n\n<p>Find the template and documentation on GitHub: <a href=\"https:\/\/github.com\/ivanjurina\/dotnet-webapi-template-script\">dotnet-webapi-template-script<\/a><\/p>\n\n\n\n<p>Or here:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#!\/bin\/bash\n\nif &#91; -z \"$1\" ]\nthen\n    echo \"Please provide a project name\"\n    echo \"Usage: .\/create-api.sh ProjectName\"\n    exit 1\nfi\n\nPROJECT_NAME=$1\n\n# Create directory for solution\nmkdir $PROJECT_NAME\ncd $PROJECT_NAME\n\n# Create solution and project\ndotnet new sln -n $PROJECT_NAME\ndotnet new webapi -n $PROJECT_NAME\ndotnet sln add $PROJECT_NAME\/$PROJECT_NAME.csproj\n\ncd $PROJECT_NAME\n\n# Create directory structure\nmkdir -p Contracts\nmkdir -p Controllers\nmkdir -p DataModel\/Entities\nmkdir -p Repositories\nmkdir -p Services\n\n# Create files\necho \"namespace $PROJECT_NAME.Contracts\n{\n    public class UserDto\n    {\n        public int Id { get; set; }\n        public string Username { get; set; }\n        public string Email { get; set; }\n    }\n}\" &gt; Contracts\/UserDto.cs\n\necho \"namespace $PROJECT_NAME.DataModel.Entities\n{\n    public class User\n    {\n        public int Id { get; set; }\n        public string Username { get; set; }\n        public string Email { get; set; }\n    }\n}\" &gt; DataModel\/Entities\/User.cs\n\necho \"using Microsoft.EntityFrameworkCore;\nusing $PROJECT_NAME.DataModel.Entities;\n\nnamespace $PROJECT_NAME.DataModel\n{\n    public class ApplicationDbContext : DbContext\n    {\n        public ApplicationDbContext(DbContextOptions&lt;ApplicationDbContext&gt; options)\n            : base(options)\n        {\n            Database.EnsureCreated();\n        }\n\n        public DbSet&lt;User&gt; Users { get; set; }\n\n        protected override void OnModelCreating(ModelBuilder modelBuilder)\n        {\n            modelBuilder.Entity&lt;User&gt;().HasKey(u =&gt; u.Id);\n            \n            \/\/ Seed some data\n            modelBuilder.Entity&lt;User&gt;().HasData(\n                new User { Id = 1, Username = \\\"user1\\\", Email = \\\"user1@example.com\\\" },\n                new User { Id = 2, Username = \\\"user2\\\", Email = \\\"user2@example.com\\\" }\n            );\n        }\n    }\n}\" &gt; DataModel\/ApplicationDbContext.cs\n\necho \"using $PROJECT_NAME.DataModel;\nusing $PROJECT_NAME.DataModel.Entities;\n\nnamespace $PROJECT_NAME.Repositories\n{\n    public class UserRepository\n    {\n        private readonly ApplicationDbContext _context;\n\n        public UserRepository(ApplicationDbContext context)\n        {\n            _context = context;\n        }\n\n        public async Task&lt;User&gt; GetByIdAsync(int id)\n        {\n            return await _context.Users.FindAsync(id);\n        }\n    }\n}\" &gt; Repositories\/UserRepository.cs\n\necho \"using $PROJECT_NAME.Contracts;\nusing $PROJECT_NAME.Repositories;\n\nnamespace $PROJECT_NAME.Services\n{\n    public class UserService\n    {\n        private readonly UserRepository _userRepository;\n\n        public UserService(UserRepository userRepository)\n        {\n            _userRepository = userRepository;\n        }\n\n        public async Task&lt;UserDto&gt; GetUserByIdAsync(int id)\n        {\n            var user = await _userRepository.GetByIdAsync(id);\n            if (user == null) return null;\n            \n            return new UserDto \n            { \n                Id = user.Id,\n                Username = user.Username,\n                Email = user.Email\n            };\n        }\n    }\n}\" &gt; Services\/UserService.cs\n\necho \"using Microsoft.AspNetCore.Mvc;\nusing $PROJECT_NAME.Contracts;\nusing $PROJECT_NAME.Services;\n\nnamespace $PROJECT_NAME.Controllers\n{\n    &#91;ApiController]\n    &#91;Route(\\\"&#91;controller]\\\")]\n    public class UsersController : ControllerBase\n    {\n        private readonly UserService _userService;\n\n        public UsersController(UserService userService)\n        {\n            _userService = userService;\n        }\n\n        &#91;HttpGet(\\\"{id}\\\")]\n        public async Task&lt;ActionResult&lt;UserDto&gt;&gt; Get(int id)\n        {\n            var user = await _userService.GetUserByIdAsync(id);\n            if (user == null) return NotFound();\n            return user;\n        }\n    }\n}\" &gt; Controllers\/UsersController.cs\n\necho \"using Microsoft.EntityFrameworkCore;\nusing $PROJECT_NAME.DataModel;\nusing $PROJECT_NAME.Repositories;\nusing $PROJECT_NAME.Services;\n\nvar builder = WebApplication.CreateBuilder(args);\n\nbuilder.Services.AddControllers();\nbuilder.Services.AddEndpointsApiExplorer();\nbuilder.Services.AddSwaggerGen();\n\nbuilder.Services.AddDbContext&lt;ApplicationDbContext&gt;(options =&gt;\n    options.UseInMemoryDatabase(\\\"$PROJECT_NAME\\\"));\n\nbuilder.Services.AddScoped&lt;UserRepository&gt;();\nbuilder.Services.AddScoped&lt;UserService&gt;();\n\nvar app = builder.Build();\n\napp.UseSwagger();\napp.UseSwaggerUI(c =&gt;\n{\n    c.SwaggerEndpoint(\\\"\/swagger\/v1\/swagger.json\\\", \\\"$PROJECT_NAME API V1\\\");\n    c.RoutePrefix = string.Empty;\n});\n\napp.UseHttpsRedirection();\napp.UseAuthorization();\napp.MapControllers();\n\napp.Run();\" &gt; Program.cs\n\n# Add packages\ndotnet add package Microsoft.EntityFrameworkCore.InMemory\ndotnet add package Swashbuckle.AspNetCore\n\necho \"Solution and project $PROJECT_NAME created successfully! Run with 'dotnet run' and visit https:\/\/localhost:5001\/swagger\"<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Inspired by a colleague&#8217;s efficient approach to standardizing microservices, I created a bash script template generator for .NET Web API [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":72,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-71","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/www.ivanjurina.com\/index.php\/wp-json\/wp\/v2\/posts\/71","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.ivanjurina.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.ivanjurina.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.ivanjurina.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ivanjurina.com\/index.php\/wp-json\/wp\/v2\/comments?post=71"}],"version-history":[{"count":2,"href":"https:\/\/www.ivanjurina.com\/index.php\/wp-json\/wp\/v2\/posts\/71\/revisions"}],"predecessor-version":[{"id":74,"href":"https:\/\/www.ivanjurina.com\/index.php\/wp-json\/wp\/v2\/posts\/71\/revisions\/74"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.ivanjurina.com\/index.php\/wp-json\/wp\/v2\/media\/72"}],"wp:attachment":[{"href":"https:\/\/www.ivanjurina.com\/index.php\/wp-json\/wp\/v2\/media?parent=71"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ivanjurina.com\/index.php\/wp-json\/wp\/v2\/categories?post=71"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ivanjurina.com\/index.php\/wp-json\/wp\/v2\/tags?post=71"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}