diff --git a/Domain/AggregateModel/AppAggregate/IAppRepository.cs b/Domain/AggregateModel/AppAggregate/IAppRepository.cs index 93a614a..e245177 100644 --- a/Domain/AggregateModel/AppAggregate/IAppRepository.cs +++ b/Domain/AggregateModel/AppAggregate/IAppRepository.cs @@ -9,7 +9,7 @@ namespace Domain.AggregateModel.AppAggregate { public interface IAppRepository:IRepository { - void Add(App app); + App Add(App app); Task GetAsync(int id); } } diff --git a/Domain/AggregateModel/LinkAggregate/ILinkRepository.cs b/Domain/AggregateModel/LinkAggregate/ILinkRepository.cs index f265131..cf41ce1 100644 --- a/Domain/AggregateModel/LinkAggregate/ILinkRepository.cs +++ b/Domain/AggregateModel/LinkAggregate/ILinkRepository.cs @@ -9,7 +9,7 @@ namespace Domain.AggregateModel.LinkAggregate { public interface ILinkRepository:IRepository { - void Add(Link link); + Link Add(Link link); Task GetAsync(string shortCode); } diff --git a/Domain/Domain.csproj b/Domain/Domain.csproj index ca8eba3..27b30d8 100644 --- a/Domain/Domain.csproj +++ b/Domain/Domain.csproj @@ -9,9 +9,4 @@ - - - - - diff --git a/Domain/Events/AppBaseUrlUpdatedDomainEvent.cs b/Domain/Events/AppBaseUrlUpdatedDomainEvent.cs new file mode 100644 index 0000000..969aa94 --- /dev/null +++ b/Domain/Events/AppBaseUrlUpdatedDomainEvent.cs @@ -0,0 +1,21 @@ +using Domain.AggregateModel.AppAggregate; +using MediatR; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Domain.Events +{ + //更新了基础地址 + public class AppBaseUrlUpdatedDomainEvent: INotification + { + public App App { get; set; } + public string OldBaseUrl { get; set; } + public AppBaseUrlUpdatedDomainEvent(App app,string oldBaseUrl) { + App = app; + OldBaseUrl = oldBaseUrl; + } + } +} diff --git a/Domain/Events/LinkCreatedDomainEvent.cs b/Domain/Events/LinkCreatedDomainEvent.cs new file mode 100644 index 0000000..5dd4a3b --- /dev/null +++ b/Domain/Events/LinkCreatedDomainEvent.cs @@ -0,0 +1,21 @@ +using Domain.AggregateModel.LinkAggregate; +using MediatR; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Domain.Events +{ + //短链接生成通知 + public class LinkCreatedDomainEvent:INotification + { + public Link Link { get; set; } + + public LinkCreatedDomainEvent(Link link) + { + Link = link; + } + } +} diff --git a/Domain/Exceptions/DomainException.cs b/Domain/Exceptions/DomainException.cs new file mode 100644 index 0000000..191ec12 --- /dev/null +++ b/Domain/Exceptions/DomainException.cs @@ -0,0 +1,13 @@ +using System; + +namespace Domain.Exceptions +{ + public class DomainException : Exception + { + public DomainException(string message) : base(message) + { } + + public DomainException(string message, Exception innerException) : base(message, innerException) + { } + } +} \ No newline at end of file diff --git a/Infrastructure/EntityConfigurations/LinkEntityTypeConfiguration.cs b/Infrastructure/EntityConfigurations/LinkEntityTypeConfiguration.cs index 2887e0c..b62ccd9 100644 --- a/Infrastructure/EntityConfigurations/LinkEntityTypeConfiguration.cs +++ b/Infrastructure/EntityConfigurations/LinkEntityTypeConfiguration.cs @@ -14,9 +14,10 @@ namespace Infrastructure.EntityConfigurations public void Configure(EntityTypeBuilder builder) { builder.ToTable("Link"); - builder.HasKey(l => l.Id); - builder.HasIndex(l => l.ShortCode).IsUnique(); builder.Ignore(l => l.DomainEvents); + builder.HasIndex(l => l.ShortCode).IsUnique(); + builder.HasKey(l => l.Id); + builder.Property(l => l.Id).ValueGeneratedOnAdd().IsRequired(); builder.Property(l => l.AppId).IsRequired(); builder.Property(l => l.ShortCode).HasMaxLength(11); } diff --git a/Infrastructure/Repositories/AppRepository.cs b/Infrastructure/Repositories/AppRepository.cs index fe747db..01a57fc 100644 --- a/Infrastructure/Repositories/AppRepository.cs +++ b/Infrastructure/Repositories/AppRepository.cs @@ -1,5 +1,6 @@ using Domain.AggregateModel.AppAggregate; using Domain.SeedWork; +using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using System.Linq; @@ -10,16 +11,31 @@ namespace Infrastructure.Repositories { public class AppRepository : IAppRepository { - public IUnitOfWork UnitOfWork => throw new NotImplementedException(); + private readonly AppDbContext dbContext; - public void Add(App app) + public AppRepository(AppDbContext dbContext) { - throw new NotImplementedException(); + this.dbContext = dbContext; } - public Task GetAsync(int id) + public IUnitOfWork UnitOfWork => dbContext; + + public App Add(App app) { - throw new NotImplementedException(); + if (app.IsTransient()) + { + return dbContext.Apps.Add(app).Entity; + } + else + { + return app; + } + } + + public async Task GetAsync(int id) + { + var app = await dbContext.Apps.Where(a => a.Id == id).SingleOrDefaultAsync(); + return app; } } } diff --git a/Infrastructure/Repositories/LinkRepository.cs b/Infrastructure/Repositories/LinkRepository.cs index c899e2b..2d8d62e 100644 --- a/Infrastructure/Repositories/LinkRepository.cs +++ b/Infrastructure/Repositories/LinkRepository.cs @@ -1,5 +1,6 @@ using Domain.AggregateModel.LinkAggregate; using Domain.SeedWork; +using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using System.Linq; @@ -10,16 +11,33 @@ namespace Infrastructure.Repositories { public class LinkRepository : ILinkRepository { - public IUnitOfWork UnitOfWork => throw new NotImplementedException(); + private AppDbContext dbContext; - public void Add(Link link) + public LinkRepository(AppDbContext dbContext) { - throw new NotImplementedException(); + this.dbContext = dbContext; } - public Task GetAsync(string shortCode) + public IUnitOfWork UnitOfWork => dbContext; + + public Link Add(Link link) { - throw new NotImplementedException(); + if (link.IsTransient()) + { + return dbContext.Links.Add(link).Entity; + } + else + { + return link; + } + } + + public async Task GetAsync(string shortCode) + { + var link = await dbContext.Links + .Where(l => l.ShortCode==shortCode) + .SingleOrDefaultAsync(); + return link; } } } diff --git a/QRCodeService.sln b/QRCodeService.sln index b34abeb..84ecdb0 100644 --- a/QRCodeService.sln +++ b/QRCodeService.sln @@ -11,6 +11,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Infrastructure", "Infrastru EndProject Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "Docker\docker-compose.dcproj", "{67E556AA-3E56-4B78-9521-6A5ABED7EEEA}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{F059136F-024F-4DB1-B4E0-FE7C31BC27E4}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/QRCodeService/Application/Behaviors/ValidatorBehavior.cs b/QRCodeService/Application/Behaviors/ValidatorBehavior.cs index ef2a90b..362e24d 100644 --- a/QRCodeService/Application/Behaviors/ValidatorBehavior.cs +++ b/QRCodeService/Application/Behaviors/ValidatorBehavior.cs @@ -1,4 +1,5 @@ -using FluentValidation; +using Domain.Exceptions; +using FluentValidation; using MediatR; using Microsoft.Extensions.Logging; using QRCodeService.Extensions; @@ -11,11 +12,11 @@ namespace QRCodeService.Application.Behaviors public class ValidatorBehavior : IPipelineBehavior { private readonly ILogger> _logger; - private readonly IValidator[] _validators; + private readonly IValidator _validator; - public ValidatorBehavior(IValidator[] validators, ILogger> logger) + public ValidatorBehavior(IValidator validator, ILogger> logger) { - _validators = validators; + _validator = validator; _logger = logger; } @@ -25,18 +26,14 @@ namespace QRCodeService.Application.Behaviors _logger.LogInformation("----- Validating command {CommandType}", typeName); - var failures = _validators - .Select(v => v.Validate(request)) - .SelectMany(result => result.Errors) - .Where(error => error != null) - .ToList(); + var failures = _validator.Validate(request).Errors; if (failures.Any()) { _logger.LogWarning("Validation errors - {CommandType} - Command: {@Command} - Errors: {@ValidationErrors}", typeName, request, failures); - //throw new OrderingDomainException( - // $"Command Validation Errors for type {typeof(TRequest).Name}", new ValidationException("Validation exception", failures)); + throw new DomainException( + $"Command Validation Errors for type {typeof(TRequest).Name}", new ValidationException("Validation exception", failures)); } return await next(); diff --git a/QRCodeService/Application/Commands/CreateLinkCommand.cs b/QRCodeService/Application/Commands/CreateLinkCommand.cs index 4c616a9..6ed1d1e 100644 --- a/QRCodeService/Application/Commands/CreateLinkCommand.cs +++ b/QRCodeService/Application/Commands/CreateLinkCommand.cs @@ -1,4 +1,5 @@ -using MediatR; +using Domain.AggregateModel.LinkAggregate; +using MediatR; using System; using System.Collections.Generic; using System.Linq; @@ -7,8 +8,14 @@ using System.Threading.Tasks; namespace QRCodeService.Application.Commands { - public class CreateLinkCommand : IRequest + public class CreateLinkCommand : IRequest { + public int AppId { get; set; } public string SuffixUrl { get; set; } + public CreateLinkCommand(string suffixUrl, int appId) + { + SuffixUrl = suffixUrl; + AppId = appId; + } } } diff --git a/QRCodeService/Application/Commands/CreateLinkCommandHandler.cs b/QRCodeService/Application/Commands/CreateLinkCommandHandler.cs index 3eb44d8..cb790a4 100644 --- a/QRCodeService/Application/Commands/CreateLinkCommandHandler.cs +++ b/QRCodeService/Application/Commands/CreateLinkCommandHandler.cs @@ -1,4 +1,7 @@ -using MediatR; +using Domain.AggregateModel.AppAggregate; +using Domain.AggregateModel.LinkAggregate; +using Domain.Exceptions; +using MediatR; using System; using System.Collections.Generic; using System.Linq; @@ -8,11 +11,33 @@ using System.Threading.Tasks; namespace QRCodeService.Application.Commands { - public class CreateLinkCommandHandler : IRequestHandler + public class CreateLinkCommandHandler : IRequestHandler { - public Task Handle(CreateLinkCommand request, CancellationToken cancellationToken) + readonly IAppRepository appRepository; + readonly ILinkRepository linkRepository; + + public CreateLinkCommandHandler(ILinkRepository linkRepository, IAppRepository appRepository) { - throw new NotImplementedException(); + this.linkRepository = linkRepository; + this.appRepository = appRepository; + } + + async Task IRequestHandler.Handle(CreateLinkCommand request, CancellationToken cancellationToken) + { + var app = await appRepository.GetAsync(request.AppId); + if (app == null) + { + throw new DomainException("app not found"); + } + var link = new Link(app.BaseUrl, request.SuffixUrl, request.AppId); + var dbLink = await linkRepository.GetAsync(link.ShortCode); + if (dbLink != null) + { + throw new DomainException("url has been registed"); + } + link = linkRepository.Add(link); + await linkRepository.UnitOfWork.SaveEntitiesAsync(); + return link; } } } diff --git a/QRCodeService/Application/Queries/LinkQueries.cs b/QRCodeService/Application/Queries/LinkQueries.cs index 17393c3..b9f02c9 100644 --- a/QRCodeService/Application/Queries/LinkQueries.cs +++ b/QRCodeService/Application/Queries/LinkQueries.cs @@ -6,6 +6,7 @@ using System.Text; using System.Threading.Tasks; using Dapper; using MySqlConnector; +using Microsoft.Extensions.Configuration; namespace QRCodeService.Application.Queries { @@ -13,9 +14,9 @@ namespace QRCodeService.Application.Queries { readonly string _connectionString; - public LinkQueries(string connectionString) + public LinkQueries(IConfiguration configuration) { - _connectionString = connectionString; + _connectionString = configuration.GetConnectionString("default"); } public async Task GetLinkAsync(string shortCode) diff --git a/QRCodeService/Controllers/Api/AppController.cs b/QRCodeService/Controllers/Api/AppController.cs new file mode 100644 index 0000000..01b8f33 --- /dev/null +++ b/QRCodeService/Controllers/Api/AppController.cs @@ -0,0 +1,25 @@ +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace QRCodeService.Controllers.Api +{ + [Route("api/v1/[controller]")] + [ApiController] + public class AppController:ControllerBase + { + [HttpGet] + public IActionResult Get() + { + return Ok(); + } + [HttpPost] + public IActionResult Create(object input) + { + return Ok(); + } + } +} diff --git a/QRCodeService/Controllers/Api/LinkController.cs b/QRCodeService/Controllers/Api/LinkController.cs new file mode 100644 index 0000000..0daf526 --- /dev/null +++ b/QRCodeService/Controllers/Api/LinkController.cs @@ -0,0 +1,46 @@ +using Domain.AggregateModel.AppAggregate; +using Domain.AggregateModel.LinkAggregate; +using Microsoft.AspNetCore.Mvc; +using QRCodeService.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using MediatR; +using QRCodeService.Application.Queries; +using QRCodeService.Application.Commands; + +namespace QRCodeService.Controllers.Api +{ + [Route("api/v1/[controller]")] + [ApiController] + public class LinkController:ControllerBase + { + readonly IMediator mediator; + readonly ILinkQueries queries; + + public LinkController(IMediator mediator, ILinkQueries queries) + { + this.mediator = mediator; + this.queries = queries; + } + + [HttpGet] + public IActionResult Get() + { + return Ok(); + } + [HttpPost] + public async Task Create(CreateLinkModel input) + { + var command = new CreateLinkCommand(input.SuffixUrl,1); + var link = await mediator.Send(command); + if (link==null) + { + return BadRequest(); + } + return Ok(link.ShortCode); + } + } +} diff --git a/QRCodeService/Controllers/AppController.cs b/QRCodeService/Controllers/AppController.cs deleted file mode 100644 index c75a6f4..0000000 --- a/QRCodeService/Controllers/AppController.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace QRCodeService.Controllers -{ - [Route("api/v1/[controller]")] - public class AppController:ControllerBase - { - - } -} diff --git a/QRCodeService/Controllers/GenController.cs b/QRCodeService/Controllers/GenController.cs deleted file mode 100644 index 0e7a8a9..0000000 --- a/QRCodeService/Controllers/GenController.cs +++ /dev/null @@ -1,58 +0,0 @@ -using Domain.AggregateModel.LinkAggregate; -using Microsoft.AspNetCore.Mvc; -using QRCodeService.Models; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Security.Cryptography; -using Domain.AggregateModel.AppAggregate; -using Base62; -using QRCodeService.Extensions; - -namespace QRCodeService.Controllers -{ - /// - /// 生成二维码图片 - /// - [Route("api/[controller]")] - [ApiController] - public class GenController:ControllerBase - { - readonly ILinkRepository linkRepository; - readonly IAppRepository appRepository; - - public GenController(ILinkRepository linkRepository, IAppRepository appRepository) - { - this.linkRepository = linkRepository; - this.appRepository = appRepository; - } - - [HttpPost] - public async Task CreateLink(GenInputModel model) - { - - var app = await appRepository.GetAsync(model.AppId); - if (app == null) - { - return BadRequest(); - } - using(var md5 = MD5.Create()) - { - var result = md5.ComputeHash(Encoding.UTF8.GetBytes($"{model.AppId}{model.SuffixUrl}{model.Time}{app.AppKey}")); - var sign = BitConverter.ToString(result); - if (sign != model.Sign) - { - return BadRequest(); - } - } - var shortCode = $"{model.SuffixUrl}".ToMD5().ToBase62(); - var link = new Link(app.BaseUrl, model.SuffixUrl,1); - linkRepository.Add(link); - await linkRepository.UnitOfWork.SaveEntitiesAsync(); - return Ok(link.ShortCode); - } - } -} diff --git a/QRCodeService/Controllers/GoController.cs b/QRCodeService/Controllers/GoController.cs deleted file mode 100644 index f95a034..0000000 --- a/QRCodeService/Controllers/GoController.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Domain.AggregateModel.LinkAggregate; -using Microsoft.AspNetCore.Mvc; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace QRCodeService.Controllers -{ - /// - /// 跳转url请求的地址 - /// - [Route("{shortCode}")] - public class GoController: Controller - { - //readonly ILinkRepository LinkRepository; - //public GoController(ILinkRepository linkRepository) - //{ - // LinkRepository = linkRepository; - //} - [HttpGet] - public async Task Index(string shortcode) - { - var a = new { Url = "asdasd" }; - //var link = await LinkRepository.GetAsync(shortcode); - return View(a); - } - } -} diff --git a/QRCodeService/Controllers/ImageController.cs b/QRCodeService/Controllers/ImageController.cs index 447ebb8..51b3dd8 100644 --- a/QRCodeService/Controllers/ImageController.cs +++ b/QRCodeService/Controllers/ImageController.cs @@ -14,6 +14,7 @@ namespace QRCodeService.Controllers public class ImageController : ControllerBase { [Route("{shortCode}")] + [HttpGet] public IActionResult Get(string shortCode) { var qrCodeGenerator = new QRCodeGenerator(); diff --git a/QRCodeService/Controllers/PlaygroundController.cs b/QRCodeService/Controllers/PlaygroundController.cs index 148b3fd..d40cc62 100644 --- a/QRCodeService/Controllers/PlaygroundController.cs +++ b/QRCodeService/Controllers/PlaygroundController.cs @@ -10,6 +10,7 @@ using Microsoft.Extensions.Logging; namespace QRCodeService.Controllers { [Route("[controller]/[action]")] + [ApiController] public class PlaygroundController:ControllerBase { private readonly ILogger logger; @@ -18,7 +19,7 @@ namespace QRCodeService.Controllers { this.logger = logger; } - + [HttpGet] public IActionResult GenShortCode(string url) { logger.LogInformation("duduledule"); diff --git a/QRCodeService/Controllers/RedirectController.cs b/QRCodeService/Controllers/RedirectController.cs new file mode 100644 index 0000000..aabac85 --- /dev/null +++ b/QRCodeService/Controllers/RedirectController.cs @@ -0,0 +1,27 @@ +using Microsoft.AspNetCore.Mvc; +using QRCodeService.Application.Queries; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace QRCodeService.Controllers +{ + [Route("{shortCode}")] + public class RedirectController:Controller + { + private readonly ILinkQueries queries; + + public RedirectController(ILinkQueries queries) + { + this.queries = queries; + } + [HttpGet] + public async Task Index(string shortCode) + { + var link = await queries.GetLinkAsync(shortCode); + return View(link); + } + } +} diff --git a/QRCodeService/Migrations/20210224014442_InitialCreate.Designer.cs b/QRCodeService/Migrations/20210224014442_InitialCreate.Designer.cs deleted file mode 100644 index a28fa63..0000000 --- a/QRCodeService/Migrations/20210224014442_InitialCreate.Designer.cs +++ /dev/null @@ -1,73 +0,0 @@ -// -using System; -using Infrastructure; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -namespace QRCodeService.Migrations -{ - [DbContext(typeof(AppDbContext))] - [Migration("20210224014442_InitialCreate")] - partial class InitialCreate - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("Relational:MaxIdentifierLength", 64) - .HasAnnotation("ProductVersion", "5.0.3"); - - modelBuilder.Entity("Domain.AggregateModel.AppAggregate.App", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("AppKey") - .HasColumnType("longtext"); - - b.Property("BaseUrl") - .HasColumnType("longtext"); - - b.Property("Remarks") - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.ToTable("Apps"); - }); - - modelBuilder.Entity("Domain.AggregateModel.LinkAggregate.Link", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("AppId") - .HasColumnType("int"); - - b.Property("BaseUrl") - .HasColumnType("longtext"); - - b.Property("FullUrl") - .HasColumnType("longtext"); - - b.Property("ShortCode") - .HasColumnType("longtext"); - - b.Property("SuffixUrl") - .HasColumnType("longtext"); - - b.Property("Time") - .HasColumnType("datetime(6)"); - - b.HasKey("Id"); - - b.ToTable("Links"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/QRCodeService/Migrations/20210224015439_AddConfiguration.Designer.cs b/QRCodeService/Migrations/20210224015439_AddConfiguration.Designer.cs deleted file mode 100644 index 1643455..0000000 --- a/QRCodeService/Migrations/20210224015439_AddConfiguration.Designer.cs +++ /dev/null @@ -1,72 +0,0 @@ -// -using System; -using Infrastructure; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -namespace QRCodeService.Migrations -{ - [DbContext(typeof(AppDbContext))] - [Migration("20210224015439_AddConfiguration")] - partial class AddConfiguration - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("Relational:MaxIdentifierLength", 64) - .HasAnnotation("ProductVersion", "5.0.3"); - - modelBuilder.Entity("Domain.AggregateModel.AppAggregate.App", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("AppKey") - .HasColumnType("longtext"); - - b.Property("BaseUrl") - .HasColumnType("longtext"); - - b.Property("Remarks") - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.ToTable("App"); - }); - - modelBuilder.Entity("Domain.AggregateModel.LinkAggregate.Link", b => - { - b.Property("ShortCode") - .HasColumnType("varchar(255)"); - - b.Property("AppId") - .HasColumnType("int"); - - b.Property("BaseUrl") - .HasColumnType("longtext"); - - b.Property("FullUrl") - .HasColumnType("longtext"); - - b.Property("Id") - .HasColumnType("int"); - - b.Property("SuffixUrl") - .HasColumnType("longtext"); - - b.Property("Time") - .HasColumnType("datetime(6)"); - - b.HasKey("ShortCode"); - - b.ToTable("Link"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/QRCodeService/Migrations/20210224015439_AddConfiguration.cs b/QRCodeService/Migrations/20210224015439_AddConfiguration.cs deleted file mode 100644 index 7efc560..0000000 --- a/QRCodeService/Migrations/20210224015439_AddConfiguration.cs +++ /dev/null @@ -1,102 +0,0 @@ -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; - -namespace QRCodeService.Migrations -{ - public partial class AddConfiguration : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropPrimaryKey( - name: "PK_Links", - table: "Links"); - - migrationBuilder.DropPrimaryKey( - name: "PK_Apps", - table: "Apps"); - - migrationBuilder.RenameTable( - name: "Links", - newName: "Link"); - - migrationBuilder.RenameTable( - name: "Apps", - newName: "App"); - - migrationBuilder.AlterColumn( - name: "ShortCode", - table: "Link", - type: "varchar(255)", - nullable: false, - defaultValue: "", - oldClrType: typeof(string), - oldType: "longtext", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "Id", - table: "Link", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AddPrimaryKey( - name: "PK_Link", - table: "Link", - column: "ShortCode"); - - migrationBuilder.AddPrimaryKey( - name: "PK_App", - table: "App", - column: "Id"); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropPrimaryKey( - name: "PK_Link", - table: "Link"); - - migrationBuilder.DropPrimaryKey( - name: "PK_App", - table: "App"); - - migrationBuilder.RenameTable( - name: "Link", - newName: "Links"); - - migrationBuilder.RenameTable( - name: "App", - newName: "Apps"); - - migrationBuilder.AlterColumn( - name: "Id", - table: "Links", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "ShortCode", - table: "Links", - type: "longtext", - nullable: true, - oldClrType: typeof(string), - oldType: "varchar(255)"); - - migrationBuilder.AddPrimaryKey( - name: "PK_Links", - table: "Links", - column: "Id"); - - migrationBuilder.AddPrimaryKey( - name: "PK_Apps", - table: "Apps", - column: "Id"); - } - } -} diff --git a/QRCodeService/Migrations/20210224015858_SetProperty.cs b/QRCodeService/Migrations/20210224015858_SetProperty.cs deleted file mode 100644 index 8895332..0000000 --- a/QRCodeService/Migrations/20210224015858_SetProperty.cs +++ /dev/null @@ -1,80 +0,0 @@ -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; - -namespace QRCodeService.Migrations -{ - public partial class SetProperty : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropPrimaryKey( - name: "PK_Link", - table: "Link"); - - migrationBuilder.AlterColumn( - name: "Id", - table: "Link", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "ShortCode", - table: "Link", - type: "varchar(11)", - maxLength: 11, - nullable: true, - oldClrType: typeof(string), - oldType: "varchar(255)"); - - migrationBuilder.AddPrimaryKey( - name: "PK_Link", - table: "Link", - column: "Id"); - - migrationBuilder.CreateIndex( - name: "IX_Link_ShortCode", - table: "Link", - column: "ShortCode", - unique: true); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropPrimaryKey( - name: "PK_Link", - table: "Link"); - - migrationBuilder.DropIndex( - name: "IX_Link_ShortCode", - table: "Link"); - - migrationBuilder.AlterColumn( - name: "ShortCode", - table: "Link", - type: "varchar(255)", - nullable: false, - defaultValue: "", - oldClrType: typeof(string), - oldType: "varchar(11)", - oldMaxLength: 11, - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "Id", - table: "Link", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AddPrimaryKey( - name: "PK_Link", - table: "Link", - column: "ShortCode"); - } - } -} diff --git a/QRCodeService/Migrations/20210224015858_SetProperty.Designer.cs b/QRCodeService/Migrations/20210224065420_init.Designer.cs similarity index 96% rename from QRCodeService/Migrations/20210224015858_SetProperty.Designer.cs rename to QRCodeService/Migrations/20210224065420_init.Designer.cs index 8010dfd..79e22bf 100644 --- a/QRCodeService/Migrations/20210224015858_SetProperty.Designer.cs +++ b/QRCodeService/Migrations/20210224065420_init.Designer.cs @@ -9,8 +9,8 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion; namespace QRCodeService.Migrations { [DbContext(typeof(AppDbContext))] - [Migration("20210224015858_SetProperty")] - partial class SetProperty + [Migration("20210224065420_init")] + partial class init { protected override void BuildTargetModel(ModelBuilder modelBuilder) { diff --git a/QRCodeService/Migrations/20210224014442_InitialCreate.cs b/QRCodeService/Migrations/20210224065420_init.cs similarity index 76% rename from QRCodeService/Migrations/20210224014442_InitialCreate.cs rename to QRCodeService/Migrations/20210224065420_init.cs index a0ba1ac..179d4ed 100644 --- a/QRCodeService/Migrations/20210224014442_InitialCreate.cs +++ b/QRCodeService/Migrations/20210224065420_init.cs @@ -4,12 +4,12 @@ using Microsoft.EntityFrameworkCore.Migrations; namespace QRCodeService.Migrations { - public partial class InitialCreate : Migration + public partial class init : Migration { protected override void Up(MigrationBuilder migrationBuilder) { migrationBuilder.CreateTable( - name: "Apps", + name: "App", columns: table => new { Id = table.Column(type: "int", nullable: false) @@ -20,16 +20,16 @@ namespace QRCodeService.Migrations }, constraints: table => { - table.PrimaryKey("PK_Apps", x => x.Id); + table.PrimaryKey("PK_App", x => x.Id); }); migrationBuilder.CreateTable( - name: "Links", + name: "Link", columns: table => new { Id = table.Column(type: "int", nullable: false) .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - ShortCode = table.Column(type: "longtext", nullable: true), + ShortCode = table.Column(type: "varchar(11)", maxLength: 11, nullable: true), BaseUrl = table.Column(type: "longtext", nullable: true), SuffixUrl = table.Column(type: "longtext", nullable: true), FullUrl = table.Column(type: "longtext", nullable: true), @@ -38,17 +38,23 @@ namespace QRCodeService.Migrations }, constraints: table => { - table.PrimaryKey("PK_Links", x => x.Id); + table.PrimaryKey("PK_Link", x => x.Id); }); + + migrationBuilder.CreateIndex( + name: "IX_Link_ShortCode", + table: "Link", + column: "ShortCode", + unique: true); } protected override void Down(MigrationBuilder migrationBuilder) { migrationBuilder.DropTable( - name: "Apps"); + name: "App"); migrationBuilder.DropTable( - name: "Links"); + name: "Link"); } } } diff --git a/QRCodeService/Models/CreateLinkModel.cs b/QRCodeService/Models/CreateLinkModel.cs new file mode 100644 index 0000000..f823cc0 --- /dev/null +++ b/QRCodeService/Models/CreateLinkModel.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace QRCodeService.Models +{ + public class CreateLinkModel + { + public string SuffixUrl { get; set; } + public string Time { get; set; } + } +} diff --git a/QRCodeService/Startup.cs b/QRCodeService/Startup.cs index 9b46b95..e793c25 100644 --- a/QRCodeService/Startup.cs +++ b/QRCodeService/Startup.cs @@ -1,4 +1,9 @@ +using Domain.AggregateModel.AppAggregate; +using Domain.AggregateModel.LinkAggregate; +using FluentValidation; +using FluentValidation.AspNetCore; using Infrastructure; +using Infrastructure.Repositories; using MediatR; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; @@ -12,6 +17,9 @@ using Microsoft.OpenApi.Models; using Pomelo.EntityFrameworkCore.MySql; using Pomelo.EntityFrameworkCore.MySql.Infrastructure; using QRCodeService.Application.Behaviors; +using QRCodeService.Application.Commands; +using QRCodeService.Application.Queries; +using QRCodeService.Application.Validations; using System; using System.Collections.Generic; using System.Linq; @@ -38,12 +46,14 @@ namespace QRCodeService { c.SwaggerDoc("v1", new OpenApiInfo { Title = "QRCodeService", Version = "v1" }); }); - //MediatR - services.AddMediatR(Assembly.GetExecutingAssembly()); - services.AddTransient(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>)); - services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidatorBehavior<,>)); - services.AddTransient(typeof(IPipelineBehavior<,>), typeof(TransactionBehaviour<,>)); + //validator + services.AddTransient, CreateLinkCommandValidator>(); + //MediatR+ + services.AddMediatR(Assembly.GetExecutingAssembly()) + .AddTransient(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>)) + .AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidatorBehavior<,>)) + .AddTransient(typeof(IPipelineBehavior<,>), typeof(TransactionBehaviour<,>)); //EFCore services.AddDbContext( dbContextOptions => dbContextOptions @@ -57,6 +67,12 @@ namespace QRCodeService .EnableSensitiveDataLogging() .EnableDetailedErrors() ); + + //Repository + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. diff --git a/QRCodeService/Views/Go/Index.cshtml b/QRCodeService/Views/Redirect/Index.cshtml similarity index 100% rename from QRCodeService/Views/Go/Index.cshtml rename to QRCodeService/Views/Redirect/Index.cshtml diff --git a/QRCodeService/appsettings.json b/QRCodeService/appsettings.json index 008de18..365ebe8 100644 --- a/QRCodeService/appsettings.json +++ b/QRCodeService/appsettings.json @@ -7,6 +7,9 @@ } }, "AllowedHosts": "*", + "ConnectionStrings": { + "default": "server=localhost;user=root;password=root;database=qrcode" + }, "Serilog": { "Using": [ "SeriLog.Sinks.Console", "Serilog.Sinks.File", "Serilog.Sinks.Async" ], "MinimumLevel": {