This commit is contained in:
Mikhail Kuznetsov
2023-06-01 16:42:44 +10:00
parent f0d28c0802
commit e465932222
29 changed files with 206 additions and 34 deletions

View File

@@ -0,0 +1,42 @@
namespace PARR.API.Contracts.V1
{
// https://tproger.ru/translations/luchshie-praktiki-razrabotki-rest-api-20-sovetov/
//----------URL должен отражать структуру вложенных ресурсов----------
// GET /shops/2/products получить список продуктов из магазина 2.
// GET /shops/2/products/31 получить детали продукта 31 из магазина 2.
// DELETE /shops/2/products/31 удалить продукт 31 из магазина 2.
// PUT /shops/2/products/31 обновить данные о продукте 31. Используйте PUT на URL ресурса, а не коллекции.
// POST /shops создать новый магазин и вернуть данные о нём.Используйте POST на URL коллекции.
//---------URL должен начинаться с коллекции и заканчиваться идентификатором---------
// GET /shops/:shopId/ или GET /category/:categoryId
public static class ApiRoutes
{
public const string Root = "api";
public const string Version = "v1";
public const string Base = Root + "/" + Version;
public static class ApiStatus
{
public const string Version = Base + "/version";
public const string Health = Base + "/health";
public const string Metrics = Base + "/metrics";
}
//public static class Layer
//{
// public const string GetAll = Base + "/layers/";
// public const string Get = Base + "/layers/" + getParam;
// public const string GetAreas = Base + "/layers/" + getParam + "/areas";
// public const string GetPlaces = Base + "/layers/" + getParam + "/places";
// public const string GetTemplates = Base + "/layers/" + getParam + "/templates";
// public const string getParam = "{id}";
//}
}
}

View File

@@ -0,0 +1,9 @@
using PARR.API.Controllers.V1.Base;
namespace PARR.API.Controllers.V1
{
public class ApiStatusController : BaseApiController
{
//TODO:
}
}

View File

@@ -0,0 +1,10 @@
using Microsoft.AspNetCore.Mvc;
namespace PARR.API.Controllers.V1.Base
{
[ApiController]
public class BaseApiController : ControllerBase
{
}
}

View File

@@ -0,0 +1,26 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using PARR.DAL.Services.Interfaces;
namespace PARR.API.Controllers.V1
{
public class HomeController : Controller
{
private readonly IHostService hostService;
public HomeController(IHostService hostService)
{
this.hostService = hostService;
}
[HttpGet("test")]
public async Task<IActionResult> Index()
{
var hosts = await hostService.Get().ToListAsync();
//foreach (var host in hosts) { logger.LogInformation($"{host.HostName}"); }
//return View();
return Ok(hosts.Select(t => new { t.HostName, t.IP, t.Id }));
}
}
}

28
PARR.API/Dockerfile Normal file
View File

@@ -0,0 +1,28 @@
#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
FROM 10.99.253.167:8090/dotnet/aspnet:7.0 AS base
WORKDIR /app
EXPOSE 80
FROM 10.99.253.167:8090/dotnet/sdk:7.0 AS build
WORKDIR /src
COPY ["NuGet.config", "."]
COPY ["PARR_API/PARR.API.csproj", "PARR_API/"]
COPY ["PARR.DAL/PARR.DAL.csproj", "PARR.DAL/"]
RUN dotnet restore "PARR_API/PARR.API.csproj"
COPY . .
WORKDIR "/src/PARR_API"
RUN dotnet build "PARR.API.csproj" -c Release -o /app/build
FROM build AS publish
ARG app_version=0.0.0-default
RUN dotnet publish "PARR.API.csproj" -c Release -o /app/publish /p:UseAppHost=false /p:Version=$app_version
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "PARR.API.dll"]
### EXAMPLE ###
# docker build -t parr-api:v1.0.0 --build-arg app_version=1.0.0 -f PARR.API/Dockerfile .

View File

@@ -0,0 +1,28 @@
using PARR.API.Services.Implementations;
using PARR.API.Services.Interfaces;
namespace PARR.API.Installers
{
/// <summary>
/// Самописные сервисы которые используются для АПИ
/// </summary>
public static class ApiServicesInstaller
{
public static void InstallApiServices(this IServiceCollection services, IConfiguration configuration)
{
services.AddSingleton<IUriService>(provider =>
{
var accessor = provider.GetRequiredService<IHttpContextAccessor>();
var request = accessor.HttpContext.Request;
var absoluteUri = string.Concat(request.Scheme, "://", request.Host.ToUriComponent(), "/");
return new UriService(absoluteUri);
});
//services.AddTransient<IFileService, FileService>();
}
}
}

View File

@@ -0,0 +1,25 @@
using PARR.API.Settings;
namespace PARR.API.Installers
{
public static class CorsInstaller
{
public static void InstallCorsServices(this IServiceCollection services)
{
services.AddCors();
}
public static void InstallCors(this WebApplication app, WebApplicationBuilder builder)
{
var corsSettings = new CorsSettings();
builder.Configuration.GetSection(nameof(CorsSettings)).Bind(corsSettings);
app.UseCors(opt =>
opt.WithOrigins(corsSettings.AllowHostsArray)
.AllowAnyHeader()
.AllowAnyMethod()
);
}
}
}

View File

@@ -0,0 +1,17 @@
namespace PARR.API.Installers
{
/// <summary>
/// Биндинги из конфига appsettings
/// </summary>
public static class SettingsInstaller
{
public static void InstallSettings(this IServiceCollection services, IConfiguration configuration)
{
//var storageSettings = new StorageSettings();
//configuration.GetSection(nameof(StorageSettings)).Bind(storageSettings);
//services.AddSingleton(storageSettings);
//TODO: add other
}
}
}

View File

@@ -0,0 +1,47 @@
using Microsoft.OpenApi.Models;
using System.Reflection;
namespace PARR.API.Installers
{
public static class SwaggerInstaller
{
public static void InstallSwaggerService(this IServiceCollection services, IConfiguration configuration)
{
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
services.AddEndpointsApiExplorer();
var version = Assembly.GetEntryAssembly()?.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion ?? "1.0.0";
services.AddSwaggerGen(x =>
{
//TODO:
x.SwaggerDoc(
"v1",
new OpenApiInfo
{
Title = "GEO API",
Version = $"v{version}",
Description = "API for the project \"GEO DVGD\"",
Contact = new OpenApiContact { Email = "IVC_TrubnikovME@dvgd.rzd;IVC_KuznetsovMV@dvgd.rzd", Name = "Trubnikov M.E., Kuznetsov M.V." },
License = new OpenApiLicense { Name = "© PTK-DVGD Software LLC" }
});
// Set the comments path for the Swagger JSON and UI.
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
x.IncludeXmlComments(xmlPath);
});
}
public static void InstallSwagger(this WebApplication app)
{
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
}
}
}

View File

@@ -0,0 +1,12 @@
using AutoMapper;
namespace PARR.API.MappingProfiles
{
public class DomainToResponseProfile : Profile
{
public DomainToResponseProfile()
{
// из проекта наружу
}
}
}

View File

@@ -0,0 +1,12 @@
using AutoMapper;
namespace PARR.API.MappingProfiles
{
public class RequestToDomainProfile : Profile
{
public RequestToDomainProfile()
{
// снаружи в проект
}
}
}

47
PARR.API/PARR.API.csproj Normal file
View File

@@ -0,0 +1,47 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
<DockerComposeProjectPath>..\docker-compose.dcproj</DockerComposeProjectPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<NoWarn>1701;1702;1591;1587;1573;NU1803</NoWarn>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<NoWarn>1701;1702;1591;1587;1573;NU1803</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.1" />
<PackageReference Include="FluentValidation.DependencyInjectionExtensions" Version="11.5.2" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.5" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.17.0" />
<PackageReference Include="Serilog.AspNetCore" Version="7.0.0" />
<PackageReference Include="Serilog.Extensions.Hosting" Version="7.0.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
</ItemGroup>
<ItemGroup>
<Folder Include="Contracts\V1\Requests\Queries\" />
<Folder Include="Contracts\V1\Responses\" />
<Folder Include="MappingProfiles\Resolvers\" />
<Folder Include="Validators\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\PARR.DAL\PARR.DAL.csproj" />
</ItemGroup>
</Project>

41
PARR.API/Program.cs Normal file
View File

@@ -0,0 +1,41 @@
using FluentValidation;
using PARR.API.Installers;
using PARR.DAL;
using Serilog;
using System.Reflection;
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseSerilog((context, config) =>
{
config
.WriteTo.Console()
.ReadFrom.Configuration(builder.Configuration);
});
// Add services to the container.
builder.Services.InstallDalServices(builder.Configuration);
builder.Services.InstallApiServices(builder.Configuration);
builder.Services.InstallSettings(builder.Configuration);
builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
builder.Services.AddHttpContextAccessor();
builder.Services.AddControllers();
builder.Services.AddValidatorsFromAssembly(Assembly.GetExecutingAssembly());
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.InstallSwaggerService(builder.Configuration);
var app = builder.Build();
// Configure the HTTP request pipeline.
app.InstallSwagger();
app.UseAuthorization();
app.MapControllers();
app.Run();

View File

@@ -0,0 +1,37 @@
{
"profiles": {
"http": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"dotnetRunMessages": true,
"applicationUrl": "http://localhost:5104"
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Docker": {
"commandName": "Docker",
"launchBrowser": true,
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger",
"publishAllPorts": true
}
},
"$schema": "https://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:59274",
"sslPort": 0
}
}
}

View File

@@ -0,0 +1,35 @@
using PARR.API.Services.Interfaces;
namespace PARR.API.Services.Implementations
{
public class UriService : IUriService
{
private readonly string baseUri;
public UriService(string baseUri)
{
this.baseUri = baseUri;
}
public Uri GetAllUri(string apiRoutesGetAll)
{
return new Uri(baseUri + apiRoutesGetAll);
}
public Uri GetUri(string apiRoutesGet, string apiRoutesGetParam, string value)
{
var modifiedUri = apiRoutesGet.Replace(apiRoutesGetParam, value);
return new Uri(baseUri + modifiedUri);
}
public Uri GetUri(string apiRoutesGet, string apiRoutesGetParam, Guid value)
{
return GetUri(apiRoutesGet, apiRoutesGetParam, value.ToString());
}
public Uri GetBaseUri()
{
return new Uri(baseUri);
}
}
}

View File

@@ -0,0 +1,10 @@
namespace PARR.API.Services.Interfaces
{
public interface IUriService
{
Uri GetBaseUri();
Uri GetUri(string apiRoutesGet, string apiRoutesGetParam, string value);
Uri GetUri(string apiRoutesGet, string apiRoutesGetParam, Guid value);
Uri GetAllUri(string apiRoutesGetAll);
}
}

View File

@@ -0,0 +1,9 @@
namespace PARR.API.Settings
{
public class CorsSettings
{
public string AllowedHosts { get; set; } = string.Empty;
public string[] AllowHostsArray => AllowedHosts.Split(';').Select(t => t.Trim()).ToArray();
}
}

View File

@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

33
PARR.API/appsettings.json Normal file
View File

@@ -0,0 +1,33 @@
{
"ConnectionStrings": {
"DefaultConnection": "Server=10.99.253.184;Database=parr;User Id=app_parr; Password=PosdfkhT&)%sdfligL&%5546;"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"WriteTo": [
{
"Name": "File",
"Args": {
"path": "log/log-.txt",
"rollingInterval": "Day"
}
}
]
},
"AllowedHosts": "*",
"CorsSettings": {
"AllowedHosts": "*"
}
}