From 3732b9c0b8a28dc1fdc60375368cabafa9961e77 Mon Sep 17 00:00:00 2001 From: moti Date: Sun, 8 Feb 2026 12:26:02 +0330 Subject: [PATCH] initial --- .gitignore | 407 ++++++++++++++++++ Mf.Core/Interfaces/ICommand.cs | 26 ++ Mf.Core/Interfaces/IContextCore.cs | 20 + Mf.Core/Interfaces/IEmailSender.cs | 23 + Mf.Core/Interfaces/IGenericService.cs | 33 ++ Mf.Core/Mf.Core.csproj | 9 + .../OperationSystem/OperationSystemService.cs | 50 +++ Mf.Core/Services/DateService.cs | 151 +++++++ Mf.Core/Services/EmailSender.cs | 72 ++++ Mf.Core/SubEntities/BaseEntity.cs | 77 ++++ Mf.Core/SubEntities/IEntity.cs | 12 + Mf.Core/SubEntities/QueryModel/Filter.cs | 9 + .../SubEntities/QueryModel/QueryRequest.cs | 19 + Mf.Ef/Mf.Ef.csproj | 17 + Mf.Ef/Services/EntityFrameworkCoreServices.cs | 326 ++++++++++++++ Mf.Ef/Services/PostgresqlContextCore.cs | 127 ++++++ Mf.Ef/Services/SqlServerContextCore.cs | 129 ++++++ Mf.Ef/Services/SqliteContextCore.cs | 145 +++++++ Mf.Entity/Mf.Entity.csproj | 9 + Mf.Entity/Tables/ITable.cs | 7 + Mf.Entity/Tables/TableBase.cs | 21 + Mf.Razor.Entity/Configuration.cs | 9 + .../Interfaces/ICarouselService.cs | 11 + Mf.Razor.Entity/Interfaces/ILogger.cs | 36 ++ Mf.Razor.Entity/Interfaces/IServiceLocator.cs | 13 + Mf.Razor.Entity/Interfaces/ITokenService.cs | 13 + Mf.Razor.Entity/Mf.Razor.Entity.csproj | 9 + Mf.Razor.Entity/Theme.cs | 7 + .../ViewModels/Carousel_Vms/CarouselItemVm.cs | 17 + .../ViewModels/Carousel_Vms/CarouselVm.cs | 13 + Mf.Razor.Entity/ViewModels/Modal_Vm.cs | 11 + .../CustomAuthStateProvider.cs | 110 +++++ Mf.Razor/AuthorizationServices/JwtService.cs | 51 +++ Mf.Razor/Component1.razor | 3 + Mf.Razor/Component1.razor.css | 6 + .../Carousels/DefaultCarousel/Carousel.razor | 24 ++ .../DefaultCarousel/Carousel.razor.css | 68 +++ Mf.Razor/Components/CurrencyInput.razor | 99 +++++ Mf.Razor/Events/ServiceLocatorEventHandler.cs | 4 + Mf.Razor/ExampleJsInterop.cs | 31 ++ Mf.Razor/Interfaces/IModalService.cs | 11 + Mf.Razor/Interfaces/IServiceLocator.cs | 6 + Mf.Razor/Mf.Razor.csproj | 27 ++ Mf.Razor/RazorProvider.cs | 27 ++ Mf.Razor/Services/LogService.cs | 48 +++ Mf.Razor/Services/RequestService.cs | 55 +++ Mf.Razor/Services/ServiceLocator.cs | 49 +++ Mf.Razor/_Imports.razor | 1 + Mf.Razor/wwwroot/background.png | Bin 0 -> 378 bytes Mf.Razor/wwwroot/exampleJsInterop.js | 6 + Mf.sln | 49 +++ 51 files changed, 2503 insertions(+) create mode 100644 .gitignore create mode 100644 Mf.Core/Interfaces/ICommand.cs create mode 100644 Mf.Core/Interfaces/IContextCore.cs create mode 100644 Mf.Core/Interfaces/IEmailSender.cs create mode 100644 Mf.Core/Interfaces/IGenericService.cs create mode 100644 Mf.Core/Mf.Core.csproj create mode 100644 Mf.Core/OperationSystem/OperationSystemService.cs create mode 100644 Mf.Core/Services/DateService.cs create mode 100644 Mf.Core/Services/EmailSender.cs create mode 100644 Mf.Core/SubEntities/BaseEntity.cs create mode 100644 Mf.Core/SubEntities/IEntity.cs create mode 100644 Mf.Core/SubEntities/QueryModel/Filter.cs create mode 100644 Mf.Core/SubEntities/QueryModel/QueryRequest.cs create mode 100644 Mf.Ef/Mf.Ef.csproj create mode 100644 Mf.Ef/Services/EntityFrameworkCoreServices.cs create mode 100644 Mf.Ef/Services/PostgresqlContextCore.cs create mode 100644 Mf.Ef/Services/SqlServerContextCore.cs create mode 100644 Mf.Ef/Services/SqliteContextCore.cs create mode 100644 Mf.Entity/Mf.Entity.csproj create mode 100644 Mf.Entity/Tables/ITable.cs create mode 100644 Mf.Entity/Tables/TableBase.cs create mode 100644 Mf.Razor.Entity/Configuration.cs create mode 100644 Mf.Razor.Entity/Interfaces/ICarouselService.cs create mode 100644 Mf.Razor.Entity/Interfaces/ILogger.cs create mode 100644 Mf.Razor.Entity/Interfaces/IServiceLocator.cs create mode 100644 Mf.Razor.Entity/Interfaces/ITokenService.cs create mode 100644 Mf.Razor.Entity/Mf.Razor.Entity.csproj create mode 100644 Mf.Razor.Entity/Theme.cs create mode 100644 Mf.Razor.Entity/ViewModels/Carousel_Vms/CarouselItemVm.cs create mode 100644 Mf.Razor.Entity/ViewModels/Carousel_Vms/CarouselVm.cs create mode 100644 Mf.Razor.Entity/ViewModels/Modal_Vm.cs create mode 100644 Mf.Razor/AuthorizationServices/CustomAuthStateProvider.cs create mode 100644 Mf.Razor/AuthorizationServices/JwtService.cs create mode 100644 Mf.Razor/Component1.razor create mode 100644 Mf.Razor/Component1.razor.css create mode 100644 Mf.Razor/Components/Carousels/DefaultCarousel/Carousel.razor create mode 100644 Mf.Razor/Components/Carousels/DefaultCarousel/Carousel.razor.css create mode 100644 Mf.Razor/Components/CurrencyInput.razor create mode 100644 Mf.Razor/Events/ServiceLocatorEventHandler.cs create mode 100644 Mf.Razor/ExampleJsInterop.cs create mode 100644 Mf.Razor/Interfaces/IModalService.cs create mode 100644 Mf.Razor/Interfaces/IServiceLocator.cs create mode 100644 Mf.Razor/Mf.Razor.csproj create mode 100644 Mf.Razor/RazorProvider.cs create mode 100644 Mf.Razor/Services/LogService.cs create mode 100644 Mf.Razor/Services/RequestService.cs create mode 100644 Mf.Razor/Services/ServiceLocator.cs create mode 100644 Mf.Razor/_Imports.razor create mode 100644 Mf.Razor/wwwroot/background.png create mode 100644 Mf.Razor/wwwroot/exampleJsInterop.js create mode 100644 Mf.sln diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..516e760 --- /dev/null +++ b/.gitignore @@ -0,0 +1,407 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Oo]ut/ +[Ll]og/ +[Ll]ogs/ + + + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + + + +*.props +*.db +*.db-shm +*.db-wal + +AsilCore/[Oo]bj/ +AsilCore/[Oo]bj/ +AsilCore/[Oo]bj/ +BlazorWasm/[Oo]bj/ +SubAsil.Api/[Oo]bj/ +SubAsil.ConsoleApp/[Oo]bj/ +SubAsil.Core/[Oo]bj/ +SubAsil.DataLayer/[Oo]bj/ +SubAsil.Models/[Oo]bj/ +TelBot_Music.Console/[Oo]bj/ + + + + +AsilCore/obj/ +AsilCore/obj/ +AsilCore/obj/ +BlazorWasm/obj/ +SubAsil.Api/obj/ +SubAsil.ConsoleApp/obj/ +SubAsil.Core/obj/ +SubAsil.DataLayer/obj/ +SubAsil.Models/obj/ +TelBot_Music.Console/obj/ +/SubAsil.Api/appsettings.json + +/SubAsil.Api/appsettings.json +/SubAsil.Api/appsettings.json +.vscode +/SubAsil.Api/internal-nlog.txt +.idea/ + +**/obj +**/bin diff --git a/Mf.Core/Interfaces/ICommand.cs b/Mf.Core/Interfaces/ICommand.cs new file mode 100644 index 0000000..903c364 --- /dev/null +++ b/Mf.Core/Interfaces/ICommand.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Mf.Core.Interfaces +{ + public interface ICommand + { + + } + + public interface ICreateCommand: ICommand + { + + } + + public interface IUpdateCommand : ICommand + { + + } + + public interface IDeleteCommand : ICommand + { + + } +} diff --git a/Mf.Core/Interfaces/IContextCore.cs b/Mf.Core/Interfaces/IContextCore.cs new file mode 100644 index 0000000..652e85a --- /dev/null +++ b/Mf.Core/Interfaces/IContextCore.cs @@ -0,0 +1,20 @@ +using Mf.Core.SubEntities; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Mf.Core.Interfaces +{ + public interface IContextCore + { + public IGenericService GetService() where TEntity : class, IEntity; + + public object GetService(Type type); + + public void Dispose(); + + public void Migrate(); + } +} diff --git a/Mf.Core/Interfaces/IEmailSender.cs b/Mf.Core/Interfaces/IEmailSender.cs new file mode 100644 index 0000000..0d6db0c --- /dev/null +++ b/Mf.Core/Interfaces/IEmailSender.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Mf.Core.Interfaces +{ + public interface IEmailSender + { + string SendEmail(string subject, string address, string body); + string SendDataBaseEmail(string subject, string address, string body, string filePath); + } + + public class EmailConfig + { + public string FromAddress { get; set; } + + public string Password { get; set; } + + public int Port { get; set; } + + public string SmtAddress { get; set; } + } +} diff --git a/Mf.Core/Interfaces/IGenericService.cs b/Mf.Core/Interfaces/IGenericService.cs new file mode 100644 index 0000000..51cf85c --- /dev/null +++ b/Mf.Core/Interfaces/IGenericService.cs @@ -0,0 +1,33 @@ +using Mf.Core.SubEntities; +using Mf.Core.SubEntities.QueryModel; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Mf.Core.Interfaces +{ + public interface IGenericService where TEntity : class, IEntity + { + public IEnumerable GetAll(); + + public IEnumerable GetList(QueryRequest? query = null); + + #region Async MotimatDatabaseCore + public Task GetByIdAsync(CancellationToken cancellationToken, params object[] ids); + + public Task> AddRangeAsync(IEnumerable entities, CancellationToken cancellationToken, bool saveNow = true); + public Task UpdateAsync(object entity, CancellationToken cancellationToken, bool saveNow = true); + + + public Task DeleteAsync(object entity, CancellationToken cancellationToken, bool saveNow = true); + + public Task AddAsync(object entity, CancellationToken cancellationToken, bool saveNow = true); + + #endregion + + + + } +} diff --git a/Mf.Core/Mf.Core.csproj b/Mf.Core/Mf.Core.csproj new file mode 100644 index 0000000..237d661 --- /dev/null +++ b/Mf.Core/Mf.Core.csproj @@ -0,0 +1,9 @@ + + + + net10.0 + enable + enable + + + diff --git a/Mf.Core/OperationSystem/OperationSystemService.cs b/Mf.Core/OperationSystem/OperationSystemService.cs new file mode 100644 index 0000000..99f198a --- /dev/null +++ b/Mf.Core/OperationSystem/OperationSystemService.cs @@ -0,0 +1,50 @@ + + +namespace Mf.Core.OperationSystem +{ + public static class OperationSystemService + { + public static OperationSystemType OS + { + get + { + PlatformID platform = Environment.OSVersion.Platform; + + // Check if the operating system is Windows + if (platform == PlatformID.Win32NT || platform == PlatformID.Win32Windows) + { + Version version = Environment.OSVersion.Version; + return OperationSystemType.Windows; + // Retrieve and display the Windows version + } + else if (platform == PlatformID.Unix) + { + // Retrieve and display the Linux/Unix version + //string versionInfo = ExecuteCommand("uname -a"); + //Console.WriteLine($"Version: {versionInfo}"); + return OperationSystemType.Linux; + } + else + { + return OperationSystemType.Unknown; + + } + } + } + + public static string OperationSystemVersion + { + get + { + return System.Runtime.InteropServices.RuntimeInformation.OSDescription; + } + } + } + + public enum OperationSystemType + { + Windows, + Linux, + Unknown + } +} diff --git a/Mf.Core/Services/DateService.cs b/Mf.Core/Services/DateService.cs new file mode 100644 index 0000000..92ed293 --- /dev/null +++ b/Mf.Core/Services/DateService.cs @@ -0,0 +1,151 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Mf.Core.Services +{ + public static class DateService + { + public static DateTime GetStartOfWeek(this DateTime dt, DayOfWeek startOfWeek) + { + int diff = (7 + (dt.DayOfWeek - startOfWeek)) % 7; + return dt.AddDays(-1 * diff).Date; + } + public static string ToShamsi(this DateTime DateTime1) + { + try + { + PersianCalendar PersianCalendar1 = new PersianCalendar(); + return string.Format(@"{0}/{1}/{2} {3}:{4}:{5}", + PersianCalendar1.GetYear(DateTime1), + PersianCalendar1.GetMonth(DateTime1).ToString("00"), + PersianCalendar1.GetDayOfMonth(DateTime1).ToString("00"), + PersianCalendar1.GetHour(DateTime1).ToString("00"), + PersianCalendar1.GetMinute(DateTime1).ToString("00"), + PersianCalendar1.GetSecond(DateTime1).ToString("00") + ); + } + catch (Exception ex) + { + return "Error"; + } + + } + + public static string ToShamsiDate(this DateTime DateTime1) + { + PersianCalendar PersianCalendar1 = new PersianCalendar(); + return string.Format(@"{0}/{1}/{2}", + PersianCalendar1.GetYear(DateTime1), + PersianCalendar1.GetMonth(DateTime1).ToString("00"), + PersianCalendar1.GetDayOfMonth(DateTime1).ToString("00")); + } + + public static string ToShamsiClock(this DateTime dateTime) + { + PersianCalendar PersianCalendar1 = new PersianCalendar(); + return string.Format(@"{0}:{1}", + PersianCalendar1.GetHour(dateTime).ToString("00"), + PersianCalendar1.GetMinute(dateTime).ToString("00")); + } + + public static DateTime StringToDateTime(this string value) + { + string[] dateTmp = value.Split(' '); + string[] date = dateTmp[0].Split('/'); + string[] time; + if (dateTmp.Length == 2) + { + time = dateTmp[1].Split(':'); + } + else + time = new string[2] { "0", "0" }; + //date = value.Split('/'); + PersianCalendar persianCal = new PersianCalendar(); + return persianCal.ToDateTime(Convert.ToInt16(date[0]), Convert.ToInt16(date[1]), Convert.ToInt16(date[2]), int.Parse(time[0]), int.Parse(time[1]), int.Parse(time[2]), 0); + + return new DateTime(Convert.ToInt16(date[0]), Convert.ToInt16(date[1]), Convert.ToInt16(date[2])); + // return new JalaliDate(Convert.ToInt16(date[0]), Convert.ToByte(date[1]), Convert.ToByte(date[2])).ToDateTime().AddHours(double.Parse(time[0])).AddMinutes(double.Parse(time[1])); + + } + + + + public static DateTime StringDateToDateTime(this string value) + { + + + string[] dateTmp = value.Split(' '); + string[] date = dateTmp[0].Split('/'); + string[] time; + if (dateTmp.Length == 2) + { + time = dateTmp[1].Split(':'); + } + else + time = new string[2] { "0", "0" }; + //date = value.Split('/'); + PersianCalendar persianCal = new PersianCalendar(); + return persianCal.ToDateTime(Convert.ToInt16(date[0]), Convert.ToInt16(date[1]), Convert.ToInt16(date[2]), int.Parse(time[0]), int.Parse(time[1]), 0, 0); + + return new DateTime(Convert.ToInt16(date[0]), Convert.ToInt16(date[1]), Convert.ToInt16(date[2])); + // return new JalaliDate(Convert.ToInt16(date[0]), Convert.ToByte(date[1]), Convert.ToByte(date[2])).ToDateTime().AddHours(double.Parse(time[0])).AddMinutes(double.Parse(time[1])); + + } + + + + public static TimeSpan StringToTimeSpan(this string value) + { + try + { + var split = value.Split(":"); + return new TimeSpan(int.Parse(split[0]), int.Parse(split[1]), int.Parse(split[2])); + } + catch (Exception ex) + { + //Console.WriteLine(ex); + return new TimeSpan(); + } + } + + public static string DayOfWeekShamsi(this DayOfWeek day) + { + switch (day) + { + case (DayOfWeek.Saturday): + return "شنبه"; + break; + + case (DayOfWeek.Sunday): + return "یک شنبه"; + break; + case (DayOfWeek.Monday): + return "دو شنبه"; + case (DayOfWeek.Tuesday): + return "سه شنبه"; + case (DayOfWeek.Wednesday): + return "چهار شنبه"; + case (DayOfWeek.Thursday): + return "پنج شنبه"; + case (DayOfWeek.Friday): + return "جمعه"; + default: + return ""; + } + } + } + + + //public static class DateConvertor + //{ + // public static string ToShamsi(this DateTime date) + // { + // PersianCalendar persian = new PersianCalendar(); + // return persian.GetYear(date) + "/" + persian.GetMonth(date).ToString("00") + "/" + persian.GetDayOfMonth(date).ToString("00"); + // } + //} +} diff --git a/Mf.Core/Services/EmailSender.cs b/Mf.Core/Services/EmailSender.cs new file mode 100644 index 0000000..dad906f --- /dev/null +++ b/Mf.Core/Services/EmailSender.cs @@ -0,0 +1,72 @@ +using Mf.Core.Interfaces; +using System; +using System.Collections.Generic; +using System.Net; +using System.Net.Mail; +using System.Text; + +namespace Mf.Core.Services +{ + public class EmailSender : IEmailSender + { + public EmailConfig _config; + public EmailSender(EmailConfig config) + { + _config = config; + } + + public string SendEmail(string subject, string address, string body) + { + try + { + SmtpClient client = new SmtpClient("smtp.gmail.com", 587); + client.EnableSsl = true; + client.Credentials = new NetworkCredential(_config.FromAddress, _config.Password); + MailAddress from = new MailAddress(_config.FromAddress); + MailAddress to = new MailAddress(address); + MailMessage message = new MailMessage(from, to); + message.Body = body; + message.BodyEncoding = Encoding.UTF8; + message.Subject = subject; + message.SubjectEncoding = Encoding.UTF8; + client.Send(message); + message.Dispose(); + return "Success"; + } + catch (Exception ex) + { + return ex.Message.ToString(); + } + } + + public string SendDataBaseEmail(string subject, string address, string body, string filePath) + { + try + { + SmtpClient client = new SmtpClient("smtp.gmail.com", 587); + client.EnableSsl = true; + client.Credentials = new NetworkCredential(_config.FromAddress, _config.Password); + MailAddress from = new MailAddress(_config.FromAddress); + MailAddress to = new MailAddress(address); + MailMessage message = new MailMessage(from, to); + message.Body = body; + message.BodyEncoding = Encoding.UTF8; + message.Subject = subject; + message.SubjectEncoding = Encoding.UTF8; + if (File.Exists(filePath)) + { + Attachment attachment = new Attachment(filePath); + message.Attachments.Add(attachment); + } + client.Send(message); + message.Dispose(); + return "Success"; + } + catch (Exception ex) + { + return ex.Message.ToString(); + } + } + + } +} diff --git a/Mf.Core/SubEntities/BaseEntity.cs b/Mf.Core/SubEntities/BaseEntity.cs new file mode 100644 index 0000000..815b841 --- /dev/null +++ b/Mf.Core/SubEntities/BaseEntity.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace Mf.Core.SubEntities +{ + public abstract class BaseEntity : IEntity + { + [Key] + [Display(Name = "شماره")] + + public T Id { get; set; } + } + public abstract class BaseEntity : BaseEntity + { + + } + + public static class BaseEntityService + { + public static IEnumerable GetModelsByAttribute(Type attribute) + { + + + Assembly assembly = Assembly.GetExecutingAssembly(); + + // همه‌ی تایپ‌های موجود در Assembly را دریافت می‌کنیم + Type[] types = assembly.GetTypes(); + + // لیستی برای نگهداری تایپ‌هایی که دارای Custom Attribute مورد نظر هستند + List typesWithCustomAttribute = new List(); + + + var typess = from assemblyy in AppDomain.CurrentDomain.GetAssemblies() + from type in assemblyy.GetTypes() + where type.IsDefined(attribute) + select type; + + + // بررسی Custom Attribute هر تایپ + foreach (Type type in typess) + { + // بررسی Custom Attribute هر تایپ + var attributes = type.GetCustomAttributes(attribute, false); + if (attributes.Length > 0) + { + // این تایپ دارای Custom Attribute مورد نظر است + typesWithCustomAttribute.Add(type); + } + } + + // چاپ نتیجه‌ی تایپ‌های دارای Custom Attribute مورد نظر + + //----------------------------------------------------------------------- + //var types = from assembly in AppDomain.CurrentDomain.GetAssemblies() + // from type in assembly.GetTypes() + // where type.IsDefined(typeof(TableAttribute)) + // select type; + return typesWithCustomAttribute; + + + var ass = typeof(BaseEntity).Assembly; + var all = ass.GetExportedTypes().Where(c => typeof(BaseEntity).IsAssignableFrom(c)); + var aa = ass.GetExportedTypes().Where(c => c.IsClass && c.IsPublic && !c.IsAbstract && typeof(BaseEntity).IsAssignableFrom(c)); + return aa; + + // Assembly فعلی را دریافت می‌کنیم + + } + } + +} diff --git a/Mf.Core/SubEntities/IEntity.cs b/Mf.Core/SubEntities/IEntity.cs new file mode 100644 index 0000000..f5d170d --- /dev/null +++ b/Mf.Core/SubEntities/IEntity.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Mf.Core.SubEntities +{ + public interface IEntity + { + } +} diff --git a/Mf.Core/SubEntities/QueryModel/Filter.cs b/Mf.Core/SubEntities/QueryModel/Filter.cs new file mode 100644 index 0000000..cbaa64d --- /dev/null +++ b/Mf.Core/SubEntities/QueryModel/Filter.cs @@ -0,0 +1,9 @@ +namespace Mf.Core.SubEntities.QueryModel +{ + public class Filter + { + public string Field { get; set; } + public string Operator { get; set; } + public string Value { get; set; } + } +} diff --git a/Mf.Core/SubEntities/QueryModel/QueryRequest.cs b/Mf.Core/SubEntities/QueryModel/QueryRequest.cs new file mode 100644 index 0000000..fe6e27f --- /dev/null +++ b/Mf.Core/SubEntities/QueryModel/QueryRequest.cs @@ -0,0 +1,19 @@ +namespace Mf.Core.SubEntities.QueryModel +{ + public class QueryRequest + { + public string? ObjectType { get; set; } + public List Filters { get; set; } = new(); + public List Includes { get; set; } = new(); + public int? Skip { get; set; } + public int? Take { get; set; } + + } + + public class AlterRequest + { + public string? ObjectType { get; set; } + + public object? Model { get; set; } + } +} diff --git a/Mf.Ef/Mf.Ef.csproj b/Mf.Ef/Mf.Ef.csproj new file mode 100644 index 0000000..36e4ef7 --- /dev/null +++ b/Mf.Ef/Mf.Ef.csproj @@ -0,0 +1,17 @@ + + + + net10.0 + enable + enable + + + + + + + + + + + diff --git a/Mf.Ef/Services/EntityFrameworkCoreServices.cs b/Mf.Ef/Services/EntityFrameworkCoreServices.cs new file mode 100644 index 0000000..ea45e72 --- /dev/null +++ b/Mf.Ef/Services/EntityFrameworkCoreServices.cs @@ -0,0 +1,326 @@ +using Microsoft.EntityFrameworkCore; +using Mf.Core.Interfaces; +using Mf.Core.SubEntities; +using Mf.Core.SubEntities.QueryModel; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Security.Principal; +using System.Text; +using System.Threading.Tasks; + +namespace Mf.EfCore.Services +{ + public class EntityFrameworkCoreServices : IGenericService, IDisposable + where TEntity : class, IEntity + { + protected readonly DbContext DbContext; + public DbSet Entities { get; } + public virtual IQueryable Table => Entities; + public virtual IQueryable TableNoTracking => Entities.AsNoTracking(); + + + public EntityFrameworkCoreServices(DbContext dbContext) + { + DbContext = dbContext; + Entities = DbContext.Set(); // City => Cities + } + + #region Async Method + public virtual async Task GetByIdAsync(CancellationToken cancellationToken, params object[] ids) + { + return await Entities.FindAsync(ids, cancellationToken).AsTask(); + } + + public virtual async Task AddAsync(TEntity entity, CancellationToken cancellationToken, bool saveNow = true) + { + var entityFull = await DbContext.AddAsync(entity, cancellationToken).ConfigureAwait(false); + if (saveNow) + { + try + { + await DbContext.SaveChangesAsync(cancellationToken).ConfigureAwait(false); + } + catch (Exception ex) + { + return null; + } + finally + { + entityFull.State = EntityState.Detached; + } + } + return entityFull.Entity; + } + + public virtual async Task> AddRangeAsync(IEnumerable entities, CancellationToken cancellationToken, bool saveNow = true) + { + await Entities.AddRangeAsync(entities, cancellationToken).ConfigureAwait(false); + if (saveNow) + await DbContext.SaveChangesAsync(cancellationToken).ConfigureAwait(false); + return entities; + } + + public virtual async Task UpdateAsync(TEntity entity, CancellationToken cancellationToken, bool saveNow = true) + { + var EntityState = Entities.Update(entity); + if (saveNow) + { + await DbContext.SaveChangesAsync(cancellationToken); + EntityState.State = Microsoft.EntityFrameworkCore.EntityState.Detached; + } + return entity; + } + + public virtual async Task> UpdateRangeAsync(IEnumerable entities, CancellationToken cancellationToken, bool saveNow = true) + { + Entities.UpdateRange(entities); + if (saveNow) + await DbContext.SaveChangesAsync(cancellationToken); + + return entities; + } + + public virtual async Task DeleteAsync(TEntity entity, CancellationToken cancellationToken, bool saveNow = true) + { + try + { + Entities.Remove(entity); + } + catch (Exception ex) + { + + throw; + } + if (saveNow) + await DbContext.SaveChangesAsync(cancellationToken); + return entity; + } + + public virtual async Task> DeleteRangeAsync(IEnumerable entities, CancellationToken cancellationToken, bool saveNow = true) + { + Entities.RemoveRange(entities); + if (saveNow) + await DbContext.SaveChangesAsync(cancellationToken); + return entities; + } + #endregion + + #region Sync Methods + public virtual TEntity GetById(params object[] ids) + { + return Entities.Find(ids); + } + + public virtual void Add(TEntity entity, bool saveNow = true) + { + + Entities.Add(entity); + if (saveNow) + DbContext.SaveChanges(); + } + + public virtual void AddRange(IEnumerable entities, bool saveNow = true) + { + + Entities.AddRange(entities); + if (saveNow) + DbContext.SaveChanges(); + } + + public virtual void Update(TEntity entity, bool saveNow = true) + { + + Entities.Update(entity); + DbContext.SaveChanges(); + } + + public virtual void UpdateRange(IEnumerable entities, bool saveNow = true) + { + + Entities.UpdateRange(entities); + if (saveNow) + DbContext.SaveChanges(); + } + + public virtual void Delete(TEntity entity, bool saveNow = true) + { + + Entities.Remove(entity); + if (saveNow) + DbContext.SaveChanges(); + } + + public virtual void DeleteRange(IEnumerable entities, bool saveNow = true) + { + + Entities.RemoveRange(entities); + if (saveNow) + DbContext.SaveChanges(); + } + #endregion + + #region Attach & Detach + public virtual void Detach(TEntity entity) + { + + var entry = DbContext.Entry(entity); + if (entry != null) + entry.State = EntityState.Detached; + } + + public virtual void Attach(TEntity entity) + { + + if (DbContext.Entry(entity).State == EntityState.Detached) + Entities.Attach(entity); + } + #endregion + + #region Explicit Loading + public virtual async Task LoadCollectionAsync(TEntity entity, Expression>> collectionProperty, CancellationToken cancellationToken) + where TProperty : class + { + Attach(entity); + + var collection = DbContext.Entry(entity).Collection(collectionProperty); + if (!collection.IsLoaded) + await collection.LoadAsync(cancellationToken).ConfigureAwait(false); + } + + public virtual void LoadCollection(TEntity entity, Expression>> collectionProperty) + where TProperty : class + { + Attach(entity); + var collection = DbContext.Entry(entity).Collection(collectionProperty); + if (!collection.IsLoaded) + collection.Load(); + } + + public virtual async Task LoadReferenceAsync(TEntity entity, Expression> referenceProperty, CancellationToken cancellationToken) + where TProperty : class + { + Attach(entity); + var reference = DbContext.Entry(entity).Reference(referenceProperty); + if (!reference.IsLoaded) + await reference.LoadAsync(cancellationToken).ConfigureAwait(false); + } + + public virtual void LoadReference(TEntity entity, Expression> referenceProperty) + where TProperty : class + { + Attach(entity); + var reference = DbContext.Entry(entity).Reference(referenceProperty); + if (!reference.IsLoaded) + reference.Load(); + } + + public void SaveChange() + { + DbContext.SaveChanges(); + } + + public async Task SaveChangeAsync() + { + await DbContext.SaveChangesAsync(); + return true; + } + + + #endregion + public void Dispose() + { + DbContext.Dispose(); + } + + + //TODO: Complte there + public IEnumerable GetAll() + { + return TableNoTracking; + } + + async Task IGenericService.GetByIdAsync(CancellationToken cancellationToken, params object[] ids) + { + var res = await GetByIdAsync(cancellationToken, ids); + return (IEntity)res; + } + + public Task> AddRangeAsync(IEnumerable entities, CancellationToken cancellationToken, bool saveNow = true) + { + throw new NotImplementedException(); + } + + public async Task UpdateAsync(object entity, CancellationToken cancellationToken, bool saveNow = true) + { + var en = (TEntity)entity; + var result = await UpdateAsync(en, cancellationToken, saveNow); + return result; + } + + public async Task AddAsync(object entity, CancellationToken cancellationToken, bool saveNow = true) + { + var b = (TEntity)entity; + var res = await AddAsync(b, cancellationToken, saveNow); + return res; + } + + public async Task DeleteAsync(object entity, CancellationToken cancellationToken, bool saveNow = true) + { + var en = (TEntity)entity; + var result = await DeleteAsync(en, cancellationToken, saveNow); + return result; + } + + public IEnumerable GetList(QueryRequest? query = null) + { + var products = TableNoTracking.AsQueryable(); + if (query == null) + { + return products; + } + foreach (var include in query.Includes) + { + products = products.Include(include); + } + // 2. Apply Filters + foreach (var filter in query.Filters) + { + products = ApplyFilter(products, filter); + } + // 3. Apply Skip and Take + if (query.Skip.HasValue) + products = products.Skip(query.Skip.Value); + if (query.Take.HasValue) + products = products.Take(query.Take.Value); + return products; + } + + private IQueryable ApplyFilter(IQueryable query, Filter filter) + { + var parameter = Expression.Parameter(typeof(TEntity), "x"); + var property = Expression.Property(parameter, filter.Field); + var constant = Expression.Constant(Convert.ChangeType(filter.Value, property.Type)); + + Expression body = filter.Operator switch + { + "=" => Expression.Equal(property, constant), + ">" => Expression.GreaterThan(property, constant), + ">=" => Expression.GreaterThanOrEqual(property, constant), + "<" => Expression.LessThan(property, constant), + "<=" => Expression.LessThanOrEqual(property, constant), + "!=" => Expression.NotEqual(property, constant), + "Contains" => Expression.Call(property, nameof(string.Contains), Type.EmptyTypes, constant), + "StartsWith" => Expression.Call(property, nameof(string.Contains), Type.EmptyTypes, constant), + "EndsWith" => Expression.Call(property, nameof(string.Contains), Type.EmptyTypes, constant), + _ => throw new NotSupportedException($"Operator {filter.Operator} not supported.") + }; + + var lambda = Expression.Lambda>(body, parameter); + return query.Where(lambda); + } + + + } +} diff --git a/Mf.Ef/Services/PostgresqlContextCore.cs b/Mf.Ef/Services/PostgresqlContextCore.cs new file mode 100644 index 0000000..be033a8 --- /dev/null +++ b/Mf.Ef/Services/PostgresqlContextCore.cs @@ -0,0 +1,127 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Mf.Core.Interfaces; +using Mf.Core.SubEntities; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Mf.EfCore.Services +{ + public class PostgresqlContextCore : DbContext, IContextCore + { + public PostgresqlContextCore(DbContextOptions optinos) : base(optinos) { } + + public List? Entities { get; set; } + + public IGenericService GetService() where TypeModel : class, IEntity + { + var telBotServiceType = typeof(EntityFrameworkCoreServices<>).MakeGenericType(typeof(TypeModel)); + var constructor = telBotServiceType.GetConstructor(new[] { typeof(SqlServerContextCore) }); + if (constructor != null) + { + var telBotServiceInstance = constructor.Invoke(new object[] { this }); + return (EntityFrameworkCoreServices)telBotServiceInstance; + } + else + { + + var telBotServiceInstance = Activator.CreateInstance(telBotServiceType); + + return (EntityFrameworkCoreServices)telBotServiceInstance!; + } + } + + public object GetService(Type type) + { + var telBotServiceType = typeof(EntityFrameworkCoreServices<>).MakeGenericType(type); + var constructor = telBotServiceType.GetConstructor(new[] { typeof(SqlServerContextCore) }); + if (constructor != null) + { + var telBotServiceInstance = constructor.Invoke(new object[] { this }); + return telBotServiceInstance; + } + else + { + var telBotServiceInstance = Activator.CreateInstance(telBotServiceType); + return telBotServiceInstance!; + } + } + + + + public List GetGenericServices(List entities) + { + List services = new List(); + foreach (var type in entities) + { + var telBotServiceType = typeof(EntityFrameworkCoreServices<>).MakeGenericType(type); + // Get the constructor of the TelBot_Service type + var constructor = telBotServiceType.GetConstructor(new[] { typeof(SqlServerContextCore) }); + if (constructor != null) + { + // If constructor exists, create an instance with a parameter + var telBotServiceInstance = constructor.Invoke(new object[] { this }); // Provide the parameter value here + //var ssss = (IGenericService)telBotServiceInstance; + //var sss = (EntityFrameworkCoreServices)telBotServiceInstance; + services.Add(telBotServiceInstance); + } + else + { + // If no constructor exists, create an instance without parameters + var telBotServiceInstance = Activator.CreateInstance(telBotServiceType); + //var sss = (EntityFrameworkCoreServices)telBotServiceInstance; + services.Add(telBotServiceInstance); + } + } + return services; + } + + + + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + if (Entities != null) + { + foreach (var s in Entities) + { + var entity = modelBuilder.Entity(s); + } + + + //for postgres db + foreach (var entityType in modelBuilder.Model.GetEntityTypes()) + { + foreach (var property in entityType.GetProperties()) + { + if (property.ClrType == typeof(DateTime)) + { + property.SetValueConverter(new ValueConverter( + v => v.Kind == DateTimeKind.Utc ? v : v.ToUniversalTime(), // ذخیره + v => DateTime.SpecifyKind(v, DateTimeKind.Utc) // بازیابی + )); + } + + else if (property.ClrType == typeof(DateTime?)) + { + property.SetValueConverter(new ValueConverter( + v => v.HasValue ? (v.Value.Kind == DateTimeKind.Utc ? v : v.Value.ToUniversalTime()) : v, // ذخیره + v => v.HasValue ? DateTime.SpecifyKind(v.Value, DateTimeKind.Utc) : v // بازیابی + )); + } + } + } + } + } + void IContextCore.Dispose() + { + this.Dispose(); + } + + public void Migrate() + { + this.Migrate(); + } + } +} diff --git a/Mf.Ef/Services/SqlServerContextCore.cs b/Mf.Ef/Services/SqlServerContextCore.cs new file mode 100644 index 0000000..36e804b --- /dev/null +++ b/Mf.Ef/Services/SqlServerContextCore.cs @@ -0,0 +1,129 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Mf.Core.Interfaces; +using Mf.Core.SubEntities; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Mf.EfCore.Services +{ + public class SqlServerContextCore : DbContext, IContextCore + { + public SqlServerContextCore(DbContextOptions optinos) : base(optinos) { } + + public List? Entities { get; set; } + + public IGenericService GetService() where TypeModel : class, IEntity + { + var telBotServiceType = typeof(EntityFrameworkCoreServices<>).MakeGenericType(typeof(TypeModel)); + var constructor = telBotServiceType.GetConstructor(new[] { typeof(SqlServerContextCore) }); + if (constructor != null) + { + var telBotServiceInstance = constructor.Invoke(new object[] { this }); + return (EntityFrameworkCoreServices)telBotServiceInstance; + } + else + { + + var telBotServiceInstance = Activator.CreateInstance(telBotServiceType); + + return (EntityFrameworkCoreServices)telBotServiceInstance!; + } + } + + public object GetService(Type type) + { + var telBotServiceType = typeof(EntityFrameworkCoreServices<>).MakeGenericType(type); + var constructor = telBotServiceType.GetConstructor(new[] { typeof(SqlServerContextCore) }); + if (constructor != null) + { + var telBotServiceInstance = constructor.Invoke(new object[] { this }); + return telBotServiceInstance; + } + else + { + var telBotServiceInstance = Activator.CreateInstance(telBotServiceType); + return telBotServiceInstance!; + } + } + + + + public List GetGenericServices(List entities) + { + List services = new List(); + foreach (var type in entities) + { + var telBotServiceType = typeof(EntityFrameworkCoreServices<>).MakeGenericType(type); + // Get the constructor of the TelBot_Service type + var constructor = telBotServiceType.GetConstructor(new[] { typeof(SqlServerContextCore) }); + if (constructor != null) + { + // If constructor exists, create an instance with a parameter + var telBotServiceInstance = constructor.Invoke(new object[] { this }); // Provide the parameter value here + //var ssss = (IGenericService)telBotServiceInstance; + //var sss = (EntityFrameworkCoreServices)telBotServiceInstance; + services.Add(telBotServiceInstance); + } + else + { + // If no constructor exists, create an instance without parameters + var telBotServiceInstance = Activator.CreateInstance(telBotServiceType); + //var sss = (EntityFrameworkCoreServices)telBotServiceInstance; + services.Add(telBotServiceInstance); + } + } + return services; + } + + + + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + if (Entities != null) + { + foreach (var s in Entities) + { + var entity = modelBuilder.Entity(s); + } + + + //for postgres db + foreach (var entityType in modelBuilder.Model.GetEntityTypes()) + { + foreach (var property in entityType.GetProperties()) + { + if (property.ClrType == typeof(DateTime)) + { + property.SetValueConverter(new ValueConverter( + v => v.Kind == DateTimeKind.Utc ? v : v.ToUniversalTime(), // ذخیره + v => DateTime.SpecifyKind(v, DateTimeKind.Utc) // بازیابی + )); + } + + else if (property.ClrType == typeof(DateTime?)) + { + property.SetValueConverter(new ValueConverter( + v => v.HasValue ? (v.Value.Kind == DateTimeKind.Utc ? v : v.Value.ToUniversalTime()) : v, // ذخیره + v => v.HasValue ? DateTime.SpecifyKind(v.Value, DateTimeKind.Utc) : v // بازیابی + )); + } + } + } + } + } + void IContextCore.Dispose() + { + this.Dispose(); + } + + public void Migrate() + { + this.Migrate(); + } + } +} diff --git a/Mf.Ef/Services/SqliteContextCore.cs b/Mf.Ef/Services/SqliteContextCore.cs new file mode 100644 index 0000000..c0b9f51 --- /dev/null +++ b/Mf.Ef/Services/SqliteContextCore.cs @@ -0,0 +1,145 @@ +using Microsoft.EntityFrameworkCore; +using Mf.Core.Interfaces; +using Mf.Core.SubEntities; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Mf.EfCore.Services +{ + public abstract class SqliteContextCore : DbContext, IContextCore + { + public string DbName { get; set; } + public string DbPath { get; set; } + + public List Entities { get; set; } + + public void SetDefaultConfig() + { + DbName = "defualt-database-name.db"; + DbPath = ""; + } + public SqliteContextCore(bool setDefaultConfig = true) + { + + if (setDefaultConfig) + { + SetDefaultConfig(); + CreateDB(); + } + + } + public void CreateDB() + { + //TODO clean this + //var strDestination = "copy.db"; + //string dir = Directory.GetCurrentDirectory(); + //dir = Path.Combine(dir, strDestination); + + + //string orgDir = Path.Combine(Directory.GetCurrentDirectory(), DbPath, DbName); + + //if (!Path.Exists(Path.Combine(Directory.GetCurrentDirectory(), DbPath))) + //{ + // Directory.CreateDirectory(Path.Combine(Directory.GetCurrentDirectory(), DbPath)); + //} + + //if (!File.Exists(orgDir)) + //{ + + // System.Data.SQLite.SQLiteConnection.CreateFile(orgDir); + //} + + //if (!File.Exists(dir)) + //{ + + // System.Data.SQLite.SQLiteConnection.CreateFile(dir); + //} + + //using (var location = new System.Data.SQLite.SQLiteConnection(string.Format(@"Data Source={0};", orgDir))) + ////using (var destination = new System.Data.SQLite.SQLiteConnection(string.Format(@"Data Source={0}", dir))) + //{ + // location.Open(); + // //destination.Open(); + // //location.BackupDatabase(destination, "main", "main", -1, null, 0); + // //destination.Close(); + //} + + + + } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + optionsBuilder.UseSqlite($"Data Source={DbPath}{DbName}"); + } + + + public IGenericService GetService() where TypeModel : class, IEntity + { + var telBotServiceType = typeof(EntityFrameworkCoreServices<>).MakeGenericType(typeof(TypeModel)); + var constructor = telBotServiceType.GetConstructor(new[] { typeof(SqliteContextCore) }); + if (constructor != null) + { + var telBotServiceInstance = constructor.Invoke(new object[] { this }); + return (EntityFrameworkCoreServices)telBotServiceInstance; + } + else + { + + var telBotServiceInstance = Activator.CreateInstance(telBotServiceType); + + return (EntityFrameworkCoreServices)telBotServiceInstance!; + } + } + + public object GetService(Type type) + { + var telBotServiceType = typeof(EntityFrameworkCoreServices<>).MakeGenericType(type); + var constructor = telBotServiceType.GetConstructor(new[] { typeof(SqliteContextCore) }); + if (constructor != null) + { + var telBotServiceInstance = constructor.Invoke(new object[] { this }); + return telBotServiceInstance; + } + else + { + var telBotServiceInstance = Activator.CreateInstance(telBotServiceType); + return telBotServiceInstance!; + } + } + + void IContextCore.Dispose() + { + this.Dispose(); + } + + public void Migrate() + { + try + { + this.Migrate(); + } + catch + { + + } + + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + if (Entities != null) + { + foreach (var s in Entities) + { + var entity = modelBuilder.Entity(s); + } + } + } + + + } +} diff --git a/Mf.Entity/Mf.Entity.csproj b/Mf.Entity/Mf.Entity.csproj new file mode 100644 index 0000000..237d661 --- /dev/null +++ b/Mf.Entity/Mf.Entity.csproj @@ -0,0 +1,9 @@ + + + + net10.0 + enable + enable + + + diff --git a/Mf.Entity/Tables/ITable.cs b/Mf.Entity/Tables/ITable.cs new file mode 100644 index 0000000..2d4ab4d --- /dev/null +++ b/Mf.Entity/Tables/ITable.cs @@ -0,0 +1,7 @@ +namespace Mf.Entity.Tables; + +public interface ITable +{ + +} + diff --git a/Mf.Entity/Tables/TableBase.cs b/Mf.Entity/Tables/TableBase.cs new file mode 100644 index 0000000..2fe6cf2 --- /dev/null +++ b/Mf.Entity/Tables/TableBase.cs @@ -0,0 +1,21 @@ +using System.ComponentModel.DataAnnotations; + +namespace Mf.Entity.Tables; + +public abstract class TableBase:ITable +{ + [Key] + public T? Id { get; set; } + + private List>? _seedData = null; +} + +public abstract class Tablebase : TableBase +{ + + public Tablebase() + { + + } +} + diff --git a/Mf.Razor.Entity/Configuration.cs b/Mf.Razor.Entity/Configuration.cs new file mode 100644 index 0000000..95382bf --- /dev/null +++ b/Mf.Razor.Entity/Configuration.cs @@ -0,0 +1,9 @@ +namespace Mf.Razor.Entity +{ + public class Configuration + { + public int Radios { get; set; } + + public Theme? Theme { get; set; } + } +} diff --git a/Mf.Razor.Entity/Interfaces/ICarouselService.cs b/Mf.Razor.Entity/Interfaces/ICarouselService.cs new file mode 100644 index 0000000..d6a2a59 --- /dev/null +++ b/Mf.Razor.Entity/Interfaces/ICarouselService.cs @@ -0,0 +1,11 @@ +using Mf.Razor.Entity.ViewModels; + +namespace Mf.Razor.Entity.Interfaces; + +public interface ICarouselService +{ + public Task GetCarousel(int? carouselId = 0); + + public Task ExecuteCarousel(CarouselVm carousel); + +} \ No newline at end of file diff --git a/Mf.Razor.Entity/Interfaces/ILogger.cs b/Mf.Razor.Entity/Interfaces/ILogger.cs new file mode 100644 index 0000000..2d1f8c9 --- /dev/null +++ b/Mf.Razor.Entity/Interfaces/ILogger.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Mf.Razor.Entity.Interfaces +{ + public interface IFrontLogger + { + void Log(string content, LogMode mode, TimeSpan time); + void Log(string content, LogMode mode); + void Log(string content); + + List GetAllLogs(); + + void ClearLogs(); + + public static event EventHandler LogEvent; + } + + + public class LogModel + { + public string LogContent { get; set; } + public DateTime CreatedDate { get; set; } + public int index { get; set; } + public LogMode LogMode { get; set; } + public TimeSpan? Time { get; set; } + } + public enum LogMode + { + Info = 0, + Error = 1 + } +} diff --git a/Mf.Razor.Entity/Interfaces/IServiceLocator.cs b/Mf.Razor.Entity/Interfaces/IServiceLocator.cs new file mode 100644 index 0000000..d5ae5bd --- /dev/null +++ b/Mf.Razor.Entity/Interfaces/IServiceLocator.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Mf.Razor.Entity.Interfaces +{ + public interface IServiceLocator + { + + } +} diff --git a/Mf.Razor.Entity/Interfaces/ITokenService.cs b/Mf.Razor.Entity/Interfaces/ITokenService.cs new file mode 100644 index 0000000..5d8cfec --- /dev/null +++ b/Mf.Razor.Entity/Interfaces/ITokenService.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Mf.Razor.Entity.Interfaces +{ + public interface ITokenService + { + Task GetToken(); + Task SetToken(string token); + Task RemoveToke(); + } +} diff --git a/Mf.Razor.Entity/Mf.Razor.Entity.csproj b/Mf.Razor.Entity/Mf.Razor.Entity.csproj new file mode 100644 index 0000000..237d661 --- /dev/null +++ b/Mf.Razor.Entity/Mf.Razor.Entity.csproj @@ -0,0 +1,9 @@ + + + + net10.0 + enable + enable + + + diff --git a/Mf.Razor.Entity/Theme.cs b/Mf.Razor.Entity/Theme.cs new file mode 100644 index 0000000..34d69c5 --- /dev/null +++ b/Mf.Razor.Entity/Theme.cs @@ -0,0 +1,7 @@ +namespace Mf.Razor.Entity +{ + public class Theme + { + + } +} diff --git a/Mf.Razor.Entity/ViewModels/Carousel_Vms/CarouselItemVm.cs b/Mf.Razor.Entity/ViewModels/Carousel_Vms/CarouselItemVm.cs new file mode 100644 index 0000000..8441b0b --- /dev/null +++ b/Mf.Razor.Entity/ViewModels/Carousel_Vms/CarouselItemVm.cs @@ -0,0 +1,17 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace Mf.Razor.Entity.ViewModels; + +[NotMapped] +public class CarouselItemVm +{ + public int Index { get; set; } + + public string? Title { get; set; } + + public string? ImageAddress { get; set; } + + public string? LinkAddress { get; set; } + + public CarouselVm? Carousel{ get; set; } +} \ No newline at end of file diff --git a/Mf.Razor.Entity/ViewModels/Carousel_Vms/CarouselVm.cs b/Mf.Razor.Entity/ViewModels/Carousel_Vms/CarouselVm.cs new file mode 100644 index 0000000..6615cc8 --- /dev/null +++ b/Mf.Razor.Entity/ViewModels/Carousel_Vms/CarouselVm.cs @@ -0,0 +1,13 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace Mf.Razor.Entity.ViewModels; + +[NotMapped] +public class CarouselVm +{ + public int Height { get; set; } + + public int Width { get; set; } + + public List? Items { get; set; } +} \ No newline at end of file diff --git a/Mf.Razor.Entity/ViewModels/Modal_Vm.cs b/Mf.Razor.Entity/ViewModels/Modal_Vm.cs new file mode 100644 index 0000000..9c6ae1b --- /dev/null +++ b/Mf.Razor.Entity/ViewModels/Modal_Vm.cs @@ -0,0 +1,11 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace Mf.Razor.Entity.ViewModels +{ + [NotMapped] + public class Modal_Vm + { + public string? Title { get; set; } + public Guid Guid { get; set; } + } +} diff --git a/Mf.Razor/AuthorizationServices/CustomAuthStateProvider.cs b/Mf.Razor/AuthorizationServices/CustomAuthStateProvider.cs new file mode 100644 index 0000000..05a78cb --- /dev/null +++ b/Mf.Razor/AuthorizationServices/CustomAuthStateProvider.cs @@ -0,0 +1,110 @@ + +using Blazored.LocalStorage; +using Microsoft.AspNetCore.Components.Authorization; +using Microsoft.IdentityModel.Tokens; +using System.IdentityModel.Tokens.Jwt; +using System.Net.Http.Headers; +using System.Security.Claims; +using System.Text; +using System.Text.Json; +using Mf.Razor.Entity.Interfaces; +using Mf.Razor.Services; + +namespace Mf.Razor +{ + public class CustomAuthStateProvider : AuthenticationStateProvider + { + + private readonly ITokenService _tokenService; + private readonly LogService _logger; + public CustomAuthStateProvider(ITokenService tokenService,LogService logger) + { + _logger = logger; + _tokenService = tokenService; + } + + public async Task SetToken(string tokenKey) + { + await _tokenService.SetToken(tokenKey); + } + public async Task RemoveToke() + { + try + { + await _tokenService.RemoveToke(); + return true; + } + catch (Exception ex) + { + return false; + } + } + public override async Task GetAuthenticationStateAsync() + { + string token = await _tokenService.GetToken(); + + if (String.IsNullOrEmpty(token)) + { + var state = new AuthenticationState(new ClaimsPrincipal()); + NotifyAuthenticationStateChanged(Task.FromResult(state)); + _logger.Log("Auth Is False"); + return state; + } + + var tokenHandler = new JwtSecurityTokenHandler(); + + + try + { + + tokenHandler.ValidateToken(token, new TokenValidationParameters + { + ValidateIssuerSigningKey = true, + ValidateIssuer = false, + ValidateAudience = false, + RequireExpirationTime = true, + ValidateLifetime = true, + // Set clock skew to zero so tokens expire exactly at token expiration time (instead of 5 minutes later by default) + ClockSkew = TimeSpan.Zero + }, out SecurityToken validatedToken); + + var jwtToken = (JwtSecurityToken)validatedToken; + + // Create ClaimsPrincipal from the token's claims + var claimsIdentity = new ClaimsIdentity(jwtToken.Claims, "jwt"); + var user = new ClaimsPrincipal(claimsIdentity); + var state = new AuthenticationState(user); + NotifyAuthenticationStateChanged(Task.FromResult(state)); + _logger.Log("Auth is ON"); + return state; + } + catch (Exception) + { + + // Token validation failed + var state = new AuthenticationState(new ClaimsPrincipal()); + NotifyAuthenticationStateChanged(Task.FromResult(state)); + _logger.Log("Auth Is False"); + return state; + } + } + + public static IEnumerable ParseClaimsFromJwt(string jwt) + { + var payload = jwt.Split('.')[1]; + var jsonBytes = ParseBase64WithoutPadding(payload); + var keyValuePairs = JsonSerializer.Deserialize>(jsonBytes); + return keyValuePairs.Select(kvp => new Claim(kvp.Key, kvp.Value.ToString())); + } + + private static byte[] ParseBase64WithoutPadding(string base64) + { + switch (base64.Length % 4) + { + case 2: base64 += "=="; break; + case 3: base64 += "="; break; + } + return Convert.FromBase64String(base64); + } + } +} diff --git a/Mf.Razor/AuthorizationServices/JwtService.cs b/Mf.Razor/AuthorizationServices/JwtService.cs new file mode 100644 index 0000000..0843df3 --- /dev/null +++ b/Mf.Razor/AuthorizationServices/JwtService.cs @@ -0,0 +1,51 @@ +using Microsoft.IdentityModel.Tokens; +using System.IdentityModel.Tokens.Jwt; +using System.Security.Claims; +using System.Text; + +namespace Mf.Razor +{ + public static class JwtService + { + //static string securityAlgorithm = SecurityAlgorithms.HmacSha512Signature; + public static string CreateJwtToken(string securityKey, List claims, TimeSpan? expireDate = null) + { + var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(securityKey)); + var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); + + var expires = new DateTime(); + if(expireDate == null) + { + expires = DateTime.Now.AddDays(1); + } + else + { + expires = DateTime.Now.AddMinutes(expireDate.Value.TotalMinutes); + } + + var token = new JwtSecurityToken( + "daliranpv.ir", + "your_audience", + claims, + expires: expires, + signingCredentials: creds + ); + return new JwtSecurityTokenHandler().WriteToken(token); + + + //var tokenHandler = new JwtSecurityTokenHandler(); + //var key = Encoding.ASCII.GetBytes(Tokens.AuthenticaitonSystemOne.Key); + //var tokenDescriptor = new SecurityTokenDescriptor + //{ + // Subject = new ClaimsIdentity(claims), + // Expires = DateTime.UtcNow.AddDays(7), + // SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature) + //}; + //var token = tokenHandler.CreateToken(tokenDescriptor); + //return tokenHandler.WriteToken(token); + + + + } + } +} diff --git a/Mf.Razor/Component1.razor b/Mf.Razor/Component1.razor new file mode 100644 index 0000000..abd324b --- /dev/null +++ b/Mf.Razor/Component1.razor @@ -0,0 +1,3 @@ +
+ This component is defined in the Mf.Razor library. +
\ No newline at end of file diff --git a/Mf.Razor/Component1.razor.css b/Mf.Razor/Component1.razor.css new file mode 100644 index 0000000..c6afca4 --- /dev/null +++ b/Mf.Razor/Component1.razor.css @@ -0,0 +1,6 @@ +.my-component { + border: 2px dashed red; + padding: 1em; + margin: 1em 0; + background-image: url('background.png'); +} diff --git a/Mf.Razor/Components/Carousels/DefaultCarousel/Carousel.razor b/Mf.Razor/Components/Carousels/DefaultCarousel/Carousel.razor new file mode 100644 index 0000000..1480a12 --- /dev/null +++ b/Mf.Razor/Components/Carousels/DefaultCarousel/Carousel.razor @@ -0,0 +1,24 @@ + + +@code{ + + + +} \ No newline at end of file diff --git a/Mf.Razor/Components/Carousels/DefaultCarousel/Carousel.razor.css b/Mf.Razor/Components/Carousels/DefaultCarousel/Carousel.razor.css new file mode 100644 index 0000000..6f947a6 --- /dev/null +++ b/Mf.Razor/Components/Carousels/DefaultCarousel/Carousel.razor.css @@ -0,0 +1,68 @@ +/* GLOBAL STYLES +-------------------------------------------------- */ +/* Padding below the footer and lighter body text */ + +/* CUSTOMIZE THE CAROUSEL +-------------------------------------------------- */ + +/* Carousel base class */ +.carousel { + margin-top:1rem; + margin-bottom: 1rem; +} +/* Since positioning the image, we need to help out the caption */ +.carousel-caption { + bottom: 3rem; + z-index: 10; +} + +/* Declare heights because of positioning of img element */ +.carousel-item { +} + + +/* MARKETING CONTENT +-------------------------------------------------- */ + +/* Center align the text within the three columns below the carousel */ +.marketing .col-lg-4 { + margin-bottom: 1.5rem; + text-align: center; +} + +.marketing .col-lg-4 p { + margin-right: .75rem; + margin-left: .75rem; +} + + +/* Featurettes +------------------------- */ + +.featurette-divider { + margin: 5rem 0; /* Space out the Bootstrap
more */ +} + +/* Thin out the marketing headings */ + +/* RESPONSIVE CSS +-------------------------------------------------- */ + +@media (min-width: 40em) { + /* Bump up size of carousel content */ + .carousel-caption p { + margin-bottom: 1.25rem; + font-size: 1.25rem; + line-height: 1.4; + } + + .featurette-heading { + font-size: 50px; + } +} + +@media (min-width: 62em) { + .featurette-heading { + margin-top: 7rem; + } +} diff --git a/Mf.Razor/Components/CurrencyInput.razor b/Mf.Razor/Components/CurrencyInput.razor new file mode 100644 index 0000000..c8484a4 --- /dev/null +++ b/Mf.Razor/Components/CurrencyInput.razor @@ -0,0 +1,99 @@ +@using System.Globalization +@typeparam T + +@* + *@ + + + +@code { + [Parameter] + public T Value { get; set; } + + [Parameter] + public EventCallback ValueChanged { get; set; } + + + [Parameter] + public string? Class { get; set; } + + [Parameter] + public string? Id { get; set; } + + [Parameter] + public string? PlaceHolder { get; set; } + + + private string formattedValue = ""; + + protected override void OnParametersSet() + { + formattedValue = FormatValue(Value); + } + private void OnInputChanged(ChangeEventArgs e) + { + + + + var raw = e.Value?.ToString()?.Replace(",", "").Trim() ?? "0"; + + var sss = new string(raw.Where(char.IsDigit).ToArray()); + if (string.IsNullOrEmpty(sss)) + { + formattedValue = "0"; + return; + } + + + + + object? parsed = typeof(T) switch + { + var t when t == typeof(int) && int.TryParse(raw, out var intVal) => intVal, + var t when t == typeof(long) && long.TryParse(raw, out var longVal) => longVal, + var t when t == typeof(decimal) && decimal.TryParse(raw, out var decVal) => decVal, + _ => null + }; + + if (parsed is T tValue) + { + ValueChanged.InvokeAsync(tValue); + } + + formattedValue = raw; // temporary display while editing + } + + private void OnBlur() + { + formattedValue = FormatValue(Value); + } + + private void OnFocus() + { + formattedValue = FormatValue(Value); + // formattedValue = Value?.ToString(); + } + + private string FormatValue(T val) + { + if (val == null) return ""; + return val switch + { + int i => i.ToString("N0", CultureInfo.InvariantCulture), + long l => l.ToString("N0", CultureInfo.InvariantCulture), + decimal d => d.ToString("N0", CultureInfo.InvariantCulture), + _ => val.ToString() ?? "" + }; + } +} diff --git a/Mf.Razor/Events/ServiceLocatorEventHandler.cs b/Mf.Razor/Events/ServiceLocatorEventHandler.cs new file mode 100644 index 0000000..7928e9e --- /dev/null +++ b/Mf.Razor/Events/ServiceLocatorEventHandler.cs @@ -0,0 +1,4 @@ +namespace Mf.Razor.Events +{ + public delegate void ServiceLocatorDelegate(); +} diff --git a/Mf.Razor/ExampleJsInterop.cs b/Mf.Razor/ExampleJsInterop.cs new file mode 100644 index 0000000..44a7f38 --- /dev/null +++ b/Mf.Razor/ExampleJsInterop.cs @@ -0,0 +1,31 @@ +using Microsoft.JSInterop; + +namespace Mf.Razor; + +// This class provides an example of how JavaScript functionality can be wrapped +// in a .NET class for easy consumption. The associated JavaScript module is +// loaded on demand when first needed. +// +// This class can be registered as scoped DI service and then injected into Blazor +// components for use. + +public class ExampleJsInterop(IJSRuntime jsRuntime) : IAsyncDisposable +{ + private readonly Lazy> moduleTask = new(() => jsRuntime.InvokeAsync( + "import", "./_content/Mf.Razor/exampleJsInterop.js").AsTask()); + + public async ValueTask Prompt(string message) + { + var module = await moduleTask.Value; + return await module.InvokeAsync("showPrompt", message); + } + + public async ValueTask DisposeAsync() + { + if (moduleTask.IsValueCreated) + { + var module = await moduleTask.Value; + await module.DisposeAsync(); + } + } +} \ No newline at end of file diff --git a/Mf.Razor/Interfaces/IModalService.cs b/Mf.Razor/Interfaces/IModalService.cs new file mode 100644 index 0000000..0085946 --- /dev/null +++ b/Mf.Razor/Interfaces/IModalService.cs @@ -0,0 +1,11 @@ +namespace Mf.Razor.Interfaces +{ + public interface IModalService + { + public void Show(); + + public void Hide(); + + + } +} diff --git a/Mf.Razor/Interfaces/IServiceLocator.cs b/Mf.Razor/Interfaces/IServiceLocator.cs new file mode 100644 index 0000000..a2520c8 --- /dev/null +++ b/Mf.Razor/Interfaces/IServiceLocator.cs @@ -0,0 +1,6 @@ +namespace Mf.Razor.Interfaces +{ + public interface IServiceLocator + { + } +} diff --git a/Mf.Razor/Mf.Razor.csproj b/Mf.Razor/Mf.Razor.csproj new file mode 100644 index 0000000..b1412b3 --- /dev/null +++ b/Mf.Razor/Mf.Razor.csproj @@ -0,0 +1,27 @@ + + + + net10.0 + enable + enable + + + + + + + + + + + + + + + + + + + + + diff --git a/Mf.Razor/RazorProvider.cs b/Mf.Razor/RazorProvider.cs new file mode 100644 index 0000000..61ab1a5 --- /dev/null +++ b/Mf.Razor/RazorProvider.cs @@ -0,0 +1,27 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Mf.Razor.Entity.Interfaces; +using Mf.Razor.Services; + +namespace Mf.Razor +{ + public static class RazorProvider + { + public static IServiceCollection AddBootstrap5(this IServiceCollection serviceCollection) + { + return serviceCollection; + } + + public static IServiceCollection AddAuthentication(this IServiceCollection serviceCollection) + { + return serviceCollection; + } + + public static IServiceCollection AddLogger(this IServiceCollection serviceCollection) + { + serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); + return serviceCollection; + } + } +} diff --git a/Mf.Razor/Services/LogService.cs b/Mf.Razor/Services/LogService.cs new file mode 100644 index 0000000..c88f172 --- /dev/null +++ b/Mf.Razor/Services/LogService.cs @@ -0,0 +1,48 @@ +using Mf.Razor.Entity.Interfaces; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Mf.Razor.Services +{ + public class LogService:IFrontLogger + { + private int indexer = 1; + public event EventHandler LogEvent; + private List LogComments { get; set; } = new List(); + + public virtual void Log(string content, LogMode mode, TimeSpan time) + { + LogComments.Add(new LogModel { CreatedDate = DateTime.Now,index = indexer,LogContent = content,LogMode = mode,Time = time}); + indexer++; + LogEvent?.Invoke(null, EventArgs.Empty); + } + + public virtual void Log(string content, LogMode mode) + { + LogComments.Add(new LogModel { CreatedDate = DateTime.Now, index = indexer, LogContent = content, LogMode = mode, Time = null }); + indexer++; + LogEvent?.Invoke(null, EventArgs.Empty); + } + + public virtual void Log(string content) + { + LogComments.Add(new LogModel { CreatedDate = DateTime.Now, index = indexer, LogContent = content, LogMode = LogMode.Info, Time = null }); + indexer++; + LogEvent?.Invoke(null, EventArgs.Empty); + } + + + public virtual List GetAllLogs() + { + return LogComments.ToList(); + } + + public virtual void ClearLogs() + { + LogComments = new List(); + indexer = 0; + Log("Clear Logs"); + } + } +} diff --git a/Mf.Razor/Services/RequestService.cs b/Mf.Razor/Services/RequestService.cs new file mode 100644 index 0000000..0158d1f --- /dev/null +++ b/Mf.Razor/Services/RequestService.cs @@ -0,0 +1,55 @@ + +using Mf.Razor.Entity.Interfaces; +using Mf.Razor.Interfaces; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Mf.Razor.Services +{ + public class RequestService + { + private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1); // دو درخواست همزمان + + public async Task ExecuteAsync(Func> action) + { + await _semaphore.WaitAsync(); + try + { + return await action(); + } + catch (Exception ex) + { + Console.WriteLine(ex.ToString()); + //ServiceLocator.Log($"Error Limiter : {ex.Message}"); + return await action(); + } + finally + { + //ServiceLocator.Log($"Relase : {DateTime.Now.ToString()}"); + _semaphore.Release(); + } + + } + + public async Task ExecuteAsync(Func action) + { + await _semaphore.WaitAsync(); + try + { + await action(); + } + catch (Exception ex) + { + Console.WriteLine(ex.ToString()); + //ServiceLocator.Log($"Error Limiter : {ex.Message}"); + await action(); + } + finally + { + //ServiceLocator.Log($"Relase : {DateTime.Now.ToString()}"); + _semaphore.Release(); + } + } + } +} diff --git a/Mf.Razor/Services/ServiceLocator.cs b/Mf.Razor/Services/ServiceLocator.cs new file mode 100644 index 0000000..dfecbb1 --- /dev/null +++ b/Mf.Razor/Services/ServiceLocator.cs @@ -0,0 +1,49 @@ +using Mf.Razor.Events; +using Mf.Razor.Interfaces; + +namespace Mf.Razor.Services +{ + internal abstract class ServiceLocator : IServiceLocator + { + internal IServiceProvider _serviceProvider; + protected ServiceLocator(IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + } + + private event ServiceLocatorDelegate? Update; + public int EventNumbers { get; private set; } = 0; + public virtual Task InvokeUpdate() + { + Update?.Invoke(); + return Task.CompletedTask; + } + + public virtual void AddEvent(ServiceLocatorDelegate input) + { + try + { + Update += input; + EventNumbers++; + } + catch (Exception ex) + { + + } + + } + + public virtual void RemoveEvent(ServiceLocatorDelegate input) + { + try + { + Update -= input; + EventNumbers--; + } + catch (Exception ex) + { + + } + } + } +} diff --git a/Mf.Razor/_Imports.razor b/Mf.Razor/_Imports.razor new file mode 100644 index 0000000..c3615ef --- /dev/null +++ b/Mf.Razor/_Imports.razor @@ -0,0 +1 @@ +@using Microsoft.AspNetCore.Components.Web \ No newline at end of file diff --git a/Mf.Razor/wwwroot/background.png b/Mf.Razor/wwwroot/background.png new file mode 100644 index 0000000000000000000000000000000000000000..e15a3bde6e2bdb380df6a0b46d7ed00bdeb0aaa8 GIT binary patch literal 378 zcmeAS@N?(olHy`uVBq!ia0vp^x**KK1SGdsl%54rjKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sBugD~Uq{1qucLCF%=h?3y^w370~qEv>0#LT=By}Z;C1rt33 zJwr2>%=KS^ie7oTIEF;HpS|GCbyPusHSqiXaCu3qf)82(9Gq&mZq2{Kq}M*X&MWtJ zSi1Jo7ZzfImg%g=t(qo=wsSR2lZoP(Rj#3wacN=q0?Br(rXzgZEGK2$ID{|A=5S{xJEuzSH>!M+7wSY6hB<=-E^*n0W7 S8wY^CX7F_Nb6Mw<&;$S{dxtsz literal 0 HcmV?d00001 diff --git a/Mf.Razor/wwwroot/exampleJsInterop.js b/Mf.Razor/wwwroot/exampleJsInterop.js new file mode 100644 index 0000000..ea8d76a --- /dev/null +++ b/Mf.Razor/wwwroot/exampleJsInterop.js @@ -0,0 +1,6 @@ +// This is a JavaScript module that is loaded on demand. It can export any number of +// functions, and may import other JavaScript modules if required. + +export function showPrompt(message) { + return prompt(message, 'Type anything here'); +} diff --git a/Mf.sln b/Mf.sln new file mode 100644 index 0000000..6e3e64f --- /dev/null +++ b/Mf.sln @@ -0,0 +1,49 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mf.Core", "Mf.Core\Mf.Core.csproj", "{365652A1-EDFD-4102-B9FD-117EACFCCCC6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mf.Entity", "Mf.Entity\Mf.Entity.csproj", "{BE3FD258-BC5E-45F5-831C-7EAFB37D398C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mf.Ef", "Mf.Ef\Mf.Ef.csproj", "{9D5D4C17-9C3E-4104-8A87-7AB660B71762}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Razors", "Razors", "{5493F5AB-AEC8-4D51-AC9E-513C1505D8A2}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{ED63E99B-0EF8-4CEB-B4B5-BE795DE9FF78}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mf.Razor", "Mf.Razor\Mf.Razor.csproj", "{09763D74-4477-47A8-AE59-B9E90D9AD64F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mf.Razor.Entity", "Mf.Razor.Entity\Mf.Razor.Entity.csproj", "{9FADD8A4-A17E-4F24-96D6-E58D66471324}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {365652A1-EDFD-4102-B9FD-117EACFCCCC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {365652A1-EDFD-4102-B9FD-117EACFCCCC6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {365652A1-EDFD-4102-B9FD-117EACFCCCC6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {365652A1-EDFD-4102-B9FD-117EACFCCCC6}.Release|Any CPU.Build.0 = Release|Any CPU + {BE3FD258-BC5E-45F5-831C-7EAFB37D398C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BE3FD258-BC5E-45F5-831C-7EAFB37D398C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BE3FD258-BC5E-45F5-831C-7EAFB37D398C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BE3FD258-BC5E-45F5-831C-7EAFB37D398C}.Release|Any CPU.Build.0 = Release|Any CPU + {9D5D4C17-9C3E-4104-8A87-7AB660B71762}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9D5D4C17-9C3E-4104-8A87-7AB660B71762}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9D5D4C17-9C3E-4104-8A87-7AB660B71762}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9D5D4C17-9C3E-4104-8A87-7AB660B71762}.Release|Any CPU.Build.0 = Release|Any CPU + {09763D74-4477-47A8-AE59-B9E90D9AD64F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {09763D74-4477-47A8-AE59-B9E90D9AD64F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {09763D74-4477-47A8-AE59-B9E90D9AD64F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {09763D74-4477-47A8-AE59-B9E90D9AD64F}.Release|Any CPU.Build.0 = Release|Any CPU + {9FADD8A4-A17E-4F24-96D6-E58D66471324}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9FADD8A4-A17E-4F24-96D6-E58D66471324}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9FADD8A4-A17E-4F24-96D6-E58D66471324}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9FADD8A4-A17E-4F24-96D6-E58D66471324}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {ED63E99B-0EF8-4CEB-B4B5-BE795DE9FF78} = {5493F5AB-AEC8-4D51-AC9E-513C1505D8A2} + {09763D74-4477-47A8-AE59-B9E90D9AD64F} = {ED63E99B-0EF8-4CEB-B4B5-BE795DE9FF78} + {9FADD8A4-A17E-4F24-96D6-E58D66471324} = {ED63E99B-0EF8-4CEB-B4B5-BE795DE9FF78} + EndGlobalSection +EndGlobal