diff --git a/src/Services/Contact/Contact.API/Contact.API.csproj b/src/Services/Contact/Contact.API/Contact.API.csproj new file mode 100644 index 000000000..4c767e233 --- /dev/null +++ b/src/Services/Contact/Contact.API/Contact.API.csproj @@ -0,0 +1,26 @@ + + + + net7.0 + enable + enable + 9457faa3-370a-4009-8020-10e7de0fbf17 + Linux + ..\..\.. + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + diff --git a/src/Services/Contact/Contact.API/Controllers/ContactController.cs b/src/Services/Contact/Contact.API/Controllers/ContactController.cs new file mode 100644 index 000000000..3585f0762 --- /dev/null +++ b/src/Services/Contact/Contact.API/Controllers/ContactController.cs @@ -0,0 +1,48 @@ +using Contact.API.Model; +using Contact.API.ViewModel; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; + +namespace Contact.API.Controllers; + +[Route("api/v1/[controller]")] +[ApiController] +public class ContactController : ControllerBase +{ + private readonly ApplicationDBContext _context; + + public ContactController(ApplicationDBContext context) + { + this._context = context ?? throw new ArgumentNullException(nameof(context)); + } + + [HttpPost] + [Route("CreateContects")] + public async Task PostQuery([FromBody]ContactViewModel model) + { + if(!ModelState.IsValid) + return BadRequest(ModelState); + + var result = await _context.Contacts.AddAsync(new Model.Contact + { + Name = model.Name, + Email = model.Email, + Message = model.Query ??= string.Empty + }); + return Created(string.Empty, result); + } + + [HttpGet] + [Route("GetContacts")] + public async Task> GetContacts() + { + var result = await _context.Contacts.Select(a => new ContactViewModel + { + Email = a.Email, + Name = a.Name, + Query = a.Message + }).ToListAsync(); + return result; + } +} diff --git a/src/Services/Contact/Contact.API/Migrations/20230724050259_initilasation.Designer.cs b/src/Services/Contact/Contact.API/Migrations/20230724050259_initilasation.Designer.cs new file mode 100644 index 000000000..b6cba9278 --- /dev/null +++ b/src/Services/Contact/Contact.API/Migrations/20230724050259_initilasation.Designer.cs @@ -0,0 +1,53 @@ +// +using System; +using Contact.API.Model; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Contact.API.Migrations +{ + [DbContext(typeof(ApplicationDBContext))] + [Migration("20230724050259_initilasation")] + partial class Initilasation + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Contact.API.Model.Contact", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Email") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Message") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("ID"); + + b.ToTable("Contacts"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Services/Contact/Contact.API/Migrations/20230724050259_initilasation.cs b/src/Services/Contact/Contact.API/Migrations/20230724050259_initilasation.cs new file mode 100644 index 000000000..dfed56faf --- /dev/null +++ b/src/Services/Contact/Contact.API/Migrations/20230724050259_initilasation.cs @@ -0,0 +1,36 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Contact.API.Migrations +{ + /// + public partial class Initilasation : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Contacts", + columns: table => new + { + ID = table.Column(type: "uniqueidentifier", nullable: false), + Name = table.Column(type: "nvarchar(max)", nullable: false), + Email = table.Column(type: "nvarchar(max)", nullable: false), + Message = table.Column(type: "nvarchar(max)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Contacts", x => x.ID); + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Contacts"); + } + } +} diff --git a/src/Services/Contact/Contact.API/Migrations/ApplicationDBContextModelSnapshot.cs b/src/Services/Contact/Contact.API/Migrations/ApplicationDBContextModelSnapshot.cs new file mode 100644 index 000000000..b197acf72 --- /dev/null +++ b/src/Services/Contact/Contact.API/Migrations/ApplicationDBContextModelSnapshot.cs @@ -0,0 +1,50 @@ +// +using System; +using Contact.API.Model; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Contact.API.Migrations +{ + [DbContext(typeof(ApplicationDBContext))] + partial class ApplicationDBContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Contact.API.Model.Contact", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Email") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Message") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("ID"); + + b.ToTable("Contacts"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Services/Contact/Contact.API/Model/ApplicationDBContext.cs b/src/Services/Contact/Contact.API/Model/ApplicationDBContext.cs new file mode 100644 index 000000000..75098c637 --- /dev/null +++ b/src/Services/Contact/Contact.API/Model/ApplicationDBContext.cs @@ -0,0 +1,30 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Design; + +namespace Contact.API.Model; + +public class ApplicationDBContext : DbContext +{ + public ApplicationDBContext(DbContextOptions option) : base(option) { } + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + base.Database.EnsureCreated(); + base.OnConfiguring(optionsBuilder); + } + + public DbSet Contacts { get; set; } + +} + + + +public class DbContextFactory : IDesignTimeDbContextFactory +{ + public ApplicationDBContext CreateDbContext(string[] args) + { + var optionsBuilder = new DbContextOptionsBuilder(); + optionsBuilder.UseSqlServer("Server=.;Initial Catalog=Microsoft.eShopOnContainers.Services.ContactDb;Integrated Security=true"); + + return new ApplicationDBContext(optionsBuilder.Options); + } +} diff --git a/src/Services/Contact/Contact.API/Model/Contact.cs b/src/Services/Contact/Contact.API/Model/Contact.cs new file mode 100644 index 000000000..142abbd9e --- /dev/null +++ b/src/Services/Contact/Contact.API/Model/Contact.cs @@ -0,0 +1,18 @@ +using System.ComponentModel.DataAnnotations; + +namespace Contact.API.Model; + +public class Contact +{ + [Key] + public Guid ID { get; set; } + + [Required] + public string Name { get; set; } + + [Required] + public string Email { get; set; } + + [Required] + public string Message { get; set; } +} diff --git a/src/Services/Contact/Contact.API/Program.cs b/src/Services/Contact/Contact.API/Program.cs new file mode 100644 index 000000000..2e342ef3a --- /dev/null +++ b/src/Services/Contact/Contact.API/Program.cs @@ -0,0 +1,29 @@ +using Contact.API.Model; + +var builder = WebApplication.CreateBuilder(args); + +// Add services to the container. + +builder.Services. + AddSqlServer("server=127.0.0.1,5433;Initial Catalog=Microsoft.eShopOnContainers.Services.ContactDb;User Id=sa;Password=Pass@word;Encrypt=false"); +builder.Services.AddControllers(); +// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(); + +var app = builder.Build(); + +// Configure the HTTP request pipeline. +if (app.Environment.IsDevelopment()) +{ + app.UseSwagger(); + app.UseSwaggerUI(); +} + +app.UseHttpsRedirection(); + +app.UseAuthorization(); + +app.MapControllers(); + +app.Run(); diff --git a/src/Services/Contact/Contact.API/Properties/launchSettings.json b/src/Services/Contact/Contact.API/Properties/launchSettings.json new file mode 100644 index 000000000..a7ebb7a40 --- /dev/null +++ b/src/Services/Contact/Contact.API/Properties/launchSettings.json @@ -0,0 +1,38 @@ +{ + "profiles": { + "Contact.API": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "dotnetRunMessages": true, + "applicationUrl": "https://localhost:7237;http://localhost:5118" + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "Docker": { + "commandName": "Docker", + "launchBrowser": true, + "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger", + "publishAllPorts": true, + "useSSL": true + } + }, + "$schema": "https://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:37689", + "sslPort": 44355 + } + } +} \ No newline at end of file diff --git a/src/Services/Contact/Contact.API/ViewModel/ContactViewModel.cs b/src/Services/Contact/Contact.API/ViewModel/ContactViewModel.cs new file mode 100644 index 000000000..c1ede24c5 --- /dev/null +++ b/src/Services/Contact/Contact.API/ViewModel/ContactViewModel.cs @@ -0,0 +1,17 @@ +using System.ComponentModel.DataAnnotations; + +namespace Contact.API.ViewModel; + +public class ContactViewModel +{ + [Required] + [StringLength(maximumLength: 100, MinimumLength = 3)] + public required string Name { get; set; } + + [Required] + [EmailAddress] + public required string Email { get; set; } + + [StringLength(1000)] + public string? Query { get; set; } +} diff --git a/src/Services/Contact/Contact.API/appsettings.Development.json b/src/Services/Contact/Contact.API/appsettings.Development.json new file mode 100644 index 000000000..0c208ae91 --- /dev/null +++ b/src/Services/Contact/Contact.API/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/src/Services/Contact/Contact.API/appsettings.json b/src/Services/Contact/Contact.API/appsettings.json new file mode 100644 index 000000000..10f68b8c8 --- /dev/null +++ b/src/Services/Contact/Contact.API/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +}