{"id":22302163,"url":"https://github.com/tolgacakir/taskmanagerapp-netcore","last_synced_at":"2025-03-25T23:47:44.920Z","repository":{"id":257572038,"uuid":"290551089","full_name":"tolgacakir/TaskManagerApp-NetCore","owner":"tolgacakir","description":"The task manager sample application with Asp.NetCore MVC","archived":false,"fork":false,"pushed_at":"2021-03-20T19:27:38.000Z","size":802,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-01-30T20:55:23.502Z","etag":null,"topics":["asp-net-core","csharp","layered-architecture","mvc","net-core"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tolgacakir.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-08-26T16:40:00.000Z","updated_at":"2022-09-07T23:24:59.000Z","dependencies_parsed_at":"2024-09-17T13:41:39.705Z","dependency_job_id":"107f2b94-a324-4942-be4c-2114bcb32d2c","html_url":"https://github.com/tolgacakir/TaskManagerApp-NetCore","commit_stats":null,"previous_names":["tolgacakir/taskmanagerapp-netcore"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tolgacakir%2FTaskManagerApp-NetCore","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tolgacakir%2FTaskManagerApp-NetCore/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tolgacakir%2FTaskManagerApp-NetCore/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tolgacakir%2FTaskManagerApp-NetCore/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tolgacakir","download_url":"https://codeload.github.com/tolgacakir/TaskManagerApp-NetCore/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245563041,"owners_count":20635907,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["asp-net-core","csharp","layered-architecture","mvc","net-core"],"created_at":"2024-12-03T18:35:06.989Z","updated_at":"2025-03-25T23:47:44.897Z","avatar_url":"https://github.com/tolgacakir.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# TaskManagerApp-NetCore\nThe task manager sample application with Asp.NetCore MVC.\n\nThe traditional layered architecture is used in this project.\n\n## The Solution Architecture\n- **Core:**\nThe Core layer is a portable class library for every project. It doesn't depend on any project in this solution but it can depend on some nuget libraries. For exp.: FluentValidation. It includes technology-specific project/entity-independent codes like Logger, Validator, ORM interfaces and generic implementations and utilities. For exp.: FileManager, Entity Framework Core GenericRepository, FileLogger...\n\n- **Entities:**\nThe Entities layer is a modelling the DB objects. It includes entity objects that usable in all of the layers like **User**.\n\n- **DataAccessLayer:**\nThe Data Access Layer is layer that connecting to the data. It can includes different data access technologies for exp.: EF, Nhibernate, Ado.Net etc.\nOn the other hand, it includes technology-independent repository interfaces. For exp.: IUserDal.\nThe client (It is BLL in this solution) that using DAL uses only interfaces. However, the client can choose which concrete class (for exp.: EfUserDal or AdoNetUserDal) to implement by constructor injection.\n\n- **BusinessLogicLayer:**\nThis layer acts as a bridge between the UI and DataAccess layers. It includes service/manager classes, business codes etc.\n\n- **WebUi:**\nThis layer is an Asp.Net Core Mvc project. It includes Models, Views, Controllers and the other ready-made classes from Asp.Net Core Mvc\n\n## How to Develop\n\n### Example DB Backup\nYou can access database backup from here: https://drive.google.com/file/d/1-jMfdVZM7dU3qZ-CI2f5tiNkwuoB1u3o/view?usp=sharing\nThere are 3 users in User.dbo; username:password\n- tolga:00000000\n- FirstUser:11111111\n- test_user:22222222\n\n#### Creating New User\nThere is no user creating function on WebUi. You can edit and execute this test method: TaskManagerApp.BusinessLogicLayer.Tests.UserManagerTests.Should_Create_User()\n\n### Changing the **ConnectionString**\n- Open the TaskManagerApp.DataAccessLayer.Concrete.EntityFramework.TaskManagerDbContext.cs file\n- Change the OnConfiguring() -\u003e optionsBuilder.UseSqlServer(@\"**myConnectionString**\");\n\n### Adding the new Entity and Its EF Core based Repositories\n- **Create new entity;**\n```C#\nnamespace TaskManagerApp.Entities.Concrete\n{\n  public class MyEntity : IEntity\n  {\n    public int X {get; set;}\n  }\n}\n```\n___\n- **Create Mapping, Edit DbContext and Apply Mapping**\nCreating Entity Configuration:\n```C#\nnamespace TaskManagerApp.DataAccessLayer.Concrete.EntityFramework.Configurations\n{\n    public class MyEntityConfiguration : IEntityTypeConfiguration\u003cMyEntity\u003e\n    {\n        public void Configure(EntityTypeBuilder\u003cMyEntity\u003e builder)\n        {\n            builder.ToTable(@\"MyEntities\", \"dbo\");\n            builder.HasKey(m =\u003e m.Id);\n            builder.Property(m =\u003e m.Id).HasColumnName(\"Id\");\n            builder.Property(m =\u003e m.X).HasColumnName(\"X\");\n        }\n    }\n}\n```\nAdding DbSet to DbContext and Applying Entity Configuration:\n```C#\nnamespace TaskManagerApp.DataAccessLayer.Concrete.EntityFramework\n{\n    public class TaskManagerDbContext : DbContext\n    {\n        //...\n        public DbSet\u003cMyEntity\u003e MyEntities { get; set; }\n        \n        protected override void OnModelCreating(ModelBuilder modelBuilder)\n        {\n            //...\n            modelBuilder.ApplyConfiguration(new MyEntityConfiguration());\n        }\n    }\n}\n```\n___\n- **Create technology-independent repository interface;**\n```C#\nnamespace TaskManagerApp.DataAccessLayer.Abstract\n{\n  public interface IMyEntityDal : IEntityRepository\u003cMyEntity\u003e\n  {\n  }\n}\n```\nIEntityRepository\u003cT\u003e interface has include CRUD operations.\nIf you want to add a different operation than CRUD;\n```C#\nnamespace TaskManagerApp.DataAccessLayer.Abstract\n{\n  public interface IMyEntityDal : IEntityRepository\u003cEntity\u003e\n  {\n    public int GetCount();\n  }\n}\n```\n___\n- **Create technology-specific repository class;**\n```C#\nnamespace TaskManagerApp.DataAccessLayer.Concrete.EntityFramework\n{\n  public class EfMyEntityDal : EfEntityRepositoryBase\u003cMyEntity,MyDbContext\u003e, IMyEntityDal\n  {\n  }\n}\n```\nEfEntityRepositoryBase\u003cT\u003e has include CRUD implementations for T using EF Core.\nIf you added a different operation than CRUD to IMyEntityDal. You have to implement the method like this;\n```C#\nnamespace TaskManagerApp.DataAccessLayer.Concrete.EntityFramework\n{\n  public class EfMyEntityDal : EfEntityRepositoryBase\u003cMyEntity,MyDbContext\u003e, IMyEntityDal\n  {\n    public int GetCount()\n    {\n      //...\n    }\n  }\n}\n```\n___\n### Adding the new Service/Manager Class for MyEntity on BusinessLogicLayer\n\n- **Create an service interface;**\n```C#\nnamespace TaskManagerApp.BusinessLogicLayer.Abstract\n{\n    public interface IMyEntityService\n    {\n        List\u003cMyEntity\u003e GetAll();\n        void Add(MyEntity myEntity);\n        void Update(MyEntity myEntity);\n        void Delete(MyEntity myEntity);\n        List\u003cMyEntity\u003e GetWithMyCondition(P parameter);\n        \n        // And/Or custom methods...\n        //... \n    }\n}\n```\n___\n- **Create an manager class as an implementation the service interface;**\n```C#\nnamespace TaskManagerApp.BusinessLogicLayer.Abstract\n{\n    public class MyEntityManager : IMyEntityService\n    {\n        private readonly IMyEntityDal _myEntityDal;\n        \n        public MyEntityManager(IMyEntityDal myEntityDal)\n        {\n            _myEntityDal = myEntityDal;\n        }\n        \n        List\u003cMyEntity\u003e GetAll()\n        {\n            //...\n        }\n        \n        void Add(MyEntity myEntity)\n        {\n            //...\n        }\n        \n        void Update(MyEntity myEntity)\n        {\n            //...\n        }\n        \n        void Delete(MyEntity myEntity)\n        {\n            //...\n        }\n        \n        List\u003cMyEntity\u003e GetWithMyCondition(P parameter)\n        {\n            //...\n        }\n    }\n}\n```\nMyEntityManager doesn't know the IMyEntityService implementation or any ORM, DB technologies. This class only works with repository (dal object) interface.\n___\n### Using MyEntity Service Object In Client-Side\n- Registration for dependency injection;\n```C#\nnamespace TaskManagerApp.WebUi\n{\n    public class Startup\n    {\n        //...\n        public void ConfigureServices(IServiceCollection services)\n        {\n            services.AddScoped\u003cIMyEntityService, MyEntityManager\u003e();\n            //...\n        }\n        //...\n    }\n}\n```\n___\n- Inject with constructor and use it;\n```C#\nnamespace TaskManagerApp.WebUi.Controllers\n{\n    [Authorize]\n    public class HomeController : Controller\n    {\n        private readonly IMyEntityService _myEntityManager;\n        //...\n        \n        public HomeController(IMyEntityService myEntityManager, /*...*/)\n        {\n            _myEntityManager = myEntityManager;\n            //...\n        }\n        \n        public IActionResult Index()\n        {\n            try\n            {\n                var myEntities = _myEntityManager.GetAll();\n                //...\n            }\n            catch(Exception)\n            {\n                //...\n            }\n        }\n        //...\n    }\n}\n```\n___\n### Adding Validation For MyEntity\n\n- Create MyEntityValidator;\nTaskManagerApp.BusinessLogicLayer.ValidationRules.FluentValidation -\u003e MyEntityValidator.cs\n```C#\nnamespace TaskManagerApp.BusinessLogicLayer.ValidationRules.FluentValidation\n{\n    public class MyEntityValidator : AbstractValidator\u003cMyEntity\u003e\n    {\n        public MyEntityValidator()\n        {\n            RuleFor(m =\u003e m.X).NotEqual(0).WithMessage(\"X can not be zero.\");\n        }\n    }\n}\n```\n___\n- Use MyEntityValidator in MyEntityManger;\n```C#\nnamespace TaskManagerApp.BusinessLogicLayer.Abstract\n{\n    public class MyEntityManager : IMyEntityService\n    {\n        private readonly IMyEntityDal _myEntityDal;\n        private readonly IValidator _validator;\n        \n        public MyEntityManager(IMyEntityDal myEntityDal)\n        {\n            _myEntityDal = myEntityDal;\n            _validator = new MyEntityValidator();\n        }\n        \n        List\u003cMyEntity\u003e GetAll()\n        {\n            //...\n        }\n        \n        void Add(MyEntity myEntity)\n        {\n            ValidatorTool.Validate(_validator, myEntity);\n            //...\n        }\n        ...\n    }\n}\n```\n___\n### Adding CustomLogger\n- Create CustomLogger; \nTaskManagerApp.Core.CrossCuttingConcerns.Logging.Loggers -\u003e CustomLogger.cs\n```C#\nnamespace TaskManagerApp.Core.CrossCuttingConcerns.Logging.Loggers\n{\n    public class CustomLogger : ILogger\n    {\n        public CustomLogger()\n        {\n        }\n\n        public IDisposable BeginScope\u003cTState\u003e(TState state)\n        {\n            return null;\n        }\n\n        public bool IsEnabled(LogLevel logLevel)\n        {\n            return true;\n        }\n\n        public void Log\u003cTState\u003e(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func\u003cTState, Exception, string\u003e formatter)\n        {\n            string logMessage = $\"...**write log message**...\";\n            //...\n            //write to file, database etc.\n            //...\n        }\n    }\n}\n\n```\n___\n- Create CustomLoggerProvider;\n\n```C#\nnamespace TaskManagerApp.Core.CrossCuttingConcerns.Logging.LoggerProviders\n{\n    public class CustomLoggerProvider : ILoggerProvider\n    {\n        public CustomLoggerProvider()\n        {\n        }\n        public ILogger CreateLogger(string categoryName)\n        {\n            return new CustomLogger();\n        }\n\n        public void Dispose()\n        {\n        }\n    }\n}\n\n```\n___\n- Use CustomLoggerProvider;\n\n```C#\nnamespace TaskManagerApp.WebUi\n{\n    public class Startup\n    {\n        //...\n        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)\n        {\n            loggerFactory.AddProvider(new CustomLoggerProvider());\n            //...\n        }\n        //...\n    }\n}\n```\n___\n- Inject CustomLogger with constructor and use it;\n```C#\nnamespace TaskManagerApp.WebUi.Controllers\n{\n    [Authorize]\n    public class HomeController : Controller\n    {\n        private readonly ILogger\u003cHomeController\u003e _logger;\n        //...\n        \n        public HomeController(ILogger\u003cHomeController\u003e logger, /*...*/)\n        {\n            _logger = logger;\n            //...\n        }\n        \n        public IActionResult Index()\n        {\n            try\n            {\n                //...\n            }\n            catch(Exception)\n            {\n                //...\n               _logger.LogError(/* **log message** */);\n            }\n        }\n        //...\n    }\n}\n```\nThis controller is agnostic about logger implementation.\n___\n### Adding New User Interface\n\n- Create new user interface;\nFor exp.: Console, Winform, Wpf etc.\n\n- Use the service layer objects (in BLL);\nFor exp.: IUserService\n\n- Configure the dependency injection;\nFor ILogger, IUserService etc.\n\n___\n### For More Details\n- Autofac (5.2.0), Autofac.Extras.DynamicProxy (5.0.0) and Castle.Core (4.4.1) packages are using for AOP mechanism. [For more details about interception and DI](https://autofaccn.readthedocs.io/en/latest/advanced/interceptors.html)\n\n- FluentValidation (9.2.0) package are using for validation mechanism. [For more details about validation](https://docs.fluentvalidation.net/en/latest/start.html)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftolgacakir%2Ftaskmanagerapp-netcore","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftolgacakir%2Ftaskmanagerapp-netcore","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftolgacakir%2Ftaskmanagerapp-netcore/lists"}