├── .gitignore ├── LICENSE ├── Modular ├── Modular.sln ├── global.json └── src │ ├── Core │ └── Modular.Core │ │ ├── Domain │ │ ├── IRepository.cs │ │ ├── IRepositoryWithTypedId.cs │ │ └── Models │ │ │ ├── Entity.cs │ │ │ ├── EntityWithTypedId.cs │ │ │ └── IEntityWithTypedId.cs │ │ ├── GlobalConfiguration.cs │ │ ├── ICustomModelBuilder.cs │ │ ├── IModuleInitializer.cs │ │ ├── Modular.Core.xproj │ │ ├── ModuleInfo.cs │ │ ├── Properties │ │ └── AssemblyInfo.cs │ │ └── project.json │ ├── ExtraTest │ └── ExtraDepenencyTest │ │ ├── AnotherTestService.cs │ │ ├── ExtraDepenencyTest.xproj │ │ ├── IAnotherTestService.cs │ │ ├── Properties │ │ └── AssemblyInfo.cs │ │ └── project.json │ └── Modular.WebHost │ ├── Extensions │ └── ModuleViewLocationExpander.cs │ ├── Migrations │ ├── 20160705094120_InitialSchema.Designer.cs │ ├── 20160705094120_InitialSchema.cs │ └── ModularDbContextModelSnapshot.cs │ ├── Modular.WebHost.xproj │ ├── Modules │ ├── Modular.Modules.Core │ │ ├── Controllers │ │ │ ├── AccountController.cs │ │ │ ├── HomeController.cs │ │ │ └── ManageController.cs │ │ ├── Infrastructure │ │ │ ├── CoreCustomModelBuilder.cs │ │ │ ├── ModularDbContext.cs │ │ │ ├── Repository.cs │ │ │ └── RepositoryWithTypedId.cs │ │ ├── Models │ │ │ ├── Product.cs │ │ │ ├── Role.cs │ │ │ ├── RoleClaim.cs │ │ │ ├── User.cs │ │ │ ├── UserClaim.cs │ │ │ ├── UserLogin.cs │ │ │ └── UserRole.cs │ │ ├── Modular.Modules.Core.xproj │ │ ├── Properties │ │ │ └── AssemblyInfo.cs │ │ ├── Services │ │ │ ├── IEmailSender.cs │ │ │ ├── ISmsSender.cs │ │ │ └── MessageServices.cs │ │ ├── ViewModels │ │ │ ├── AccountViewModels │ │ │ │ ├── ExternalLoginConfirmationViewModel.cs │ │ │ │ ├── ForgotPasswordViewModel.cs │ │ │ │ ├── LoginViewModel.cs │ │ │ │ ├── RegisterViewModel.cs │ │ │ │ ├── ResetPasswordViewModel.cs │ │ │ │ ├── SendCodeViewModel.cs │ │ │ │ └── VerifyCodeViewModel.cs │ │ │ └── ManageViewModels │ │ │ │ ├── AddPhoneNumberViewModel.cs │ │ │ │ ├── ChangePasswordViewModel.cs │ │ │ │ ├── ConfigureTwoFactorViewModel.cs │ │ │ │ ├── FactorViewModel.cs │ │ │ │ ├── IndexViewModel.cs │ │ │ │ ├── ManageLoginsViewModel.cs │ │ │ │ ├── RemoveLoginViewModel.cs │ │ │ │ ├── SetPasswordViewModel.cs │ │ │ │ └── VerifyPhoneNumberViewModel.cs │ │ ├── Views │ │ │ ├── Account │ │ │ │ ├── ConfirmEmail.cshtml │ │ │ │ ├── ExternalLoginConfirmation.cshtml │ │ │ │ ├── ExternalLoginFailure.cshtml │ │ │ │ ├── ForgotPassword.cshtml │ │ │ │ ├── ForgotPasswordConfirmation.cshtml │ │ │ │ ├── Lockout.cshtml │ │ │ │ ├── Login.cshtml │ │ │ │ ├── Register.cshtml │ │ │ │ ├── ResetPassword.cshtml │ │ │ │ ├── ResetPasswordConfirmation.cshtml │ │ │ │ ├── SendCode.cshtml │ │ │ │ └── VerifyCode.cshtml │ │ │ ├── Home │ │ │ │ ├── About.cshtml │ │ │ │ ├── Contact.cshtml │ │ │ │ └── Index.cshtml │ │ │ ├── Manage │ │ │ │ ├── AddPhoneNumber.cshtml │ │ │ │ ├── ChangePassword.cshtml │ │ │ │ ├── Index.cshtml │ │ │ │ ├── ManageLogins.cshtml │ │ │ │ ├── SetPassword.cshtml │ │ │ │ └── VerifyPhoneNumber.cshtml │ │ │ ├── _ViewImports.cshtml │ │ │ └── _ViewStart.cshtml │ │ └── project.json │ ├── Modular.Modules.ModuleA │ │ ├── Controllers │ │ │ └── TestAController.cs │ │ ├── Infrastructure │ │ │ └── ModuleACustomModelBuilder.cs │ │ ├── Models │ │ │ └── Sample.cs │ │ ├── Modular.Modules.ModuleA.xproj │ │ ├── ModuleInitializer.cs │ │ ├── Properties │ │ │ └── AssemblyInfo.cs │ │ ├── Services │ │ │ ├── ITestService.cs │ │ │ └── TestService.cs │ │ ├── ViewModels │ │ │ └── TestViewModel.cs │ │ ├── Views │ │ │ ├── TestA │ │ │ │ └── Index.cshtml │ │ │ └── _ViewStart.cshtml │ │ ├── project.json │ │ └── wwwroot │ │ │ └── logo.png │ └── Modular.Modules.ModuleB │ │ ├── Controllers │ │ └── TestBController.cs │ │ ├── Models │ │ └── Sample.cs │ │ ├── Modular.Modules.ModuleB.xproj │ │ ├── ModuleInitializer.cs │ │ ├── Properties │ │ └── AssemblyInfo.cs │ │ ├── Views │ │ ├── TestB │ │ │ └── Index.cshtml │ │ └── _ViewStart.cshtml │ │ └── project.json │ ├── Program.cs │ ├── Project_Readme.html │ ├── Properties │ └── launchSettings.json │ ├── Startup.cs │ ├── Views │ ├── Shared │ │ ├── Error.cshtml │ │ ├── _Layout.cshtml │ │ ├── _LoginPartial.cshtml │ │ └── _ValidationScriptsPartial.cshtml │ └── _ViewImports.cshtml │ ├── appsettings.json │ ├── project.json │ ├── web.config │ └── wwwroot │ ├── _references.js │ ├── css │ ├── site.css │ └── site.min.css │ ├── favicon.ico │ ├── images │ ├── banner1.svg │ ├── banner2.svg │ ├── banner3.svg │ └── banner4.svg │ ├── js │ ├── site.js │ └── site.min.js │ └── lib │ ├── bootstrap │ ├── .bower.json │ ├── LICENSE │ └── dist │ │ ├── css │ │ ├── bootstrap-theme.css │ │ ├── bootstrap-theme.css.map │ │ ├── bootstrap-theme.min.css │ │ ├── bootstrap-theme.min.css.map │ │ ├── bootstrap.css │ │ ├── bootstrap.css.map │ │ ├── bootstrap.min.css │ │ └── bootstrap.min.css.map │ │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ └── glyphicons-halflings-regular.woff2 │ │ └── js │ │ ├── bootstrap.js │ │ ├── bootstrap.min.js │ │ └── npm.js │ ├── jquery-validation-unobtrusive │ ├── .bower.json │ ├── jquery.validate.unobtrusive.js │ └── jquery.validate.unobtrusive.min.js │ ├── jquery-validation │ ├── .bower.json │ ├── LICENSE.md │ └── dist │ │ ├── additional-methods.js │ │ ├── additional-methods.min.js │ │ ├── jquery.validate.js │ │ └── jquery.validate.min.js │ └── jquery │ ├── .bower.json │ ├── LICENSE.txt │ └── dist │ ├── jquery.js │ ├── jquery.min.js │ └── jquery.min.map ├── README.md └── folder-structure.png /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | *.VC.db 84 | *.VC.VC.opendb 85 | 86 | # Visual Studio profiler 87 | *.psess 88 | *.vsp 89 | *.vspx 90 | *.sap 91 | 92 | # TFS 2012 Local Workspace 93 | $tf/ 94 | 95 | # Guidance Automation Toolkit 96 | *.gpState 97 | 98 | # ReSharper is a .NET coding add-in 99 | _ReSharper*/ 100 | *.[Rr]e[Ss]harper 101 | *.DotSettings.user 102 | 103 | # JustCode is a .NET coding add-in 104 | .JustCode 105 | 106 | # TeamCity is a build add-in 107 | _TeamCity* 108 | 109 | # DotCover is a Code Coverage Tool 110 | *.dotCover 111 | 112 | # NCrunch 113 | _NCrunch_* 114 | .*crunch*.local.xml 115 | nCrunchTemp_* 116 | 117 | # MightyMoose 118 | *.mm.* 119 | AutoTest.Net/ 120 | 121 | # Web workbench (sass) 122 | .sass-cache/ 123 | 124 | # Installshield output folder 125 | [Ee]xpress/ 126 | 127 | # DocProject is a documentation generator add-in 128 | DocProject/buildhelp/ 129 | DocProject/Help/*.HxT 130 | DocProject/Help/*.HxC 131 | DocProject/Help/*.hhc 132 | DocProject/Help/*.hhk 133 | DocProject/Help/*.hhp 134 | DocProject/Help/Html2 135 | DocProject/Help/html 136 | 137 | # Click-Once directory 138 | publish/ 139 | 140 | # Publish Web Output 141 | *.[Pp]ublish.xml 142 | *.azurePubxml 143 | # TODO: Comment the next line if you want to checkin your web deploy settings 144 | # but database connection strings (with potential passwords) will be unencrypted 145 | *.pubxml 146 | *.publishproj 147 | 148 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 149 | # checkin your Azure Web App publish settings, but sensitive information contained 150 | # in these scripts will be unencrypted 151 | PublishScripts/ 152 | 153 | # NuGet Packages 154 | *.nupkg 155 | # The packages folder can be ignored because of Package Restore 156 | **/packages/* 157 | # except build/, which is used as an MSBuild target. 158 | !**/packages/build/ 159 | # Uncomment if necessary however generally it will be regenerated when needed 160 | #!**/packages/repositories.config 161 | # NuGet v3's project.json files produces more ignoreable files 162 | *.nuget.props 163 | *.nuget.targets 164 | 165 | # Microsoft Azure Build Output 166 | csx/ 167 | *.build.csdef 168 | 169 | # Microsoft Azure Emulator 170 | ecf/ 171 | rcf/ 172 | 173 | # Windows Store app package directories and files 174 | AppPackages/ 175 | BundleArtifacts/ 176 | Package.StoreAssociation.xml 177 | _pkginfo.txt 178 | 179 | # Visual Studio cache files 180 | # files ending in .cache can be ignored 181 | *.[Cc]ache 182 | # but keep track of directories ending in .cache 183 | !*.[Cc]ache/ 184 | 185 | # Others 186 | ClientBin/ 187 | ~$* 188 | *~ 189 | *.dbmdl 190 | *.dbproj.schemaview 191 | *.pfx 192 | *.publishsettings 193 | node_modules/ 194 | orleans.codegen.cs 195 | 196 | # Since there are multiple workflows, uncomment next line to ignore bower_components 197 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 198 | #bower_components/ 199 | 200 | # RIA/Silverlight projects 201 | Generated_Code/ 202 | 203 | # Backup & report files from converting an old project file 204 | # to a newer Visual Studio version. Backup files are not needed, 205 | # because we have git ;-) 206 | _UpgradeReport_Files/ 207 | Backup*/ 208 | UpgradeLog*.XML 209 | UpgradeLog*.htm 210 | 211 | # SQL Server files 212 | *.mdf 213 | *.ldf 214 | 215 | # Business Intelligence projects 216 | *.rdl.data 217 | *.bim.layout 218 | *.bim_*.settings 219 | 220 | # Microsoft Fakes 221 | FakesAssemblies/ 222 | 223 | # GhostDoc plugin setting file 224 | *.GhostDoc.xml 225 | 226 | # Node.js Tools for Visual Studio 227 | .ntvs_analysis.dat 228 | 229 | # Visual Studio 6 build log 230 | *.plg 231 | 232 | # Visual Studio 6 workspace options file 233 | *.opt 234 | 235 | # Visual Studio LightSwitch build output 236 | **/*.HTMLClient/GeneratedArtifacts 237 | **/*.DesktopClient/GeneratedArtifacts 238 | **/*.DesktopClient/ModelManifest.xml 239 | **/*.Server/GeneratedArtifacts 240 | **/*.Server/ModelManifest.xml 241 | _Pvt_Extensions 242 | 243 | # Paket dependency manager 244 | .paket/paket.exe 245 | paket-files/ 246 | 247 | # FAKE - F# Make 248 | .fake/ 249 | 250 | # JetBrains Rider 251 | .idea/ 252 | *.sln.iml 253 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Thien Nguyen Le Quynh 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Modular/Modular.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25123.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{10D8E54E-1058-4834-A19E-64515D0E9F6D}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{36299440-5126-4027-8EDE-737227A0F6EE}" 9 | ProjectSection(SolutionItems) = preProject 10 | global.json = global.json 11 | EndProjectSection 12 | EndProject 13 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Hosting", "Hosting", "{C0096AF7-92B2-4ADD-80E1-E4D896C80407}" 14 | EndProject 15 | Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Modular.WebHost", "src\Modular.WebHost\Modular.WebHost.xproj", "{B13EC77A-FD31-4DBC-A417-F35280D86280}" 16 | EndProject 17 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core", "Core", "{ACCAF020-C4EB-4412-8CA3-41EB27FBDAFB}" 18 | EndProject 19 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Modules", "Modules", "{10BAC5B3-1A22-401D-90B4-146E07F71CE6}" 20 | EndProject 21 | Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Modular.Core", "src\Core\Modular.Core\Modular.Core.xproj", "{DC18B7FB-EFB4-4340-B8F6-48A52FB273BE}" 22 | EndProject 23 | Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Modular.Modules.ModuleA", "src\Modular.WebHost\Modules\Modular.Modules.ModuleA\Modular.Modules.ModuleA.xproj", "{FC71B7C8-C4D2-4CC3-B3E7-B630CD552C35}" 24 | EndProject 25 | Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Modular.Modules.ModuleB", "src\Modular.WebHost\Modules\Modular.Modules.ModuleB\Modular.Modules.ModuleB.xproj", "{CE294E9D-9F20-400F-8051-E6A98AB76C71}" 26 | EndProject 27 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ExtraTest", "ExtraTest", "{A969EA5A-E0AE-47E0-ADEF-53C37131F485}" 28 | EndProject 29 | Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ExtraDepenencyTest", "src\ExtraTest\ExtraDepenencyTest\ExtraDepenencyTest.xproj", "{F2941F46-F442-43D5-8D60-D53E110C9FB2}" 30 | EndProject 31 | Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Modular.Modules.Core", "src\Modular.WebHost\Modules\Modular.Modules.Core\Modular.Modules.Core.xproj", "{13FC1529-FA8B-47B2-B633-3AACC3FE7C20}" 32 | EndProject 33 | Global 34 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 35 | Debug|Any CPU = Debug|Any CPU 36 | Release|Any CPU = Release|Any CPU 37 | EndGlobalSection 38 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 39 | {B13EC77A-FD31-4DBC-A417-F35280D86280}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 40 | {B13EC77A-FD31-4DBC-A417-F35280D86280}.Debug|Any CPU.Build.0 = Debug|Any CPU 41 | {B13EC77A-FD31-4DBC-A417-F35280D86280}.Release|Any CPU.ActiveCfg = Release|Any CPU 42 | {B13EC77A-FD31-4DBC-A417-F35280D86280}.Release|Any CPU.Build.0 = Release|Any CPU 43 | {DC18B7FB-EFB4-4340-B8F6-48A52FB273BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 44 | {DC18B7FB-EFB4-4340-B8F6-48A52FB273BE}.Debug|Any CPU.Build.0 = Debug|Any CPU 45 | {DC18B7FB-EFB4-4340-B8F6-48A52FB273BE}.Release|Any CPU.ActiveCfg = Release|Any CPU 46 | {DC18B7FB-EFB4-4340-B8F6-48A52FB273BE}.Release|Any CPU.Build.0 = Release|Any CPU 47 | {FC71B7C8-C4D2-4CC3-B3E7-B630CD552C35}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 48 | {FC71B7C8-C4D2-4CC3-B3E7-B630CD552C35}.Debug|Any CPU.Build.0 = Debug|Any CPU 49 | {FC71B7C8-C4D2-4CC3-B3E7-B630CD552C35}.Release|Any CPU.ActiveCfg = Release|Any CPU 50 | {FC71B7C8-C4D2-4CC3-B3E7-B630CD552C35}.Release|Any CPU.Build.0 = Release|Any CPU 51 | {CE294E9D-9F20-400F-8051-E6A98AB76C71}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 52 | {CE294E9D-9F20-400F-8051-E6A98AB76C71}.Debug|Any CPU.Build.0 = Debug|Any CPU 53 | {CE294E9D-9F20-400F-8051-E6A98AB76C71}.Release|Any CPU.ActiveCfg = Release|Any CPU 54 | {CE294E9D-9F20-400F-8051-E6A98AB76C71}.Release|Any CPU.Build.0 = Release|Any CPU 55 | {F2941F46-F442-43D5-8D60-D53E110C9FB2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 56 | {F2941F46-F442-43D5-8D60-D53E110C9FB2}.Debug|Any CPU.Build.0 = Debug|Any CPU 57 | {F2941F46-F442-43D5-8D60-D53E110C9FB2}.Release|Any CPU.ActiveCfg = Release|Any CPU 58 | {F2941F46-F442-43D5-8D60-D53E110C9FB2}.Release|Any CPU.Build.0 = Release|Any CPU 59 | {13FC1529-FA8B-47B2-B633-3AACC3FE7C20}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 60 | {13FC1529-FA8B-47B2-B633-3AACC3FE7C20}.Debug|Any CPU.Build.0 = Debug|Any CPU 61 | {13FC1529-FA8B-47B2-B633-3AACC3FE7C20}.Release|Any CPU.ActiveCfg = Release|Any CPU 62 | {13FC1529-FA8B-47B2-B633-3AACC3FE7C20}.Release|Any CPU.Build.0 = Release|Any CPU 63 | EndGlobalSection 64 | GlobalSection(SolutionProperties) = preSolution 65 | HideSolutionNode = FALSE 66 | EndGlobalSection 67 | GlobalSection(NestedProjects) = preSolution 68 | {C0096AF7-92B2-4ADD-80E1-E4D896C80407} = {10D8E54E-1058-4834-A19E-64515D0E9F6D} 69 | {B13EC77A-FD31-4DBC-A417-F35280D86280} = {C0096AF7-92B2-4ADD-80E1-E4D896C80407} 70 | {ACCAF020-C4EB-4412-8CA3-41EB27FBDAFB} = {10D8E54E-1058-4834-A19E-64515D0E9F6D} 71 | {10BAC5B3-1A22-401D-90B4-146E07F71CE6} = {10D8E54E-1058-4834-A19E-64515D0E9F6D} 72 | {DC18B7FB-EFB4-4340-B8F6-48A52FB273BE} = {ACCAF020-C4EB-4412-8CA3-41EB27FBDAFB} 73 | {FC71B7C8-C4D2-4CC3-B3E7-B630CD552C35} = {10BAC5B3-1A22-401D-90B4-146E07F71CE6} 74 | {CE294E9D-9F20-400F-8051-E6A98AB76C71} = {10BAC5B3-1A22-401D-90B4-146E07F71CE6} 75 | {A969EA5A-E0AE-47E0-ADEF-53C37131F485} = {10D8E54E-1058-4834-A19E-64515D0E9F6D} 76 | {F2941F46-F442-43D5-8D60-D53E110C9FB2} = {A969EA5A-E0AE-47E0-ADEF-53C37131F485} 77 | {13FC1529-FA8B-47B2-B633-3AACC3FE7C20} = {10BAC5B3-1A22-401D-90B4-146E07F71CE6} 78 | EndGlobalSection 79 | EndGlobal 80 | -------------------------------------------------------------------------------- /Modular/global.json: -------------------------------------------------------------------------------- 1 | { 2 | "projects": [ "src", "test", "src/Core", "src/ExtraTest", "src/Modular.WebHost/Modules" ], 3 | "sdk": { 4 | "version": "1.0.0-preview2-003121" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Modular/src/Core/Modular.Core/Domain/IRepository.cs: -------------------------------------------------------------------------------- 1 | using Modular.Core.Domain.Models; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace Modular.Core.Domain 8 | { 9 | public interface IRepository : IRepositoryWithTypedId where T : IEntityWithTypedId 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Modular/src/Core/Modular.Core/Domain/IRepositoryWithTypedId.cs: -------------------------------------------------------------------------------- 1 | using Modular.Core.Domain.Models; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace Modular.Core.Domain 8 | { 9 | public interface IRepositoryWithTypedId where T : IEntityWithTypedId 10 | { 11 | IQueryable Query(); 12 | 13 | void Add(T entity); 14 | 15 | void SaveChange(); 16 | 17 | void Remove(T entity); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Modular/src/Core/Modular.Core/Domain/Models/Entity.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace Modular.Core.Domain.Models 7 | { 8 | public abstract class Entity : EntityWithTypedId 9 | { 10 | 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Modular/src/Core/Modular.Core/Domain/Models/EntityWithTypedId.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace Modular.Core.Domain.Models 7 | { 8 | public class EntityWithTypedId : IEntityWithTypedId 9 | { 10 | public TId Id { get; protected set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Modular/src/Core/Modular.Core/Domain/Models/IEntityWithTypedId.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace Modular.Core.Domain.Models 7 | { 8 | public interface IEntityWithTypedId 9 | { 10 | TId Id { get; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Modular/src/Core/Modular.Core/GlobalConfiguration.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace Modular.Core 7 | { 8 | public static class GlobalConfiguration 9 | { 10 | static GlobalConfiguration() 11 | { 12 | Modules = new List(); 13 | } 14 | 15 | public static IList Modules { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Modular/src/Core/Modular.Core/ICustomModelBuilder.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | 3 | namespace Modular.Core 4 | { 5 | public interface ICustomModelBuilder 6 | { 7 | void Build(ModelBuilder modelBuilder); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Modular/src/Core/Modular.Core/IModuleInitializer.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace Modular.Core 8 | { 9 | public interface IModuleInitializer 10 | { 11 | void Init(IServiceCollection serviceCollection); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Modular/src/Core/Modular.Core/Modular.Core.xproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 14.0 5 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 6 | 7 | 8 | 9 | 10 | dc18b7fb-efb4-4340-b8f6-48a52fb273be 11 | Modular.Core 12 | .\obj 13 | .\bin\ 14 | v4.6.1 15 | 16 | 17 | 18 | 2.0 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /Modular/src/Core/Modular.Core/ModuleInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | using System.Threading.Tasks; 6 | 7 | namespace Modular.Core 8 | { 9 | public class ModuleInfo 10 | { 11 | public string Name { get; set; } 12 | 13 | public Assembly Assembly { get; set; } 14 | 15 | public string ShortName 16 | { 17 | get 18 | { 19 | return Name.Split('.').Last(); 20 | } 21 | } 22 | 23 | public string Path { get; set; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Modular/src/Core/Modular.Core/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyConfiguration("")] 9 | [assembly: AssemblyCompany("")] 10 | [assembly: AssemblyProduct("Modular.Core")] 11 | [assembly: AssemblyTrademark("")] 12 | 13 | // Setting ComVisible to false makes the types in this assembly not visible 14 | // to COM components. If you need to access a type in this assembly from 15 | // COM, set the ComVisible attribute to true on that type. 16 | [assembly: ComVisible(false)] 17 | 18 | // The following GUID is for the ID of the typelib if this project is exposed to COM 19 | [assembly: Guid("dc18b7fb-efb4-4340-b8f6-48a52fb273be")] 20 | -------------------------------------------------------------------------------- /Modular/src/Core/Modular.Core/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0-*", 3 | 4 | "dependencies": { 5 | "NETStandard.Library": "1.6.0", 6 | "Microsoft.AspNetCore.Mvc.Core": "1.0.0", 7 | "Microsoft.EntityFrameworkCore": "1.0.0" 8 | }, 9 | 10 | "frameworks": { 11 | "netstandard1.6": { 12 | "imports": [ 13 | "dnxcore50" 14 | ] 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Modular/src/ExtraTest/ExtraDepenencyTest/AnotherTestService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace ExtraDepenencyTest 7 | { 8 | public class AnotherTestService : IAnotherTestService 9 | { 10 | public string Test() 11 | { 12 | return "Other service outside modules"; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Modular/src/ExtraTest/ExtraDepenencyTest/ExtraDepenencyTest.xproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 14.0 5 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 6 | 7 | 8 | 9 | 10 | f2941f46-f442-43d5-8d60-d53e110c9fb2 11 | ExtraDepenencyTest 12 | .\obj 13 | .\bin\ 14 | v4.6.1 15 | 16 | 17 | 18 | 2.0 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /Modular/src/ExtraTest/ExtraDepenencyTest/IAnotherTestService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace ExtraDepenencyTest 7 | { 8 | public interface IAnotherTestService 9 | { 10 | string Test(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Modular/src/ExtraTest/ExtraDepenencyTest/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyConfiguration("")] 9 | [assembly: AssemblyCompany("")] 10 | [assembly: AssemblyProduct("ExtraDepenencyTest")] 11 | [assembly: AssemblyTrademark("")] 12 | 13 | // Setting ComVisible to false makes the types in this assembly not visible 14 | // to COM components. If you need to access a type in this assembly from 15 | // COM, set the ComVisible attribute to true on that type. 16 | [assembly: ComVisible(false)] 17 | 18 | // The following GUID is for the ID of the typelib if this project is exposed to COM 19 | [assembly: Guid("f2941f46-f442-43d5-8d60-d53e110c9fb2")] 20 | -------------------------------------------------------------------------------- /Modular/src/ExtraTest/ExtraDepenencyTest/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0-*", 3 | 4 | "dependencies": { 5 | "NETStandard.Library": "1.6.0" 6 | }, 7 | 8 | "frameworks": { 9 | "netstandard1.6": { 10 | "imports": "dnxcore50" 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Extensions/ModuleViewLocationExpander.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc.Razor; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace Modular.WebHost.Extensions 8 | { 9 | public class ModuleViewLocationExpander : IViewLocationExpander 10 | { 11 | private const string _moduleKey = "module"; 12 | 13 | public IEnumerable ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable viewLocations) 14 | { 15 | if (context.Values.ContainsKey(_moduleKey)) 16 | { 17 | var module = context.Values[_moduleKey]; 18 | if (!string.IsNullOrWhiteSpace(module)) 19 | { 20 | var moduleViewLocations = new string[] 21 | { 22 | "/Modules/Modular.Modules." + module + "/Views/{1}/{0}.cshtml", 23 | "/Modules/Modular.Modules." + module + "/Views/Shared/{0}.cshtml" 24 | }; 25 | 26 | viewLocations = moduleViewLocations.Concat(viewLocations); 27 | } 28 | } 29 | return viewLocations; 30 | } 31 | 32 | public void PopulateValues(ViewLocationExpanderContext context) 33 | { 34 | var controller = context.ActionContext.ActionDescriptor.DisplayName; 35 | var moduleName = controller.Split('.')[2]; 36 | if(moduleName != "WebHost") 37 | { 38 | context.Values[_moduleKey] = moduleName; 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Migrations/20160705094120_InitialSchema.Designer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.EntityFrameworkCore; 3 | using Microsoft.EntityFrameworkCore.Infrastructure; 4 | using Microsoft.EntityFrameworkCore.Metadata; 5 | using Microsoft.EntityFrameworkCore.Migrations; 6 | using Modular.Modules.Core.Infrastructure; 7 | 8 | namespace Modular.WebHost.Migrations 9 | { 10 | [DbContext(typeof(ModularDbContext))] 11 | [Migration("20160705094120_InitialSchema")] 12 | partial class InitialSchema 13 | { 14 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 15 | { 16 | modelBuilder 17 | .HasAnnotation("ProductVersion", "1.0.0-rtm-21431") 18 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 19 | 20 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRoleClaim", b => 21 | { 22 | b.Property("Id") 23 | .ValueGeneratedOnAdd(); 24 | 25 | b.Property("ClaimType"); 26 | 27 | b.Property("ClaimValue"); 28 | 29 | b.Property("RoleId"); 30 | 31 | b.HasKey("Id"); 32 | 33 | b.HasIndex("RoleId"); 34 | 35 | b.ToTable("Core_RoleClaim"); 36 | }); 37 | 38 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserClaim", b => 39 | { 40 | b.Property("Id") 41 | .ValueGeneratedOnAdd(); 42 | 43 | b.Property("ClaimType"); 44 | 45 | b.Property("ClaimValue"); 46 | 47 | b.Property("UserId"); 48 | 49 | b.HasKey("Id"); 50 | 51 | b.HasIndex("UserId"); 52 | 53 | b.ToTable("Core_UserClaim"); 54 | }); 55 | 56 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserLogin", b => 57 | { 58 | b.Property("LoginProvider"); 59 | 60 | b.Property("ProviderKey"); 61 | 62 | b.Property("ProviderDisplayName"); 63 | 64 | b.Property("UserId"); 65 | 66 | b.HasKey("LoginProvider", "ProviderKey"); 67 | 68 | b.HasIndex("UserId"); 69 | 70 | b.ToTable("Core_UserLogin"); 71 | }); 72 | 73 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserRole", b => 74 | { 75 | b.Property("UserId"); 76 | 77 | b.Property("RoleId"); 78 | 79 | b.HasKey("UserId", "RoleId"); 80 | 81 | b.HasIndex("RoleId"); 82 | 83 | b.HasIndex("UserId"); 84 | 85 | b.ToTable("Core_UserRole"); 86 | }); 87 | 88 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserToken", b => 89 | { 90 | b.Property("UserId"); 91 | 92 | b.Property("LoginProvider"); 93 | 94 | b.Property("Name"); 95 | 96 | b.Property("Value"); 97 | 98 | b.HasKey("UserId", "LoginProvider", "Name"); 99 | 100 | b.ToTable("Core_UserToken"); 101 | }); 102 | 103 | modelBuilder.Entity("Modular.Modules.Core.Models.Product", b => 104 | { 105 | b.Property("Id") 106 | .ValueGeneratedOnAdd(); 107 | 108 | b.Property("Description"); 109 | 110 | b.Property("Name"); 111 | 112 | b.Property("Price"); 113 | 114 | b.HasKey("Id"); 115 | 116 | b.ToTable("Core_Product"); 117 | }); 118 | 119 | modelBuilder.Entity("Modular.Modules.Core.Models.Role", b => 120 | { 121 | b.Property("Id") 122 | .ValueGeneratedOnAdd(); 123 | 124 | b.Property("ConcurrencyStamp") 125 | .IsConcurrencyToken(); 126 | 127 | b.Property("Name") 128 | .HasAnnotation("MaxLength", 256); 129 | 130 | b.Property("NormalizedName") 131 | .HasAnnotation("MaxLength", 256); 132 | 133 | b.HasKey("Id"); 134 | 135 | b.HasIndex("NormalizedName") 136 | .HasName("RoleNameIndex"); 137 | 138 | b.ToTable("Core_Role"); 139 | }); 140 | 141 | modelBuilder.Entity("Modular.Modules.Core.Models.User", b => 142 | { 143 | b.Property("Id") 144 | .ValueGeneratedOnAdd(); 145 | 146 | b.Property("AccessFailedCount"); 147 | 148 | b.Property("ConcurrencyStamp") 149 | .IsConcurrencyToken(); 150 | 151 | b.Property("CreatedOn"); 152 | 153 | b.Property("Email") 154 | .HasAnnotation("MaxLength", 256); 155 | 156 | b.Property("EmailConfirmed"); 157 | 158 | b.Property("FullName"); 159 | 160 | b.Property("IsDeleted"); 161 | 162 | b.Property("LockoutEnabled"); 163 | 164 | b.Property("LockoutEnd"); 165 | 166 | b.Property("NormalizedEmail") 167 | .HasAnnotation("MaxLength", 256); 168 | 169 | b.Property("NormalizedUserName") 170 | .HasAnnotation("MaxLength", 256); 171 | 172 | b.Property("PasswordHash"); 173 | 174 | b.Property("PhoneNumber"); 175 | 176 | b.Property("PhoneNumberConfirmed"); 177 | 178 | b.Property("SecurityStamp"); 179 | 180 | b.Property("TwoFactorEnabled"); 181 | 182 | b.Property("UpdatedOn"); 183 | 184 | b.Property("UserName") 185 | .HasAnnotation("MaxLength", 256); 186 | 187 | b.HasKey("Id"); 188 | 189 | b.HasIndex("NormalizedEmail") 190 | .HasName("EmailIndex"); 191 | 192 | b.HasIndex("NormalizedUserName") 193 | .IsUnique() 194 | .HasName("UserNameIndex"); 195 | 196 | b.ToTable("Core_User"); 197 | }); 198 | 199 | modelBuilder.Entity("Modular.Modules.ModuleA.Models.Sample", b => 200 | { 201 | b.Property("Id") 202 | .ValueGeneratedOnAdd(); 203 | 204 | b.Property("Description"); 205 | 206 | b.Property("Name") 207 | .HasColumnName("TestName"); 208 | 209 | b.HasKey("Id"); 210 | 211 | b.ToTable("ModuleA_Sample"); 212 | }); 213 | 214 | modelBuilder.Entity("Modular.Modules.ModuleB.Models.Sample", b => 215 | { 216 | b.Property("Id") 217 | .ValueGeneratedOnAdd(); 218 | 219 | b.Property("Name"); 220 | 221 | b.HasKey("Id"); 222 | 223 | b.ToTable("ModuleB_Sample"); 224 | }); 225 | 226 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRoleClaim", b => 227 | { 228 | b.HasOne("Modular.Modules.Core.Models.Role") 229 | .WithMany("Claims") 230 | .HasForeignKey("RoleId") 231 | .OnDelete(DeleteBehavior.Cascade); 232 | }); 233 | 234 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserClaim", b => 235 | { 236 | b.HasOne("Modular.Modules.Core.Models.User") 237 | .WithMany("Claims") 238 | .HasForeignKey("UserId") 239 | .OnDelete(DeleteBehavior.Cascade); 240 | }); 241 | 242 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserLogin", b => 243 | { 244 | b.HasOne("Modular.Modules.Core.Models.User") 245 | .WithMany("Logins") 246 | .HasForeignKey("UserId") 247 | .OnDelete(DeleteBehavior.Cascade); 248 | }); 249 | 250 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserRole", b => 251 | { 252 | b.HasOne("Modular.Modules.Core.Models.Role") 253 | .WithMany("Users") 254 | .HasForeignKey("RoleId") 255 | .OnDelete(DeleteBehavior.Cascade); 256 | 257 | b.HasOne("Modular.Modules.Core.Models.User") 258 | .WithMany("Roles") 259 | .HasForeignKey("UserId") 260 | .OnDelete(DeleteBehavior.Cascade); 261 | }); 262 | } 263 | } 264 | } 265 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Migrations/ModularDbContextModelSnapshot.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.EntityFrameworkCore; 3 | using Microsoft.EntityFrameworkCore.Infrastructure; 4 | using Microsoft.EntityFrameworkCore.Metadata; 5 | using Microsoft.EntityFrameworkCore.Migrations; 6 | using Modular.Modules.Core.Infrastructure; 7 | 8 | namespace Modular.WebHost.Migrations 9 | { 10 | [DbContext(typeof(ModularDbContext))] 11 | partial class ModularDbContextModelSnapshot : ModelSnapshot 12 | { 13 | protected override void BuildModel(ModelBuilder modelBuilder) 14 | { 15 | modelBuilder 16 | .HasAnnotation("ProductVersion", "1.0.0-rtm-21431") 17 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 18 | 19 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRoleClaim", b => 20 | { 21 | b.Property("Id") 22 | .ValueGeneratedOnAdd(); 23 | 24 | b.Property("ClaimType"); 25 | 26 | b.Property("ClaimValue"); 27 | 28 | b.Property("RoleId"); 29 | 30 | b.HasKey("Id"); 31 | 32 | b.HasIndex("RoleId"); 33 | 34 | b.ToTable("Core_RoleClaim"); 35 | }); 36 | 37 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserClaim", b => 38 | { 39 | b.Property("Id") 40 | .ValueGeneratedOnAdd(); 41 | 42 | b.Property("ClaimType"); 43 | 44 | b.Property("ClaimValue"); 45 | 46 | b.Property("UserId"); 47 | 48 | b.HasKey("Id"); 49 | 50 | b.HasIndex("UserId"); 51 | 52 | b.ToTable("Core_UserClaim"); 53 | }); 54 | 55 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserLogin", b => 56 | { 57 | b.Property("LoginProvider"); 58 | 59 | b.Property("ProviderKey"); 60 | 61 | b.Property("ProviderDisplayName"); 62 | 63 | b.Property("UserId"); 64 | 65 | b.HasKey("LoginProvider", "ProviderKey"); 66 | 67 | b.HasIndex("UserId"); 68 | 69 | b.ToTable("Core_UserLogin"); 70 | }); 71 | 72 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserRole", b => 73 | { 74 | b.Property("UserId"); 75 | 76 | b.Property("RoleId"); 77 | 78 | b.HasKey("UserId", "RoleId"); 79 | 80 | b.HasIndex("RoleId"); 81 | 82 | b.HasIndex("UserId"); 83 | 84 | b.ToTable("Core_UserRole"); 85 | }); 86 | 87 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserToken", b => 88 | { 89 | b.Property("UserId"); 90 | 91 | b.Property("LoginProvider"); 92 | 93 | b.Property("Name"); 94 | 95 | b.Property("Value"); 96 | 97 | b.HasKey("UserId", "LoginProvider", "Name"); 98 | 99 | b.ToTable("Core_UserToken"); 100 | }); 101 | 102 | modelBuilder.Entity("Modular.Modules.Core.Models.Product", b => 103 | { 104 | b.Property("Id") 105 | .ValueGeneratedOnAdd(); 106 | 107 | b.Property("Description"); 108 | 109 | b.Property("Name"); 110 | 111 | b.Property("Price"); 112 | 113 | b.HasKey("Id"); 114 | 115 | b.ToTable("Core_Product"); 116 | }); 117 | 118 | modelBuilder.Entity("Modular.Modules.Core.Models.Role", b => 119 | { 120 | b.Property("Id") 121 | .ValueGeneratedOnAdd(); 122 | 123 | b.Property("ConcurrencyStamp") 124 | .IsConcurrencyToken(); 125 | 126 | b.Property("Name") 127 | .HasAnnotation("MaxLength", 256); 128 | 129 | b.Property("NormalizedName") 130 | .HasAnnotation("MaxLength", 256); 131 | 132 | b.HasKey("Id"); 133 | 134 | b.HasIndex("NormalizedName") 135 | .HasName("RoleNameIndex"); 136 | 137 | b.ToTable("Core_Role"); 138 | }); 139 | 140 | modelBuilder.Entity("Modular.Modules.Core.Models.User", b => 141 | { 142 | b.Property("Id") 143 | .ValueGeneratedOnAdd(); 144 | 145 | b.Property("AccessFailedCount"); 146 | 147 | b.Property("ConcurrencyStamp") 148 | .IsConcurrencyToken(); 149 | 150 | b.Property("CreatedOn"); 151 | 152 | b.Property("Email") 153 | .HasAnnotation("MaxLength", 256); 154 | 155 | b.Property("EmailConfirmed"); 156 | 157 | b.Property("FullName"); 158 | 159 | b.Property("IsDeleted"); 160 | 161 | b.Property("LockoutEnabled"); 162 | 163 | b.Property("LockoutEnd"); 164 | 165 | b.Property("NormalizedEmail") 166 | .HasAnnotation("MaxLength", 256); 167 | 168 | b.Property("NormalizedUserName") 169 | .HasAnnotation("MaxLength", 256); 170 | 171 | b.Property("PasswordHash"); 172 | 173 | b.Property("PhoneNumber"); 174 | 175 | b.Property("PhoneNumberConfirmed"); 176 | 177 | b.Property("SecurityStamp"); 178 | 179 | b.Property("TwoFactorEnabled"); 180 | 181 | b.Property("UpdatedOn"); 182 | 183 | b.Property("UserName") 184 | .HasAnnotation("MaxLength", 256); 185 | 186 | b.HasKey("Id"); 187 | 188 | b.HasIndex("NormalizedEmail") 189 | .HasName("EmailIndex"); 190 | 191 | b.HasIndex("NormalizedUserName") 192 | .IsUnique() 193 | .HasName("UserNameIndex"); 194 | 195 | b.ToTable("Core_User"); 196 | }); 197 | 198 | modelBuilder.Entity("Modular.Modules.ModuleA.Models.Sample", b => 199 | { 200 | b.Property("Id") 201 | .ValueGeneratedOnAdd(); 202 | 203 | b.Property("Description"); 204 | 205 | b.Property("Name") 206 | .HasColumnName("TestName"); 207 | 208 | b.HasKey("Id"); 209 | 210 | b.ToTable("ModuleA_Sample"); 211 | }); 212 | 213 | modelBuilder.Entity("Modular.Modules.ModuleB.Models.Sample", b => 214 | { 215 | b.Property("Id") 216 | .ValueGeneratedOnAdd(); 217 | 218 | b.Property("Name"); 219 | 220 | b.HasKey("Id"); 221 | 222 | b.ToTable("ModuleB_Sample"); 223 | }); 224 | 225 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRoleClaim", b => 226 | { 227 | b.HasOne("Modular.Modules.Core.Models.Role") 228 | .WithMany("Claims") 229 | .HasForeignKey("RoleId") 230 | .OnDelete(DeleteBehavior.Cascade); 231 | }); 232 | 233 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserClaim", b => 234 | { 235 | b.HasOne("Modular.Modules.Core.Models.User") 236 | .WithMany("Claims") 237 | .HasForeignKey("UserId") 238 | .OnDelete(DeleteBehavior.Cascade); 239 | }); 240 | 241 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserLogin", b => 242 | { 243 | b.HasOne("Modular.Modules.Core.Models.User") 244 | .WithMany("Logins") 245 | .HasForeignKey("UserId") 246 | .OnDelete(DeleteBehavior.Cascade); 247 | }); 248 | 249 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserRole", b => 250 | { 251 | b.HasOne("Modular.Modules.Core.Models.Role") 252 | .WithMany("Users") 253 | .HasForeignKey("RoleId") 254 | .OnDelete(DeleteBehavior.Cascade); 255 | 256 | b.HasOne("Modular.Modules.Core.Models.User") 257 | .WithMany("Roles") 258 | .HasForeignKey("UserId") 259 | .OnDelete(DeleteBehavior.Cascade); 260 | }); 261 | } 262 | } 263 | } 264 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modular.WebHost.xproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 14.0 5 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 6 | 7 | 8 | 9 | b13ec77a-fd31-4dbc-a417-f35280d86280 10 | Modular.WebHost 11 | .\obj 12 | .\bin\ 13 | v4.6.1 14 | 15 | 16 | 2.0 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | 7 | namespace Modular.Modules.Core.Controllers 8 | { 9 | public class HomeController : Controller 10 | { 11 | public IActionResult Index() 12 | { 13 | return View(); 14 | } 15 | 16 | public IActionResult About() 17 | { 18 | ViewData["Message"] = "Your application description page."; 19 | 20 | return View(); 21 | } 22 | 23 | public IActionResult Contact() 24 | { 25 | ViewData["Message"] = "Your contact page."; 26 | 27 | return View(); 28 | } 29 | 30 | public IActionResult Error() 31 | { 32 | return View(); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/Infrastructure/CoreCustomModelBuilder.cs: -------------------------------------------------------------------------------- 1 | using Modular.Core; 2 | using Microsoft.EntityFrameworkCore; 3 | using Modular.Modules.Core.Models; 4 | using Microsoft.AspNetCore.Identity.EntityFrameworkCore; 5 | 6 | namespace Modular.Modules.Core.Infrastructure 7 | { 8 | public class CoreCustomModelBuilder : ICustomModelBuilder 9 | { 10 | public void Build(ModelBuilder modelBuilder) 11 | { 12 | modelBuilder.Entity() 13 | .ToTable("Core_User"); 14 | 15 | modelBuilder.Entity() 16 | .ToTable("Core_Role"); 17 | 18 | modelBuilder.Entity>(b => 19 | { 20 | b.HasKey(uc => uc.Id); 21 | b.ToTable("Core_UserClaim"); 22 | }); 23 | 24 | modelBuilder.Entity>(b => 25 | { 26 | b.HasKey(rc => rc.Id); 27 | b.ToTable("Core_RoleClaim"); 28 | }); 29 | 30 | modelBuilder.Entity>(b => 31 | { 32 | b.HasKey(r => new { r.UserId, r.RoleId }); 33 | b.ToTable("Core_UserRole"); 34 | }); 35 | 36 | modelBuilder.Entity>(b => 37 | { 38 | b.ToTable("Core_UserLogin"); 39 | }); 40 | 41 | modelBuilder.Entity>(b => 42 | { 43 | b.ToTable("Core_UserToken"); 44 | }); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/Infrastructure/ModularDbContext.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Identity.EntityFrameworkCore; 2 | using Microsoft.EntityFrameworkCore; 3 | using Modular.Core; 4 | using Modular.Core.Domain.Models; 5 | using Modular.Modules.Core.Models; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Reflection; 10 | 11 | namespace Modular.Modules.Core.Infrastructure 12 | { 13 | public class ModularDbContext : IdentityDbContext 14 | { 15 | public ModularDbContext(DbContextOptions options) : base(options) 16 | { 17 | } 18 | 19 | protected override void OnModelCreating(ModelBuilder modelBuilder) 20 | { 21 | List typeToRegisters = new List(); 22 | foreach (var module in GlobalConfiguration.Modules) 23 | { 24 | typeToRegisters.AddRange(module.Assembly.DefinedTypes.Select(t => t.AsType())); 25 | } 26 | 27 | RegisterEntities(modelBuilder, typeToRegisters); 28 | 29 | RegiserConvention(modelBuilder); 30 | 31 | base.OnModelCreating(modelBuilder); 32 | 33 | RegisterCustomMappings(modelBuilder, typeToRegisters); 34 | } 35 | 36 | private static void RegiserConvention(ModelBuilder modelBuilder) 37 | { 38 | foreach (var entity in modelBuilder.Model.GetEntityTypes()) 39 | { 40 | if (entity.ClrType.Namespace != null) 41 | { 42 | var nameParts = entity.ClrType.Namespace.Split('.'); 43 | var tableName = string.Concat(nameParts[2], "_", entity.ClrType.Name); 44 | modelBuilder.Entity(entity.Name).ToTable(tableName); 45 | } 46 | } 47 | } 48 | 49 | private static void RegisterEntities(ModelBuilder modelBuilder, IEnumerable typeToRegisters) 50 | { 51 | var entityTypes = typeToRegisters.Where(x => x.GetTypeInfo().IsSubclassOf(typeof(Entity)) && !x.GetTypeInfo().IsAbstract); 52 | foreach (var type in entityTypes) 53 | { 54 | modelBuilder.Entity(type); 55 | } 56 | } 57 | 58 | private static void RegisterCustomMappings(ModelBuilder modelBuilder, IEnumerable typeToRegisters) 59 | { 60 | 61 | var customModelBuilderTypes = typeToRegisters.Where(x => typeof(ICustomModelBuilder).IsAssignableFrom(x)); 62 | foreach(var builderType in customModelBuilderTypes) 63 | { 64 | if (builderType != null && builderType != typeof(ICustomModelBuilder)) 65 | { 66 | var builder = (ICustomModelBuilder)Activator.CreateInstance(builderType); 67 | builder.Build(modelBuilder); 68 | } 69 | } 70 | 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/Infrastructure/Repository.cs: -------------------------------------------------------------------------------- 1 | using Modular.Core.Domain; 2 | using Modular.Core.Domain.Models; 3 | using Modular.Modules.Core.Infrastructure; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Threading.Tasks; 8 | 9 | namespace Modular.WebHost.Modules.Modular.Modules.Core.Infrastructure 10 | { 11 | public class Repository : RepositoryWithTypedId, IRepository 12 | where T : class, IEntityWithTypedId 13 | { 14 | public Repository(ModularDbContext context) : base(context) 15 | { 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/Infrastructure/RepositoryWithTypedId.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Modular.Core.Domain; 3 | using Modular.Core.Domain.Models; 4 | using System.Linq; 5 | 6 | namespace Modular.Modules.Core.Infrastructure 7 | { 8 | public class RepositoryWithTypedId : IRepositoryWithTypedId where T : class, IEntityWithTypedId 9 | { 10 | public RepositoryWithTypedId(ModularDbContext context) 11 | { 12 | Context = context; 13 | DbSet = Context.Set(); 14 | } 15 | 16 | protected DbContext Context { get; } 17 | 18 | protected DbSet DbSet { get; } 19 | 20 | public void Add(T entity) 21 | { 22 | DbSet.Add(entity); 23 | } 24 | 25 | public void SaveChange() 26 | { 27 | Context.SaveChanges(); 28 | } 29 | 30 | public IQueryable Query() 31 | { 32 | return DbSet; 33 | } 34 | 35 | public void Remove(T entity) 36 | { 37 | DbSet.Remove(entity); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/Models/Product.cs: -------------------------------------------------------------------------------- 1 | using Modular.Core.Domain.Models; 2 | 3 | namespace Modular.Modules.Core.Models 4 | { 5 | public class Product : Entity 6 | { 7 | public string Name { get; set; } 8 | 9 | public string Description { get; set; } 10 | 11 | public decimal Price { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/Models/Role.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Identity.EntityFrameworkCore; 2 | using Modular.Core.Domain.Models; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | 8 | namespace Modular.Modules.Core.Models 9 | { 10 | public class Role : IdentityRole, IEntityWithTypedId 11 | { 12 | public Role() 13 | { 14 | } 15 | 16 | public Role(string name) 17 | { 18 | Name = name; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/Models/RoleClaim.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Identity.EntityFrameworkCore; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace Modular.Modules.Core.Models 8 | { 9 | public class RoleClaim : IdentityRoleClaim 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/Models/User.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Identity.EntityFrameworkCore; 2 | using Modular.Core.Domain.Models; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | 8 | namespace Modular.Modules.Core.Models 9 | { 10 | public class User : IdentityUser, IEntityWithTypedId 11 | { 12 | public User() 13 | { 14 | CreatedOn = DateTime.Now; 15 | UpdatedOn = DateTime.Now; 16 | } 17 | 18 | public string FullName { get; set; } 19 | 20 | public bool IsDeleted { get; set; } 21 | 22 | public DateTime CreatedOn { get; set; } 23 | 24 | public DateTime UpdatedOn { get; set; } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/Models/UserClaim.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Identity.EntityFrameworkCore; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace Modular.Modules.Core.Models 8 | { 9 | public class UserClaim : IdentityUserClaim 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/Models/UserLogin.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Identity.EntityFrameworkCore; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace Modular.Modules.Core.Models 8 | { 9 | public class UserLogin : IdentityUserLogin 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/Models/UserRole.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Identity.EntityFrameworkCore; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace Modular.Modules.Core.Models 8 | { 9 | public class UserRole : IdentityUserRole 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/Modular.Modules.Core.xproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 14.0 5 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 6 | 7 | 8 | 9 | 10 | 13fc1529-fa8b-47b2-b633-3aacc3fe7c20 11 | Modular.Modules.Core 12 | .\obj 13 | .\bin\ 14 | v4.6.1 15 | 16 | 17 | 18 | 2.0 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyConfiguration("")] 9 | [assembly: AssemblyCompany("")] 10 | [assembly: AssemblyProduct("Modular.Modules.Core")] 11 | [assembly: AssemblyTrademark("")] 12 | 13 | // Setting ComVisible to false makes the types in this assembly not visible 14 | // to COM components. If you need to access a type in this assembly from 15 | // COM, set the ComVisible attribute to true on that type. 16 | [assembly: ComVisible(false)] 17 | 18 | // The following GUID is for the ID of the typelib if this project is exposed to COM 19 | [assembly: Guid("13fc1529-fa8b-47b2-b633-3aacc3fe7c20")] 20 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/Services/IEmailSender.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace Modular.Modules.Core.Services 7 | { 8 | public interface IEmailSender 9 | { 10 | Task SendEmailAsync(string email, string subject, string message); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/Services/ISmsSender.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace Modular.Modules.Core.Services 7 | { 8 | public interface ISmsSender 9 | { 10 | Task SendSmsAsync(string number, string message); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/Services/MessageServices.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace Modular.Modules.Core.Services 7 | { 8 | // This class is used by the application to send Email and SMS 9 | // when you turn on two-factor authentication in ASP.NET Identity. 10 | // For more details see this link http://go.microsoft.com/fwlink/?LinkID=532713 11 | public class AuthMessageSender : IEmailSender, ISmsSender 12 | { 13 | public Task SendEmailAsync(string email, string subject, string message) 14 | { 15 | // Plug in your email service here to send an email. 16 | return Task.FromResult(0); 17 | } 18 | 19 | public Task SendSmsAsync(string number, string message) 20 | { 21 | // Plug in your SMS service here to send a text message. 22 | return Task.FromResult(0); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/ViewModels/AccountViewModels/ExternalLoginConfirmationViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace Modular.Modules.Core.Models.AccountViewModels 8 | { 9 | public class ExternalLoginConfirmationViewModel 10 | { 11 | [Required] 12 | [EmailAddress] 13 | public string Email { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/ViewModels/AccountViewModels/ForgotPasswordViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace Modular.Modules.Core.Models.AccountViewModels 8 | { 9 | public class ForgotPasswordViewModel 10 | { 11 | [Required] 12 | [EmailAddress] 13 | public string Email { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/ViewModels/AccountViewModels/LoginViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace Modular.Modules.Core.Models.AccountViewModels 8 | { 9 | public class LoginViewModel 10 | { 11 | [Required] 12 | [EmailAddress] 13 | public string Email { get; set; } 14 | 15 | [Required] 16 | [DataType(DataType.Password)] 17 | public string Password { get; set; } 18 | 19 | [Display(Name = "Remember me?")] 20 | public bool RememberMe { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/ViewModels/AccountViewModels/RegisterViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace Modular.Modules.Core.Models.AccountViewModels 8 | { 9 | public class RegisterViewModel 10 | { 11 | [Required] 12 | [EmailAddress] 13 | [Display(Name = "Email")] 14 | public string Email { get; set; } 15 | 16 | [Required] 17 | [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] 18 | [DataType(DataType.Password)] 19 | [Display(Name = "Password")] 20 | public string Password { get; set; } 21 | 22 | [DataType(DataType.Password)] 23 | [Display(Name = "Confirm password")] 24 | [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] 25 | public string ConfirmPassword { get; set; } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/ViewModels/AccountViewModels/ResetPasswordViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace Modular.Modules.Core.Models.AccountViewModels 8 | { 9 | public class ResetPasswordViewModel 10 | { 11 | [Required] 12 | [EmailAddress] 13 | public string Email { get; set; } 14 | 15 | [Required] 16 | [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] 17 | [DataType(DataType.Password)] 18 | public string Password { get; set; } 19 | 20 | [DataType(DataType.Password)] 21 | [Display(Name = "Confirm password")] 22 | [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] 23 | public string ConfirmPassword { get; set; } 24 | 25 | public string Code { get; set; } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/ViewModels/AccountViewModels/SendCodeViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc.Rendering; 6 | 7 | namespace Modular.Modules.Core.Models.AccountViewModels 8 | { 9 | public class SendCodeViewModel 10 | { 11 | public string SelectedProvider { get; set; } 12 | 13 | public ICollection Providers { get; set; } 14 | 15 | public string ReturnUrl { get; set; } 16 | 17 | public bool RememberMe { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/ViewModels/AccountViewModels/VerifyCodeViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace Modular.Modules.Core.Models.AccountViewModels 8 | { 9 | public class VerifyCodeViewModel 10 | { 11 | [Required] 12 | public string Provider { get; set; } 13 | 14 | [Required] 15 | public string Code { get; set; } 16 | 17 | public string ReturnUrl { get; set; } 18 | 19 | [Display(Name = "Remember this browser?")] 20 | public bool RememberBrowser { get; set; } 21 | 22 | [Display(Name = "Remember me?")] 23 | public bool RememberMe { get; set; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/ViewModels/ManageViewModels/AddPhoneNumberViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace Modular.Modules.Core.Models.ManageViewModels 8 | { 9 | public class AddPhoneNumberViewModel 10 | { 11 | [Required] 12 | [Phone] 13 | [Display(Name = "Phone number")] 14 | public string PhoneNumber { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/ViewModels/ManageViewModels/ChangePasswordViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace Modular.Modules.Core.Models.ManageViewModels 8 | { 9 | public class ChangePasswordViewModel 10 | { 11 | [Required] 12 | [DataType(DataType.Password)] 13 | [Display(Name = "Current password")] 14 | public string OldPassword { get; set; } 15 | 16 | [Required] 17 | [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] 18 | [DataType(DataType.Password)] 19 | [Display(Name = "New password")] 20 | public string NewPassword { get; set; } 21 | 22 | [DataType(DataType.Password)] 23 | [Display(Name = "Confirm new password")] 24 | [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")] 25 | public string ConfirmPassword { get; set; } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/ViewModels/ManageViewModels/ConfigureTwoFactorViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc.Rendering; 6 | 7 | namespace Modular.Modules.Core.Models.ManageViewModels 8 | { 9 | public class ConfigureTwoFactorViewModel 10 | { 11 | public string SelectedProvider { get; set; } 12 | 13 | public ICollection Providers { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/ViewModels/ManageViewModels/FactorViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace Modular.Modules.Core.Models.ManageViewModels 7 | { 8 | public class FactorViewModel 9 | { 10 | public string Purpose { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/ViewModels/ManageViewModels/IndexViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Identity; 6 | 7 | namespace Modular.Modules.Core.Models.ManageViewModels 8 | { 9 | public class IndexViewModel 10 | { 11 | public bool HasPassword { get; set; } 12 | 13 | public IList Logins { get; set; } 14 | 15 | public string PhoneNumber { get; set; } 16 | 17 | public bool TwoFactor { get; set; } 18 | 19 | public bool BrowserRemembered { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/ViewModels/ManageViewModels/ManageLoginsViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Http.Authentication; 6 | using Microsoft.AspNetCore.Identity; 7 | 8 | namespace Modular.Modules.Core.Models.ManageViewModels 9 | { 10 | public class ManageLoginsViewModel 11 | { 12 | public IList CurrentLogins { get; set; } 13 | 14 | public IList OtherLogins { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/ViewModels/ManageViewModels/RemoveLoginViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace Modular.Modules.Core.Models.ManageViewModels 8 | { 9 | public class RemoveLoginViewModel 10 | { 11 | public string LoginProvider { get; set; } 12 | public string ProviderKey { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/ViewModels/ManageViewModels/SetPasswordViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace Modular.Modules.Core.Models.ManageViewModels 8 | { 9 | public class SetPasswordViewModel 10 | { 11 | [Required] 12 | [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] 13 | [DataType(DataType.Password)] 14 | [Display(Name = "New password")] 15 | public string NewPassword { get; set; } 16 | 17 | [DataType(DataType.Password)] 18 | [Display(Name = "Confirm new password")] 19 | [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")] 20 | public string ConfirmPassword { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/ViewModels/ManageViewModels/VerifyPhoneNumberViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace Modular.Modules.Core.Models.ManageViewModels 8 | { 9 | public class VerifyPhoneNumberViewModel 10 | { 11 | [Required] 12 | public string Code { get; set; } 13 | 14 | [Required] 15 | [Phone] 16 | [Display(Name = "Phone number")] 17 | public string PhoneNumber { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/Views/Account/ConfirmEmail.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Confirm Email"; 3 | } 4 | 5 |

@ViewData["Title"].

6 |
7 |

8 | Thank you for confirming your email. Please Click here to Log in. 9 |

10 |
11 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/Views/Account/ExternalLoginConfirmation.cshtml: -------------------------------------------------------------------------------- 1 | @model ExternalLoginConfirmationViewModel 2 | @{ 3 | ViewData["Title"] = "Register"; 4 | } 5 | 6 |

@ViewData["Title"].

7 |

Associate your @ViewData["LoginProvider"] account.

8 | 9 |
10 |

Association Form

11 |
12 |
13 | 14 |

15 | You've successfully authenticated with @ViewData["LoginProvider"]. 16 | Please enter an email address for this site below and click the Register button to finish 17 | logging in. 18 |

19 |
20 | 21 |
22 | 23 | 24 |
25 |
26 |
27 |
28 | 29 |
30 |
31 |
32 | 33 | @section Scripts { 34 | @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } 35 | } 36 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/Views/Account/ExternalLoginFailure.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Login Failure"; 3 | } 4 | 5 |
6 |

@ViewData["Title"].

7 |

Unsuccessful login with service.

8 |
9 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/Views/Account/ForgotPassword.cshtml: -------------------------------------------------------------------------------- 1 | @model ForgotPasswordViewModel 2 | @{ 3 | ViewData["Title"] = "Forgot your password?"; 4 | } 5 | 6 |

@ViewData["Title"]

7 |

8 | For more information on how to enable reset password please see this article. 9 |

10 | 11 | @*
12 |

Enter your email.

13 |
14 |
15 |
16 | 17 |
18 | 19 | 20 |
21 |
22 |
23 |
24 | 25 |
26 |
27 |
*@ 28 | 29 | @section Scripts { 30 | @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } 31 | } 32 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/Views/Account/ForgotPasswordConfirmation.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Forgot Password Confirmation"; 3 | } 4 | 5 |

@ViewData["Title"].

6 |

7 | Please check your email to reset your password. 8 |

9 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/Views/Account/Lockout.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Locked out"; 3 | } 4 | 5 |
6 |

Locked out.

7 |

This account has been locked out, please try again later.

8 |
9 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/Views/Account/Login.cshtml: -------------------------------------------------------------------------------- 1 | @using System.Collections.Generic 2 | @using Microsoft.AspNetCore.Http 3 | @using Microsoft.AspNetCore.Http.Authentication 4 | @model LoginViewModel 5 | @inject SignInManager SignInManager 6 | 7 | @{ 8 | ViewData["Title"] = "Log in"; 9 | } 10 | 11 |

@ViewData["Title"].

12 |
13 |
14 |
15 |
16 |

Use a local account to log in.

17 |
18 |
19 |
20 | 21 |
22 | 23 | 24 |
25 |
26 |
27 | 28 |
29 | 30 | 31 |
32 |
33 |
34 |
35 |
36 | 40 |
41 |
42 |
43 |
44 |
45 | 46 |
47 |
48 |

49 | Register as a new user? 50 |

51 |

52 | Forgot your password? 53 |

54 |
55 |
56 |
57 |
58 |
59 |

Use another service to log in.

60 |
61 | @{ 62 | var loginProviders = SignInManager.GetExternalAuthenticationSchemes().ToList(); 63 | if (loginProviders.Count == 0) 64 | { 65 |
66 |

67 | There are no external authentication services configured. See this article 68 | for details on setting up this ASP.NET application to support logging in via external services. 69 |

70 |
71 | } 72 | else 73 | { 74 |
75 |
76 |

77 | @foreach (var provider in loginProviders) 78 | { 79 | 80 | } 81 |

82 |
83 |
84 | } 85 | } 86 |
87 |
88 |
89 | 90 | @section Scripts { 91 | @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } 92 | } 93 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/Views/Account/Register.cshtml: -------------------------------------------------------------------------------- 1 | @model RegisterViewModel 2 | @{ 3 | ViewData["Title"] = "Register"; 4 | } 5 | 6 |

@ViewData["Title"].

7 | 8 |
9 |

Create a new account.

10 |
11 |
12 |
13 | 14 |
15 | 16 | 17 |
18 |
19 |
20 | 21 |
22 | 23 | 24 |
25 |
26 |
27 | 28 |
29 | 30 | 31 |
32 |
33 |
34 |
35 | 36 |
37 |
38 |
39 | 40 | @section Scripts { 41 | @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } 42 | } 43 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/Views/Account/ResetPassword.cshtml: -------------------------------------------------------------------------------- 1 | @model ResetPasswordViewModel 2 | @{ 3 | ViewData["Title"] = "Reset password"; 4 | } 5 | 6 |

@ViewData["Title"].

7 | 8 |
9 |

Reset your password.

10 |
11 |
12 | 13 |
14 | 15 |
16 | 17 | 18 |
19 |
20 |
21 | 22 |
23 | 24 | 25 |
26 |
27 |
28 | 29 |
30 | 31 | 32 |
33 |
34 |
35 |
36 | 37 |
38 |
39 |
40 | 41 | @section Scripts { 42 | @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } 43 | } 44 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/Views/Account/ResetPasswordConfirmation.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Reset password confirmation"; 3 | } 4 | 5 |

@ViewData["Title"].

6 |

7 | Your password has been reset. Please Click here to log in. 8 |

9 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/Views/Account/SendCode.cshtml: -------------------------------------------------------------------------------- 1 | @model SendCodeViewModel 2 | @{ 3 | ViewData["Title"] = "Send Verification Code"; 4 | } 5 | 6 |

@ViewData["Title"].

7 | 8 |
9 | 10 |
11 |
12 | Select Two-Factor Authentication Provider: 13 | 14 | 15 |
16 |
17 |
18 | 19 | @section Scripts { 20 | @{await Html.RenderPartialAsync("_ValidationScriptsPartial"); } 21 | } 22 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/Views/Account/VerifyCode.cshtml: -------------------------------------------------------------------------------- 1 | @model VerifyCodeViewModel 2 | @{ 3 | ViewData["Title"] = "Verify"; 4 | } 5 | 6 |

@ViewData["Title"].

7 | 8 |
9 |
10 | 11 | 12 |

@ViewData["Status"]

13 |
14 |
15 | 16 |
17 | 18 | 19 |
20 |
21 |
22 |
23 |
24 | 25 | 26 |
27 |
28 |
29 |
30 |
31 | 32 |
33 |
34 |
35 | 36 | @section Scripts { 37 | @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } 38 | } 39 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/Views/Home/About.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "About"; 3 | } 4 |

@ViewData["Title"].

5 |

@ViewData["Message"]

6 | 7 |

Use this area to provide additional information.

8 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/Views/Home/Contact.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Contact"; 3 | } 4 |

@ViewData["Title"].

5 |

@ViewData["Message"]

6 | 7 |
8 | One Microsoft Way
9 | Redmond, WA 98052-6399
10 | P: 11 | 425.555.0100 12 |
13 | 14 |
15 | Support: Support@example.com
16 | Marketing: Marketing@example.com 17 |
18 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Home Page"; 3 | } 4 | 5 | 67 | 68 | 110 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/Views/Manage/AddPhoneNumber.cshtml: -------------------------------------------------------------------------------- 1 | @model AddPhoneNumberViewModel 2 | @{ 3 | ViewData["Title"] = "Add Phone Number"; 4 | } 5 | 6 |

@ViewData["Title"].

7 |
8 |

Add a phone number.

9 |
10 |
11 |
12 | 13 |
14 | 15 | 16 |
17 |
18 |
19 |
20 | 21 |
22 |
23 |
24 | 25 | @section Scripts { 26 | @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } 27 | } 28 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/Views/Manage/ChangePassword.cshtml: -------------------------------------------------------------------------------- 1 | @model ChangePasswordViewModel 2 | @{ 3 | ViewData["Title"] = "Change Password"; 4 | } 5 | 6 |

@ViewData["Title"].

7 | 8 |
9 |

Change Password Form

10 |
11 |
12 |
13 | 14 |
15 | 16 | 17 |
18 |
19 |
20 | 21 |
22 | 23 | 24 |
25 |
26 |
27 | 28 |
29 | 30 | 31 |
32 |
33 |
34 |
35 | 36 |
37 |
38 |
39 | 40 | @section Scripts { 41 | @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } 42 | } 43 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/Views/Manage/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model IndexViewModel 2 | @{ 3 | ViewData["Title"] = "Manage your account"; 4 | } 5 | 6 |

@ViewData["Title"].

7 |

@ViewData["StatusMessage"]

8 | 9 |
10 |

Change your account settings

11 |
12 |
13 |
Password:
14 |
15 | @if (Model.HasPassword) 16 | { 17 | Change 18 | } 19 | else 20 | { 21 | Create 22 | } 23 |
24 |
External Logins:
25 |
26 | 27 | @Model.Logins.Count Manage 28 |
29 |
Phone Number:
30 |
31 |

32 | Phone Numbers can used as a second factor of verification in two-factor authentication. 33 | See this article 34 | for details on setting up this ASP.NET application to support two-factor authentication using SMS. 35 |

36 | @*@(Model.PhoneNumber ?? "None") 37 | @if (Model.PhoneNumber != null) 38 | { 39 |
40 | Change 41 |
42 | [] 43 |
44 | } 45 | else 46 | { 47 | Add 48 | }*@ 49 |
50 | 51 |
Two-Factor Authentication:
52 |
53 |

54 | There are no two-factor authentication providers configured. See this article 55 | for setting up this application to support two-factor authentication. 56 |

57 | @*@if (Model.TwoFactor) 58 | { 59 |
60 | Enabled 61 |
62 | } 63 | else 64 | { 65 |
66 | Disabled 67 |
68 | }*@ 69 |
70 |
71 |
72 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/Views/Manage/ManageLogins.cshtml: -------------------------------------------------------------------------------- 1 | @model ManageLoginsViewModel 2 | @using Microsoft.AspNetCore.Http.Authentication 3 | @{ 4 | ViewData["Title"] = "Manage your external logins"; 5 | } 6 | 7 |

@ViewData["Title"].

8 | 9 |

@ViewData["StatusMessage"]

10 | @if (Model.CurrentLogins.Count > 0) 11 | { 12 |

Registered Logins

13 | 14 | 15 | @for (var index = 0; index < Model.CurrentLogins.Count; index++) 16 | { 17 | 18 | 19 | 35 | 36 | } 37 | 38 |
@Model.CurrentLogins[index].LoginProvider 20 | @if ((bool)ViewData["ShowRemoveButton"]) 21 | { 22 |
23 |
24 | 25 | 26 | 27 |
28 |
29 | } 30 | else 31 | { 32 | @:   33 | } 34 |
39 | } 40 | @if (Model.OtherLogins.Count > 0) 41 | { 42 |

Add another service to log in.

43 |
44 |
45 |
46 |

47 | @foreach (var provider in Model.OtherLogins) 48 | { 49 | 50 | } 51 |

52 |
53 |
54 | } 55 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/Views/Manage/SetPassword.cshtml: -------------------------------------------------------------------------------- 1 | @model SetPasswordViewModel 2 | @{ 3 | ViewData["Title"] = "Set Password"; 4 | } 5 | 6 |

7 | You do not have a local username/password for this site. Add a local 8 | account so you can log in without an external login. 9 |

10 | 11 |
12 |

Set your password

13 |
14 |
15 |
16 | 17 |
18 | 19 | 20 |
21 |
22 |
23 | 24 |
25 | 26 | 27 |
28 |
29 |
30 |
31 | 32 |
33 |
34 |
35 | 36 | @section Scripts { 37 | @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } 38 | } 39 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/Views/Manage/VerifyPhoneNumber.cshtml: -------------------------------------------------------------------------------- 1 | @model VerifyPhoneNumberViewModel 2 | @{ 3 | ViewData["Title"] = "Verify Phone Number"; 4 | } 5 | 6 |

@ViewData["Title"].

7 | 8 |
9 | 10 |

Add a phone number.

11 |
@ViewData["Status"]
12 |
13 |
14 |
15 | 16 |
17 | 18 | 19 |
20 |
21 |
22 |
23 | 24 |
25 |
26 |
27 | 28 | @section Scripts { 29 | @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } 30 | } 31 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using Modular.Modules.Core 2 | @using Modular.Modules.Core.Models 3 | @using Modular.Modules.Core.Models.AccountViewModels 4 | @using Modular.Modules.Core.Models.ManageViewModels 5 | @using Microsoft.AspNetCore.Identity 6 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 7 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } 4 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.Core/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0-*", 3 | 4 | "dependencies": { 5 | "NETStandard.Library": "1.6.0", 6 | "Modular.Core": "1.0.0-*", 7 | "Microsoft.AspNetCore.Mvc": "1.0.0", 8 | "Microsoft.AspNetCore.Identity.EntityFrameworkCore": "1.0.0" 9 | }, 10 | 11 | "frameworks": { 12 | "netstandard1.6": { 13 | "imports": [ 14 | "dnxcore50" 15 | ] 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.ModuleA/Controllers/TestAController.cs: -------------------------------------------------------------------------------- 1 | using ExtraDepenencyTest; 2 | using Microsoft.AspNetCore.Mvc; 3 | using Modular.Core.Domain; 4 | using Modular.Modules.ModuleA.Models; 5 | using Modular.Modules.ModuleA.Services; 6 | using Modular.Modules.ModuleA.ViewModels; 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Linq; 10 | using System.Threading.Tasks; 11 | 12 | namespace Modular.Modules.ModuleA.Controllers 13 | { 14 | public class TestAController : Controller 15 | { 16 | private ITestService _testService; 17 | private IAnotherTestService _anotherTestService; 18 | private IRepository _sampleRepository; 19 | 20 | public TestAController(ITestService testService, IAnotherTestService anotherTestService, IRepository sampleRepository) 21 | { 22 | _testService = testService; 23 | _anotherTestService = anotherTestService; 24 | _sampleRepository = sampleRepository; 25 | } 26 | 27 | public IActionResult Index() 28 | { 29 | ViewBag.TestData = _testService.Test(); 30 | ViewBag.AnotherTestData = _anotherTestService.Test(); 31 | 32 | var sample = new Sample { Name = "Name test", Description = "Decription Test" }; 33 | _sampleRepository.Add(sample); 34 | _sampleRepository.SaveChange(); 35 | 36 | var model = new TestViewModel { Name = sample.Name, Description = sample.Description }; 37 | 38 | return View(model); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.ModuleA/Infrastructure/ModuleACustomModelBuilder.cs: -------------------------------------------------------------------------------- 1 | using Modular.Core; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.EntityFrameworkCore; 7 | using Modular.Modules.ModuleA.Models; 8 | 9 | namespace Modular.Modules.ModuleA.Infrastructure 10 | { 11 | public class ModuleACustomModelBuilder : ICustomModelBuilder 12 | { 13 | public void Build(ModelBuilder modelBuilder) 14 | { 15 | modelBuilder.Entity() 16 | .Property(x => x.Name).HasColumnName("TestName"); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.ModuleA/Models/Sample.cs: -------------------------------------------------------------------------------- 1 | using Modular.Core.Domain.Models; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace Modular.Modules.ModuleA.Models 8 | { 9 | public class Sample : Entity 10 | { 11 | public string Name { get; set; } 12 | 13 | public string Description { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.ModuleA/Modular.Modules.ModuleA.xproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 14.0 5 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 6 | 7 | 8 | 9 | 10 | fc71b7c8-c4d2-4cc3-b3e7-b630cd552c35 11 | Modular.Modules.ModuleA 12 | .\obj 13 | .\bin\ 14 | v4.6.1 15 | 16 | 17 | 18 | 2.0 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.ModuleA/ModuleInitializer.cs: -------------------------------------------------------------------------------- 1 | using ExtraDepenencyTest; 2 | using Microsoft.Extensions.DependencyInjection; 3 | using Modular.Core; 4 | using Modular.Modules.ModuleA.Services; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Threading.Tasks; 9 | 10 | namespace Modular.Modules.ModuleA 11 | { 12 | public class ModuleInitializer : IModuleInitializer 13 | { 14 | public void Init(IServiceCollection services) 15 | { 16 | services.AddTransient(); 17 | services.AddTransient(); 18 | 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.ModuleA/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyConfiguration("")] 9 | [assembly: AssemblyCompany("")] 10 | [assembly: AssemblyProduct("Modular.Modules.ModuleA")] 11 | [assembly: AssemblyTrademark("")] 12 | 13 | // Setting ComVisible to false makes the types in this assembly not visible 14 | // to COM components. If you need to access a type in this assembly from 15 | // COM, set the ComVisible attribute to true on that type. 16 | [assembly: ComVisible(false)] 17 | 18 | // The following GUID is for the ID of the typelib if this project is exposed to COM 19 | [assembly: Guid("fc71b7c8-c4d2-4cc3-b3e7-b630cd552c35")] 20 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.ModuleA/Services/ITestService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace Modular.Modules.ModuleA.Services 7 | { 8 | public interface ITestService 9 | { 10 | string Test(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.ModuleA/Services/TestService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace Modular.Modules.ModuleA.Services 7 | { 8 | public class TestService : ITestService 9 | { 10 | public string Test() 11 | { 12 | return "This is a test, return by Test method in Test Service"; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.ModuleA/ViewModels/TestViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace Modular.Modules.ModuleA.ViewModels 7 | { 8 | public class TestViewModel 9 | { 10 | public string Name { get; set; } 11 | 12 | public string Description { get; set; } 13 | 14 | public string Test { get; set; } = "It's good"; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.ModuleA/Views/TestA/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model Modular.Modules.ModuleA.ViewModels.TestViewModel 2 |

Hello, I'm from module A

3 | 4 |

Test data: @ViewBag.TestData

5 | 6 |

Another test: @ViewBag.AnotherTestData

7 | 8 |

Strong type view

9 |

@Model.Name

10 |

@Model.Description

11 |

@Model.Test

-------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.ModuleA/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } 4 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.ModuleA/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0-*", 3 | 4 | "dependencies": { 5 | "NETStandard.Library": "1.6.0", 6 | "Microsoft.AspNetCore.Mvc": "1.0.0", 7 | "Microsoft.EntityFrameworkCore.Relational": "1.0.0", 8 | "Modular.Core": "1.0.0-*", 9 | "ExtraDepenencyTest": "1.0.0-*" 10 | }, 11 | 12 | "frameworks": { 13 | "netstandard1.6": { 14 | "imports": "dnxcore50" 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.ModuleA/wwwroot/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thiennn/trymodular/852cfea165bf9fe232f2e4633b052d64eba4133d/Modular/src/Modular.WebHost/Modules/Modular.Modules.ModuleA/wwwroot/logo.png -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.ModuleB/Controllers/TestBController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using Modular.Core.Domain; 3 | using Modular.Modules.ModuleB.Models; 4 | 5 | namespace Modular.Modules.ModuleB.Controllers 6 | { 7 | public class TestBController : Controller 8 | { 9 | private IRepository _sampleRepository; 10 | 11 | public TestBController(IRepository sampleRepository) 12 | { 13 | _sampleRepository = sampleRepository; 14 | } 15 | 16 | public IActionResult Index() 17 | { 18 | var sample = new Sample { Name = "Text" }; 19 | _sampleRepository.Add(sample); 20 | _sampleRepository.SaveChange(); 21 | return View(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.ModuleB/Models/Sample.cs: -------------------------------------------------------------------------------- 1 | using Modular.Core.Domain.Models; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace Modular.Modules.ModuleB.Models 8 | { 9 | public class Sample : Entity 10 | { 11 | public string Name { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.ModuleB/Modular.Modules.ModuleB.xproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 14.0 5 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 6 | 7 | 8 | 9 | 10 | ce294e9d-9f20-400f-8051-e6a98ab76c71 11 | Modular.Modules.ModuleB 12 | .\obj 13 | .\bin\ 14 | v4.6.1 15 | 16 | 17 | 18 | 2.0 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.ModuleB/ModuleInitializer.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | using Modular.Core; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | 8 | namespace Modular.Modules.ModuleB 9 | { 10 | public class ModuleInitializer : IModuleInitializer 11 | { 12 | public void Init(IServiceCollection services) 13 | { 14 | 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.ModuleB/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyConfiguration("")] 9 | [assembly: AssemblyCompany("")] 10 | [assembly: AssemblyProduct("Modular.Modules.ModuleB")] 11 | [assembly: AssemblyTrademark("")] 12 | 13 | // Setting ComVisible to false makes the types in this assembly not visible 14 | // to COM components. If you need to access a type in this assembly from 15 | // COM, set the ComVisible attribute to true on that type. 16 | [assembly: ComVisible(false)] 17 | 18 | // The following GUID is for the ID of the typelib if this project is exposed to COM 19 | [assembly: Guid("ce294e9d-9f20-400f-8051-e6a98ab76c71")] 20 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.ModuleB/Views/TestB/Index.cshtml: -------------------------------------------------------------------------------- 1 | 

Hello, I'm from module B

-------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.ModuleB/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } 4 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Modules/Modular.Modules.ModuleB/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0-*", 3 | 4 | "dependencies": { 5 | "NETStandard.Library": "1.6.0", 6 | "Modular.Core": "1.0.0-*", 7 | "Microsoft.AspNetCore.Mvc": "1.0.0" 8 | }, 9 | 10 | "frameworks": { 11 | "netstandard1.6": { 12 | "imports": "dnxcore50" 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore.Hosting; 7 | 8 | namespace Modular.WebHost 9 | { 10 | public class Program 11 | { 12 | public static void Main(string[] args) 13 | { 14 | var host = new WebHostBuilder() 15 | .UseKestrel() 16 | .UseContentRoot(Directory.GetCurrentDirectory()) 17 | .UseIISIntegration() 18 | .UseStartup() 19 | .Build(); 20 | 21 | host.Run(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Project_Readme.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Welcome to ASP.NET Core 6 | 127 | 128 | 129 | 130 | 138 | 139 |
140 |
141 |

This application consists of:

142 |
    143 |
  • Sample pages using ASP.NET Core MVC
  • 144 |
  • Gulp and Bower for managing client-side libraries
  • 145 |
  • Theming using Bootstrap
  • 146 |
147 |
148 | 160 | 172 |
173 |

Run & Deploy

174 | 179 |
180 | 181 | 184 |
185 | 186 | 187 | 188 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:57965/", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "Modular.WebHost": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "launchUrl": "http://localhost:5000", 22 | "environmentVariables": { 23 | "ASPNETCORE_ENVIRONMENT": "Development" 24 | } 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Startup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Microsoft.AspNetCore.Builder; 5 | using Microsoft.AspNetCore.Hosting; 6 | using Microsoft.EntityFrameworkCore; 7 | using Microsoft.Extensions.Configuration; 8 | using Microsoft.Extensions.DependencyInjection; 9 | using Microsoft.Extensions.Logging; 10 | using System.Reflection; 11 | using System.Runtime.Loader; 12 | using Microsoft.AspNetCore.Mvc.Razor; 13 | using Modular.WebHost.Extensions; 14 | using System.IO; 15 | using Modular.Core; 16 | using Microsoft.Extensions.FileProviders; 17 | using Microsoft.AspNetCore.Http; 18 | using Modular.Modules.Core.Models; 19 | using Modular.Modules.Core.Infrastructure; 20 | using Autofac; 21 | using Modular.Core.Domain; 22 | using Autofac.Extensions.DependencyInjection; 23 | using Modular.WebHost.Modules.Modular.Modules.Core.Infrastructure; 24 | using Microsoft.CodeAnalysis; 25 | 26 | namespace Modular.WebHost 27 | { 28 | public class Startup 29 | { 30 | private readonly IHostingEnvironment _hostingEnvironment; 31 | private readonly IList modules = new List(); 32 | 33 | public Startup(IHostingEnvironment env) 34 | { 35 | _hostingEnvironment = env; 36 | 37 | var builder = new ConfigurationBuilder() 38 | .SetBasePath(env.ContentRootPath) 39 | .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) 40 | .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true); 41 | 42 | if (env.IsDevelopment()) 43 | { 44 | // For more details on using the user secret store see http://go.microsoft.com/fwlink/?LinkID=532709 45 | builder.AddUserSecrets(); 46 | } 47 | 48 | builder.AddEnvironmentVariables(); 49 | Configuration = builder.Build(); 50 | } 51 | 52 | public IConfigurationRoot Configuration { get; } 53 | 54 | // This method gets called by the runtime. Use this method to add services to the container. 55 | public IServiceProvider ConfigureServices(IServiceCollection services) 56 | { 57 | 58 | LoadInstalledModules(); 59 | 60 | services.AddDbContext(options => 61 | options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"), b => b.MigrationsAssembly("Modular.WebHost"))); 62 | 63 | services.AddIdentity() 64 | .AddEntityFrameworkStores() 65 | .AddDefaultTokenProviders(); 66 | 67 | services.Configure(options => 68 | { 69 | options.ViewLocationExpanders.Add(new ModuleViewLocationExpander()); 70 | }); 71 | 72 | var mvcBuilder = services.AddMvc() 73 | .AddRazorOptions(o => 74 | { 75 | foreach (var module in modules) 76 | { 77 | o.AdditionalCompilationReferences.Add(MetadataReference.CreateFromFile(module.Assembly.Location)); 78 | } 79 | }); 80 | 81 | var moduleInitializerInterface = typeof(IModuleInitializer); 82 | foreach (var module in modules) 83 | { 84 | // Register controller from modules 85 | mvcBuilder.AddApplicationPart(module.Assembly); 86 | 87 | // Register dependency in modules 88 | var moduleInitializerType = module.Assembly.GetTypes().Where(x => typeof(IModuleInitializer).IsAssignableFrom(x)).FirstOrDefault(); 89 | if (moduleInitializerType != null && moduleInitializerType != typeof(IModuleInitializer)) 90 | { 91 | var moduleInitializer = (IModuleInitializer)Activator.CreateInstance(moduleInitializerType); 92 | moduleInitializer.Init(services); 93 | } 94 | } 95 | 96 | // TODO: break down to new method in new class 97 | var builder = new ContainerBuilder(); 98 | builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>)); 99 | builder.RegisterGeneric(typeof(RepositoryWithTypedId<,>)).As(typeof(IRepositoryWithTypedId<,>)); 100 | foreach (var module in GlobalConfiguration.Modules) 101 | { 102 | builder.RegisterAssemblyTypes(module.Assembly).AsImplementedInterfaces(); 103 | } 104 | 105 | builder.RegisterInstance(Configuration); 106 | builder.RegisterInstance(_hostingEnvironment); 107 | builder.Populate(services); 108 | var container = builder.Build(); 109 | return container.Resolve(); 110 | } 111 | 112 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 113 | public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) 114 | { 115 | loggerFactory.AddConsole(Configuration.GetSection("Logging")); 116 | loggerFactory.AddDebug(); 117 | 118 | if (env.IsDevelopment()) 119 | { 120 | app.UseDeveloperExceptionPage(); 121 | app.UseDatabaseErrorPage(); 122 | app.UseBrowserLink(); 123 | } 124 | else 125 | { 126 | app.UseExceptionHandler("/Home/Error"); 127 | } 128 | 129 | app.UseStaticFiles(); 130 | 131 | // Serving static file for modules 132 | foreach(var module in modules) 133 | { 134 | var wwwrootDir = new DirectoryInfo(Path.Combine(module.Path, "wwwroot")); 135 | if (!wwwrootDir.Exists) 136 | { 137 | continue; 138 | } 139 | 140 | app.UseStaticFiles(new StaticFileOptions() 141 | { 142 | FileProvider = new PhysicalFileProvider(wwwrootDir.FullName), 143 | RequestPath = new PathString("/"+ module.ShortName) 144 | }); 145 | } 146 | 147 | app.UseIdentity(); 148 | 149 | app.UseMvc(routes => 150 | { 151 | routes.MapRoute( 152 | name: "default", 153 | template: "{controller=Home}/{action=Index}/{id?}"); 154 | }); 155 | } 156 | 157 | private void LoadInstalledModules() 158 | { 159 | var moduleRootFolder = new DirectoryInfo(Path.Combine(_hostingEnvironment.ContentRootPath, "Modules")); 160 | var moduleFolders = moduleRootFolder.GetDirectories(); 161 | 162 | foreach (var moduleFolder in moduleFolders) 163 | { 164 | var binFolder = new DirectoryInfo(Path.Combine(moduleFolder.FullName, "bin")); 165 | if (!binFolder.Exists) 166 | { 167 | continue; 168 | } 169 | 170 | foreach (var file in binFolder.GetFileSystemInfos("*.dll", SearchOption.AllDirectories)) 171 | { 172 | Assembly assembly = null; 173 | try 174 | { 175 | assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(file.FullName); 176 | } 177 | catch (FileLoadException) 178 | { 179 | // Get loaded assembly 180 | assembly = Assembly.Load(new AssemblyName(Path.GetFileNameWithoutExtension(file.Name))); 181 | 182 | if (assembly == null) 183 | { 184 | throw; 185 | } 186 | } 187 | 188 | if (assembly.FullName.Contains(moduleFolder.Name)) 189 | { 190 | modules.Add(new ModuleInfo { Name = moduleFolder.Name, Assembly = assembly, Path = moduleFolder.FullName }); 191 | } 192 | } 193 | } 194 | 195 | GlobalConfiguration.Modules = modules; 196 | } 197 | } 198 | } 199 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Error"; 3 | } 4 | 5 |

Error.

6 |

An error occurred while processing your request.

7 | 8 |

Development Mode

9 |

10 | Swapping to Development environment will display more detailed information about the error that occurred. 11 |

12 |

13 | Development environment should not be enabled in deployed applications, as it can result in sensitive information from exceptions being displayed to end users. For local debugging, development environment can be enabled by setting the ASPNETCORE_ENVIRONMENT environment variable to Development, and restarting the application. 14 |

15 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | @ViewData["Title"] - Modular.Modules.Core 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 44 |
45 | @RenderBody() 46 |
47 |
48 |

© 2016 - Modular.Modules.Core

49 |
50 |
51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 62 | 66 | 67 | 68 | 69 | @RenderSection("scripts", required: false) 70 | 71 | 72 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Views/Shared/_LoginPartial.cshtml: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Identity 2 | @using Modular.Modules.Core.Models 3 | 4 | @inject SignInManager SignInManager 5 | @inject UserManager UserManager 6 | 7 | @if (SignInManager.IsSignedIn(User)) 8 | { 9 | 19 | } 20 | else 21 | { 22 | 26 | } 27 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Views/Shared/_ValidationScriptsPartial.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 10 | 14 | 15 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using Modular.Modules.Core 2 | @using Modular.Modules.Core.Models 3 | @using Modular.Modules.Core.Models.AccountViewModels 4 | @using Modular.Modules.Core.Models.ManageViewModels 5 | @using Microsoft.AspNetCore.Identity 6 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 7 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ConnectionStrings": { 3 | "DefaultConnection": "Server=.\\sqlexpress;Database=TryModular;Trusted_Connection=True;MultipleActiveResultSets=true" 4 | }, 5 | "Logging": { 6 | "IncludeScopes": false, 7 | "LogLevel": { 8 | "Default": "Debug", 9 | "System": "Information", 10 | "Microsoft": "Information" 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "userSecretsId": "aspnet-Modular.WebHost-dca604fa-ee10-4a6c-8e7d-8cc79dca8c8f", 3 | 4 | "dependencies": { 5 | "Microsoft.NETCore.App": { 6 | "version": "1.0.0", 7 | "type": "platform" 8 | }, 9 | "Microsoft.AspNetCore.Authentication.Cookies": "1.0.0", 10 | "Microsoft.AspNetCore.Diagnostics": "1.0.0", 11 | "Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore": "1.0.0", 12 | "Microsoft.AspNetCore.Identity.EntityFrameworkCore": "1.0.0", 13 | "Microsoft.AspNetCore.Mvc": "1.0.0", 14 | "Microsoft.AspNetCore.Razor.Tools": { 15 | "version": "1.0.0-preview2-final", 16 | "type": "build" 17 | }, 18 | "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0", 19 | "Microsoft.AspNetCore.Server.Kestrel": "1.0.0", 20 | "Microsoft.AspNetCore.StaticFiles": "1.0.0", 21 | "Microsoft.EntityFrameworkCore.SqlServer": "1.0.0", 22 | "Microsoft.EntityFrameworkCore.Tools": { 23 | "version": "1.0.0-preview2-final", 24 | "type": "build" 25 | }, 26 | "Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0", 27 | "Microsoft.Extensions.Configuration.Json": "1.0.0", 28 | "Microsoft.Extensions.Configuration.UserSecrets": "1.0.0", 29 | "Microsoft.Extensions.Logging": "1.0.0", 30 | "Microsoft.Extensions.Logging.Console": "1.0.0", 31 | "Microsoft.Extensions.Logging.Debug": "1.0.0", 32 | "Microsoft.VisualStudio.Web.BrowserLink.Loader": "14.0.0", 33 | "Microsoft.VisualStudio.Web.CodeGeneration.Tools": { 34 | "version": "1.0.0-preview2-final", 35 | "type": "build" 36 | }, 37 | "Microsoft.VisualStudio.Web.CodeGenerators.Mvc": { 38 | "version": "1.0.0-preview2-final", 39 | "type": "build" 40 | }, 41 | "Modular.Core": "1.0.0-*", 42 | "Modular.Modules.Core": "1.0.0-*", 43 | "Autofac.Extensions.DependencyInjection": "4.0.0-rc3-280" 44 | }, 45 | 46 | "tools": { 47 | "BundlerMinifier.Core": "2.0.238", 48 | "Microsoft.AspNetCore.Razor.Tools": "1.0.0-preview2-final", 49 | "Microsoft.AspNetCore.Server.IISIntegration.Tools": "1.0.0-preview2-final", 50 | "Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final", 51 | "Microsoft.Extensions.SecretManager.Tools": "1.0.0-preview2-final", 52 | "Microsoft.VisualStudio.Web.CodeGeneration.Tools": { 53 | "version": "1.0.0-preview2-final", 54 | "imports": [ 55 | "portable-net45+win8" 56 | ] 57 | } 58 | }, 59 | 60 | "frameworks": { 61 | "netcoreapp1.0": { 62 | "imports": [ 63 | "dotnet5.6", 64 | "portable-net45+win8" 65 | ] 66 | } 67 | }, 68 | 69 | "buildOptions": { 70 | "emitEntryPoint": true, 71 | "preserveCompilationContext": true, 72 | "copyToOutput": { 73 | "include": [ 74 | "Views", 75 | "web.config" 76 | ] 77 | }, 78 | "compile": { 79 | "exclude": [ 80 | "wwwroot", 81 | "node_modules", 82 | "App_Data", 83 | "Core", 84 | "Modules", 85 | "Themes" 86 | ] 87 | } 88 | }, 89 | 90 | "runtimeOptions": { 91 | "configProperties": { 92 | "System.GC.Server": true 93 | } 94 | }, 95 | 96 | "publishOptions": { 97 | "include": [ 98 | "wwwroot", 99 | "Views", 100 | "appsettings.json", 101 | "web.config" 102 | ] 103 | }, 104 | 105 | "scripts": { 106 | "prepublish": [ "npm install", "bower install", "gulp clean", "gulp min" ], 107 | "postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ] 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/wwwroot/_references.js: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | /// 4 | /// 5 | /// 6 | /// 7 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/wwwroot/css/site.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding-top: 50px; 3 | padding-bottom: 20px; 4 | } 5 | 6 | /* Wrapping element */ 7 | /* Set some basic padding to keep content from hitting the edges */ 8 | .body-content { 9 | padding-left: 15px; 10 | padding-right: 15px; 11 | } 12 | 13 | /* Set widths on the form inputs since otherwise they're 100% wide */ 14 | input, 15 | select, 16 | textarea { 17 | max-width: 280px; 18 | } 19 | 20 | /* Carousel */ 21 | .carousel-caption p { 22 | font-size: 20px; 23 | line-height: 1.4; 24 | } 25 | 26 | /* buttons and links extension to use brackets: [ click me ] */ 27 | .btn-bracketed::before { 28 | display:inline-block; 29 | content: "["; 30 | padding-right: 0.5em; 31 | } 32 | .btn-bracketed::after { 33 | display:inline-block; 34 | content: "]"; 35 | padding-left: 0.5em; 36 | } 37 | 38 | /* Hide/rearrange for smaller screens */ 39 | @media screen and (max-width: 767px) { 40 | /* Hide captions */ 41 | .carousel-caption { 42 | display: none 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/wwwroot/css/site.min.css: -------------------------------------------------------------------------------- 1 | body{padding-top:50px;padding-bottom:20px}.body-content{padding-left:15px;padding-right:15px}input,select,textarea{max-width:280px}.carousel-caption p{font-size:20px;line-height:1.4}.btn-bracketed::before{display:inline-block;content:"[";padding-right:.5em}.btn-bracketed::after{display:inline-block;content:"]";padding-left:.5em}@media screen and (max-width:767px){.carousel-caption{display:none}} -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thiennn/trymodular/852cfea165bf9fe232f2e4633b052d64eba4133d/Modular/src/Modular.WebHost/wwwroot/favicon.ico -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/wwwroot/images/banner1.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/wwwroot/images/banner2.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/wwwroot/images/banner3.svg: -------------------------------------------------------------------------------- 1 | banner3b -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/wwwroot/images/banner4.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/wwwroot/js/site.js: -------------------------------------------------------------------------------- 1 | // Write your Javascript code. 2 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/wwwroot/js/site.min.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thiennn/trymodular/852cfea165bf9fe232f2e4633b052d64eba4133d/Modular/src/Modular.WebHost/wwwroot/js/site.min.js -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/wwwroot/lib/bootstrap/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bootstrap", 3 | "description": "The most popular front-end framework for developing responsive, mobile first projects on the web.", 4 | "keywords": [ 5 | "css", 6 | "js", 7 | "less", 8 | "mobile-first", 9 | "responsive", 10 | "front-end", 11 | "framework", 12 | "web" 13 | ], 14 | "homepage": "http://getbootstrap.com", 15 | "license": "MIT", 16 | "moduleType": "globals", 17 | "main": [ 18 | "less/bootstrap.less", 19 | "dist/js/bootstrap.js" 20 | ], 21 | "ignore": [ 22 | "/.*", 23 | "_config.yml", 24 | "CNAME", 25 | "composer.json", 26 | "CONTRIBUTING.md", 27 | "docs", 28 | "js/tests", 29 | "test-infra" 30 | ], 31 | "dependencies": { 32 | "jquery": "1.9.1 - 2" 33 | }, 34 | "version": "3.3.6", 35 | "_release": "3.3.6", 36 | "_resolution": { 37 | "type": "version", 38 | "tag": "v3.3.6", 39 | "commit": "81df608a40bf0629a1dc08e584849bb1e43e0b7a" 40 | }, 41 | "_source": "git://github.com/twbs/bootstrap.git", 42 | "_target": "3.3.6", 43 | "_originalSource": "bootstrap" 44 | } -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/wwwroot/lib/bootstrap/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2011-2015 Twitter, Inc 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/wwwroot/lib/bootstrap/dist/css/bootstrap-theme.min.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["less/theme.less","less/mixins/vendor-prefixes.less","less/mixins/gradients.less","less/mixins/reset-filter.less"],"names":[],"mappings":";;;;AAmBA,YAAA,aAAA,UAAA,aAAA,aAAA,aAME,YAAA,EAAA,KAAA,EAAA,eC2CA,mBAAA,MAAA,EAAA,IAAA,EAAA,sBAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,MAAA,EAAA,IAAA,EAAA,sBAAA,EAAA,IAAA,IAAA,iBDvCR,mBAAA,mBAAA,oBAAA,oBAAA,iBAAA,iBAAA,oBAAA,oBAAA,oBAAA,oBAAA,oBAAA,oBCsCA,mBAAA,MAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,MAAA,EAAA,IAAA,IAAA,iBDlCR,qBAAA,sBAAA,sBAAA,uBAAA,mBAAA,oBAAA,sBAAA,uBAAA,sBAAA,uBAAA,sBAAA,uBAAA,+BAAA,gCAAA,6BAAA,gCAAA,gCAAA,gCCiCA,mBAAA,KACQ,WAAA,KDlDV,mBAAA,oBAAA,iBAAA,oBAAA,oBAAA,oBAuBI,YAAA,KAyCF,YAAA,YAEE,iBAAA,KAKJ,aErEI,YAAA,EAAA,IAAA,EAAA,KACA,iBAAA,iDACA,iBAAA,4CAAA,iBAAA,qEAEA,iBAAA,+CCnBF,OAAA,+GH4CA,OAAA,0DACA,kBAAA,SAuC2C,aAAA,QAA2B,aAAA,KArCtE,mBAAA,mBAEE,iBAAA,QACA,oBAAA,EAAA,MAGF,oBAAA,oBAEE,iBAAA,QACA,aAAA,QAMA,sBAAA,6BAAA,4BAAA,6BAAA,4BAAA,4BAAA,uBAAA,8BAAA,6BAAA,8BAAA,6BAAA,6BAAA,gCAAA,uCAAA,sCAAA,uCAAA,sCAAA,sCAME,iBAAA,QACA,iBAAA,KAgBN,aEtEI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDAEA,OAAA,+GCnBF,OAAA,0DH4CA,kBAAA,SACA,aAAA,QAEA,mBAAA,mBAEE,iBAAA,QACA,oBAAA,EAAA,MAGF,oBAAA,oBAEE,iBAAA,QACA,aAAA,QAMA,sBAAA,6BAAA,4BAAA,6BAAA,4BAAA,4BAAA,uBAAA,8BAAA,6BAAA,8BAAA,6BAAA,6BAAA,gCAAA,uCAAA,sCAAA,uCAAA,sCAAA,sCAME,iBAAA,QACA,iBAAA,KAiBN,aEvEI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDAEA,OAAA,+GCnBF,OAAA,0DH4CA,kBAAA,SACA,aAAA,QAEA,mBAAA,mBAEE,iBAAA,QACA,oBAAA,EAAA,MAGF,oBAAA,oBAEE,iBAAA,QACA,aAAA,QAMA,sBAAA,6BAAA,4BAAA,6BAAA,4BAAA,4BAAA,uBAAA,8BAAA,6BAAA,8BAAA,6BAAA,6BAAA,gCAAA,uCAAA,sCAAA,uCAAA,sCAAA,sCAME,iBAAA,QACA,iBAAA,KAkBN,UExEI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDAEA,OAAA,+GCnBF,OAAA,0DH4CA,kBAAA,SACA,aAAA,QAEA,gBAAA,gBAEE,iBAAA,QACA,oBAAA,EAAA,MAGF,iBAAA,iBAEE,iBAAA,QACA,aAAA,QAMA,mBAAA,0BAAA,yBAAA,0BAAA,yBAAA,yBAAA,oBAAA,2BAAA,0BAAA,2BAAA,0BAAA,0BAAA,6BAAA,oCAAA,mCAAA,oCAAA,mCAAA,mCAME,iBAAA,QACA,iBAAA,KAmBN,aEzEI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDAEA,OAAA,+GCnBF,OAAA,0DH4CA,kBAAA,SACA,aAAA,QAEA,mBAAA,mBAEE,iBAAA,QACA,oBAAA,EAAA,MAGF,oBAAA,oBAEE,iBAAA,QACA,aAAA,QAMA,sBAAA,6BAAA,4BAAA,6BAAA,4BAAA,4BAAA,uBAAA,8BAAA,6BAAA,8BAAA,6BAAA,6BAAA,gCAAA,uCAAA,sCAAA,uCAAA,sCAAA,sCAME,iBAAA,QACA,iBAAA,KAoBN,YE1EI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDAEA,OAAA,+GCnBF,OAAA,0DH4CA,kBAAA,SACA,aAAA,QAEA,kBAAA,kBAEE,iBAAA,QACA,oBAAA,EAAA,MAGF,mBAAA,mBAEE,iBAAA,QACA,aAAA,QAMA,qBAAA,4BAAA,2BAAA,4BAAA,2BAAA,2BAAA,sBAAA,6BAAA,4BAAA,6BAAA,4BAAA,4BAAA,+BAAA,sCAAA,qCAAA,sCAAA,qCAAA,qCAME,iBAAA,QACA,iBAAA,KA2BN,eAAA,WClCE,mBAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,EAAA,IAAA,IAAA,iBD2CV,0BAAA,0BE3FI,iBAAA,QACA,iBAAA,oDACA,iBAAA,+CAAA,iBAAA,wEACA,iBAAA,kDACA,OAAA,+GF0FF,kBAAA,SAEF,yBAAA,+BAAA,+BEhGI,iBAAA,QACA,iBAAA,oDACA,iBAAA,+CAAA,iBAAA,wEACA,iBAAA,kDACA,OAAA,+GFgGF,kBAAA,SASF,gBE7GI,iBAAA,iDACA,iBAAA,4CACA,iBAAA,qEAAA,iBAAA,+CACA,OAAA,+GACA,OAAA,0DCnBF,kBAAA,SH+HA,cAAA,ICjEA,mBAAA,MAAA,EAAA,IAAA,EAAA,sBAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,MAAA,EAAA,IAAA,EAAA,sBAAA,EAAA,IAAA,IAAA,iBD6DV,sCAAA,oCE7GI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SD2CF,mBAAA,MAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,MAAA,EAAA,IAAA,IAAA,iBD0EV,cAAA,iBAEE,YAAA,EAAA,IAAA,EAAA,sBAIF,gBEhII,iBAAA,iDACA,iBAAA,4CACA,iBAAA,qEAAA,iBAAA,+CACA,OAAA,+GACA,OAAA,0DCnBF,kBAAA,SHkJA,cAAA,IAHF,sCAAA,oCEhII,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SD2CF,mBAAA,MAAA,EAAA,IAAA,IAAA,gBACQ,WAAA,MAAA,EAAA,IAAA,IAAA,gBDgFV,8BAAA,iCAYI,YAAA,EAAA,KAAA,EAAA,gBAKJ,qBAAA,kBAAA,mBAGE,cAAA,EAqBF,yBAfI,mDAAA,yDAAA,yDAGE,MAAA,KE7JF,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,UFqKJ,OACE,YAAA,EAAA,IAAA,EAAA,qBC3HA,mBAAA,MAAA,EAAA,IAAA,EAAA,sBAAA,EAAA,IAAA,IAAA,gBACQ,WAAA,MAAA,EAAA,IAAA,EAAA,sBAAA,EAAA,IAAA,IAAA,gBDsIV,eEtLI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF8KF,aAAA,QAKF,YEvLI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF8KF,aAAA,QAMF,eExLI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF8KF,aAAA,QAOF,cEzLI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF8KF,aAAA,QAeF,UEjMI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFuMJ,cE3MI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFwMJ,sBE5MI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFyMJ,mBE7MI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF0MJ,sBE9MI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF2MJ,qBE/MI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF+MJ,sBElLI,iBAAA,yKACA,iBAAA,oKACA,iBAAA,iKFyLJ,YACE,cAAA,IC9KA,mBAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,EAAA,IAAA,IAAA,iBDgLV,wBAAA,8BAAA,8BAGE,YAAA,EAAA,KAAA,EAAA,QEnOE,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFiOF,aAAA,QALF,+BAAA,qCAAA,qCAQI,YAAA,KAUJ,OCnME,mBAAA,EAAA,IAAA,IAAA,gBACQ,WAAA,EAAA,IAAA,IAAA,gBD4MV,8BE5PI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFyPJ,8BE7PI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF0PJ,8BE9PI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF2PJ,2BE/PI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF4PJ,8BEhQI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF6PJ,6BEjQI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFoQJ,MExQI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFsQF,aAAA,QC3NA,mBAAA,MAAA,EAAA,IAAA,IAAA,gBAAA,EAAA,IAAA,EAAA,qBACQ,WAAA,MAAA,EAAA,IAAA,IAAA,gBAAA,EAAA,IAAA,EAAA"} -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thiennn/trymodular/852cfea165bf9fe232f2e4633b052d64eba4133d/Modular/src/Modular.WebHost/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thiennn/trymodular/852cfea165bf9fe232f2e4633b052d64eba4133d/Modular/src/Modular.WebHost/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thiennn/trymodular/852cfea165bf9fe232f2e4633b052d64eba4133d/Modular/src/Modular.WebHost/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thiennn/trymodular/852cfea165bf9fe232f2e4633b052d64eba4133d/Modular/src/Modular.WebHost/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/wwwroot/lib/bootstrap/dist/js/npm.js: -------------------------------------------------------------------------------- 1 | // This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment. 2 | require('../../js/transition.js') 3 | require('../../js/alert.js') 4 | require('../../js/button.js') 5 | require('../../js/carousel.js') 6 | require('../../js/collapse.js') 7 | require('../../js/dropdown.js') 8 | require('../../js/modal.js') 9 | require('../../js/tooltip.js') 10 | require('../../js/popover.js') 11 | require('../../js/scrollspy.js') 12 | require('../../js/tab.js') 13 | require('../../js/affix.js') -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/wwwroot/lib/jquery-validation-unobtrusive/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery-validation-unobtrusive", 3 | "version": "3.2.6", 4 | "homepage": "https://github.com/aspnet/jquery-validation-unobtrusive", 5 | "description": "Add-on to jQuery Validation to enable unobtrusive validation options in data-* attributes.", 6 | "main": [ 7 | "jquery.validate.unobtrusive.js" 8 | ], 9 | "ignore": [ 10 | "**/.*", 11 | "*.json", 12 | "*.md", 13 | "*.txt", 14 | "gulpfile.js" 15 | ], 16 | "keywords": [ 17 | "jquery", 18 | "asp.net", 19 | "mvc", 20 | "validation", 21 | "unobtrusive" 22 | ], 23 | "authors": [ 24 | "Microsoft" 25 | ], 26 | "license": "http://www.microsoft.com/web/webpi/eula/net_library_eula_enu.htm", 27 | "repository": { 28 | "type": "git", 29 | "url": "git://github.com/aspnet/jquery-validation-unobtrusive.git" 30 | }, 31 | "dependencies": { 32 | "jquery-validation": ">=1.8", 33 | "jquery": ">=1.8" 34 | }, 35 | "_release": "3.2.6", 36 | "_resolution": { 37 | "type": "version", 38 | "tag": "v3.2.6", 39 | "commit": "13386cd1b5947d8a5d23a12b531ce3960be1eba7" 40 | }, 41 | "_source": "git://github.com/aspnet/jquery-validation-unobtrusive.git", 42 | "_target": "3.2.6", 43 | "_originalSource": "jquery-validation-unobtrusive" 44 | } -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | ** Unobtrusive validation support library for jQuery and jQuery Validate 3 | ** Copyright (C) Microsoft Corporation. All rights reserved. 4 | */ 5 | !function(a){function e(a,e,n){a.rules[e]=n,a.message&&(a.messages[e]=a.message)}function n(a){return a.replace(/^\s+|\s+$/g,"").split(/\s*,\s*/g)}function t(a){return a.replace(/([!"#$%&'()*+,./:;<=>?@\[\\\]^`{|}~])/g,"\\$1")}function r(a){return a.substr(0,a.lastIndexOf(".")+1)}function i(a,e){return 0===a.indexOf("*.")&&(a=a.replace("*.",e)),a}function o(e,n){var r=a(this).find("[data-valmsg-for='"+t(n[0].name)+"']"),i=r.attr("data-valmsg-replace"),o=i?a.parseJSON(i)!==!1:null;r.removeClass("field-validation-valid").addClass("field-validation-error"),e.data("unobtrusiveContainer",r),o?(r.empty(),e.removeClass("input-validation-error").appendTo(r)):e.hide()}function d(e,n){var t=a(this).find("[data-valmsg-summary=true]"),r=t.find("ul");r&&r.length&&n.errorList.length&&(r.empty(),t.addClass("validation-summary-errors").removeClass("validation-summary-valid"),a.each(n.errorList,function(){a("
  • ").html(this.message).appendTo(r)}))}function s(e){var n=e.data("unobtrusiveContainer");if(n){var t=n.attr("data-valmsg-replace"),r=t?a.parseJSON(t):null;n.addClass("field-validation-valid").removeClass("field-validation-error"),e.removeData("unobtrusiveContainer"),r&&n.empty()}}function l(e){var n=a(this),t="__jquery_unobtrusive_validation_form_reset";if(!n.data(t)){n.data(t,!0);try{n.data("validator").resetForm()}finally{n.removeData(t)}n.find(".validation-summary-errors").addClass("validation-summary-valid").removeClass("validation-summary-errors"),n.find(".field-validation-error").addClass("field-validation-valid").removeClass("field-validation-error").removeData("unobtrusiveContainer").find(">*").removeData("unobtrusiveContainer")}}function m(e){var n=a(e),t=n.data(v),r=a.proxy(l,e),i=p.unobtrusive.options||{},m=function(n,t){var r=i[n];r&&a.isFunction(r)&&r.apply(e,t)};return t||(t={options:{errorClass:i.errorClass||"input-validation-error",errorElement:i.errorElement||"span",errorPlacement:function(){o.apply(e,arguments),m("errorPlacement",arguments)},invalidHandler:function(){d.apply(e,arguments),m("invalidHandler",arguments)},messages:{},rules:{},success:function(){s.apply(e,arguments),m("success",arguments)}},attachValidation:function(){n.off("reset."+v,r).on("reset."+v,r).validate(this.options)},validate:function(){return n.validate(),n.valid()}},n.data(v,t)),t}var u,p=a.validator,v="unobtrusiveValidation";p.unobtrusive={adapters:[],parseElement:function(e,n){var t,r,i,o=a(e),d=o.parents("form")[0];d&&(t=m(d),t.options.rules[e.name]=r={},t.options.messages[e.name]=i={},a.each(this.adapters,function(){var n="data-val-"+this.name,t=o.attr(n),s={};void 0!==t&&(n+="-",a.each(this.params,function(){s[this]=o.attr(n+this)}),this.adapt({element:e,form:d,message:t,params:s,rules:r,messages:i}))}),a.extend(r,{__dummy__:!0}),n||t.attachValidation())},parse:function(e){var n=a(e),t=n.parents().addBack().filter("form").add(n.find("form")).has("[data-val=true]");n.find("[data-val=true]").each(function(){p.unobtrusive.parseElement(this,!0)}),t.each(function(){var a=m(this);a&&a.attachValidation()})}},u=p.unobtrusive.adapters,u.add=function(a,e,n){return n||(n=e,e=[]),this.push({name:a,params:e,adapt:n}),this},u.addBool=function(a,n){return this.add(a,function(t){e(t,n||a,!0)})},u.addMinMax=function(a,n,t,r,i,o){return this.add(a,[i||"min",o||"max"],function(a){var i=a.params.min,o=a.params.max;i&&o?e(a,r,[i,o]):i?e(a,n,i):o&&e(a,t,o)})},u.addSingleVal=function(a,n,t){return this.add(a,[n||"val"],function(r){e(r,t||a,r.params[n])})},p.addMethod("__dummy__",function(a,e,n){return!0}),p.addMethod("regex",function(a,e,n){var t;return this.optional(e)?!0:(t=new RegExp(n).exec(a),t&&0===t.index&&t[0].length===a.length)}),p.addMethod("nonalphamin",function(a,e,n){var t;return n&&(t=a.match(/\W/g),t=t&&t.length>=n),t}),p.methods.extension?(u.addSingleVal("accept","mimtype"),u.addSingleVal("extension","extension")):u.addSingleVal("extension","extension","accept"),u.addSingleVal("regex","pattern"),u.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url"),u.addMinMax("length","minlength","maxlength","rangelength").addMinMax("range","min","max","range"),u.addMinMax("minlength","minlength").addMinMax("maxlength","minlength","maxlength"),u.add("equalto",["other"],function(n){var o=r(n.element.name),d=n.params.other,s=i(d,o),l=a(n.form).find(":input").filter("[name='"+t(s)+"']")[0];e(n,"equalTo",l)}),u.add("required",function(a){("INPUT"!==a.element.tagName.toUpperCase()||"CHECKBOX"!==a.element.type.toUpperCase())&&e(a,"required",!0)}),u.add("remote",["url","type","additionalfields"],function(o){var d={url:o.params.url,type:o.params.type||"GET",data:{}},s=r(o.element.name);a.each(n(o.params.additionalfields||o.element.name),function(e,n){var r=i(n,s);d.data[r]=function(){var e=a(o.form).find(":input").filter("[name='"+t(r)+"']");return e.is(":checkbox")?e.filter(":checked").val()||e.filter(":hidden").val()||"":e.is(":radio")?e.filter(":checked").val()||"":e.val()}}),e(o,"remote",d)}),u.add("password",["min","nonalphamin","regex"],function(a){a.params.min&&e(a,"minlength",a.params.min),a.params.nonalphamin&&e(a,"nonalphamin",a.params.nonalphamin),a.params.regex&&e(a,"regex",a.params.regex)}),a(function(){p.unobtrusive.parse(document)})}(jQuery); -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/wwwroot/lib/jquery-validation/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery-validation", 3 | "homepage": "http://jqueryvalidation.org/", 4 | "repository": { 5 | "type": "git", 6 | "url": "git://github.com/jzaefferer/jquery-validation.git" 7 | }, 8 | "authors": [ 9 | "Jörn Zaefferer " 10 | ], 11 | "description": "Form validation made easy", 12 | "main": "dist/jquery.validate.js", 13 | "keywords": [ 14 | "forms", 15 | "validation", 16 | "validate" 17 | ], 18 | "license": "MIT", 19 | "ignore": [ 20 | "**/.*", 21 | "node_modules", 22 | "bower_components", 23 | "test", 24 | "demo", 25 | "lib" 26 | ], 27 | "dependencies": { 28 | "jquery": ">= 1.7.2" 29 | }, 30 | "version": "1.14.0", 31 | "_release": "1.14.0", 32 | "_resolution": { 33 | "type": "version", 34 | "tag": "1.14.0", 35 | "commit": "c1343fb9823392aa9acbe1c3ffd337b8c92fed48" 36 | }, 37 | "_source": "git://github.com/jzaefferer/jquery-validation.git", 38 | "_target": ">=1.8", 39 | "_originalSource": "jquery-validation" 40 | } -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/wwwroot/lib/jquery-validation/LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | ===================== 3 | 4 | Copyright Jörn Zaefferer 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/wwwroot/lib/jquery/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery", 3 | "main": "dist/jquery.js", 4 | "license": "MIT", 5 | "ignore": [ 6 | "package.json" 7 | ], 8 | "keywords": [ 9 | "jquery", 10 | "javascript", 11 | "browser", 12 | "library" 13 | ], 14 | "homepage": "https://github.com/jquery/jquery-dist", 15 | "version": "2.2.0", 16 | "_release": "2.2.0", 17 | "_resolution": { 18 | "type": "version", 19 | "tag": "2.2.0", 20 | "commit": "6fc01e29bdad0964f62ef56d01297039cdcadbe5" 21 | }, 22 | "_source": "git://github.com/jquery/jquery-dist.git", 23 | "_target": "2.2.0", 24 | "_originalSource": "jquery" 25 | } -------------------------------------------------------------------------------- /Modular/src/Modular.WebHost/wwwroot/lib/jquery/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright jQuery Foundation and other contributors, https://jquery.org/ 2 | 3 | This software consists of voluntary contributions made by many 4 | individuals. For exact contribution history, see the revision history 5 | available at https://github.com/jquery/jquery 6 | 7 | The following license applies to all parts of this software except as 8 | documented below: 9 | 10 | ==== 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining 13 | a copy of this software and associated documentation files (the 14 | "Software"), to deal in the Software without restriction, including 15 | without limitation the rights to use, copy, modify, merge, publish, 16 | distribute, sublicense, and/or sell copies of the Software, and to 17 | permit persons to whom the Software is furnished to do so, subject to 18 | the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be 21 | included in all copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 27 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 28 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 29 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 | 31 | ==== 32 | 33 | All files located in the node_modules and external directories are 34 | externally maintained libraries used by this software which have their 35 | own licenses; we recommend you read them, as their terms may differ from 36 | the terms above. 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Modular Web Application with ASP.NET Core 2 | I am looking for a solution to modularize my simple commerce https://github.com/simplcommerce/SimplCommerce. I have been researching for a few days. Some instructions have been found for example: 3 | 4 | * https://github.com/aspnet/Mvc/issues/4572 5 | * https://github.com/ExtCore/ExtCore 6 | * http://shazwazza.com/post/custom-assembly-loading-with-aspnet-core/ 7 | * https://github.com/OrchardCMS/Orchard2 8 | 9 | They seem not completed yet or too complicated for me. Struggling for a while, finally I can make it work. To be honest, I not sure this is best solution and I am looking for comments 10 | 11 | There are few things we need to address to make our application modularized: 12 | 13 | 1. How can MVC know about our controllers when they are in other class libraries, in other folder and not being referenced by the host 14 | 2. How can the ViewEngine pick up the right location for the Views 15 | 3. How to register services used in modules 16 | 4. How to serve static file: js, css, image for modules 17 | 18 | Below is general folder structure I have come up with 19 | 20 | ![](https://github.com/thiennn/trymodular/blob/master/folder-structure.png) 21 | 22 | The Modular.WebHost is the ASP.NET Core project and it will act as the host. It will bootstrap the app and load all the modules it found in the Modules folder. 23 | 24 | Each module contains all the stuff for itself to run including Controllers, Services, Views and event static files. 25 | 26 | For easy development, in the visual studio solution I create a "Modules" solution items and add module projects in Modular.WebHost/Modules phycial folder. 27 | To prevent Modular.WebHost to compile stuff in Modules folder, we need to exclude them in the project.json. 28 | 29 | 1. Fist, in the Startup.cs, we scan all the *.dll in each module and load them up 30 | 31 | ```cs 32 | var moduleRootFolder = _hostingEnvironment.ContentRootFileProvider.GetDirectoryContents("/Modules"); 33 | foreach(var moduleFolder in moduleRootFolder.Where(x => x.IsDirectory)) 34 | { 35 | var binFolder = new DirectoryInfo(Path.Combine(moduleFolder.PhysicalPath, "bin")); 36 | if (!binFolder.Exists) 37 | { 38 | continue; 39 | } 40 | 41 | foreach(var file in binFolder.GetFileSystemInfos("*.dll", SearchOption.AllDirectories)) 42 | { 43 | Assembly assembly; 44 | try 45 | { 46 | assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(file.FullName); 47 | } 48 | catch(FileLoadException ex) 49 | { 50 | if (ex.Message == "Assembly with same name is already loaded") 51 | { 52 | continue; 53 | } 54 | throw; 55 | } 56 | 57 | if (assembly.FullName.Contains(moduleFolder.Name)) 58 | { 59 | modules.Add(new ModuleInfo { Name = moduleFolder.Name, Assembly = assembly, Path = moduleFolder.PhysicalPath }); 60 | } 61 | } 62 | } 63 | } 64 | ``` 65 | 66 | Then module assemblies will be added to MVC by ApplicationPart 67 | 68 | ```cs 69 | var mvcBuilder = services.AddMvc(); 70 | foreach (var module in modules) 71 | { 72 | // Register controller from modules 73 | mvcBuilder.AddApplicationPart(module.Assembly); 74 | } 75 | ``` 76 | 77 | 2. ModuleViewLocationExpander is used to help the view engine lookup up the right module folder the views 78 | 79 | ```cs 80 | services.Configure(options => 81 | { 82 | options.ViewLocationExpanders.Add(new ModuleViewLocationExpander()); 83 | }); 84 | ``` 85 | 86 | 3. Each module contains an ModuleInitializer.cs where services for that module is registered. 87 | 88 | ```cs 89 | // Register dependency in modules 90 | var moduleInitializerInterface = typeof(IModuleInitializer); 91 | foreach(var module in modules) 92 | { 93 | // Register dependency in modules 94 | var moduleInitializerType = module.Assembly.GetTypes().Where(x => typeof(IModuleInitializer).IsAssignableFrom(x)).FirstOrDefault(); 95 | 96 | if(moduleInitializerType != null && moduleInitializerType != typeof(IModuleInitializer)) 97 | { 98 | var moduleInitializer = (IModuleInitializer)Activator.CreateInstance(moduleInitializerType); 99 | moduleInitializer.Init(services); 100 | } 101 | } 102 | ``` 103 | 104 | 4. And this is how I serve static files for modules 105 | 106 | ```cs 107 | // Serving static file for modules 108 | foreach(var module in modules) 109 | { 110 | var wwwrootDir = new DirectoryInfo(Path.Combine(module.Path, "wwwroot")); 111 | if (!wwwrootDir.Exists) 112 | { 113 | continue; 114 | } 115 | 116 | app.UseStaticFiles(new StaticFileOptions() 117 | { 118 | FileProvider = new PhysicalFileProvider(wwwrootDir.FullName), 119 | RequestPath = new PathString("/"+ module.SortName) 120 | }); 121 | } 122 | ``` 123 | -------------------------------------------------------------------------------- /folder-structure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thiennn/trymodular/852cfea165bf9fe232f2e4633b052d64eba4133d/folder-structure.png --------------------------------------------------------------------------------