diff --git a/CoreProfilerExample.Common/Constants/WeatherConstant.cs b/CoreProfilerExample.Common/Constants/WeatherConstant.cs new file mode 100644 index 0000000..2210cba --- /dev/null +++ b/CoreProfilerExample.Common/Constants/WeatherConstant.cs @@ -0,0 +1,10 @@ +namespace CoreProfilerExample.Common.Constants +{ + public static class WeatherConstant + { + public readonly static string[] WeatherSummaries = + [ + "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" + ]; + } +} diff --git a/CoreProfilerExample.Common/CoreProfilerExample.Common.csproj b/CoreProfilerExample.Common/CoreProfilerExample.Common.csproj new file mode 100644 index 0000000..fa71b7a --- /dev/null +++ b/CoreProfilerExample.Common/CoreProfilerExample.Common.csproj @@ -0,0 +1,9 @@ + + + + net8.0 + enable + enable + + + diff --git a/CoreProfilerExample.Repository/CoreProfilerExample.Repository.csproj b/CoreProfilerExample.Repository/CoreProfilerExample.Repository.csproj new file mode 100644 index 0000000..e4acc0c --- /dev/null +++ b/CoreProfilerExample.Repository/CoreProfilerExample.Repository.csproj @@ -0,0 +1,13 @@ + + + + net8.0 + enable + enable + + + + + + + diff --git a/CoreProfilerExample.Repository/Implements/WeatherForecastRepository.cs b/CoreProfilerExample.Repository/Implements/WeatherForecastRepository.cs new file mode 100644 index 0000000..65d929d --- /dev/null +++ b/CoreProfilerExample.Repository/Implements/WeatherForecastRepository.cs @@ -0,0 +1,19 @@ +using CoreProfilerExample.Repository.Interfaces; +using CoreProfilerExample.Repository.Models.DataModels; +using static CoreProfilerExample.Common.Constants.WeatherConstant; + +namespace CoreProfilerExample.Repository.Implements +{ + public class WeatherForecastRepository : IWeatherForecastRepository + { + public Task> GetAsync(int days) + { + return Task.Run(() => days > 0 ? Enumerable.Range(1, days).Select(index => new WeatherForecastDataModel + { + Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)), + TemperatureC = Random.Shared.Next(-20, 55), + Summary = WeatherSummaries[Random.Shared.Next(WeatherSummaries.Length)] + }) : []); + } + } +} diff --git a/CoreProfilerExample.Repository/Interfaces/IWeatherForecastRepository.cs b/CoreProfilerExample.Repository/Interfaces/IWeatherForecastRepository.cs new file mode 100644 index 0000000..ca43b08 --- /dev/null +++ b/CoreProfilerExample.Repository/Interfaces/IWeatherForecastRepository.cs @@ -0,0 +1,9 @@ +using CoreProfilerExample.Repository.Models.DataModels; + +namespace CoreProfilerExample.Repository.Interfaces +{ + public interface IWeatherForecastRepository + { + public Task> GetAsync(int days); + } +} diff --git a/CoreProfilerExample.Repository/Models/DataModels/WeatherForecastDataModel.cs b/CoreProfilerExample.Repository/Models/DataModels/WeatherForecastDataModel.cs new file mode 100644 index 0000000..c8ee910 --- /dev/null +++ b/CoreProfilerExample.Repository/Models/DataModels/WeatherForecastDataModel.cs @@ -0,0 +1,11 @@ +namespace CoreProfilerExample.Repository.Models.DataModels +{ + public class WeatherForecastDataModel + { + public DateOnly Date { get; set; } + + public int TemperatureC { get; set; } + + public string? Summary { get; set; } + } +} diff --git a/CoreProfilerExample.Service/CoreProfilerExample.Service.csproj b/CoreProfilerExample.Service/CoreProfilerExample.Service.csproj new file mode 100644 index 0000000..a2e8e3b --- /dev/null +++ b/CoreProfilerExample.Service/CoreProfilerExample.Service.csproj @@ -0,0 +1,13 @@ + + + + net8.0 + enable + enable + + + + + + + diff --git a/CoreProfilerExample.Service/Extensions/MapperExtension.cs b/CoreProfilerExample.Service/Extensions/MapperExtension.cs new file mode 100644 index 0000000..b597b76 --- /dev/null +++ b/CoreProfilerExample.Service/Extensions/MapperExtension.cs @@ -0,0 +1,33 @@ +using CoreProfilerExample.Repository.Models.DataModels; +using CoreProfilerExample.Service.Models.Dtos; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CoreProfilerExample.Service.Extensions +{ + public static class MapperExtension + { + public static async Task ToDtoAsync(this Task> task) + { + var dataModels = await task; + + return new GetWeatherForecastDto + { + WeatherForecasts = dataModels.Select(model => model.ToDto()), + }; + } + + public static GetWeatherForecastItemDto ToDto(this WeatherForecastDataModel dataModel) + { + return new GetWeatherForecastItemDto + { + Date = dataModel.Date, + Summary = dataModel.Summary, + TemperatureC = dataModel.TemperatureC, + }; + } + } +} diff --git a/CoreProfilerExample.Service/Implements/WeatherService.cs b/CoreProfilerExample.Service/Implements/WeatherService.cs new file mode 100644 index 0000000..46e5555 --- /dev/null +++ b/CoreProfilerExample.Service/Implements/WeatherService.cs @@ -0,0 +1,21 @@ +using CoreProfilerExample.Repository.Interfaces; +using CoreProfilerExample.Service.Extensions; +using CoreProfilerExample.Service.Interfaces; +using CoreProfilerExample.Service.Models.Dtos; +using CoreProfilerExample.Service.Models.ParameterDtos; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CoreProfilerExample.Service.Implements +{ + public class WeatherService(IWeatherForecastRepository weatherForecast) : IWeatherService + { + public Task GetWeatherForecastAsync(GetWeatherForecastParameterDto parameterDto) + { + return weatherForecast.GetAsync(parameterDto.ForecastDays).ToDtoAsync(); + } + } +} diff --git a/CoreProfilerExample.Service/Interfaces/IWeatherService.cs b/CoreProfilerExample.Service/Interfaces/IWeatherService.cs new file mode 100644 index 0000000..19bca89 --- /dev/null +++ b/CoreProfilerExample.Service/Interfaces/IWeatherService.cs @@ -0,0 +1,10 @@ +using CoreProfilerExample.Service.Models.Dtos; +using CoreProfilerExample.Service.Models.ParameterDtos; + +namespace CoreProfilerExample.Service.Interfaces +{ + public interface IWeatherService + { + public Task GetWeatherForecastAsync(GetWeatherForecastParameterDto parameterDto); + } +} diff --git a/CoreProfilerExample.Service/Models/Dtos/GetWeatherForecastDto.cs b/CoreProfilerExample.Service/Models/Dtos/GetWeatherForecastDto.cs new file mode 100644 index 0000000..1ed21fb --- /dev/null +++ b/CoreProfilerExample.Service/Models/Dtos/GetWeatherForecastDto.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CoreProfilerExample.Service.Models.Dtos +{ + public class GetWeatherForecastDto + { + public IEnumerable WeatherForecasts { get; set; } = []; + } +} diff --git a/CoreProfilerExample.Service/Models/Dtos/GetWeatherForecastItemDto.cs b/CoreProfilerExample.Service/Models/Dtos/GetWeatherForecastItemDto.cs new file mode 100644 index 0000000..79a36b7 --- /dev/null +++ b/CoreProfilerExample.Service/Models/Dtos/GetWeatherForecastItemDto.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CoreProfilerExample.Service.Models.Dtos +{ + public class GetWeatherForecastItemDto + { + public DateOnly Date { get; set; } + + public int TemperatureC { get; set; } + + public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); + + public string? Summary { get; set; } + } +} diff --git a/CoreProfilerExample.Service/Models/ParameterDtos/GetWeatherForecastParameterDto.cs b/CoreProfilerExample.Service/Models/ParameterDtos/GetWeatherForecastParameterDto.cs new file mode 100644 index 0000000..15e89b0 --- /dev/null +++ b/CoreProfilerExample.Service/Models/ParameterDtos/GetWeatherForecastParameterDto.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CoreProfilerExample.Service.Models.ParameterDtos +{ + public class GetWeatherForecastParameterDto + { + public int ForecastDays { get; set; } + } +} diff --git a/CoreProfilerExample.sln b/CoreProfilerExample.sln new file mode 100644 index 0000000..75a48a1 --- /dev/null +++ b/CoreProfilerExample.sln @@ -0,0 +1,43 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.9.34607.119 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CoreProfilerExample", "CoreProfilerExample\CoreProfilerExample.csproj", "{A7B95E40-1807-45E8-831C-88246897C9B5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CoreProfilerExample.Repository", "CoreProfilerExample.Repository\CoreProfilerExample.Repository.csproj", "{F5114126-C965-4F36-9302-AC897C29D898}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CoreProfilerExample.Service", "CoreProfilerExample.Service\CoreProfilerExample.Service.csproj", "{69C081ED-D31A-4C66-9EC9-5CF46A16C8E8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CoreProfilerExample.Common", "CoreProfilerExample.Common\CoreProfilerExample.Common.csproj", "{DDD6FCC3-454E-42CB-94D0-23A7EA57D039}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A7B95E40-1807-45E8-831C-88246897C9B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A7B95E40-1807-45E8-831C-88246897C9B5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A7B95E40-1807-45E8-831C-88246897C9B5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A7B95E40-1807-45E8-831C-88246897C9B5}.Release|Any CPU.Build.0 = Release|Any CPU + {F5114126-C965-4F36-9302-AC897C29D898}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F5114126-C965-4F36-9302-AC897C29D898}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F5114126-C965-4F36-9302-AC897C29D898}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F5114126-C965-4F36-9302-AC897C29D898}.Release|Any CPU.Build.0 = Release|Any CPU + {69C081ED-D31A-4C66-9EC9-5CF46A16C8E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {69C081ED-D31A-4C66-9EC9-5CF46A16C8E8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {69C081ED-D31A-4C66-9EC9-5CF46A16C8E8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {69C081ED-D31A-4C66-9EC9-5CF46A16C8E8}.Release|Any CPU.Build.0 = Release|Any CPU + {DDD6FCC3-454E-42CB-94D0-23A7EA57D039}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DDD6FCC3-454E-42CB-94D0-23A7EA57D039}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DDD6FCC3-454E-42CB-94D0-23A7EA57D039}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DDD6FCC3-454E-42CB-94D0-23A7EA57D039}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {626E928F-5EA0-4F58-BFD4-1A47EF4043B4} + EndGlobalSection +EndGlobal diff --git a/CoreProfilerExample/Controllers/WeatherController.cs b/CoreProfilerExample/Controllers/WeatherController.cs new file mode 100644 index 0000000..db44914 --- /dev/null +++ b/CoreProfilerExample/Controllers/WeatherController.cs @@ -0,0 +1,30 @@ +using CoreProfilerExample.Infrastructure.Extensions; +using CoreProfilerExample.Models.Parameters; +using CoreProfilerExample.Models.ViewModels; +using CoreProfilerExample.Service.Interfaces; +using Microsoft.AspNetCore.Mvc; +using System.Net; + +namespace CoreProfilerExample.Controllers +{ + [ApiController] + [Route("weather")] + public class WeatherController(IWeatherService weather) : ControllerBase + { + [HttpPost("forecast", Name = "GetWeatherForecast")] + [Produces("application/json")] + [ProducesResponseType(typeof(GetWeatherForecastItemViewModel), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(ExceptionViewModel), (int)HttpStatusCode.BadRequest)] + public async Task GetWeatherForecastAsync(GetWeatherForecastParameter parameter) + { + try + { + return Ok(await weather.GetWeatherForecastAsync(parameter.ToDto()).ToViewModel()); + } + catch (Exception ex) + { + return BadRequest(ex.ToViewModel()); + } + } + } +} diff --git a/CoreProfilerExample/CoreProfilerExample.csproj b/CoreProfilerExample/CoreProfilerExample.csproj new file mode 100644 index 0000000..0b8764a --- /dev/null +++ b/CoreProfilerExample/CoreProfilerExample.csproj @@ -0,0 +1,17 @@ + + + + net8.0 + enable + enable + + + + + + + + + + + diff --git a/CoreProfilerExample/Infrastructure/Extensions/DependencyInjectionExtension.cs b/CoreProfilerExample/Infrastructure/Extensions/DependencyInjectionExtension.cs new file mode 100644 index 0000000..cf85aed --- /dev/null +++ b/CoreProfilerExample/Infrastructure/Extensions/DependencyInjectionExtension.cs @@ -0,0 +1,22 @@ +using CoreProfilerExample.Repository.Implements; +using CoreProfilerExample.Repository.Interfaces; +using CoreProfilerExample.Service.Implements; +using CoreProfilerExample.Service.Interfaces; + +namespace CoreProfilerExample.Infrastructure.Extensions +{ + public static class DependencyInjectionExtension + { + public static IServiceCollection AddRepository(this IServiceCollection services) + { + services.AddScoped(); + return services; + } + + public static IServiceCollection AddService(this IServiceCollection services) + { + services.AddScoped(); + return services; + } + } +} diff --git a/CoreProfilerExample/Infrastructure/Extensions/MapperExtension.cs b/CoreProfilerExample/Infrastructure/Extensions/MapperExtension.cs new file mode 100644 index 0000000..8998a99 --- /dev/null +++ b/CoreProfilerExample/Infrastructure/Extensions/MapperExtension.cs @@ -0,0 +1,47 @@ +using CoreProfilerExample.Models.Parameters; +using CoreProfilerExample.Models.ViewModels; +using CoreProfilerExample.Service.Models.Dtos; +using CoreProfilerExample.Service.Models.ParameterDtos; + +namespace CoreProfilerExample.Infrastructure.Extensions +{ + public static class MapperExtension + { + public static ExceptionViewModel ToViewModel(this Exception exception) + { + return new ExceptionViewModel + { + Message = exception.Message, + }; + } + + public static async Task ToViewModel(this Task task) + { + var dto = await task; + + return new GetWeatherForecastViewModel + { + WeatherForecasts = dto.WeatherForecasts.Select(forecast => forecast.ToViewModel()) + }; + } + + public static GetWeatherForecastItemViewModel ToViewModel(this GetWeatherForecastItemDto dto) + { + return new GetWeatherForecastItemViewModel + { + Date = dto.Date, + Summary = dto.Summary, + TemperatureC = dto.TemperatureC, + TemperatureF = dto.TemperatureF, + }; + } + + public static GetWeatherForecastParameterDto ToDto(this GetWeatherForecastParameter parameter) + { + return new GetWeatherForecastParameterDto + { + ForecastDays = parameter.ForecastDays, + }; + } + } +} diff --git a/CoreProfilerExample/Models/Parameters/GetWeatherForecastParameter.cs b/CoreProfilerExample/Models/Parameters/GetWeatherForecastParameter.cs new file mode 100644 index 0000000..0baad4f --- /dev/null +++ b/CoreProfilerExample/Models/Parameters/GetWeatherForecastParameter.cs @@ -0,0 +1,7 @@ +namespace CoreProfilerExample.Models.Parameters +{ + public class GetWeatherForecastParameter + { + public int ForecastDays { get; set; } + } +} diff --git a/CoreProfilerExample/Models/ViewModels/ExceptionViewModel.cs b/CoreProfilerExample/Models/ViewModels/ExceptionViewModel.cs new file mode 100644 index 0000000..be5b31f --- /dev/null +++ b/CoreProfilerExample/Models/ViewModels/ExceptionViewModel.cs @@ -0,0 +1,7 @@ +namespace CoreProfilerExample.Models.ViewModels +{ + public class ExceptionViewModel + { + public string? Message { get; set; } + } +} diff --git a/CoreProfilerExample/Models/ViewModels/GetWeatherForecastItemViewModel.cs b/CoreProfilerExample/Models/ViewModels/GetWeatherForecastItemViewModel.cs new file mode 100644 index 0000000..fae57c1 --- /dev/null +++ b/CoreProfilerExample/Models/ViewModels/GetWeatherForecastItemViewModel.cs @@ -0,0 +1,13 @@ +namespace CoreProfilerExample.Models.ViewModels +{ + public class GetWeatherForecastItemViewModel + { + public DateOnly Date { get; set; } + + public int TemperatureC { get; set; } + + public int TemperatureF { get; set; } + + public string? Summary { get; set; } + } +} diff --git a/CoreProfilerExample/Models/ViewModels/GetWeatherForecastViewModel.cs b/CoreProfilerExample/Models/ViewModels/GetWeatherForecastViewModel.cs new file mode 100644 index 0000000..4765b76 --- /dev/null +++ b/CoreProfilerExample/Models/ViewModels/GetWeatherForecastViewModel.cs @@ -0,0 +1,7 @@ +namespace CoreProfilerExample.Models.ViewModels +{ + public class GetWeatherForecastViewModel + { + public IEnumerable WeatherForecasts { get; set; } = []; + } +} diff --git a/CoreProfilerExample/Program.cs b/CoreProfilerExample/Program.cs new file mode 100644 index 0000000..c03b524 --- /dev/null +++ b/CoreProfilerExample/Program.cs @@ -0,0 +1,25 @@ +using CoreProfilerExample.Infrastructure.Extensions; + +var builder = WebApplication.CreateBuilder(args); + +// Add services to the container. +#region CoreProfilerExample +builder.Services.AddRepository(); +builder.Services.AddService(); +#endregion +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. +app.UseSwagger(); +app.UseSwaggerUI(); + +app.UseAuthorization(); + +app.MapControllers(); + +app.Run(); diff --git a/CoreProfilerExample/Properties/launchSettings.json b/CoreProfilerExample/Properties/launchSettings.json new file mode 100644 index 0000000..a4e488f --- /dev/null +++ b/CoreProfilerExample/Properties/launchSettings.json @@ -0,0 +1,31 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:22953", + "sslPort": 0 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "http://localhost:5100", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/CoreProfilerExample/appsettings.Development.json b/CoreProfilerExample/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/CoreProfilerExample/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/CoreProfilerExample/appsettings.json b/CoreProfilerExample/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/CoreProfilerExample/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +}