├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── build.bat ├── psake-config.ps1 ├── psake.psm1 ├── psakefile.ps1 ├── src ├── ContosoUniversity.sln ├── ContosoUniversity │ ├── App_Start │ │ ├── BundleConfig.cs │ │ ├── FilterConfig.cs │ │ ├── RouteConfig.cs │ │ └── StructuremapMvc.cs │ ├── Content │ │ ├── PagedList.css │ │ ├── Site.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 │ ├── ContosoUniversity.csproj │ ├── DAL │ │ ├── SchoolConfiguration.cs │ │ ├── SchoolContext.cs │ │ ├── SchoolInitializer.cs │ │ ├── SchoolInterceptorLogging.cs │ │ └── SchoolInterceptorTransientErrors.cs │ ├── DependencyResolution │ │ ├── ControllerConvention.cs │ │ ├── DefaultRegistry.cs │ │ ├── IoC.cs │ │ ├── StructureMapDependencyScope.cs │ │ └── StructureMapScopeModule.cs │ ├── Features │ │ ├── Course │ │ │ ├── Create.cs │ │ │ ├── Create.cshtml │ │ │ ├── Delete.cs │ │ │ ├── Delete.cshtml │ │ │ ├── Details.cs │ │ │ ├── Details.cshtml │ │ │ ├── Edit.cs │ │ │ ├── Edit.cshtml │ │ │ ├── Index.cs │ │ │ ├── Index.cshtml │ │ │ ├── MappingProfile.cs │ │ │ ├── UiController.cs │ │ │ └── UpdateCourseCredits.cshtml │ │ ├── Department │ │ │ ├── Create.cs │ │ │ ├── Create.cshtml │ │ │ ├── Delete.cs │ │ │ ├── Delete.cshtml │ │ │ ├── Details.cs │ │ │ ├── Details.cshtml │ │ │ ├── Edit.cs │ │ │ ├── Edit.cshtml │ │ │ ├── Index.cs │ │ │ ├── Index.cshtml │ │ │ ├── MappingProfile.cs │ │ │ └── UiController.cs │ │ ├── Home │ │ │ ├── About.cs │ │ │ ├── About.cshtml │ │ │ ├── Contact.cshtml │ │ │ ├── Index.cshtml │ │ │ └── UiController.cs │ │ ├── Instructor │ │ │ ├── CreateEdit.cs │ │ │ ├── CreateEdit.cshtml │ │ │ ├── Delete.cs │ │ │ ├── Delete.cshtml │ │ │ ├── Details.cs │ │ │ ├── Details.cshtml │ │ │ ├── Index.cs │ │ │ ├── Index.cshtml │ │ │ ├── MappingProfile.cs │ │ │ └── UiController.cs │ │ ├── Shared │ │ │ ├── Error.cshtml │ │ │ └── _Layout.cshtml │ │ ├── Student │ │ │ ├── Create.cs │ │ │ ├── Create.cshtml │ │ │ ├── Delete.cs │ │ │ ├── Delete.cshtml │ │ │ ├── Details.cs │ │ │ ├── Details.cshtml │ │ │ ├── Edit.cs │ │ │ ├── Edit.cshtml │ │ │ ├── Index.cs │ │ │ ├── Index.cshtml │ │ │ ├── MappingProfile.cs │ │ │ └── UiController.cs │ │ ├── Web.config │ │ └── _ViewStart.cshtml │ ├── GlimpseSecurityPolicy.cs │ ├── Global.asax │ ├── Global.asax.cs │ ├── Infrastructure │ │ ├── CommandProcessing │ │ │ └── CommandProcessingRegistry.cs │ │ ├── ControllerExtensions.cs │ │ ├── ControllerFactory.cs │ │ ├── DataAccess │ │ │ └── MvcTransactionFilter.cs │ │ ├── DepartmentModelBinder.cs │ │ ├── DepartmentModelBinderProvider.cs │ │ ├── FeatureViewLocationRazorViewEngine.cs │ │ ├── HtmlHelperExtensions.cs │ │ ├── InstructorModelBinder.cs │ │ ├── InstructorModelBinderProvider.cs │ │ ├── LinkBuilder.cs │ │ ├── Mapping │ │ │ ├── AutoMapperInitializer.cs │ │ │ └── MappingExtensions.cs │ │ ├── Tags │ │ │ ├── DefaultAspNetMvcHtmlConventions.cs │ │ │ ├── DefaultDisplayLabelBuilder.cs │ │ │ ├── DepartmentSelectElementBuilder.cs │ │ │ ├── EntitySelectElementBuilder.cs │ │ │ ├── HtmlTagExtensions.cs │ │ │ ├── HtmlTagRegistry.cs │ │ │ └── InstructorSelectElementBuilder.cs │ │ ├── UrlHelperExtensions.cs │ │ ├── Validation │ │ │ └── StructureMapValidatorFactory.cs │ │ └── ValidatorActionFilter.cs │ ├── Logging │ │ ├── ILogger.cs │ │ └── Logger.cs │ ├── Migrations │ │ ├── 201411021828194_InitialCreate.Designer.cs │ │ ├── 201411021828194_InitialCreate.cs │ │ ├── 201411021828194_InitialCreate.resx │ │ ├── 201411021834484_MaxLengthOnNames.Designer.cs │ │ ├── 201411021834484_MaxLengthOnNames.cs │ │ ├── 201411021834484_MaxLengthOnNames.resx │ │ ├── 201411021841373_ComplexDataModel.Designer.cs │ │ ├── 201411021841373_ComplexDataModel.cs │ │ ├── 201411021841373_ComplexDataModel.resx │ │ ├── 201411021957458_DepartmentSP.Designer.cs │ │ ├── 201411021957458_DepartmentSP.cs │ │ ├── 201411021957458_DepartmentSP.resx │ │ ├── 201411022009135_RowVersion.Designer.cs │ │ ├── 201411022009135_RowVersion.cs │ │ ├── 201411022009135_RowVersion.resx │ │ ├── 201411022351064_Inheritance.Designer.cs │ │ ├── 201411022351064_Inheritance.cs │ │ ├── 201411022351064_Inheritance.resx │ │ └── Configuration.cs │ ├── Models │ │ ├── Course.cs │ │ ├── Department.cs │ │ ├── Enrollment.cs │ │ ├── IEntity.cs │ │ ├── Instructor.cs │ │ ├── OfficeAssignment.cs │ │ ├── Person.cs │ │ └── Student.cs │ ├── Project_Readme.html │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── Scripts │ │ ├── _references.js │ │ ├── bootstrap.js │ │ ├── bootstrap.min.js │ │ ├── jquery-1.10.2.intellisense.js │ │ ├── jquery-2.1.4.intellisense.js │ │ ├── jquery-2.1.4.js │ │ ├── jquery-2.1.4.min.js │ │ ├── jquery-2.1.4.min.map │ │ ├── jquery.validate-vsdoc.js │ │ ├── jquery.validate.js │ │ ├── jquery.validate.min.js │ │ ├── jquery.validate.unobtrusive.js │ │ ├── jquery.validate.unobtrusive.min.js │ │ ├── lodash.js │ │ ├── modernizr-2.6.2.js │ │ ├── modernizr-2.8.3.js │ │ ├── respond.js │ │ ├── respond.matchmedia.addListener.js │ │ ├── respond.matchmedia.addListener.min.js │ │ └── respond.min.js │ ├── Web.Debug.config │ ├── Web.Release.config │ ├── Web.config │ ├── favicon.ico │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ └── glyphicons-halflings-regular.woff2 │ └── packages.config ├── DBDeployment │ ├── DBDeployment.csproj │ └── Properties │ │ └── AssemblyInfo.cs ├── DatabaseMigration │ └── up │ │ ├── 000001.Initial_Schema.sql │ │ └── 000002.Initial_Data.sql └── IntegrationTests │ ├── AutoFixtureCustomization.cs │ ├── AutoFixtureFactory.cs │ ├── ContainerBuilder.cs │ ├── DeleteData.cs │ ├── Features │ ├── Course │ │ └── CreateTests.cs │ └── FooTests.cs │ ├── FixieConvention.cs │ ├── FixieExtensions.cs │ ├── FixturePerClassConvention.cs │ ├── FixturePerMethodConvention.cs │ ├── IdOmitterBuilder.cs │ ├── IntegrationTestContainerFactory.cs │ ├── IntegrationTestConvention.cs │ ├── IntegrationTests.csproj │ ├── IntegrationTestsFixtureCustomization.cs │ ├── LocalDbFactory.cs │ ├── OmitListBuilder.cs │ ├── Properties │ └── AssemblyInfo.cs │ ├── TestContextFixture.cs │ ├── app.config │ ├── log4net.dll │ ├── log4net.xml │ └── packages.config └── tools ├── fixie ├── Fixie.Console.exe ├── Fixie.Console.exe.config └── Fixie.dll ├── nuget └── nuget.exe └── roundhouse ├── output └── migrations │ └── ContosoUniversity │ ├── SQL2014 │ ├── 20150302_142703_4853 │ │ └── itemsRan │ │ │ └── up │ │ │ └── 000001.Initial_Schema.sql │ └── 20150302_142707_3495 │ │ └── itemsRan │ │ └── up │ │ └── 000001.Initial_Schema.sql │ └── mssqllocaldb │ ├── 20230616_203715_3800 │ └── itemsRan │ │ └── up │ │ └── 000001.Initial_Schema.sql │ └── 20230616_203725_6147 │ └── itemsRan │ └── up │ └── 000001.Initial_Schema.sql └── rh.exe /.gitattributes: -------------------------------------------------------------------------------- 1 | *.doc diff=astextplain 2 | *.DOC diff=astextplain 3 | *.docx diff=astextplain 4 | *.DOCX diff=astextplain 5 | *.dot diff=astextplain 6 | *.DOT diff=astextplain 7 | *.pdf diff=astextplain 8 | *.PDF diff=astextplain 9 | *.rtf diff=astextplain 10 | *.RTF diff=astextplain 11 | 12 | *.jpg binary 13 | *.png binary 14 | *.gif binary 15 | 16 | core.eol crlf 17 | 18 | *.cs diff=csharp 19 | 20 | *.csproj merge=union 21 | *.vbproj merge=union 22 | *.fsproj merge=union 23 | *.dbproj merge=union 24 | *.sln merge=union 25 | -------------------------------------------------------------------------------- /.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 | *.sln.docstates 8 | 9 | # Build results 10 | [Dd]ebug/ 11 | [Dd]ebugPublic/ 12 | [Rr]elease/ 13 | [Rr]eleases/ 14 | x64/ 15 | x86/ 16 | build/ 17 | bld/ 18 | [Bb]in/ 19 | [Oo]bj/ 20 | .vs/ 21 | 22 | # Roslyn cache directories 23 | *.ide/ 24 | 25 | # MSTest test Results 26 | [Tt]est[Rr]esult*/ 27 | [Bb]uild[Ll]og.* 28 | 29 | #NUNIT 30 | *.VisualState.xml 31 | TestResult.xml 32 | 33 | # Build Results of an ATL Project 34 | [Dd]ebugPS/ 35 | [Rr]eleasePS/ 36 | dlldata.c 37 | 38 | *_i.c 39 | *_p.c 40 | *_i.h 41 | *.ilk 42 | *.meta 43 | *.obj 44 | *.pch 45 | *.pdb 46 | *.pgc 47 | *.pgd 48 | *.rsp 49 | *.sbr 50 | *.tlb 51 | *.tli 52 | *.tlh 53 | *.tmp 54 | *.tmp_proj 55 | *.log 56 | *.vspscc 57 | *.vssscc 58 | .builds 59 | *.pidb 60 | *.svclog 61 | *.scc 62 | 63 | # Chutzpah Test files 64 | _Chutzpah* 65 | 66 | # Visual C++ cache files 67 | ipch/ 68 | *.aps 69 | *.ncb 70 | *.opensdf 71 | *.sdf 72 | *.cachefile 73 | 74 | # Visual Studio profiler 75 | *.psess 76 | *.vsp 77 | *.vspx 78 | 79 | # TFS 2012 Local Workspace 80 | $tf/ 81 | 82 | # Guidance Automation Toolkit 83 | *.gpState 84 | 85 | # ReSharper is a .NET coding add-in 86 | _ReSharper*/ 87 | *.[Rr]e[Ss]harper 88 | *.DotSettings.user 89 | 90 | # JustCode is a .NET coding addin-in 91 | .JustCode 92 | 93 | # TeamCity is a build add-in 94 | _TeamCity* 95 | 96 | # DotCover is a Code Coverage Tool 97 | *.dotCover 98 | 99 | # NCrunch 100 | _NCrunch_* 101 | .*crunch*.local.xml 102 | 103 | # MightyMoose 104 | *.mm.* 105 | AutoTest.Net/ 106 | 107 | # Web workbench (sass) 108 | .sass-cache/ 109 | 110 | # Installshield output folder 111 | [Ee]xpress/ 112 | 113 | # DocProject is a documentation generator add-in 114 | DocProject/buildhelp/ 115 | DocProject/Help/*.HxT 116 | DocProject/Help/*.HxC 117 | DocProject/Help/*.hhc 118 | DocProject/Help/*.hhk 119 | DocProject/Help/*.hhp 120 | DocProject/Help/Html2 121 | DocProject/Help/html 122 | 123 | # Click-Once directory 124 | publish/ 125 | 126 | # Publish Web Output 127 | *.[Pp]ublish.xml 128 | *.azurePubxml 129 | # TODO: Comment the next line if you want to checkin your web deploy settings 130 | # but database connection strings (with potential passwords) will be unencrypted 131 | *.pubxml 132 | *.publishproj 133 | 134 | # NuGet Packages 135 | *.nupkg 136 | # The packages folder can be ignored because of Package Restore 137 | **/packages/* 138 | # except build/, which is used as an MSBuild target. 139 | !**/packages/build/ 140 | # If using the old MSBuild-Integrated Package Restore, uncomment this: 141 | #!**/packages/repositories.config 142 | 143 | # Windows Azure Build Output 144 | csx/ 145 | *.build.csdef 146 | 147 | # Windows Store app package directory 148 | AppPackages/ 149 | 150 | # Others 151 | sql/ 152 | *.Cache 153 | ClientBin/ 154 | [Ss]tyle[Cc]op.* 155 | ~$* 156 | *~ 157 | *.dbmdl 158 | *.dbproj.schemaview 159 | *.pfx 160 | *.publishsettings 161 | node_modules/ 162 | 163 | # RIA/Silverlight projects 164 | Generated_Code/ 165 | 166 | # Backup & report files from converting an old project file 167 | # to a newer Visual Studio version. Backup files are not needed, 168 | # because we have git ;-) 169 | _UpgradeReport_Files/ 170 | Backup*/ 171 | UpgradeLog*.XML 172 | UpgradeLog*.htm 173 | 174 | # SQL Server files 175 | *.mdf 176 | *.ldf 177 | 178 | # Business Intelligence projects 179 | *.rdl.data 180 | *.bim.layout 181 | *.bim_*.settings 182 | 183 | # Microsoft Fakes 184 | FakesAssemblies/ 185 | 186 | tools/roundhouse/output -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ContosoUniversity 2 | Contoso University sample re-done the way I would build it 3 | -------------------------------------------------------------------------------- /build.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | rem Helper script for those who want to run psake from cmd.exe 3 | 4 | powershell -NoProfile -ExecutionPolicy Bypass -Command "invoke-psake %*; if ($psake.build_success -eq $false) { exit 1 } else { exit 0 }" 5 | -------------------------------------------------------------------------------- /psake-config.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | ------------------------------------------------------------------- 3 | Defaults 4 | ------------------------------------------------------------------- 5 | $config.buildFileName="default.ps1" 6 | $config.framework = "4.0" 7 | $config.taskNameFormat="Executing {0}" 8 | $config.verboseError=$false 9 | $config.coloredOutput = $true 10 | $config.modules=$null 11 | 12 | ------------------------------------------------------------------- 13 | Load modules from .\modules folder and from file my_module.psm1 14 | ------------------------------------------------------------------- 15 | $config.modules=(".\modules\*.psm1",".\my_module.psm1") 16 | 17 | ------------------------------------------------------------------- 18 | Use scriptblock for taskNameFormat 19 | ------------------------------------------------------------------- 20 | $config.taskNameFormat= { param($taskName) "Executing $taskName at $(get-date)" } 21 | #> 22 | -------------------------------------------------------------------------------- /src/ContosoUniversity.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.6.33723.286 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ContosoUniversity", "ContosoUniversity\ContosoUniversity.csproj", "{264E21D6-4024-4A53-B1BE-1CD42F3348FE}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{BA324694-07F7-4D59-868A-AA10BAC225CA}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DBDeployment", "DBDeployment\DBDeployment.csproj", "{92616CCC-80EB-4C45-83DC-12FEA110EBA6}" 11 | EndProject 12 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{0836D058-C1DC-4E4F-8943-054110E698E5}" 13 | ProjectSection(SolutionItems) = preProject 14 | ..\.gitattributes = ..\.gitattributes 15 | ..\.gitignore = ..\.gitignore 16 | ..\build.bat = ..\build.bat 17 | ..\psakefile.ps1 = ..\psakefile.ps1 18 | EndProjectSection 19 | EndProject 20 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IntegrationTests", "IntegrationTests\IntegrationTests.csproj", "{23EA02DB-B0D1-4408-8850-B3735B677D91}" 21 | EndProject 22 | Global 23 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 24 | Debug|Any CPU = Debug|Any CPU 25 | Release|Any CPU = Release|Any CPU 26 | EndGlobalSection 27 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 28 | {264E21D6-4024-4A53-B1BE-1CD42F3348FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 29 | {264E21D6-4024-4A53-B1BE-1CD42F3348FE}.Debug|Any CPU.Build.0 = Debug|Any CPU 30 | {264E21D6-4024-4A53-B1BE-1CD42F3348FE}.Release|Any CPU.ActiveCfg = Release|Any CPU 31 | {264E21D6-4024-4A53-B1BE-1CD42F3348FE}.Release|Any CPU.Build.0 = Release|Any CPU 32 | {92616CCC-80EB-4C45-83DC-12FEA110EBA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 33 | {92616CCC-80EB-4C45-83DC-12FEA110EBA6}.Debug|Any CPU.Build.0 = Debug|Any CPU 34 | {92616CCC-80EB-4C45-83DC-12FEA110EBA6}.Release|Any CPU.ActiveCfg = Release|Any CPU 35 | {92616CCC-80EB-4C45-83DC-12FEA110EBA6}.Release|Any CPU.Build.0 = Release|Any CPU 36 | {23EA02DB-B0D1-4408-8850-B3735B677D91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 37 | {23EA02DB-B0D1-4408-8850-B3735B677D91}.Debug|Any CPU.Build.0 = Debug|Any CPU 38 | {23EA02DB-B0D1-4408-8850-B3735B677D91}.Release|Any CPU.ActiveCfg = Release|Any CPU 39 | {23EA02DB-B0D1-4408-8850-B3735B677D91}.Release|Any CPU.Build.0 = Release|Any CPU 40 | EndGlobalSection 41 | GlobalSection(SolutionProperties) = preSolution 42 | HideSolutionNode = FALSE 43 | EndGlobalSection 44 | GlobalSection(ExtensibilityGlobals) = postSolution 45 | SolutionGuid = {6B4F6E5E-7259-4FD0-A35B-12EED2E87AAD} 46 | EndGlobalSection 47 | EndGlobal 48 | -------------------------------------------------------------------------------- /src/ContosoUniversity/App_Start/BundleConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Web; 2 | using System.Web.Optimization; 3 | 4 | namespace ContosoUniversity 5 | { 6 | public class BundleConfig 7 | { 8 | // For more information on bundling, visit http://go.microsoft.com/fwlink/?LinkId=301862 9 | public static void RegisterBundles(BundleCollection bundles) 10 | { 11 | bundles.Add(new ScriptBundle("~/bundles/jquery").Include( 12 | "~/Scripts/jquery-{version}.js")); 13 | 14 | bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include( 15 | "~/Scripts/jquery.validate*")); 16 | 17 | // Use the development version of Modernizr to develop with and learn from. Then, when you're 18 | // ready for production, use the build tool at http://modernizr.com to pick only the tests you need. 19 | bundles.Add(new ScriptBundle("~/bundles/modernizr").Include( 20 | "~/Scripts/modernizr-*")); 21 | 22 | bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include( 23 | "~/Scripts/bootstrap.js", 24 | "~/Scripts/respond.js")); 25 | 26 | bundles.Add(new ScriptBundle("~/bundles/lodash").Include( 27 | "~/Scripts/lodash.js")); 28 | 29 | bundles.Add(new StyleBundle("~/Content/css").Include( 30 | "~/Content/bootstrap.css", 31 | "~/Content/site.css")); 32 | 33 | // Set EnableOptimizations to false for debugging. For more information, 34 | // visit http://go.microsoft.com/fwlink/?LinkId=301862 35 | BundleTable.EnableOptimizations = true; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/ContosoUniversity/App_Start/FilterConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Web; 2 | using System.Web.Mvc; 3 | 4 | namespace ContosoUniversity 5 | { 6 | using Infrastructure; 7 | using Infrastructure.DataAccess; 8 | 9 | public class FilterConfig 10 | { 11 | public static void RegisterGlobalFilters(GlobalFilterCollection filters) 12 | { 13 | filters.Add(new HandleErrorAttribute()); 14 | filters.Add(new ValidatorActionFilter()); 15 | filters.Add(new MvcTransactionFilter()); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/ContosoUniversity/App_Start/RouteConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | using System.Web.Routing; 7 | 8 | namespace ContosoUniversity 9 | { 10 | public class RouteConfig 11 | { 12 | public static void RegisterRoutes(RouteCollection routes) 13 | { 14 | routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 15 | 16 | routes.MapRoute( 17 | name: "Default", 18 | url: "{controller}/{action}/{id}", 19 | defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } 20 | ); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/ContosoUniversity/App_Start/StructuremapMvc.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright 2012 Web Advanced (www.webadvanced.com) 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | // -------------------------------------------------------------------------------------------------------------------- 17 | 18 | using ContosoUniversity.App_Start; 19 | 20 | using WebActivatorEx; 21 | 22 | [assembly: PreApplicationStartMethod(typeof(StructuremapMvc), "Start")] 23 | [assembly: ApplicationShutdownMethod(typeof(StructuremapMvc), "End")] 24 | 25 | namespace ContosoUniversity.App_Start { 26 | using System.Web; 27 | using System.Web.Mvc; 28 | 29 | using Microsoft.Web.Infrastructure.DynamicModuleHelper; 30 | 31 | using ContosoUniversity.DependencyResolution; 32 | using Infrastructure.Mapping; 33 | using StructureMap; 34 | 35 | public static class StructuremapMvc 36 | { 37 | public static StructureMapDependencyScope ParentScope { get; set; } 38 | 39 | public static void End() 40 | { 41 | ParentScope.Dispose(); 42 | ParentScope.DisposeParentContainer(); 43 | } 44 | 45 | public static void Start() 46 | { 47 | IContainer container = IoC.Initialize(); 48 | ParentScope = new StructureMapDependencyScope(container, new HttpContextNestedContainerScope()); 49 | DependencyResolver.SetResolver(ParentScope); 50 | DynamicModuleUtility.RegisterModule(typeof(StructureMapScopeModule)); 51 | } 52 | } 53 | 54 | public class HttpContextNestedContainerScope : INestedContainerScope 55 | { 56 | private const string NestedContainerKey = "Nested.Container.Key"; 57 | 58 | public IContainer NestedContainer 59 | { 60 | get { return (IContainer)(HttpContext.Current != null ? HttpContext.Current.Items[NestedContainerKey] : null); } 61 | set { HttpContext.Current.Items[NestedContainerKey] = value; } 62 | } 63 | } 64 | 65 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Content/PagedList.css: -------------------------------------------------------------------------------- 1 | .pagination { 2 | display: inline-block; 3 | padding-left: 0; 4 | margin: 20px 0; 5 | border-radius: 4px; 6 | } 7 | 8 | .pagination > li { 9 | display: inline; 10 | } 11 | 12 | .pagination > li > a, 13 | .pagination > li > span { 14 | position: relative; 15 | float: left; 16 | padding: 6px 12px; 17 | margin-left: -1px; 18 | line-height: 1.428571429; 19 | text-decoration: none; 20 | background-color: #ffffff; 21 | border: 1px solid #dddddd; 22 | } 23 | 24 | .pagination > li:first-child > a, 25 | .pagination > li:first-child > span { 26 | margin-left: 0; 27 | border-bottom-left-radius: 4px; 28 | border-top-left-radius: 4px; 29 | } 30 | 31 | .pagination > li:last-child > a, 32 | .pagination > li:last-child > span { 33 | border-top-right-radius: 4px; 34 | border-bottom-right-radius: 4px; 35 | } 36 | 37 | .pagination > li > a:hover, 38 | .pagination > li > span:hover, 39 | .pagination > li > a:focus, 40 | .pagination > li > span:focus { 41 | background-color: #eeeeee; 42 | } 43 | 44 | .pagination > .active > a, 45 | .pagination > .active > span, 46 | .pagination > .active > a:hover, 47 | .pagination > .active > span:hover, 48 | .pagination > .active > a:focus, 49 | .pagination > .active > span:focus { 50 | z-index: 2; 51 | color: #ffffff; 52 | cursor: default; 53 | background-color: #428bca; 54 | border-color: #428bca; 55 | } 56 | 57 | .pagination > .disabled > span, 58 | .pagination > .disabled > a, 59 | .pagination > .disabled > a:hover, 60 | .pagination > .disabled > a:focus { 61 | color: #999999; 62 | cursor: not-allowed; 63 | background-color: #ffffff; 64 | border-color: #dddddd; 65 | } 66 | 67 | .pagination-lg > li > a, 68 | .pagination-lg > li > span { 69 | padding: 10px 16px; 70 | font-size: 18px; 71 | } 72 | 73 | .pagination-lg > li:first-child > a, 74 | .pagination-lg > li:first-child > span { 75 | border-bottom-left-radius: 6px; 76 | border-top-left-radius: 6px; 77 | } 78 | 79 | .pagination-lg > li:last-child > a, 80 | .pagination-lg > li:last-child > span { 81 | border-top-right-radius: 6px; 82 | border-bottom-right-radius: 6px; 83 | } 84 | 85 | .pagination-sm > li > a, 86 | .pagination-sm > li > span { 87 | padding: 5px 10px; 88 | font-size: 12px; 89 | } 90 | 91 | .pagination-sm > li:first-child > a, 92 | .pagination-sm > li:first-child > span { 93 | border-bottom-left-radius: 3px; 94 | border-top-left-radius: 3px; 95 | } 96 | 97 | .pagination-sm > li:last-child > a, 98 | .pagination-sm > li:last-child > span { 99 | border-top-right-radius: 3px; 100 | border-bottom-right-radius: 3px; 101 | } 102 | 103 | .pager { 104 | padding-left: 0; 105 | margin: 20px 0; 106 | text-align: center; 107 | list-style: none; 108 | } 109 | 110 | .pager:before, 111 | .pager:after { 112 | display: table; 113 | content: " "; 114 | } 115 | 116 | .pager:after { 117 | clear: both; 118 | } 119 | 120 | .pager:before, 121 | .pager:after { 122 | display: table; 123 | content: " "; 124 | } 125 | 126 | .pager:after { 127 | clear: both; 128 | } 129 | 130 | .pager li { 131 | display: inline; 132 | } 133 | 134 | .pager li > a, 135 | .pager li > span { 136 | display: inline-block; 137 | padding: 5px 14px; 138 | background-color: #ffffff; 139 | border: 1px solid #dddddd; 140 | border-radius: 15px; 141 | } 142 | 143 | .pager li > a:hover, 144 | .pager li > a:focus { 145 | text-decoration: none; 146 | background-color: #eeeeee; 147 | } 148 | 149 | .pager .next > a, 150 | .pager .next > span { 151 | float: right; 152 | } 153 | 154 | .pager .previous > a, 155 | .pager .previous > span { 156 | float: left; 157 | } 158 | 159 | .pager .disabled > a, 160 | .pager .disabled > a:hover, 161 | .pager .disabled > a:focus, 162 | .pager .disabled > span { 163 | color: #999999; 164 | cursor: not-allowed; 165 | background-color: #ffffff; 166 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Content/Site.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding-top: 50px; 3 | padding-bottom: 20px; 4 | } 5 | 6 | /* Set padding to keep content from hitting the edges */ 7 | .body-content { 8 | padding-left: 15px; 9 | padding-right: 15px; 10 | } 11 | 12 | /* Override the default bootstrap behavior where horizontal description lists 13 | will truncate terms that are too long to fit in the left column 14 | */ 15 | .dl-horizontal dt { 16 | white-space: normal; 17 | } 18 | 19 | /* Set width on the form input elements since they're 100% wide by default */ 20 | input, 21 | select, 22 | textarea { 23 | max-width: 280px; 24 | } 25 | -------------------------------------------------------------------------------- /src/ContosoUniversity/DAL/SchoolConfiguration.cs: -------------------------------------------------------------------------------- 1 | using System.Data.Entity; 2 | using System.Data.Entity.SqlServer; 3 | 4 | namespace ContosoUniversity.DAL 5 | { 6 | using System.Data.Entity.Infrastructure; 7 | 8 | public class SchoolConfiguration : DbConfiguration 9 | { 10 | public SchoolConfiguration() 11 | { 12 | SetExecutionStrategy("System.Data.SqlClient", () => new DefaultExecutionStrategy()); 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/DAL/SchoolContext.cs: -------------------------------------------------------------------------------- 1 | using ContosoUniversity.Models; 2 | using System.Data.Entity; 3 | using System.Data.Entity.ModelConfiguration.Conventions; 4 | 5 | namespace ContosoUniversity.DAL 6 | { 7 | using System; 8 | using System.Data; 9 | using System.Threading.Tasks; 10 | 11 | public class SchoolContext : DbContext 12 | { 13 | private DbContextTransaction _currentTransaction; 14 | 15 | 16 | public SchoolContext(string nameOrConnectionString) : base(nameOrConnectionString) 17 | { 18 | //Database.SetInitializer(new SchoolInitializer()); 19 | } 20 | 21 | public DbSet Courses { get; set; } 22 | public DbSet Departments { get; set; } 23 | public DbSet Enrollments { get; set; } 24 | public DbSet Instructors { get; set; } 25 | public DbSet Students { get; set; } 26 | public DbSet OfficeAssignments { get; set; } 27 | public DbSet People { get; set; } 28 | public DbSet CourseInstructors { get; set; } 29 | 30 | protected override void OnModelCreating(DbModelBuilder modelBuilder) 31 | { 32 | modelBuilder.Conventions.Remove(); 33 | 34 | modelBuilder.Entity().HasKey(ci => new {ci.CourseID, ci.InstructorID}); 35 | 36 | modelBuilder.Entity().MapToStoredProcedures(); 37 | } 38 | 39 | public void BeginTransaction() 40 | { 41 | try 42 | { 43 | if (_currentTransaction != null) 44 | { 45 | return; 46 | } 47 | 48 | _currentTransaction = Database.BeginTransaction(IsolationLevel.ReadCommitted); 49 | } 50 | catch (Exception) 51 | { 52 | // todo: log transaction exception 53 | throw; 54 | } 55 | } 56 | 57 | public void CloseTransaction() 58 | { 59 | CloseTransaction(exception: null); 60 | } 61 | 62 | public void CloseTransaction(Exception exception) 63 | { 64 | try 65 | { 66 | if (_currentTransaction != null && exception != null) 67 | { 68 | // todo: log exception 69 | _currentTransaction.Rollback(); 70 | return; 71 | } 72 | 73 | SaveChanges(); 74 | 75 | if (_currentTransaction != null) 76 | { 77 | _currentTransaction.Commit(); 78 | } 79 | } 80 | catch (Exception) 81 | { 82 | // todo: log exception 83 | if (_currentTransaction != null && _currentTransaction.UnderlyingTransaction.Connection != null) 84 | { 85 | _currentTransaction.Rollback(); 86 | } 87 | 88 | throw; 89 | } 90 | finally 91 | { 92 | if (_currentTransaction != null) 93 | { 94 | _currentTransaction.Dispose(); 95 | _currentTransaction = null; 96 | } 97 | } 98 | } 99 | 100 | } 101 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/DAL/SchoolInterceptorLogging.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Data.Common; 3 | using System.Data.Entity; 4 | using System.Data.Entity.Infrastructure.Interception; 5 | using System.Data.Entity.SqlServer; 6 | using System.Data.SqlClient; 7 | using System.Diagnostics; 8 | using System.Reflection; 9 | using System.Linq; 10 | using ContosoUniversity.Logging; 11 | 12 | namespace ContosoUniversity.DAL 13 | { 14 | public class SchoolInterceptorLogging : DbCommandInterceptor 15 | { 16 | private ILogger _logger = new Logger(); 17 | private readonly Stopwatch _stopwatch = new Stopwatch(); 18 | 19 | public override void ScalarExecuting(DbCommand command, DbCommandInterceptionContext interceptionContext) 20 | { 21 | base.ScalarExecuting(command, interceptionContext); 22 | _stopwatch.Restart(); 23 | } 24 | 25 | public override void ScalarExecuted(DbCommand command, DbCommandInterceptionContext interceptionContext) 26 | { 27 | _stopwatch.Stop(); 28 | if (interceptionContext.Exception != null) 29 | { 30 | _logger.Error(interceptionContext.Exception, "Error executing command: {0}", command.CommandText); 31 | } 32 | else 33 | { 34 | _logger.TraceApi("SQL Database", "SchoolInterceptor.ScalarExecuted", _stopwatch.Elapsed, "Command: {0}: ", command.CommandText); 35 | } 36 | base.ScalarExecuted(command, interceptionContext); 37 | } 38 | 39 | public override void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext interceptionContext) 40 | { 41 | base.NonQueryExecuting(command, interceptionContext); 42 | _stopwatch.Restart(); 43 | } 44 | 45 | public override void NonQueryExecuted(DbCommand command, DbCommandInterceptionContext interceptionContext) 46 | { 47 | _stopwatch.Stop(); 48 | if (interceptionContext.Exception != null) 49 | { 50 | _logger.Error(interceptionContext.Exception, "Error executing command: {0}", command.CommandText); 51 | } 52 | else 53 | { 54 | _logger.TraceApi("SQL Database", "SchoolInterceptor.NonQueryExecuted", _stopwatch.Elapsed, "Command: {0}: ", command.CommandText); 55 | } 56 | base.NonQueryExecuted(command, interceptionContext); 57 | } 58 | 59 | public override void ReaderExecuting(DbCommand command, DbCommandInterceptionContext interceptionContext) 60 | { 61 | base.ReaderExecuting(command, interceptionContext); 62 | _stopwatch.Restart(); 63 | } 64 | public override void ReaderExecuted(DbCommand command, DbCommandInterceptionContext interceptionContext) 65 | { 66 | _stopwatch.Stop(); 67 | if (interceptionContext.Exception != null) 68 | { 69 | _logger.Error(interceptionContext.Exception, "Error executing command: {0}", command.CommandText); 70 | } 71 | else 72 | { 73 | _logger.TraceApi("SQL Database", "SchoolInterceptor.ReaderExecuted", _stopwatch.Elapsed, "Command: {0}: ", command.CommandText); 74 | } 75 | base.ReaderExecuted(command, interceptionContext); 76 | } 77 | } 78 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/DAL/SchoolInterceptorTransientErrors.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Data.Common; 3 | using System.Data.Entity; 4 | using System.Data.Entity.Infrastructure.Interception; 5 | using System.Data.Entity.SqlServer; 6 | using System.Data.SqlClient; 7 | using System.Diagnostics; 8 | using System.Reflection; 9 | using System.Linq; 10 | using ContosoUniversity.Logging; 11 | 12 | namespace ContosoUniversity.DAL 13 | { 14 | public class SchoolInterceptorTransientErrors : DbCommandInterceptor 15 | { 16 | private int _counter = 0; 17 | private ILogger _logger = new Logger(); 18 | 19 | public override void ReaderExecuting(DbCommand command, DbCommandInterceptionContext interceptionContext) 20 | { 21 | bool throwTransientErrors = false; 22 | if (command.Parameters.Count > 0 && command.Parameters[0].Value.ToString() == "%Throw%") 23 | { 24 | throwTransientErrors = true; 25 | command.Parameters[0].Value = "%an%"; 26 | command.Parameters[1].Value = "%an%"; 27 | } 28 | 29 | if (throwTransientErrors && _counter < 4) 30 | { 31 | _logger.Information("Returning transient error for command: {0}", command.CommandText); 32 | _counter++; 33 | interceptionContext.Exception = CreateDummySqlException(); 34 | } 35 | } 36 | 37 | private SqlException CreateDummySqlException() 38 | { 39 | // The instance of SQL Server you attempted to connect to does not support encryption 40 | var sqlErrorNumber = 20; 41 | 42 | var sqlErrorCtor = typeof(SqlError).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic).Where(c => c.GetParameters().Count() == 7).Single(); 43 | var sqlError = sqlErrorCtor.Invoke(new object[] { sqlErrorNumber, (byte)0, (byte)0, "", "", "", 1 }); 44 | 45 | var errorCollection = Activator.CreateInstance(typeof(SqlErrorCollection), true); 46 | var addMethod = typeof(SqlErrorCollection).GetMethod("Add", BindingFlags.Instance | BindingFlags.NonPublic); 47 | addMethod.Invoke(errorCollection, new[] { sqlError }); 48 | 49 | var sqlExceptionCtor = typeof(SqlException).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic).Where(c => c.GetParameters().Count() == 4).Single(); 50 | var sqlException = (SqlException)sqlExceptionCtor.Invoke(new object[] { "Dummy", errorCollection, null, Guid.NewGuid() }); 51 | 52 | return sqlException; 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/DependencyResolution/ControllerConvention.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright 2012 Web Advanced (www.webadvanced.com) 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | // -------------------------------------------------------------------------------------------------------------------- 17 | 18 | namespace ContosoUniversity.DependencyResolution { 19 | using System; 20 | using System.Web.Mvc; 21 | 22 | using StructureMap; 23 | using StructureMap.Graph; 24 | using StructureMap.Graph.Scanning; 25 | using StructureMap.Pipeline; 26 | using StructureMap.TypeRules; 27 | 28 | public class ControllerConvention : IRegistrationConvention { 29 | public void ScanTypes(TypeSet types, Registry registry) 30 | { 31 | foreach (var type in types.AllTypes()) 32 | { 33 | if (type.CanBeCastTo() && !type.IsAbstract) 34 | { 35 | registry.For(type).LifecycleIs(new UniquePerRequestLifecycle()); 36 | } 37 | } 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/DependencyResolution/DefaultRegistry.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright 2012 Web Advanced (www.webadvanced.com) 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | // -------------------------------------------------------------------------------------------------------------------- 17 | 18 | using StructureMap; 19 | 20 | namespace ContosoUniversity.DependencyResolution { 21 | using System.Web.Mvc; 22 | using DAL; 23 | using FluentValidation; 24 | using FluentValidation.Mvc; 25 | using Infrastructure; 26 | using Infrastructure.Validation; 27 | using StructureMap.Configuration.DSL; 28 | using StructureMap.Graph; 29 | using StructureMap.Pipeline; 30 | 31 | public class DefaultRegistry : Registry { 32 | #region Constructors and Destructors 33 | 34 | public DefaultRegistry() { 35 | Scan( 36 | scan => { 37 | scan.TheCallingAssembly(); 38 | scan.WithDefaultConventions(); 39 | scan.LookForRegistries(); 40 | scan.AssemblyContainingType(); 41 | scan.AddAllTypesOf(typeof(IModelBinder)); 42 | scan.AddAllTypesOf(typeof(IModelBinderProvider)); 43 | scan.With(new ControllerConvention()); 44 | }); 45 | For().Use(() => new SchoolContext("SchoolContext")).LifecycleIs(); 46 | For().Use(); 47 | For().Use(); 48 | For().Use(); 49 | } 50 | 51 | #endregion 52 | } 53 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/DependencyResolution/IoC.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright 2012 Web Advanced (www.webadvanced.com) 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | // -------------------------------------------------------------------------------------------------------------------- 17 | 18 | 19 | namespace ContosoUniversity.DependencyResolution { 20 | using StructureMap; 21 | 22 | public static class IoC { 23 | public static IContainer Initialize() { 24 | return new Container(c => c.AddRegistry()); 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/DependencyResolution/StructureMapScopeModule.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.DependencyResolution { 2 | using System.Web; 3 | 4 | using ContosoUniversity.App_Start; 5 | 6 | using StructureMap.Web.Pipeline; 7 | 8 | public class StructureMapScopeModule : IHttpModule { 9 | #region Public Methods and Operators 10 | 11 | public void Dispose() { 12 | } 13 | 14 | public void Init(HttpApplication context) { 15 | context.BeginRequest += (sender, e) => StructuremapMvc.ParentScope.CreateNestedContainer(); 16 | context.EndRequest += (sender, e) => { 17 | HttpContextLifecycle.DisposeAndClearAll(); 18 | StructuremapMvc.ParentScope.DisposeNestedContainer(); 19 | }; 20 | } 21 | 22 | #endregion 23 | } 24 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Course/Create.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Features.Course 2 | { 3 | using System.ComponentModel.DataAnnotations; 4 | using AutoMapper; 5 | using DAL; 6 | using MediatR; 7 | using Models; 8 | 9 | public class Create 10 | { 11 | public class Command : IRequest 12 | { 13 | [Display(Name = "Number")] 14 | public int CourseNumber { get; set; } 15 | public string Title { get; set; } 16 | public int Credits { get; set; } 17 | public Department Department { get; set; } 18 | } 19 | 20 | public class Handler : RequestHandler 21 | { 22 | private readonly SchoolContext _db; 23 | 24 | public Handler(SchoolContext db) 25 | { 26 | _db = db; 27 | } 28 | 29 | protected override void HandleCore(Command message) 30 | { 31 | var course = Mapper.Map(message); 32 | 33 | _db.Courses.Add(course); 34 | } 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Course/Create.cshtml: -------------------------------------------------------------------------------- 1 | @model ContosoUniversity.Features.Course.Create.Command 2 | 3 | @{ 4 | ViewBag.Title = "Create"; 5 | } 6 | 7 |

Create

8 | 9 | 10 | @using (Html.BeginForm()) 11 | { 12 | @Html.AntiForgeryToken() 13 | 14 |
15 |

Course

16 |
17 | @Html.ValidationDiv() 18 | @Html.FormBlock(m => m.CourseNumber) 19 | @Html.FormBlock(m => m.Title) 20 | @Html.FormBlock(m => m.Credits) 21 | @Html.FormBlock(m => m.Department) 22 | 23 |
24 |
25 | 26 |
27 |
28 |
29 | } 30 | 31 |
32 | @Html.ActionLink("Back to List", "Index") 33 |
34 | 35 | @section Scripts { 36 | @Scripts.Render("~/bundles/jqueryval") 37 | } 38 | -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Course/Delete.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Features.Course 2 | { 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using AutoMapper; 7 | using DAL; 8 | using FluentValidation; 9 | using MediatR; 10 | 11 | public class Delete 12 | { 13 | public class Query : IAsyncRequest 14 | { 15 | public int? Id { get; set; } 16 | } 17 | 18 | public class QueryValidator : AbstractValidator 19 | { 20 | public QueryValidator() 21 | { 22 | RuleFor(m => m.Id).NotNull(); 23 | } 24 | } 25 | 26 | public class QueryHandler : IAsyncRequestHandler 27 | { 28 | private readonly SchoolContext _db; 29 | 30 | public QueryHandler(SchoolContext db) 31 | { 32 | _db = db; 33 | } 34 | 35 | public async Task Handle(Query message) 36 | { 37 | return await _db.Courses.Where(c => c.CourseID == message.Id).ProjectToSingleOrDefaultAsync(); 38 | } 39 | } 40 | 41 | public class Command : IAsyncRequest 42 | { 43 | [Display(Name = "Number")] 44 | public int CourseID { get; set; } 45 | public string Title { get; set; } 46 | public int Credits { get; set; } 47 | public string DepartmentName { get; set; } 48 | } 49 | 50 | public class CommandHandler : AsyncRequestHandler 51 | { 52 | private readonly SchoolContext _db; 53 | 54 | public CommandHandler(SchoolContext db) 55 | { 56 | _db = db; 57 | } 58 | 59 | protected override async Task HandleCore(Command message) 60 | { 61 | var course = await _db.Courses.FindAsync(message.CourseID); 62 | 63 | _db.Courses.Remove(course); 64 | } 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Course/Delete.cshtml: -------------------------------------------------------------------------------- 1 | @model ContosoUniversity.Features.Course.Delete.Command 2 | 3 | @{ 4 | ViewBag.Title = "Delete"; 5 | } 6 | 7 |

Delete

8 | 9 |

Are you sure you want to delete this?

10 |
11 |

Course

12 |
13 |
14 |
15 | Department 16 |
17 | 18 |
19 | @Html.Display(model => model.DepartmentName) 20 |
21 | 22 |
23 | @Html.DisplayLabel(model => model.CourseID) 24 |
25 | 26 |
27 | @Html.Display(model => model.CourseID) 28 |
29 | 30 |
31 | @Html.DisplayLabel(model => model.Title) 32 |
33 | 34 |
35 | @Html.Display(model => model.Title) 36 |
37 | 38 |
39 | @Html.DisplayLabel(model => model.Credits) 40 |
41 | 42 |
43 | @Html.Display(model => model.Credits) 44 |
45 | 46 |
47 | 48 | @using (Html.BeginForm()) { 49 | @Html.AntiForgeryToken() 50 | 51 |
52 | | 53 | @Html.ActionLink("Back to List", "Index") 54 |
55 | } 56 |
57 | -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Course/Details.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Features.Course 2 | { 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using AutoMapper; 6 | using DAL; 7 | using FluentValidation; 8 | using MediatR; 9 | 10 | public class Details 11 | { 12 | public class Query : IAsyncRequest 13 | { 14 | public int? Id { get; set; } 15 | } 16 | 17 | public class Validator : AbstractValidator 18 | { 19 | public Validator() 20 | { 21 | RuleFor(m => m.Id).NotNull(); 22 | } 23 | } 24 | 25 | public class Model 26 | { 27 | public int CourseID { get; set; } 28 | public string Title { get; set; } 29 | public int Credits { get; set; } 30 | public string DepartmentName { get; set; } 31 | } 32 | 33 | public class Handler : IAsyncRequestHandler 34 | { 35 | private readonly SchoolContext _db; 36 | 37 | public Handler(SchoolContext db) 38 | { 39 | _db = db; 40 | } 41 | 42 | public async Task Handle(Query message) 43 | { 44 | return await _db.Courses.Where(i => i.CourseID == message.Id).ProjectToSingleOrDefaultAsync(); 45 | } 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Course/Details.cshtml: -------------------------------------------------------------------------------- 1 | @model ContosoUniversity.Features.Course.Details.Model 2 | 3 | @{ 4 | ViewBag.Title = "Details"; 5 | } 6 | 7 |

Details

8 | 9 |
10 |

Course

11 |
12 |
13 |
14 | Department 15 |
16 | 17 |
18 | @Html.Display(model => model.DepartmentName) 19 |
20 | 21 |
22 | @Html.DisplayLabel(model => model.CourseID) 23 |
24 | 25 |
26 | @Html.Display(model => model.CourseID) 27 |
28 | 29 |
30 | @Html.DisplayLabel(model => model.Title) 31 |
32 | 33 |
34 | @Html.Display(model => model.Title) 35 |
36 | 37 |
38 | @Html.DisplayLabel(model => model.Credits) 39 |
40 | 41 |
42 | @Html.Display(model => model.Credits) 43 |
44 | 45 |
46 |
47 |

48 | @Html.ActionLink("Edit", "Edit", new { id = Model.CourseID }) | 49 | @Html.ActionLink("Back to List", "Index") 50 |

51 | -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Course/Edit.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Features.Course 2 | { 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using AutoMapper; 7 | using DAL; 8 | using FluentValidation; 9 | using Infrastructure.Mapping; 10 | using MediatR; 11 | using Models; 12 | 13 | public class Edit 14 | { 15 | public class Query : IAsyncRequest 16 | { 17 | public int? Id { get; set; } 18 | } 19 | 20 | public class QueryValidator : AbstractValidator 21 | { 22 | public QueryValidator() 23 | { 24 | RuleFor(m => m.Id).NotNull(); 25 | } 26 | } 27 | 28 | public class QueryHandler : IAsyncRequestHandler 29 | { 30 | private readonly SchoolContext _db; 31 | 32 | public QueryHandler(SchoolContext db) 33 | { 34 | _db = db; 35 | } 36 | 37 | public async Task Handle(Query message) 38 | { 39 | return await _db.Courses.Where(c => c.CourseID == message.Id).ProjectToSingleOrDefaultAsync(); 40 | } 41 | } 42 | 43 | public class Command : IAsyncRequest 44 | { 45 | [Display(Name = "Number")] 46 | public int CourseID { get; set; } 47 | public string Title { get; set; } 48 | public int? Credits { get; set; } 49 | public Department Department { get; set; } 50 | } 51 | 52 | public class CommandValidator : AbstractValidator 53 | { 54 | public CommandValidator() 55 | { 56 | RuleFor(m => m.Title).NotNull().Length(3, 50); 57 | RuleFor(m => m.Credits).NotNull().InclusiveBetween(0, 5); 58 | } 59 | } 60 | 61 | public class CommandHandler : AsyncRequestHandler 62 | { 63 | private readonly SchoolContext _db; 64 | 65 | public CommandHandler(SchoolContext db) 66 | { 67 | _db = db; 68 | } 69 | 70 | protected override async Task HandleCore(Command message) 71 | { 72 | var course = await _db.Courses.FindAsync(message.CourseID); 73 | 74 | Mapper.Map(message, course); 75 | } 76 | } 77 | } 78 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Course/Edit.cshtml: -------------------------------------------------------------------------------- 1 | @model ContosoUniversity.Features.Course.Edit.Command 2 | 3 | @{ 4 | ViewBag.Title = "Edit"; 5 | } 6 | 7 |

Edit

8 | 9 | 10 | @using (Html.BeginForm()) 11 | { 12 | @Html.AntiForgeryToken() 13 | 14 |
15 |

Course

16 |
17 | @Html.ValidationDiv() 18 | @Html.Input(model => model.CourseID) 19 | 20 |
21 | @Html.Label(m => m.CourseID) 22 |
23 | @Html.Display(model => model.CourseID) 24 |
25 |
26 | 27 | @Html.FormBlock(m => m.Title) 28 | @Html.FormBlock(m => m.Credits) 29 | @Html.FormBlock(m => m.Department) 30 | 31 |
32 |
33 | 34 |
35 |
36 |
37 | } 38 | 39 |
40 | @Html.ActionLink("Back to List", "Index") 41 |
42 | 43 | @section Scripts { 44 | @Scripts.Render("~/bundles/jqueryval") 45 | } 46 | -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Course/Index.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Features.Course 2 | { 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using AutoMapper; 7 | using DAL; 8 | using MediatR; 9 | using Models; 10 | 11 | public class Index 12 | { 13 | public class Query : IAsyncRequest 14 | { 15 | public Department SelectedDepartment { get; set; } 16 | } 17 | 18 | public class Result 19 | { 20 | public Department SelectedDepartment { get; set; } 21 | public List Courses { get; set; } 22 | 23 | public class Course 24 | { 25 | public int CourseID { get; set; } 26 | public string Title { get; set; } 27 | public int Credits { get; set; } 28 | public string DepartmentName { get; set; } 29 | } 30 | } 31 | 32 | public class Handler : IAsyncRequestHandler 33 | { 34 | private readonly SchoolContext _db; 35 | 36 | public Handler(SchoolContext db) 37 | { 38 | _db = db; 39 | } 40 | 41 | public async Task Handle(Query message) 42 | { 43 | int? departmentID = message.SelectedDepartment == null 44 | ? (int?)null 45 | : message.SelectedDepartment.DepartmentID; 46 | 47 | var courses = await _db.Courses 48 | .Where(c => !departmentID.HasValue || c.DepartmentID == departmentID) 49 | .OrderBy(d => d.CourseID) 50 | .ProjectToListAsync(); 51 | 52 | return new Result 53 | { 54 | Courses = courses, 55 | SelectedDepartment = message.SelectedDepartment 56 | }; 57 | } 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Course/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model ContosoUniversity.Features.Course.Index.Result 2 | 3 | @{ 4 | ViewBag.Title = "Courses"; 5 | } 6 | 7 |

Courses

8 | 9 |

10 | @Html.ActionLink("Create New", "Create") 11 |

12 | 13 |
14 |

15 | Select Department: @Html.Input(m => m.SelectedDepartment).RemoveClass("form-control") 16 | 17 |

18 |
19 | 20 | 21 | 22 | 25 | 28 | 31 | 34 | 35 | 36 | @{ int i = 0;} 37 | @foreach (var item in Model.Courses) 38 | { 39 | 40 | 43 | 46 | 49 | 52 | 57 | 58 | i++; 59 | } 60 | 61 |
23 | Number 24 | 26 | Title 27 | 29 | Credits 30 | 32 | Department 33 |
41 | @Html.Display(modelItem => modelItem.Courses[i].CourseID) 42 | 44 | @Html.Display(modelItem => modelItem.Courses[i].Title) 45 | 47 | @Html.Display(modelItem => modelItem.Courses[i].Credits) 48 | 50 | @Html.Display(modelItem => modelItem.Courses[i].DepartmentName) 51 | 53 | @Html.ActionLink("Edit", "Edit", new {id = item.CourseID}) | 54 | @Html.ActionLink("Details", "Details", new {id = item.CourseID}) | 55 | @Html.ActionLink("Delete", "Delete", new {id = item.CourseID}) 56 |
-------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Course/MappingProfile.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Features.Course 2 | { 3 | using AutoMapper; 4 | using Models; 5 | 6 | public class MappingProfile : Profile 7 | { 8 | public MappingProfile() 9 | { 10 | CreateMap(); 11 | CreateMap(); 12 | CreateMap().ForMember(x => x.CourseID, x => x.MapFrom(z => z.CourseNumber)); 13 | CreateMap().ReverseMap(); 14 | CreateMap(); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Course/UiController.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Features.Course 2 | { 3 | using System.Threading.Tasks; 4 | using System.Web.Mvc; 5 | using Infrastructure; 6 | using MediatR; 7 | 8 | public class UiController : Controller 9 | { 10 | private readonly IMediator _mediator; 11 | 12 | public UiController(IMediator mediator) 13 | { 14 | _mediator = mediator; 15 | } 16 | 17 | public async Task Index(Index.Query query) 18 | { 19 | var model = await _mediator.SendAsync(query); 20 | 21 | return View(model); 22 | } 23 | 24 | public async Task Details(Details.Query query) 25 | { 26 | var model = await _mediator.SendAsync(query); 27 | 28 | return View(model); 29 | } 30 | 31 | public ActionResult Create() 32 | { 33 | return View(); 34 | } 35 | 36 | [HttpPost] 37 | [ValidateAntiForgeryToken] 38 | public ActionResult Create(Create.Command command) 39 | { 40 | _mediator.Send(command); 41 | 42 | return this.RedirectToActionJson("Index"); 43 | } 44 | 45 | public async Task Edit(Edit.Query query) 46 | { 47 | var model = await _mediator.SendAsync(query); 48 | 49 | return View(model); 50 | } 51 | 52 | [HttpPost] 53 | [ValidateAntiForgeryToken] 54 | public async Task Edit(Edit.Command command) 55 | { 56 | await _mediator.SendAsync(command); 57 | 58 | return this.RedirectToActionJson("Index"); 59 | } 60 | 61 | public async Task Delete(Delete.Query query) 62 | { 63 | var model = await _mediator.SendAsync(query); 64 | 65 | return View(model); 66 | } 67 | 68 | [HttpPost] 69 | [ValidateAntiForgeryToken] 70 | public async Task Delete(Delete.Command command) 71 | { 72 | await _mediator.SendAsync(command); 73 | 74 | return this.RedirectToActionJson("Index"); 75 | } 76 | } 77 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Course/UpdateCourseCredits.cshtml: -------------------------------------------------------------------------------- 1 | @model ContosoUniversity.Models.Course 2 | 3 | @{ 4 | ViewBag.Title = "UpdateCourseCredits"; 5 | } 6 | 7 |

Update Course Credits

8 | 9 | @if (ViewBag.RowsAffected == null) 10 | { 11 | using (Html.BeginForm()) 12 | { 13 |

14 | Enter a number to multiply every course's credits by: @Html.TextBox("multiplier") 15 |

16 |

17 | 18 |

19 | } 20 | } 21 | @if (ViewBag.RowsAffected != null) 22 | { 23 |

24 | Number of rows updated: @ViewBag.RowsAffected 25 |

26 | } 27 |
28 | @Html.ActionLink("Back to List", "Index") 29 |
30 | 31 | -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Department/Create.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Features.Department 2 | { 3 | using System; 4 | using System.ComponentModel.DataAnnotations; 5 | using System.ComponentModel.DataAnnotations.Schema; 6 | using System.Threading.Tasks; 7 | using AutoMapper; 8 | using DAL; 9 | using FluentValidation; 10 | using MediatR; 11 | using Models; 12 | 13 | public class Create 14 | { 15 | public class Validator : AbstractValidator 16 | { 17 | public Validator() 18 | { 19 | RuleFor(m => m.Name).NotNull().Length(3, 50); 20 | RuleFor(m => m.Budget).NotNull(); 21 | RuleFor(m => m.StartDate).NotNull(); 22 | RuleFor(m => m.Administrator).NotNull(); 23 | } 24 | } 25 | 26 | public class Command : IRequest 27 | { 28 | [StringLength(50, MinimumLength = 3)] 29 | public string Name { get; set; } 30 | 31 | [DataType(DataType.Currency)] 32 | [Column(TypeName = "money")] 33 | public decimal? Budget { get; set; } 34 | 35 | [DataType(DataType.Date)] 36 | [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)] 37 | public DateTime? StartDate { get; set; } 38 | 39 | public Instructor Administrator { get; set; } 40 | } 41 | 42 | public class CommandHandler : RequestHandler 43 | { 44 | private readonly SchoolContext _context; 45 | 46 | public CommandHandler(SchoolContext context) 47 | { 48 | _context = context; 49 | } 50 | 51 | protected override void HandleCore(Command message) 52 | { 53 | var department = Mapper.Map(message); 54 | 55 | _context.Departments.Add(department); 56 | } 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Department/Create.cshtml: -------------------------------------------------------------------------------- 1 | @using ContosoUniversity.Features.Department 2 | @model Create.Command 3 | 4 | @{ 5 | ViewBag.Title = "Create"; 6 | } 7 | 8 |

Create

9 | 10 | 11 | @using (Html.BeginForm()) 12 | { 13 | @Html.AntiForgeryToken() 14 | 15 |
16 |

Department

17 |
18 | @Html.ValidationDiv() 19 | @Html.FormBlock(m => m.Name) 20 | @Html.FormBlock(m => m.Budget) 21 | @Html.FormBlock(m => m.StartDate) 22 | @Html.FormBlock(m => m.Administrator) 23 | 24 |
25 |
26 | 27 |
28 |
29 |
30 | } 31 | 32 |
33 | @(Html.Link(c => c.Index(), "Back to List")) 34 |
35 | 36 | @section Scripts { 37 | @Scripts.Render("~/bundles/jqueryval") 38 | } 39 | -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Department/Delete.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Features.Department 2 | { 3 | using System; 4 | using System.ComponentModel.DataAnnotations; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | using AutoMapper; 8 | using DAL; 9 | using MediatR; 10 | 11 | public class Delete 12 | { 13 | public class Query : IAsyncRequest 14 | { 15 | public int Id { get; set; } 16 | } 17 | 18 | public class Command : IAsyncRequest 19 | { 20 | public string Name { get; set; } 21 | 22 | public decimal Budget { get; set; } 23 | 24 | public DateTime StartDate { get; set; } 25 | 26 | public int DepartmentID { get; set; } 27 | 28 | [Display(Name = "Administrator")] 29 | public string AdministratorFullName { get; set; } 30 | 31 | public byte[] RowVersion { get; set; } 32 | } 33 | 34 | public class QueryHandler : IAsyncRequestHandler 35 | { 36 | private readonly SchoolContext _db; 37 | 38 | public QueryHandler(SchoolContext db) 39 | { 40 | _db = db; 41 | } 42 | 43 | public async Task Handle(Query message) 44 | { 45 | var department = await _db.Departments 46 | .Where(d => d.DepartmentID == message.Id) 47 | .ProjectToSingleOrDefaultAsync(); 48 | 49 | return department; 50 | } 51 | } 52 | 53 | public class CommandHandler : AsyncRequestHandler 54 | { 55 | private readonly SchoolContext _db; 56 | 57 | public CommandHandler(SchoolContext db) 58 | { 59 | _db = db; 60 | } 61 | 62 | protected override async Task HandleCore(Command message) 63 | { 64 | var department = await _db.Departments.FindAsync(message.DepartmentID); 65 | 66 | _db.Departments.Remove(department); 67 | } 68 | } 69 | } 70 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Department/Delete.cshtml: -------------------------------------------------------------------------------- 1 | @using ContosoUniversity.Features.Department 2 | @model Delete.Command 3 | 4 | @{ 5 | ViewBag.Title = "Delete"; 6 | } 7 | 8 |

Delete

9 | 10 |

Are you sure you want to delete this?

11 |
12 |

Department

13 |
14 |
15 |
16 | Administrator 17 |
18 | 19 |
20 | @Html.Display(model => model.AdministratorFullName) 21 |
22 | 23 |
24 | @Html.DisplayLabel(model => model.Name) 25 |
26 | 27 |
28 | @Html.Display(model => model.Name) 29 |
30 | 31 |
32 | @Html.DisplayLabel(model => model.Budget) 33 |
34 | 35 |
36 | @Html.Display(model => model.Budget) 37 |
38 | 39 |
40 | @Html.DisplayLabel(model => model.StartDate) 41 |
42 | 43 |
44 | @Html.Display(model => model.StartDate) 45 |
46 | 47 |
48 | 49 | @using (Html.BeginForm()) 50 | { 51 | @Html.AntiForgeryToken() 52 | @Html.Input(model => model.DepartmentID) 53 | @Html.Input(model => model.RowVersion) 54 | 55 |
56 | | 57 | @(Html.Link(c => c.Index(), "Back to List")) 58 |
59 | } 60 |
61 | -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Department/Details.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Features.Department 2 | { 3 | using System; 4 | using System.ComponentModel.DataAnnotations; 5 | using System.Threading.Tasks; 6 | using DAL; 7 | using MediatR; 8 | 9 | public class Details 10 | { 11 | public class Query : IAsyncRequest 12 | { 13 | public int Id { get; set; } 14 | } 15 | 16 | public class Model 17 | { 18 | public string Name { get; set; } 19 | 20 | public decimal Budget { get; set; } 21 | 22 | public DateTime StartDate { get; set; } 23 | 24 | public int DepartmentID { get; set; } 25 | 26 | [Display(Name = "Administrator")] 27 | public string AdministratorFullName { get; set; } 28 | 29 | } 30 | 31 | public class QueryHandler : IAsyncRequestHandler 32 | { 33 | private readonly SchoolContext _context; 34 | 35 | public QueryHandler(SchoolContext context) 36 | { 37 | _context = context; 38 | } 39 | 40 | public async Task Handle(Query message) 41 | { 42 | string query = @" 43 | SELECT d.*, p.LastName + ', ' + p.FirstName AS [AdministratorFullName] 44 | FROM Department d 45 | LEFT OUTER JOIN Person p ON d.InstructorID = p.ID 46 | WHERE d.DepartmentID = @p0"; 47 | Model department = await _context.Database.SqlQuery(query, message.Id).SingleOrDefaultAsync(); 48 | 49 | return department; 50 | } 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Department/Details.cshtml: -------------------------------------------------------------------------------- 1 | @using ContosoUniversity.Features.Department 2 | @model Details.Model 3 | 4 | @{ 5 | ViewBag.Title = "Details"; 6 | } 7 | 8 |

Details

9 | 10 |
11 |

Department

12 |
13 |
14 |
15 | @Html.DisplayLabel(model => model.Name) 16 |
17 | 18 |
19 | @Html.Display(model => model.Name) 20 |
21 | 22 |
23 | @Html.DisplayLabel(model => model.Budget) 24 |
25 | 26 |
27 | @Html.Display(model => model.Budget) 28 |
29 | 30 |
31 | @Html.DisplayLabel(model => model.StartDate) 32 |
33 | 34 |
35 | @Html.Display(model => model.StartDate) 36 |
37 | 38 |
39 | @Html.DisplayLabel(model => model.AdministratorFullName) 40 |
41 | 42 |
43 | @Html.Display(model => model.AdministratorFullName) 44 |
45 |
46 |
47 |

48 | @(Html.Link(c => c.Edit(new Edit.Query {Id = Model.DepartmentID}), "Edit")) | 49 | @(Html.Link(c => c.Index(), "Back to List")) 50 |

51 | -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Department/Edit.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Features.Department 2 | { 3 | using System; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using AutoMapper; 7 | using DAL; 8 | using FluentValidation; 9 | using Infrastructure.Mapping; 10 | using MediatR; 11 | using Models; 12 | 13 | public class Edit 14 | { 15 | public class Query : IAsyncRequest 16 | { 17 | public int Id { get; set; } 18 | } 19 | 20 | public class Command : IAsyncRequest 21 | { 22 | public string Name { get; set; } 23 | 24 | public decimal? Budget { get; set; } 25 | 26 | public DateTime? StartDate { get; set; } 27 | 28 | public Instructor Administrator { get; set; } 29 | public int DepartmentID { get; set; } 30 | public byte[] RowVersion { get; set; } 31 | } 32 | 33 | public class Validator : AbstractValidator 34 | { 35 | public Validator() 36 | { 37 | RuleFor(m => m.Name).NotNull().Length(3, 50); 38 | RuleFor(m => m.Budget).NotNull(); 39 | RuleFor(m => m.StartDate).NotNull(); 40 | RuleFor(m => m.Administrator).NotNull(); 41 | } 42 | } 43 | 44 | public class QueryHandler : IAsyncRequestHandler 45 | { 46 | private readonly SchoolContext _db; 47 | 48 | public QueryHandler(SchoolContext db) 49 | { 50 | _db = db; 51 | } 52 | 53 | public async Task Handle(Query message) 54 | { 55 | var department = await _db.Departments 56 | .Where(d => d.DepartmentID == message.Id) 57 | .ProjectToSingleOrDefaultAsync(); 58 | 59 | return department; 60 | } 61 | } 62 | 63 | public class CommandHandler : AsyncRequestHandler 64 | { 65 | private readonly SchoolContext _db; 66 | 67 | public CommandHandler(SchoolContext db) 68 | { 69 | _db = db; 70 | } 71 | 72 | protected override async Task HandleCore(Command message) 73 | { 74 | var dept = await _db.Departments.FindAsync(message.DepartmentID); 75 | 76 | Mapper.Map(message, dept); 77 | } 78 | } 79 | } 80 | 81 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Department/Edit.cshtml: -------------------------------------------------------------------------------- 1 | @using ContosoUniversity.Features.Department 2 | @model Edit.Command 3 | 4 | @{ 5 | ViewBag.Title = "Edit"; 6 | } 7 | 8 |

Edit

9 | 10 | 11 | @using (Html.BeginForm()) 12 | { 13 | @Html.AntiForgeryToken() 14 | 15 |
16 |

Department

17 |
18 | @Html.ValidationDiv() 19 | @Html.Input(model => model.DepartmentID) 20 | @Html.Input(model => model.RowVersion) 21 | 22 | @Html.FormBlock(m => m.Name) 23 | @Html.FormBlock(m => m.Budget) 24 | @Html.FormBlock(m => m.StartDate) 25 | @Html.FormBlock(m => m.Administrator) 26 | 27 |
28 |
29 | 30 |
31 |
32 |
33 | } 34 | 35 |
36 | @(Html.Link(c => c.Index(), "Back to List")) 37 |
38 | 39 | @section Scripts { 40 | @Scripts.Render("~/bundles/jqueryval") 41 | } 42 | -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Department/Index.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Features.Department 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.ComponentModel.DataAnnotations; 6 | using System.Threading.Tasks; 7 | using AutoMapper; 8 | using DAL; 9 | using MediatR; 10 | 11 | public class Index 12 | { 13 | public class Query : IAsyncRequest> 14 | { 15 | } 16 | 17 | public class Model 18 | { 19 | public string Name { get; set; } 20 | 21 | public decimal Budget { get; set; } 22 | 23 | public DateTime StartDate { get; set; } 24 | 25 | public int DepartmentID { get; set; } 26 | 27 | [Display(Name = "Administrator")] 28 | public string AdministratorFullName { get; set; } 29 | } 30 | 31 | public class QueryHandler : IAsyncRequestHandler> 32 | { 33 | private readonly SchoolContext _context; 34 | 35 | public QueryHandler(SchoolContext context) 36 | { 37 | _context = context; 38 | } 39 | 40 | public async Task> Handle(Query message) 41 | { 42 | return await _context.Departments 43 | .ProjectToListAsync(); 44 | } 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Department/Index.cshtml: -------------------------------------------------------------------------------- 1 | @using ContosoUniversity.Features.Department 2 | @model IList 3 | @{ 4 | ViewBag.Title = "Departments"; 5 | } 6 |

Departments

7 |

8 | @(Html.Link(c => c.Create(), "Create New")) 9 |

10 | 11 | 12 | 15 | 18 | 21 | 24 | 25 | 26 | @{ int i = 0; } 27 | @foreach (var item in Model) 28 | { 29 | 30 | 33 | 36 | 39 | 42 | 47 | 48 | i++; 49 | } 50 |
13 | @Html.DisplayLabel(model => model.Name) 14 | 16 | @Html.DisplayLabel(model => model.Budget) 17 | 19 | @Html.DisplayLabel(model => model.StartDate) 20 | 22 | @Html.DisplayLabel(model => model.AdministratorFullName) 23 |
31 | @Html.Display(modelItem => modelItem[i].Name) 32 | 34 | @Html.Display(modelItem => modelItem[i].Budget) 35 | 37 | @Html.Display(modelItem => modelItem[i].StartDate) 38 | 40 | @Html.Display(modelItem => modelItem[i].AdministratorFullName) 41 | 43 | @(Html.Link(c => c.Edit(new Edit.Query { Id = item.DepartmentID }))) | 44 | @(Html.Link(c => c.Details(new Details.Query { Id = item.DepartmentID }))) | 45 | @(Html.Link(c => c.Delete(new Delete.Query { Id = item.DepartmentID }))) 46 |
-------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Department/MappingProfile.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Features.Department 2 | { 3 | using AutoMapper; 4 | using Models; 5 | 6 | public class MappingProfile : Profile 7 | { 8 | public MappingProfile() 9 | { 10 | CreateMap(); 11 | CreateMap(MemberList.Source); 12 | CreateMap().ReverseMap(); 13 | CreateMap(); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Department/UiController.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Features.Department 2 | { 3 | using System.Threading.Tasks; 4 | using System.Web.Mvc; 5 | using Infrastructure; 6 | using MediatR; 7 | 8 | public class UiController : Controller 9 | { 10 | private readonly IMediator _mediator; 11 | 12 | public UiController(IMediator mediator) 13 | { 14 | _mediator = mediator; 15 | } 16 | 17 | public async Task Index() 18 | { 19 | var model = await _mediator.SendAsync(new Index.Query()); 20 | 21 | return View(model); 22 | } 23 | 24 | public async Task Details(Details.Query query) 25 | { 26 | var department = await _mediator.SendAsync(query); 27 | 28 | if (department == null) 29 | { 30 | return HttpNotFound(); 31 | } 32 | return View(department); 33 | } 34 | 35 | public ActionResult Create() 36 | { 37 | return View(new Create.Command()); 38 | } 39 | 40 | [HttpPost] 41 | [ValidateAntiForgeryToken] 42 | public ActionResult Create(Create.Command model) 43 | { 44 | _mediator.Send(model); 45 | 46 | return this.RedirectToActionJson(c => c.Index()); 47 | } 48 | 49 | public async Task Edit(Edit.Query query) 50 | { 51 | var department = await _mediator.SendAsync(query); 52 | 53 | if (department == null) 54 | { 55 | return HttpNotFound(); 56 | } 57 | return View(department); 58 | } 59 | 60 | [HttpPost] 61 | [ValidateAntiForgeryToken] 62 | public async Task Edit(Edit.Command model) 63 | { 64 | await _mediator.SendAsync(model); 65 | 66 | return this.RedirectToActionJson(c => c.Index()); 67 | } 68 | 69 | public async Task Delete(Delete.Query query) 70 | { 71 | var model = await _mediator.SendAsync(query); 72 | 73 | return View(model); 74 | } 75 | 76 | [HttpPost] 77 | [ValidateAntiForgeryToken] 78 | public async Task Delete(Delete.Command command) 79 | { 80 | await _mediator.SendAsync(command); 81 | 82 | return this.RedirectToActionJson(c => c.Index()); 83 | } 84 | } 85 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Home/About.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Features.Home 2 | { 3 | using ContosoUniversity.DAL; 4 | using MediatR; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.ComponentModel.DataAnnotations; 8 | using System.Threading.Tasks; 9 | 10 | public class About 11 | { 12 | public class EnrollmentDateGroup 13 | { 14 | [DataType(DataType.Date)] 15 | public DateTime? EnrollmentDate { get; set; } 16 | 17 | public int StudentCount { get; set; } 18 | } 19 | 20 | public class Query : IAsyncRequest> { } 21 | 22 | public class Handler : IAsyncRequestHandler> 23 | { 24 | private readonly SchoolContext _dbContext; 25 | 26 | public Handler(SchoolContext dbContext) 27 | { 28 | _dbContext = dbContext; 29 | } 30 | 31 | public async Task> Handle(Query message) 32 | { 33 | // Commenting out LINQ to show how to do the same thing in SQL. 34 | //IQueryable = from student in db.Students 35 | // group student by student.EnrollmentDate into dateGroup 36 | // select new EnrollmentDateGroup() 37 | // { 38 | // EnrollmentDate = dateGroup.Key, 39 | // StudentCount = dateGroup.Count() 40 | // }; 41 | 42 | // SQL version of the above LINQ code. 43 | string query = "SELECT EnrollmentDate, COUNT(*) AS StudentCount " 44 | + "FROM Person " 45 | + "WHERE Discriminator = 'Student' " 46 | + "GROUP BY EnrollmentDate"; 47 | IEnumerable data = await _dbContext.Database.SqlQuery(query).ToListAsync(); 48 | 49 | return data; 50 | } 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Home/About.cshtml: -------------------------------------------------------------------------------- 1 | @using ContosoUniversity.Features.Home 2 | @model IEnumerable 3 | 4 | @{ 5 | ViewBag.Title = "Student Body Statistics"; 6 | } 7 | 8 |

Student Body Statistics

9 | 10 | 11 | 12 | 15 | 18 | 19 | 20 | @foreach (var item in Model) 21 | { 22 | 23 | 26 | 29 | 30 | } 31 |
13 | Enrollment Date 14 | 16 | Students 17 |
24 | @Html.DisplayFor(modelItem => item.EnrollmentDate) 25 | 27 | @item.StudentCount 28 |
-------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Home/Contact.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Contact"; 3 | } 4 |

@ViewBag.Title.

5 |

@ViewBag.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 |
-------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Home Page"; 3 | } 4 | 5 |
6 |

Contoso University

7 |
8 |
9 |
10 |

Welcome to Contoso University

11 |

12 | Contoso University is a sample application that 13 | demonstrates how to use Entity Framework 6 in an 14 | ASP.NET MVC 5 web application. 15 |

16 |
17 |
18 |

Build it from scratch

19 |

You can build the application by following the steps in the tutorial series on the ASP.NET site.

20 |

See the tutorial »

21 |
22 |
23 |

Download it

24 |

You can download the completed project from the Microsoft Code Gallery.

25 |

Download »

26 |
27 |
-------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Home/UiController.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Features.Home 2 | { 3 | using MediatR; 4 | using System.Threading.Tasks; 5 | using System.Web.Mvc; 6 | 7 | public class UiController : Controller 8 | { 9 | private readonly IMediator _mediator; 10 | 11 | public UiController(IMediator mediator) 12 | { 13 | _mediator = mediator; 14 | } 15 | 16 | public ActionResult Index() 17 | { 18 | return View(); 19 | } 20 | 21 | public async Task About() 22 | { 23 | var data = await _mediator.SendAsync(new About.Query()); 24 | 25 | return View(data); 26 | } 27 | 28 | public ActionResult Contact() 29 | { 30 | ViewBag.Message = "Your contact page."; 31 | 32 | return View(); 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Instructor/CreateEdit.cshtml: -------------------------------------------------------------------------------- 1 | @using ContosoUniversity.Features.Instructor 2 | @model CreateEdit.Command 3 | 4 | @{ 5 | ViewBag.Title = Model.Id == null ? "Create" : "Edit"; 6 | } 7 | 8 |

@(Model.Id == null ? "Create" : "Edit")

9 | 10 | 11 | @using (Html.BeginForm()) 12 | { 13 | @Html.AntiForgeryToken() 14 | 15 |
16 |

Instructor

17 |
18 | @Html.ValidationDiv() 19 | @Html.FormBlock(m => m.LastName) 20 | @Html.FormBlock(m => m.FirstMidName) 21 | @Html.FormBlock(m => m.HireDate) 22 | @Html.FormBlock(m => m.OfficeAssignmentLocation) 23 | 24 | 25 |
26 |
27 | 28 | 29 | @{ 30 | int cnt = 0; 31 | 32 | foreach (var course in Model.AssignedCourses) 33 | { 34 | if (cnt++ % 3 == 0) 35 | { 36 | @: 37 | } 38 | @: 47 | } 48 | @: 49 | } 50 |
39 | 46 | @:
51 |
52 |
53 | 54 |
55 |
56 | 57 |
58 |
59 |
60 | } 61 | 62 |
63 | @(Html.Link(c => c.Index(null), "Back to List")) 64 |
65 | 66 | @section Scripts { 67 | @Scripts.Render("~/bundles/jqueryval") 68 | } 69 | -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Instructor/Delete.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Features.Instructor 2 | { 3 | using System; 4 | using System.ComponentModel.DataAnnotations; 5 | using System.Data.Entity; 6 | using System.Linq; 7 | using System.Threading.Tasks; 8 | using AutoMapper; 9 | using DAL; 10 | using FluentValidation; 11 | using MediatR; 12 | using Models; 13 | 14 | public class Delete 15 | { 16 | public class Query : IAsyncRequest 17 | { 18 | public int? Id { get; set; } 19 | } 20 | 21 | public class Validator : AbstractValidator 22 | { 23 | public Validator() 24 | { 25 | RuleFor(m => m.Id).NotNull(); 26 | } 27 | } 28 | 29 | public class Command : IAsyncRequest 30 | { 31 | public int? ID { get; set; } 32 | 33 | public string LastName { get; set; } 34 | [Display(Name = "First Name")] 35 | public string FirstMidName { get; set; } 36 | 37 | [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}")] 38 | public DateTime? HireDate { get; set; } 39 | 40 | [Display(Name = "Location")] 41 | public string OfficeAssignmentLocation { get; set; } 42 | } 43 | 44 | public class QueryHandler : IAsyncRequestHandler 45 | { 46 | private readonly SchoolContext _db; 47 | 48 | public QueryHandler(SchoolContext db) 49 | { 50 | _db = db; 51 | } 52 | 53 | public async Task Handle(Query message) 54 | { 55 | return await _db.Instructors.Where(i => i.ID == message.Id).ProjectToSingleOrDefaultAsync(); 56 | } 57 | } 58 | 59 | public class CommandHandler : AsyncRequestHandler 60 | { 61 | private readonly SchoolContext _db; 62 | 63 | public CommandHandler(SchoolContext db) 64 | { 65 | _db = db; 66 | } 67 | 68 | protected override async Task HandleCore(Command message) 69 | { 70 | Instructor instructor = await _db.Instructors 71 | .Include(i => i.OfficeAssignment) 72 | .Where(i => i.ID == message.ID) 73 | .SingleAsync(); 74 | 75 | instructor.OfficeAssignment = null; 76 | _db.Instructors.Remove(instructor); 77 | 78 | var department = await _db.Departments 79 | .Where(d => d.InstructorID == message.ID) 80 | .SingleOrDefaultAsync(); 81 | if (department != null) 82 | { 83 | department.InstructorID = null; 84 | } 85 | 86 | } 87 | } 88 | } 89 | 90 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Instructor/Delete.cshtml: -------------------------------------------------------------------------------- 1 | @using ContosoUniversity.Features.Instructor 2 | @model Delete.Command 3 | 4 | @{ 5 | ViewBag.Title = "Delete"; 6 | } 7 | 8 |

Delete

9 | 10 |

Are you sure you want to delete this?

11 |
12 |

Instructor

13 |
14 |
15 |
16 | @Html.DisplayLabel(model => model.OfficeAssignmentLocation) 17 |
18 | 19 |
20 | @Html.Display(model => model.OfficeAssignmentLocation) 21 |
22 | 23 |
24 | @Html.DisplayLabel(model => model.LastName) 25 |
26 | 27 |
28 | @Html.Display(model => model.LastName) 29 |
30 | 31 |
32 | @Html.DisplayLabel(model => model.FirstMidName) 33 |
34 | 35 |
36 | @Html.Display(model => model.FirstMidName) 37 |
38 | 39 |
40 | @Html.DisplayLabel(model => model.HireDate) 41 |
42 | 43 |
44 | @Html.Display(model => model.HireDate) 45 |
46 | 47 |
48 | 49 | @using (Html.BeginForm()) { 50 | @Html.AntiForgeryToken() 51 | @Html.Input(m => m.ID) 52 |
53 | | 54 | @(Html.Link(c => c.Index(null), "Back to List")) 55 |
56 | } 57 |
58 | -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Instructor/Details.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Features.Instructor 2 | { 3 | using System; 4 | using System.ComponentModel.DataAnnotations; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | using AutoMapper; 8 | using DAL; 9 | using FluentValidation; 10 | using MediatR; 11 | 12 | public class Details 13 | { 14 | public class Query : IAsyncRequest 15 | { 16 | public int? Id { get; set; } 17 | } 18 | 19 | public class Validator : AbstractValidator 20 | { 21 | public Validator() 22 | { 23 | RuleFor(m => m.Id).NotNull(); 24 | } 25 | } 26 | 27 | public class Model 28 | { 29 | public int? ID { get; set; } 30 | 31 | public string LastName { get; set; } 32 | [Display(Name = "First Name")] 33 | public string FirstMidName { get; set; } 34 | 35 | [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}")] 36 | public DateTime? HireDate { get; set; } 37 | 38 | [Display(Name = "Location")] 39 | public string OfficeAssignmentLocation { get; set; } 40 | } 41 | 42 | public class Handler : IAsyncRequestHandler 43 | { 44 | private readonly SchoolContext _db; 45 | 46 | public Handler(SchoolContext db) 47 | { 48 | _db = db; 49 | } 50 | 51 | public async Task Handle(Query message) 52 | { 53 | return await _db.Instructors.Where(i => i.ID == message.Id).ProjectToSingleOrDefaultAsync(); 54 | } 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Instructor/Details.cshtml: -------------------------------------------------------------------------------- 1 | @using ContosoUniversity.Features.Instructor 2 | @model Details.Model 3 | 4 | @{ 5 | ViewBag.Title = "Details"; 6 | } 7 | 8 |

Details

9 | 10 |
11 |

Instructor

12 |
13 |
14 |
15 | @Html.DisplayLabel(model => model.OfficeAssignmentLocation) 16 |
17 | 18 |
19 | @Html.Display(model => model.OfficeAssignmentLocation) 20 |
21 | 22 |
23 | @Html.DisplayLabel(model => model.LastName) 24 |
25 | 26 |
27 | @Html.Display(model => model.LastName) 28 |
29 | 30 |
31 | @Html.DisplayLabel(model => model.FirstMidName) 32 |
33 | 34 |
35 | @Html.Display(model => model.FirstMidName) 36 |
37 | 38 |
39 | @Html.DisplayLabel(model => model.HireDate) 40 |
41 | 42 |
43 | @Html.Display(model => model.HireDate) 44 |
45 | 46 |
47 |
48 |

49 | @(Html.Link(c => c.Edit(new CreateEdit.Query { Id = Model.ID}))) 50 | @(Html.Link(c => c.Index(null), "Back to List")) 51 |

52 | -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Instructor/MappingProfile.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Features.Instructor 2 | { 3 | using AutoMapper; 4 | using Models; 5 | 6 | public class MappingProfile : Profile 7 | { 8 | public MappingProfile() 9 | { 10 | CreateMap(); 11 | CreateMap(); 12 | CreateMap(); 13 | CreateMap(); 14 | 15 | CreateMap(); 16 | CreateMap(); 17 | 18 | CreateMap(); 19 | CreateMap(); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Instructor/UiController.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Features.Instructor 2 | { 3 | using System.Threading.Tasks; 4 | using System.Web.Mvc; 5 | using Infrastructure; 6 | using MediatR; 7 | 8 | public class UiController : Controller 9 | { 10 | private readonly IMediator _mediator; 11 | 12 | public UiController(IMediator mediator) 13 | { 14 | _mediator = mediator; 15 | } 16 | 17 | public async Task Index(Index.Query query) 18 | { 19 | var model = await _mediator.SendAsync(query); 20 | 21 | return View(model); 22 | } 23 | 24 | public async Task Details(Details.Query query) 25 | { 26 | var model = await _mediator.SendAsync(query); 27 | 28 | return View(model); 29 | } 30 | 31 | public async Task Create() 32 | { 33 | var model = await _mediator.SendAsync(new CreateEdit.Query()); 34 | 35 | return View("CreateEdit", model); 36 | } 37 | 38 | [HttpPost] 39 | [ValidateAntiForgeryToken] 40 | public async Task Create(CreateEdit.Command command) 41 | { 42 | await _mediator.SendAsync(command); 43 | 44 | return this.RedirectToActionJson("Index"); 45 | } 46 | 47 | public async Task Edit(CreateEdit.Query query) 48 | { 49 | var model = await _mediator.SendAsync(query); 50 | 51 | return View("CreateEdit", model); 52 | } 53 | 54 | [HttpPost] 55 | [ValidateAntiForgeryToken] 56 | public async Task Edit(CreateEdit.Command command) 57 | { 58 | await _mediator.SendAsync(command); 59 | 60 | return this.RedirectToActionJson("Index"); 61 | } 62 | 63 | public async Task Delete(Delete.Query query) 64 | { 65 | var model = await _mediator.SendAsync(query); 66 | 67 | return View(model); 68 | } 69 | 70 | [HttpPost] 71 | [ValidateAntiForgeryToken] 72 | public async Task Delete(Delete.Command command) 73 | { 74 | await _mediator.SendAsync(command); 75 | 76 | return this.RedirectToActionJson("Index"); 77 | } 78 | } 79 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = null; 3 | } 4 | 5 | 6 | 7 | 8 | 9 | Error 10 | 11 | 12 |
13 |

Error.

14 |

An error occurred while processing your request.

15 |
16 | 17 | 18 | -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Student/Create.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Features.Student 2 | { 3 | using System; 4 | using System.ComponentModel.DataAnnotations; 5 | using AutoMapper; 6 | using DAL; 7 | using FluentValidation; 8 | using MediatR; 9 | using Models; 10 | 11 | public class Create 12 | { 13 | public class Command : IRequest 14 | { 15 | public string LastName { get; set; } 16 | 17 | [Display(Name = "First Name")] 18 | public string FirstMidName { get; set; } 19 | 20 | public DateTime? EnrollmentDate { get; set; } 21 | } 22 | 23 | public class Validator : AbstractValidator 24 | { 25 | public Validator() 26 | { 27 | RuleFor(m => m.LastName).NotNull().Length(1, 50); 28 | RuleFor(m => m.FirstMidName).NotNull().Length(1, 50); 29 | RuleFor(m => m.EnrollmentDate).NotNull(); 30 | } 31 | } 32 | 33 | public class Handler : RequestHandler 34 | { 35 | private readonly SchoolContext _db; 36 | 37 | public Handler(SchoolContext db) 38 | { 39 | _db = db; 40 | } 41 | 42 | protected override void HandleCore(Command message) 43 | { 44 | var student = Mapper.Map(message); 45 | 46 | _db.Students.Add(student); 47 | } 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Student/Create.cshtml: -------------------------------------------------------------------------------- 1 | @using ContosoUniversity.Features.Student 2 | @model Create.Command 3 | 4 | @{ 5 | ViewBag.Title = "Create"; 6 | } 7 | 8 |

Create

9 | 10 | 11 | @using (Html.BeginForm()) 12 | { 13 | @Html.AntiForgeryToken() 14 | 15 |
16 |

Student

17 |
18 | @Html.ValidationDiv() 19 | @Html.FormBlock(m => m.LastName) 20 | @Html.FormBlock(m => m.FirstMidName) 21 | @Html.FormBlock(m => m.EnrollmentDate) 22 | 23 |
24 |
25 | 26 |
27 |
28 |
29 | } 30 | 31 |
32 | @(Html.Link(c => c.Index(null), "Back to List")) 33 |
34 | 35 | @section Scripts { 36 | @Scripts.Render("~/bundles/jqueryval") 37 | } 38 | -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Student/Delete.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Features.Student 2 | { 3 | using System; 4 | using System.ComponentModel.DataAnnotations; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | using AutoMapper; 8 | using DAL; 9 | using MediatR; 10 | 11 | public class Delete 12 | { 13 | public class Query : IAsyncRequest 14 | { 15 | public int Id { get; set; } 16 | } 17 | 18 | public class Command : IAsyncRequest 19 | { 20 | public int ID { get; set; } 21 | [Display(Name = "First Name")] 22 | public string FirstMidName { get; set; } 23 | public string LastName { get; set; } 24 | public DateTime EnrollmentDate { get; set; } 25 | } 26 | 27 | public class QueryHandler : IAsyncRequestHandler 28 | { 29 | private readonly SchoolContext _db; 30 | 31 | public QueryHandler(SchoolContext db) 32 | { 33 | _db = db; 34 | } 35 | 36 | public async Task Handle(Query message) 37 | { 38 | return await _db.Students.Where(s => s.ID == message.Id).ProjectToSingleOrDefaultAsync(); 39 | } 40 | } 41 | 42 | public class CommandHandler : AsyncRequestHandler 43 | { 44 | private readonly SchoolContext _db; 45 | 46 | public CommandHandler(SchoolContext db) 47 | { 48 | _db = db; 49 | } 50 | 51 | protected override async Task HandleCore(Command message) 52 | { 53 | var student = await _db.Students.FindAsync(message.ID); 54 | 55 | _db.Students.Remove(student); 56 | } 57 | } 58 | 59 | } 60 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Student/Delete.cshtml: -------------------------------------------------------------------------------- 1 | @using ContosoUniversity.Features.Student 2 | @model Delete.Command 3 | 4 | @{ 5 | ViewBag.Title = "Delete"; 6 | } 7 | 8 |

Delete

9 |

@ViewBag.ErrorMessage

10 |

Are you sure you want to delete this?

11 |
12 |

Student

13 |
14 |
15 |
16 | @Html.DisplayLabel(model => model.LastName) 17 |
18 | 19 |
20 | @Html.Display(model => model.LastName) 21 |
22 | 23 |
24 | @Html.Display(model => model.FirstMidName) 25 |
26 | 27 |
28 | @Html.DisplayFor(model => model.FirstMidName) 29 |
30 | 31 |
32 | @Html.Display(model => model.EnrollmentDate) 33 |
34 | 35 |
36 | @Html.DisplayFor(model => model.EnrollmentDate) 37 |
38 | 39 |
40 | 41 | @using (Html.BeginForm()) { 42 | @Html.AntiForgeryToken() 43 | @Html.Input(model => model.ID) 44 | 45 |
46 | | 47 | @(Html.Link(c => c.Index(null), "Back to List")) 48 |
49 | } 50 |
51 | -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Student/Details.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Features.Student 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.ComponentModel.DataAnnotations; 6 | using System.Linq; 7 | using System.Threading.Tasks; 8 | using AutoMapper; 9 | using DAL; 10 | using MediatR; 11 | using Models; 12 | 13 | public class Details 14 | { 15 | public class Query : IAsyncRequest 16 | { 17 | public int Id { get; set; } 18 | } 19 | 20 | public class Model 21 | { 22 | public int ID { get; set; } 23 | [Display(Name = "First Name")] 24 | public string FirstMidName { get; set; } 25 | public string LastName { get; set; } 26 | public DateTime EnrollmentDate { get; set; } 27 | public List Enrollments { get; set; } 28 | 29 | public class Enrollment 30 | { 31 | public string CourseTitle { get; set; } 32 | public Grade? Grade { get; set; } 33 | } 34 | } 35 | 36 | public class Handler : IAsyncRequestHandler 37 | { 38 | private readonly SchoolContext _db; 39 | 40 | public Handler(SchoolContext db) 41 | { 42 | _db = db; 43 | } 44 | 45 | public async Task Handle(Query message) 46 | { 47 | return await _db.Students.Where(s => s.ID == message.Id).ProjectToSingleOrDefaultAsync(); 48 | } 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Student/Details.cshtml: -------------------------------------------------------------------------------- 1 | @using ContosoUniversity.Features.Student 2 | @model Details.Model 3 | 4 | @{ 5 | ViewBag.Title = "Details"; 6 | } 7 | 8 |

Details

9 | 10 |
11 |

Student

12 |
13 |
14 |
15 | @Html.DisplayLabel(model => model.LastName) 16 |
17 | 18 |
19 | @Html.Display(model => model.LastName) 20 |
21 | 22 |
23 | @Html.DisplayLabel(model => model.FirstMidName) 24 |
25 | 26 |
27 | @Html.Display(model => model.FirstMidName) 28 |
29 | 30 |
31 | @Html.DisplayLabel(model => model.EnrollmentDate) 32 |
33 | 34 |
35 | @Html.Display(model => model.EnrollmentDate) 36 |
37 |
38 | @Html.DisplayLabel(model => model.Enrollments) 39 |
40 |
41 | 42 | 43 | 44 | 45 | 46 | @for (var i = 0; i < Model.Enrollments.Count; i++) 47 | { 48 | 49 | 52 | 55 | 56 | } 57 |
Course TitleGrade
50 | @Html.Display(m => m.Enrollments[i].CourseTitle) 51 | 53 | @Html.Display(m => m.Enrollments[i].Grade) 54 |
58 |
59 |
60 |
61 |

62 | @(Html.Link(c => c.Edit(new Edit.Query {Id = Model.ID}))) | 63 | @(Html.Link(c => c.Index(null), "Back to List")) 64 |

65 | -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Student/Edit.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Features.Student 2 | { 3 | using System; 4 | using System.ComponentModel.DataAnnotations; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | using AutoMapper; 8 | using DAL; 9 | using FluentValidation; 10 | using Infrastructure.Mapping; 11 | using MediatR; 12 | 13 | public class Edit 14 | { 15 | public class Query : IAsyncRequest 16 | { 17 | public int? Id { get; set; } 18 | } 19 | 20 | public class QueryValidator : AbstractValidator 21 | { 22 | public QueryValidator() 23 | { 24 | RuleFor(m => m.Id).NotNull(); 25 | } 26 | } 27 | 28 | public class Command : IAsyncRequest 29 | { 30 | public int ID { get; set; } 31 | public string LastName { get; set; } 32 | 33 | [Display(Name = "First Name")] 34 | public string FirstMidName { get; set; } 35 | 36 | public DateTime? EnrollmentDate { get; set; } 37 | } 38 | 39 | public class Validator : AbstractValidator 40 | { 41 | public Validator() 42 | { 43 | RuleFor(m => m.LastName).NotNull().Length(1, 50); 44 | RuleFor(m => m.FirstMidName).NotNull().Length(1, 50); 45 | RuleFor(m => m.EnrollmentDate).NotNull(); 46 | } 47 | } 48 | 49 | public class QueryHandler : IAsyncRequestHandler 50 | { 51 | private readonly SchoolContext _db; 52 | 53 | public QueryHandler(SchoolContext db) 54 | { 55 | _db = db; 56 | } 57 | 58 | public async Task Handle(Query message) 59 | { 60 | return await _db.Students 61 | .Where(s => s.ID == message.Id) 62 | .ProjectToSingleOrDefaultAsync(); 63 | } 64 | } 65 | 66 | public class CommandHandler : AsyncRequestHandler 67 | { 68 | private readonly SchoolContext _db; 69 | 70 | public CommandHandler(SchoolContext db) 71 | { 72 | _db = db; 73 | } 74 | 75 | protected override async Task HandleCore(Command message) 76 | { 77 | var student = await _db.Students.FindAsync(message.ID); 78 | 79 | Mapper.Map(message, student); 80 | } 81 | } 82 | } 83 | 84 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Student/Edit.cshtml: -------------------------------------------------------------------------------- 1 | @using ContosoUniversity.Features.Student 2 | @model Edit.Command 3 | 4 | @{ 5 | ViewBag.Title = "Edit"; 6 | } 7 | 8 |

Edit

9 | 10 | 11 | @using (Html.BeginForm()) 12 | { 13 | @Html.AntiForgeryToken() 14 | 15 |
16 |

Student

17 |
18 | @Html.ValidationDiv() 19 | @Html.Input(m => m.ID) 20 | @Html.FormBlock(m => m.LastName) 21 | @Html.FormBlock(m => m.FirstMidName) 22 | @Html.FormBlock(m => m.EnrollmentDate) 23 | 24 |
25 |
26 | 27 |
28 |
29 |
30 | } 31 | 32 |
33 | @(Html.Link(c => c.Index(null), "Back to List")) 34 |
35 | 36 | @section Scripts { 37 | @Scripts.Render("~/bundles/jqueryval") 38 | } 39 | -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Student/Index.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Features.Student 2 | { 3 | using System; 4 | using System.ComponentModel.DataAnnotations; 5 | using System.Linq; 6 | using DAL; 7 | using Infrastructure.Mapping; 8 | using MediatR; 9 | using Models; 10 | using PagedList; 11 | 12 | public class Index 13 | { 14 | public class Query : IRequest 15 | { 16 | public string SortOrder { get; set; } 17 | public string CurrentFilter { get; set; } 18 | public string SearchString { get; set; } 19 | public int? Page { get; set; } 20 | } 21 | 22 | public class Result 23 | { 24 | public string CurrentSort { get; set; } 25 | public string NameSortParm { get; set; } 26 | public string DateSortParm { get; set; } 27 | public string CurrentFilter { get; set; } 28 | public string SearchString { get; set; } 29 | 30 | public IPagedList Results { get; set; } 31 | } 32 | 33 | public class Model 34 | { 35 | public int ID { get; set; } 36 | [Display(Name = "First Name")] 37 | public string FirstMidName { get; set; } 38 | public string LastName { get; set; } 39 | public DateTime EnrollmentDate { get; set; } 40 | } 41 | 42 | public class QueryHandler : IRequestHandler 43 | { 44 | private readonly SchoolContext _db; 45 | 46 | public QueryHandler(SchoolContext db) 47 | { 48 | _db = db; 49 | } 50 | 51 | public Result Handle(Query message) 52 | { 53 | var model = new Result 54 | { 55 | CurrentSort = message.SortOrder, 56 | NameSortParm = String.IsNullOrEmpty(message.SortOrder) ? "name_desc" : "", 57 | DateSortParm = message.SortOrder == "Date" ? "date_desc" : "Date", 58 | }; 59 | 60 | if (message.SearchString != null) 61 | { 62 | message.Page = 1; 63 | } 64 | else 65 | { 66 | message.SearchString = message.CurrentFilter; 67 | } 68 | 69 | model.CurrentFilter = message.SearchString; 70 | model.SearchString = message.SearchString; 71 | 72 | var students = from s in _db.Students 73 | select s; 74 | if (!String.IsNullOrEmpty(message.SearchString)) 75 | { 76 | students = students.Where(s => s.LastName.Contains(message.SearchString) 77 | || s.FirstMidName.Contains(message.SearchString)); 78 | } 79 | switch (message.SortOrder) 80 | { 81 | case "name_desc": 82 | students = students.OrderByDescending(s => s.LastName); 83 | break; 84 | case "Date": 85 | students = students.OrderBy(s => s.EnrollmentDate); 86 | break; 87 | case "date_desc": 88 | students = students.OrderByDescending(s => s.EnrollmentDate); 89 | break; 90 | default: // Name ascending 91 | students = students.OrderBy(s => s.LastName); 92 | break; 93 | } 94 | 95 | int pageSize = 3; 96 | int pageNumber = (message.Page ?? 1); 97 | model.Results = students.ProjectToPagedList(pageNumber, pageSize); 98 | 99 | return model; 100 | } 101 | } 102 | } 103 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Student/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model Index.Result 2 | @using ContosoUniversity.Features.Student; 3 | @using PagedList.Mvc; 4 | 5 | 6 | @{ 7 | ViewBag.Title = "Students"; 8 | } 9 | 10 |

Students

11 | 12 |

13 | @(Html.Link(c => c.Create(), "Create New")) 14 |

15 |
16 |

17 | Find by name: @Html.Input(m => m.SearchString).RemoveClass("form-control") 18 | 19 |

20 |
21 | 22 | 23 | 26 | 29 | 32 | 33 | 34 | 35 | 36 | @{ int i = 0; } 37 | @foreach (var item in Model.Results) 38 | { 39 | 40 | 43 | 46 | 49 | 54 | 55 | i++; 56 | } 57 | 58 |
24 | @(Html.Link(c => c.Index(new Index.Query { SortOrder = Model.NameSortParm, CurrentFilter = Model.CurrentFilter }), "Last Name")) 25 | 27 | First Name 28 | 30 | @(Html.Link(c => c.Index(new Index.Query { SortOrder = Model.DateSortParm, CurrentFilter = Model.CurrentFilter }), "Enrollment Date")) 31 |
41 | @Html.Display(modelItem => modelItem.Results[i].LastName) 42 | 44 | @Html.Display(modelItem => modelItem.Results[i].FirstMidName) 45 | 47 | @Html.Display(modelItem => modelItem.Results[i].EnrollmentDate) 48 | 50 | @(Html.Link(c => c.Edit(new Edit.Query {Id = item.ID}))) | 51 | @(Html.Link(c => c.Details(new Details.Query {Id = item.ID }))) | 52 | @(Html.Link(c => c.Delete(new Delete.Query { Id = item.ID }))) 53 |
59 |
60 | Page @(Model.Results.PageCount < Model.Results.PageNumber ? 0 : Model.Results.PageNumber) of @Model.Results.PageCount 61 | 62 | @(Html.PagedListPager(Model.Results, page => Url.Action(c => c.Index(new Index.Query { Page = page, SortOrder = Model.CurrentSort, CurrentFilter = Model.CurrentFilter })))) 63 | -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Student/MappingProfile.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Features.Student 2 | { 3 | using AutoMapper; 4 | using Models; 5 | 6 | public class MappingProfile : Profile 7 | { 8 | public MappingProfile() 9 | { 10 | CreateMap(); 11 | CreateMap(); 12 | CreateMap(); 13 | CreateMap(MemberList.Source); 14 | CreateMap().ReverseMap(); 15 | CreateMap().ReverseMap(); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Student/UiController.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Features.Student 2 | { 3 | using System.Threading.Tasks; 4 | using System.Web.Mvc; 5 | using Infrastructure; 6 | using MediatR; 7 | 8 | public class UiController : Controller 9 | { 10 | private readonly IMediator _mediator; 11 | 12 | public UiController(IMediator mediator) 13 | { 14 | _mediator = mediator; 15 | } 16 | 17 | public ViewResult Index(Index.Query query) 18 | { 19 | var model = _mediator.Send(query); 20 | 21 | return View(model); 22 | } 23 | 24 | public async Task Details(Details.Query query) 25 | { 26 | var model = await _mediator.SendAsync(query); 27 | 28 | return View(model); 29 | } 30 | 31 | public ActionResult Create() 32 | { 33 | return View(new Create.Command()); 34 | } 35 | 36 | [HttpPost] 37 | [ValidateAntiForgeryToken] 38 | public ActionResult Create(Create.Command command) 39 | { 40 | _mediator.Send(command); 41 | 42 | return this.RedirectToActionJson(c => c.Index(null)); 43 | } 44 | 45 | 46 | public async Task Edit(Edit.Query query) 47 | { 48 | var model = await _mediator.SendAsync(query); 49 | 50 | return View(model); 51 | } 52 | 53 | [HttpPost] 54 | [ValidateAntiForgeryToken] 55 | public async Task Edit(Edit.Command command) 56 | { 57 | await _mediator.SendAsync(command); 58 | 59 | return this.RedirectToActionJson(c => c.Index(null)); 60 | } 61 | 62 | public async Task Delete(Delete.Query query) 63 | { 64 | var model = await _mediator.SendAsync(query); 65 | 66 | return View(model); 67 | } 68 | 69 | [HttpPost] 70 | [ValidateAntiForgeryToken] 71 | public async Task Delete(Delete.Command command) 72 | { 73 | await _mediator.SendAsync(command); 74 | 75 | return this.RedirectToActionJson(c => c.Index(null)); 76 | } 77 | } 78 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/Web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 |
7 |
8 | 9 | 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 | -------------------------------------------------------------------------------- /src/ContosoUniversity/Features/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "~/Features/Shared/_Layout.cshtml"; 3 | } 4 | -------------------------------------------------------------------------------- /src/ContosoUniversity/GlimpseSecurityPolicy.cs: -------------------------------------------------------------------------------- 1 | /* 2 | // Uncomment this class to provide custom runtime policy for Glimpse 3 | 4 | using Glimpse.AspNet.Extensions; 5 | using Glimpse.Core.Extensibility; 6 | 7 | namespace ContosoUniversity 8 | { 9 | public class GlimpseSecurityPolicy:IRuntimePolicy 10 | { 11 | public RuntimePolicy Execute(IRuntimePolicyContext policyContext) 12 | { 13 | // You can perform a check like the one below to control Glimpse's permissions within your application. 14 | // More information about RuntimePolicies can be found at http://getglimpse.com/Help/Custom-Runtime-Policy 15 | // var httpContext = policyContext.GetHttpContext(); 16 | // if (!httpContext.User.IsInRole("Administrator")) 17 | // { 18 | // return RuntimePolicy.Off; 19 | // } 20 | 21 | return RuntimePolicy.On; 22 | } 23 | 24 | public RuntimeEvent ExecuteOn 25 | { 26 | // The RuntimeEvent.ExecuteResource is only needed in case you create a security policy 27 | // Have a look at http://blog.getglimpse.com/2013/12/09/protect-glimpse-axd-with-your-custom-runtime-policy/ for more details 28 | get { return RuntimeEvent.EndRequest | RuntimeEvent.ExecuteResource; } 29 | } 30 | } 31 | } 32 | */ -------------------------------------------------------------------------------- /src/ContosoUniversity/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.cs" Inherits="ContosoUniversity.MvcApplication" Language="C#" %> 2 | -------------------------------------------------------------------------------- /src/ContosoUniversity/Global.asax.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity 2 | { 3 | using System.Data.Entity.Infrastructure.Interception; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | using System.Web.Optimization; 7 | using System.Web.Routing; 8 | using DAL; 9 | using Infrastructure; 10 | using Infrastructure.Mapping; 11 | 12 | public class MvcApplication : HttpApplication 13 | { 14 | protected void Application_Start() 15 | { 16 | AreaRegistration.RegisterAllAreas(); 17 | FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 18 | RouteConfig.RegisterRoutes(RouteTable.Routes); 19 | BundleConfig.RegisterBundles(BundleTable.Bundles); 20 | DbInterception.Add(new SchoolInterceptorTransientErrors()); 21 | DbInterception.Add(new SchoolInterceptorLogging()); 22 | AutoMapperInitializer.Initialize(); 23 | 24 | ViewEngines.Engines.Clear(); 25 | ViewEngines.Engines.Add(new FeatureViewLocationRazorViewEngine()); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Infrastructure/CommandProcessing/CommandProcessingRegistry.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Infrastructure.CommandProcessing 2 | { 3 | using FluentValidation; 4 | using MediatR; 5 | using StructureMap; 6 | 7 | public class CommandProcessingRegistry : Registry 8 | { 9 | public CommandProcessingRegistry() 10 | { 11 | Scan(scan => 12 | { 13 | scan.AssemblyContainingType(); 14 | scan.AssemblyContainingType(); 15 | 16 | scan.AddAllTypesOf(typeof(IRequestHandler<,>)); 17 | scan.AddAllTypesOf(typeof(IAsyncRequestHandler<,>)); 18 | scan.AddAllTypesOf(typeof (IValidator<>)); 19 | scan.WithDefaultConventions(); 20 | }); 21 | 22 | For().Use(ctx => t => ctx.GetInstance(t)); 23 | For().Use(ctx => t => ctx.GetAllInstances(t)); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Infrastructure/ControllerExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Infrastructure 2 | { 3 | using System; 4 | using System.Linq; 5 | using System.Linq.Expressions; 6 | using System.Web.Mvc; 7 | using Newtonsoft.Json; 8 | 9 | public static class ControllerExtensions 10 | { 11 | public static ActionResult RedirectToActionJson(this Controller controller, Expression> action) 12 | where TController : Controller 13 | { 14 | return controller.JsonNet(new 15 | { 16 | redirect = controller.Url.Action(action) 17 | } 18 | ); 19 | } 20 | 21 | public static ActionResult RedirectToActionJson(this TController controller, Expression> action) 22 | where TController : Controller 23 | { 24 | return controller.JsonNet(new 25 | { 26 | redirect = controller.Url.Action(action) 27 | } 28 | ); 29 | } 30 | 31 | public static ActionResult RedirectToActionJson(this TController controller, string action) 32 | where TController : Controller 33 | { 34 | return controller.JsonNet(new 35 | { 36 | redirect = controller.Url.Action(action) 37 | } 38 | ); 39 | } 40 | 41 | public static ContentResult JsonNet(this Controller controller, object model) 42 | { 43 | var serialized = JsonConvert.SerializeObject(model, new JsonSerializerSettings 44 | { 45 | ReferenceLoopHandling = ReferenceLoopHandling.Ignore 46 | }); 47 | 48 | return new ContentResult 49 | { 50 | Content = serialized, 51 | ContentType = "application/json" 52 | }; 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Infrastructure/ControllerFactory.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Infrastructure 2 | { 3 | using System; 4 | using System.Web.Mvc; 5 | using System.Web.Routing; 6 | 7 | public class ControllerFactory : DefaultControllerFactory 8 | { 9 | protected override Type GetControllerType(RequestContext requestContext, string controllerName) 10 | { 11 | return 12 | typeof (ControllerFactory).Assembly.GetType("ContosoUniversity.Features." + controllerName + 13 | ".UiController"); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Infrastructure/DataAccess/MvcTransactionFilter.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Infrastructure.DataAccess 2 | { 3 | using System.Web.Mvc; 4 | using App_Start; 5 | using DAL; 6 | 7 | public class MvcTransactionFilter : ActionFilterAttribute 8 | { 9 | public override void OnActionExecuting(ActionExecutingContext filterContext) 10 | { 11 | // Logger.Instance.Verbose("MvcTransactionFilter::OnActionExecuting"); 12 | var context = StructuremapMvc.ParentScope.CurrentNestedContainer.GetInstance(); 13 | context.BeginTransaction(); 14 | } 15 | 16 | public override void OnActionExecuted(ActionExecutedContext filterContext) 17 | { 18 | // Logger.Instance.Verbose("MvcTransactionFilter::OnActionExecuted"); 19 | var instance = StructuremapMvc.ParentScope.CurrentNestedContainer.GetInstance(); 20 | instance.CloseTransaction(filterContext.Exception); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Infrastructure/DepartmentModelBinder.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Infrastructure 2 | { 3 | using System.Web.Mvc; 4 | using DAL; 5 | 6 | public class DepartmentModelBinder : IModelBinder 7 | { 8 | private readonly SchoolContext _dbContext; 9 | 10 | public DepartmentModelBinder(SchoolContext dbContext) 11 | { 12 | _dbContext = dbContext; 13 | } 14 | 15 | public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 16 | { 17 | var attemptedValue = bindingContext.ValueProvider.GetValue(bindingContext.ModelName).AttemptedValue; 18 | 19 | return string.IsNullOrWhiteSpace(attemptedValue) ? null : _dbContext.Departments.Find(int.Parse(attemptedValue)); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Infrastructure/DepartmentModelBinderProvider.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Infrastructure 2 | { 3 | using System; 4 | using System.Web.Mvc; 5 | using App_Start; 6 | using Models; 7 | 8 | public class DepartmentModelBinderProvider : IModelBinderProvider 9 | { 10 | public IModelBinder GetBinder(Type modelType) 11 | { 12 | return typeof(Department).IsAssignableFrom(modelType) ? StructuremapMvc.ParentScope.GetInstance() : null; 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Infrastructure/FeatureViewLocationRazorViewEngine.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Infrastructure 2 | { 3 | using System.Web.Mvc; 4 | 5 | public class FeatureViewLocationRazorViewEngine : RazorViewEngine 6 | { 7 | public FeatureViewLocationRazorViewEngine() 8 | { 9 | ViewLocationFormats = new[] 10 | { 11 | "~/Features/{1}/{0}.cshtml", 12 | "~/Features/{1}/{0}.vbhtml", 13 | "~/Features/Shared/{0}.cshtml", 14 | "~/Features/Shared/{0}.vbhtml", 15 | }; 16 | 17 | MasterLocationFormats = ViewLocationFormats; 18 | 19 | PartialViewLocationFormats = new[] 20 | { 21 | "~/Features/{1}/{0}.cshtml", 22 | "~/Features/{1}/{0}.vbhtml", 23 | "~/Features/Shared/{0}.cshtml", 24 | "~/Features/Shared/{0}.vbhtml", 25 | }; 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Infrastructure/InstructorModelBinder.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Infrastructure 2 | { 3 | using System.Web.Mvc; 4 | using DAL; 5 | 6 | public class InstructorModelBinder : IModelBinder 7 | { 8 | private readonly SchoolContext _dbContext; 9 | 10 | public InstructorModelBinder(SchoolContext dbContext) 11 | { 12 | _dbContext = dbContext; 13 | } 14 | 15 | public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 16 | { 17 | var attemptedValue = bindingContext.ValueProvider.GetValue(bindingContext.ModelName).AttemptedValue; 18 | 19 | return string.IsNullOrWhiteSpace(attemptedValue) ? null : _dbContext.Instructors.Find(int.Parse(attemptedValue)); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Infrastructure/InstructorModelBinderProvider.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Infrastructure 2 | { 3 | using System; 4 | using System.Web.Mvc; 5 | using App_Start; 6 | using Models; 7 | 8 | public class InstructorModelBinderProvider : IModelBinderProvider 9 | { 10 | public IModelBinder GetBinder(Type modelType) 11 | { 12 | return typeof(Instructor).IsAssignableFrom(modelType) ? StructuremapMvc.ParentScope.GetInstance() : null; 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Infrastructure/Mapping/AutoMapperInitializer.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Infrastructure.Mapping 2 | { 3 | using AutoMapper; 4 | 5 | public class AutoMapperInitializer 6 | { 7 | public static void Initialize() 8 | { 9 | Mapper.Initialize(cfg => 10 | { 11 | cfg.AddProfiles(typeof(AutoMapperInitializer)); 12 | }); 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Infrastructure/Mapping/MappingExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Infrastructure.Mapping 2 | { 3 | using System.Linq; 4 | using AutoMapper; 5 | using AutoMapper.QueryableExtensions; 6 | using DelegateDecompiler; 7 | using PagedList; 8 | 9 | public static class MapperExtensions 10 | { 11 | public static IPagedList ProjectToPagedList(this IQueryable queryable, int pageNumber, int pageSize) 12 | { 13 | return queryable.ProjectTo().Decompile().ToPagedList(pageNumber, pageSize); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Infrastructure/Tags/DefaultAspNetMvcHtmlConventions.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Infrastructure.Tags 2 | { 3 | using System; 4 | using System.ComponentModel.DataAnnotations; 5 | using HtmlTags; 6 | using HtmlTags.Conventions; 7 | 8 | public class DefaultAspNetMvcHtmlConventions : HtmlConventionRegistry 9 | { 10 | public DefaultAspNetMvcHtmlConventions() 11 | { 12 | Editors.Always.AddClass("form-control"); 13 | 14 | Editors.IfPropertyIs().ModifyWith(m => m.CurrentTag 15 | .AddPattern("9{1,2}/9{1,2}/9999") 16 | .AddPlaceholder("MM/DD/YYYY") 17 | .AddClass("datepicker") 18 | .Value(m.Value() != null ? m.Value().ToShortDateString() : string.Empty)); 19 | Editors.If(er => er.Accessor.Name.EndsWith("id", StringComparison.OrdinalIgnoreCase)).BuildBy(a => new HiddenTag().Value(a.StringValue())); 20 | Editors.IfPropertyIs().BuildBy(a => new HiddenTag().Value(Convert.ToBase64String(a.Value()))); 21 | 22 | 23 | Labels.Always.AddClass("control-label"); 24 | Labels.Always.AddClass("col-md-2"); 25 | Labels.ModifyForAttribute((t, a) => t.Text(a.Name)); 26 | Editors.BuilderPolicy(); 27 | Editors.BuilderPolicy(); 28 | DisplayLabels.Always.BuildBy(); 29 | DisplayLabels.ModifyForAttribute((t, a) => t.Text(a.Name)); 30 | Displays.IfPropertyIs().ModifyWith(m => m.CurrentTag.Text(m.Value().ToShortDateString())); 31 | Displays.IfPropertyIs().ModifyWith(m => m.CurrentTag.Text(m.Value() == null ? null : m.Value().Value.ToShortDateString())); 32 | Displays.IfPropertyIs().ModifyWith(m => m.CurrentTag.Text(m.Value().ToString("C"))); 33 | } 34 | 35 | public ElementCategoryExpression DisplayLabels 36 | { 37 | get { return new ElementCategoryExpression(Library.TagLibrary.Category("DisplayLabels").Profile(TagConstants.Default)); } 38 | } 39 | 40 | } 41 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Infrastructure/Tags/DefaultDisplayLabelBuilder.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Infrastructure.Tags 2 | { 3 | using System.Linq; 4 | using System.Text.RegularExpressions; 5 | using HtmlTags; 6 | using HtmlTags.Conventions; 7 | using HtmlTags.Conventions.Elements; 8 | 9 | public class DefaultDisplayLabelBuilder : IElementBuilder 10 | { 11 | public bool Matches(ElementRequest subject) 12 | { 13 | return true; 14 | } 15 | 16 | public HtmlTag Build(ElementRequest request) 17 | { 18 | return new HtmlTag("").NoTag().Text(BreakUpCamelCase(request.Accessor.Name)); 19 | } 20 | 21 | public static string BreakUpCamelCase(string fieldName) 22 | { 23 | var patterns = new[] 24 | { 25 | "([a-z])([A-Z])", 26 | "([0-9])([a-zA-Z])", 27 | "([a-zA-Z])([0-9])" 28 | }; 29 | var output = patterns.Aggregate(fieldName, 30 | (current, pattern) => Regex.Replace(current, pattern, "$1 $2", RegexOptions.IgnorePatternWhitespace)); 31 | return output.Replace('_', ' '); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Infrastructure/Tags/DepartmentSelectElementBuilder.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Infrastructure.Tags 2 | { 3 | using Models; 4 | 5 | public class DepartmentSelectElementBuilder : EntitySelectElementBuilder 6 | { 7 | protected override int GetValue(Department instance) 8 | { 9 | return instance.DepartmentID; 10 | } 11 | 12 | protected override string GetDisplayValue(Department instance) 13 | { 14 | return instance.Name; 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Infrastructure/Tags/EntitySelectElementBuilder.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Infrastructure.Tags 2 | { 3 | using System.Collections.Generic; 4 | using DAL; 5 | using HtmlTags; 6 | using HtmlTags.Conventions; 7 | using HtmlTags.Conventions.Elements; 8 | 9 | public abstract class EntitySelectElementBuilder : ElementTagBuilder where T : class 10 | { 11 | public override bool Matches(ElementRequest subject) 12 | { 13 | return typeof(T).IsAssignableFrom(subject.Accessor.PropertyType); 14 | } 15 | 16 | public override HtmlTag Build(ElementRequest request) 17 | { 18 | var results = Source(request); 19 | 20 | var selectTag = new SelectTag(t => 21 | { 22 | t.Option(string.Empty, string.Empty); // blank default option 23 | foreach (var result in results) 24 | { 25 | BuildOptionTag(t, result, request); 26 | } 27 | }); 28 | 29 | var entity = request.Value(); 30 | 31 | if (entity != null) 32 | { 33 | selectTag.SelectByValue(GetValue(entity)); 34 | } 35 | 36 | return selectTag; 37 | } 38 | 39 | protected virtual HtmlTag BuildOptionTag(SelectTag select, T model, ElementRequest request) 40 | { 41 | return select.Option(GetDisplayValue(model), GetValue(model)); 42 | } 43 | 44 | protected abstract int GetValue(T instance); 45 | protected abstract string GetDisplayValue(T instance); 46 | 47 | protected virtual IEnumerable Source(ElementRequest request) 48 | { 49 | return request.Get().Set(); 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Infrastructure/Tags/HtmlTagExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Infrastructure.Tags 2 | { 3 | using HtmlTags; 4 | 5 | public static class HtmlTagExtensions 6 | { 7 | public static HtmlTag AddPlaceholder(this HtmlTag tag, string placeholder) 8 | { 9 | return tag.Attr("placeholder", placeholder); 10 | } 11 | 12 | public static HtmlTag AddPattern(this HtmlTag tag, string pattern) 13 | { 14 | var retVal = tag.Data("pattern", pattern); 15 | return retVal; 16 | } 17 | 18 | public static HtmlTag AutoCapitalize(this HtmlTag tag) 19 | { 20 | return tag.Data("autocapitalize", "true"); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Infrastructure/Tags/HtmlTagRegistry.cs: -------------------------------------------------------------------------------- 1 | using StructureMap; 2 | 3 | namespace ContosoUniversity.Infrastructure.Tags 4 | { 5 | using HtmlTags.Conventions; 6 | 7 | public class HtmlTagRegistry : Registry 8 | { 9 | 10 | public HtmlTagRegistry() 11 | { 12 | 13 | var htmlConventionLibrary = new HtmlConventionLibrary(); 14 | new DefaultAspNetMvcHtmlConventions().Apply(htmlConventionLibrary); 15 | new DefaultHtmlConventions().Apply(htmlConventionLibrary); 16 | For().Use(htmlConventionLibrary); 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Infrastructure/Tags/InstructorSelectElementBuilder.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Infrastructure.Tags 2 | { 3 | using Models; 4 | 5 | public class InstructorSelectElementBuilder : EntitySelectElementBuilder 6 | { 7 | protected override int GetValue(Instructor instance) 8 | { 9 | return instance.ID; 10 | } 11 | 12 | protected override string GetDisplayValue(Instructor instance) 13 | { 14 | return instance.FullName; 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Infrastructure/UrlHelperExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Infrastructure 2 | { 3 | using System; 4 | using System.Linq.Expressions; 5 | using System.Web.Mvc; 6 | using System.Web.Routing; 7 | using Microsoft.Web.Mvc; 8 | 9 | public static class UrlHelperExtensions 10 | { 11 | public static string Action(this UrlHelper helper, Expression> action) 12 | where TController : Controller 13 | { 14 | var url = LinkBuilder.BuildUrlFromExpression(helper.RequestContext, RouteTable.Routes, action); 15 | 16 | return UrlHelper.GenerateContentUrl("~/" + url, helper.RequestContext.HttpContext); 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Infrastructure/Validation/StructureMapValidatorFactory.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Infrastructure.Validation 2 | { 3 | using System; 4 | using App_Start; 5 | using FluentValidation; 6 | 7 | public class StructureMapValidatorFactory : ValidatorFactoryBase 8 | { 9 | public override IValidator CreateInstance(Type validatorType) 10 | { 11 | return StructuremapMvc.ParentScope.CurrentNestedContainer.TryGetInstance(validatorType) as IValidator; 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Infrastructure/ValidatorActionFilter.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Infrastructure 2 | { 3 | using System.Net; 4 | using System.Web.Mvc; 5 | using Newtonsoft.Json; 6 | 7 | public class ValidatorActionFilter : IActionFilter 8 | { 9 | public void OnActionExecuting(ActionExecutingContext filterContext) 10 | { 11 | if (!filterContext.Controller.ViewData.ModelState.IsValid) 12 | { 13 | if (filterContext.HttpContext.Request.HttpMethod == "GET") 14 | { 15 | var result = new HttpStatusCodeResult(HttpStatusCode.BadRequest); 16 | filterContext.Result = result; 17 | } 18 | else 19 | { 20 | var result = new ContentResult(); 21 | string content = JsonConvert.SerializeObject(filterContext.Controller.ViewData.ModelState, 22 | new JsonSerializerSettings 23 | { 24 | ReferenceLoopHandling = ReferenceLoopHandling.Ignore 25 | }); 26 | result.Content = content; 27 | result.ContentType = "application/json"; 28 | 29 | filterContext.HttpContext.Response.StatusCode = 400; 30 | filterContext.Result = result; 31 | } 32 | } 33 | } 34 | 35 | public void OnActionExecuted(ActionExecutedContext filterContext) 36 | { 37 | 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Logging/ILogger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace ContosoUniversity.Logging 4 | { 5 | public interface ILogger 6 | { 7 | void Information(string message); 8 | void Information(string fmt, params object[] vars); 9 | void Information(Exception exception, string fmt, params object[] vars); 10 | 11 | void Warning(string message); 12 | void Warning(string fmt, params object[] vars); 13 | void Warning(Exception exception, string fmt, params object[] vars); 14 | 15 | void Error(string message); 16 | void Error(string fmt, params object[] vars); 17 | void Error(Exception exception, string fmt, params object[] vars); 18 | 19 | void TraceApi(string componentName, string method, TimeSpan timespan); 20 | void TraceApi(string componentName, string method, TimeSpan timespan, string properties); 21 | void TraceApi(string componentName, string method, TimeSpan timespan, string fmt, params object[] vars); 22 | 23 | } 24 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Logging/Logger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Text; 4 | 5 | namespace ContosoUniversity.Logging 6 | { 7 | public class Logger : ILogger 8 | { 9 | 10 | public void Information(string message) 11 | { 12 | Trace.TraceInformation(message); 13 | } 14 | 15 | public void Information(string fmt, params object[] vars) 16 | { 17 | Trace.TraceInformation(fmt, vars); 18 | } 19 | 20 | public void Information(Exception exception, string fmt, params object[] vars) 21 | { 22 | Trace.TraceInformation(FormatExceptionMessage(exception, fmt, vars)); 23 | } 24 | 25 | public void Warning(string message) 26 | { 27 | Trace.TraceWarning(message); 28 | } 29 | 30 | public void Warning(string fmt, params object[] vars) 31 | { 32 | Trace.TraceWarning(fmt, vars); 33 | } 34 | 35 | public void Warning(Exception exception, string fmt, params object[] vars) 36 | { 37 | Trace.TraceWarning(FormatExceptionMessage(exception, fmt, vars)); 38 | } 39 | 40 | public void Error(string message) 41 | { 42 | Trace.TraceError(message); 43 | } 44 | 45 | public void Error(string fmt, params object[] vars) 46 | { 47 | Trace.TraceError(fmt, vars); 48 | } 49 | 50 | public void Error(Exception exception, string fmt, params object[] vars) 51 | { 52 | Trace.TraceError(FormatExceptionMessage(exception, fmt, vars)); 53 | } 54 | 55 | public void TraceApi(string componentName, string method, TimeSpan timespan) 56 | { 57 | TraceApi(componentName, method, timespan, ""); 58 | } 59 | 60 | public void TraceApi(string componentName, string method, TimeSpan timespan, string fmt, params object[] vars) 61 | { 62 | TraceApi(componentName, method, timespan, string.Format(fmt, vars)); 63 | } 64 | public void TraceApi(string componentName, string method, TimeSpan timespan, string properties) 65 | { 66 | string message = String.Concat("Component:", componentName, ";Method:", method, ";Timespan:", timespan.ToString(), ";Properties:", properties); 67 | Trace.TraceInformation(message); 68 | } 69 | 70 | private static string FormatExceptionMessage(Exception exception, string fmt, object[] vars) 71 | { 72 | // Simple exception formatting: for a more comprehensive version see 73 | // http://code.msdn.microsoft.com/windowsazure/Fix-It-app-for-Building-cdd80df4 74 | var sb = new StringBuilder(); 75 | sb.Append(string.Format(fmt, vars)); 76 | sb.Append(" Exception: "); 77 | sb.Append(exception.ToString()); 78 | return sb.ToString(); 79 | } 80 | } 81 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Migrations/201411021828194_InitialCreate.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | namespace ContosoUniversity.Migrations 3 | { 4 | using System.CodeDom.Compiler; 5 | using System.Data.Entity.Migrations; 6 | using System.Data.Entity.Migrations.Infrastructure; 7 | using System.Resources; 8 | 9 | [GeneratedCode("EntityFramework.Migrations", "6.1.1-30610")] 10 | public sealed partial class InitialCreate : IMigrationMetadata 11 | { 12 | private readonly ResourceManager Resources = new ResourceManager(typeof(InitialCreate)); 13 | 14 | string IMigrationMetadata.Id 15 | { 16 | get { return "201411021828194_InitialCreate"; } 17 | } 18 | 19 | string IMigrationMetadata.Source 20 | { 21 | get { return null; } 22 | } 23 | 24 | string IMigrationMetadata.Target 25 | { 26 | get { return Resources.GetString("Target"); } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/ContosoUniversity/Migrations/201411021828194_InitialCreate.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Migrations 2 | { 3 | using System; 4 | using System.Data.Entity.Migrations; 5 | 6 | public partial class InitialCreate : DbMigration 7 | { 8 | public override void Up() 9 | { 10 | CreateTable( 11 | "dbo.Course", 12 | c => new 13 | { 14 | CourseID = c.Int(nullable: false), 15 | Title = c.String(), 16 | Credits = c.Int(nullable: false), 17 | }) 18 | .PrimaryKey(t => t.CourseID); 19 | 20 | CreateTable( 21 | "dbo.Enrollment", 22 | c => new 23 | { 24 | EnrollmentID = c.Int(nullable: false, identity: true), 25 | CourseID = c.Int(nullable: false), 26 | StudentID = c.Int(nullable: false), 27 | Grade = c.Int(), 28 | }) 29 | .PrimaryKey(t => t.EnrollmentID) 30 | .ForeignKey("dbo.Course", t => t.CourseID, cascadeDelete: true) 31 | .ForeignKey("dbo.Student", t => t.StudentID, cascadeDelete: true) 32 | .Index(t => t.CourseID) 33 | .Index(t => t.StudentID); 34 | 35 | CreateTable( 36 | "dbo.Student", 37 | c => new 38 | { 39 | ID = c.Int(nullable: false, identity: true), 40 | LastName = c.String(), 41 | FirstMidName = c.String(), 42 | EnrollmentDate = c.DateTime(nullable: false), 43 | }) 44 | .PrimaryKey(t => t.ID); 45 | 46 | } 47 | 48 | public override void Down() 49 | { 50 | DropForeignKey("dbo.Enrollment", "StudentID", "dbo.Student"); 51 | DropForeignKey("dbo.Enrollment", "CourseID", "dbo.Course"); 52 | DropIndex("dbo.Enrollment", new[] { "StudentID" }); 53 | DropIndex("dbo.Enrollment", new[] { "CourseID" }); 54 | DropTable("dbo.Student"); 55 | DropTable("dbo.Enrollment"); 56 | DropTable("dbo.Course"); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/ContosoUniversity/Migrations/201411021834484_MaxLengthOnNames.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | namespace ContosoUniversity.Migrations 3 | { 4 | using System.CodeDom.Compiler; 5 | using System.Data.Entity.Migrations; 6 | using System.Data.Entity.Migrations.Infrastructure; 7 | using System.Resources; 8 | 9 | [GeneratedCode("EntityFramework.Migrations", "6.1.1-30610")] 10 | public sealed partial class MaxLengthOnNames : IMigrationMetadata 11 | { 12 | private readonly ResourceManager Resources = new ResourceManager(typeof(MaxLengthOnNames)); 13 | 14 | string IMigrationMetadata.Id 15 | { 16 | get { return "201411021834484_MaxLengthOnNames"; } 17 | } 18 | 19 | string IMigrationMetadata.Source 20 | { 21 | get { return null; } 22 | } 23 | 24 | string IMigrationMetadata.Target 25 | { 26 | get { return Resources.GetString("Target"); } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/ContosoUniversity/Migrations/201411021834484_MaxLengthOnNames.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Migrations 2 | { 3 | using System; 4 | using System.Data.Entity.Migrations; 5 | 6 | public partial class MaxLengthOnNames : DbMigration 7 | { 8 | public override void Up() 9 | { 10 | AlterColumn("dbo.Student", "LastName", c => c.String(maxLength: 50)); 11 | AlterColumn("dbo.Student", "FirstMidName", c => c.String(maxLength: 50)); 12 | } 13 | 14 | public override void Down() 15 | { 16 | AlterColumn("dbo.Student", "FirstMidName", c => c.String()); 17 | AlterColumn("dbo.Student", "LastName", c => c.String()); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/ContosoUniversity/Migrations/201411021841373_ComplexDataModel.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | namespace ContosoUniversity.Migrations 3 | { 4 | using System.CodeDom.Compiler; 5 | using System.Data.Entity.Migrations; 6 | using System.Data.Entity.Migrations.Infrastructure; 7 | using System.Resources; 8 | 9 | [GeneratedCode("EntityFramework.Migrations", "6.1.1-30610")] 10 | public sealed partial class ComplexDataModel : IMigrationMetadata 11 | { 12 | private readonly ResourceManager Resources = new ResourceManager(typeof(ComplexDataModel)); 13 | 14 | string IMigrationMetadata.Id 15 | { 16 | get { return "201411021841373_ComplexDataModel"; } 17 | } 18 | 19 | string IMigrationMetadata.Source 20 | { 21 | get { return null; } 22 | } 23 | 24 | string IMigrationMetadata.Target 25 | { 26 | get { return Resources.GetString("Target"); } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/ContosoUniversity/Migrations/201411021957458_DepartmentSP.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | namespace ContosoUniversity.Migrations 3 | { 4 | using System.CodeDom.Compiler; 5 | using System.Data.Entity.Migrations; 6 | using System.Data.Entity.Migrations.Infrastructure; 7 | using System.Resources; 8 | 9 | [GeneratedCode("EntityFramework.Migrations", "6.1.1-30610")] 10 | public sealed partial class DepartmentSP : IMigrationMetadata 11 | { 12 | private readonly ResourceManager Resources = new ResourceManager(typeof(DepartmentSP)); 13 | 14 | string IMigrationMetadata.Id 15 | { 16 | get { return "201411021957458_DepartmentSP"; } 17 | } 18 | 19 | string IMigrationMetadata.Source 20 | { 21 | get { return null; } 22 | } 23 | 24 | string IMigrationMetadata.Target 25 | { 26 | get { return Resources.GetString("Target"); } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/ContosoUniversity/Migrations/201411021957458_DepartmentSP.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Migrations 2 | { 3 | using System; 4 | using System.Data.Entity.Migrations; 5 | 6 | public partial class DepartmentSP : DbMigration 7 | { 8 | public override void Up() 9 | { 10 | CreateStoredProcedure( 11 | "dbo.Department_Insert", 12 | p => new 13 | { 14 | Name = p.String(maxLength: 50), 15 | Budget = p.Decimal(precision: 19, scale: 4, storeType: "money"), 16 | StartDate = p.DateTime(), 17 | InstructorID = p.Int(), 18 | }, 19 | body: 20 | @"INSERT [dbo].[Department]([Name], [Budget], [StartDate], [InstructorID]) 21 | VALUES (@Name, @Budget, @StartDate, @InstructorID) 22 | 23 | DECLARE @DepartmentID int 24 | SELECT @DepartmentID = [DepartmentID] 25 | FROM [dbo].[Department] 26 | WHERE @@ROWCOUNT > 0 AND [DepartmentID] = scope_identity() 27 | 28 | SELECT t0.[DepartmentID] 29 | FROM [dbo].[Department] AS t0 30 | WHERE @@ROWCOUNT > 0 AND t0.[DepartmentID] = @DepartmentID" 31 | ); 32 | 33 | CreateStoredProcedure( 34 | "dbo.Department_Update", 35 | p => new 36 | { 37 | DepartmentID = p.Int(), 38 | Name = p.String(maxLength: 50), 39 | Budget = p.Decimal(precision: 19, scale: 4, storeType: "money"), 40 | StartDate = p.DateTime(), 41 | InstructorID = p.Int(), 42 | }, 43 | body: 44 | @"UPDATE [dbo].[Department] 45 | SET [Name] = @Name, [Budget] = @Budget, [StartDate] = @StartDate, [InstructorID] = @InstructorID 46 | WHERE ([DepartmentID] = @DepartmentID)" 47 | ); 48 | 49 | CreateStoredProcedure( 50 | "dbo.Department_Delete", 51 | p => new 52 | { 53 | DepartmentID = p.Int(), 54 | }, 55 | body: 56 | @"DELETE [dbo].[Department] 57 | WHERE ([DepartmentID] = @DepartmentID)" 58 | ); 59 | 60 | } 61 | 62 | public override void Down() 63 | { 64 | DropStoredProcedure("dbo.Department_Delete"); 65 | DropStoredProcedure("dbo.Department_Update"); 66 | DropStoredProcedure("dbo.Department_Insert"); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/ContosoUniversity/Migrations/201411022009135_RowVersion.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | namespace ContosoUniversity.Migrations 3 | { 4 | using System.CodeDom.Compiler; 5 | using System.Data.Entity.Migrations; 6 | using System.Data.Entity.Migrations.Infrastructure; 7 | using System.Resources; 8 | 9 | [GeneratedCode("EntityFramework.Migrations", "6.1.1-30610")] 10 | public sealed partial class RowVersion : IMigrationMetadata 11 | { 12 | private readonly ResourceManager Resources = new ResourceManager(typeof(RowVersion)); 13 | 14 | string IMigrationMetadata.Id 15 | { 16 | get { return "201411022009135_RowVersion"; } 17 | } 18 | 19 | string IMigrationMetadata.Source 20 | { 21 | get { return null; } 22 | } 23 | 24 | string IMigrationMetadata.Target 25 | { 26 | get { return Resources.GetString("Target"); } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/ContosoUniversity/Migrations/201411022009135_RowVersion.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Migrations 2 | { 3 | using System; 4 | using System.Data.Entity.Migrations; 5 | 6 | public partial class RowVersion : DbMigration 7 | { 8 | public override void Up() 9 | { 10 | AddColumn("dbo.Department", "RowVersion", c => c.Binary(nullable: false, fixedLength: true, timestamp: true, storeType: "rowversion")); 11 | AlterStoredProcedure( 12 | "dbo.Department_Insert", 13 | p => new 14 | { 15 | Name = p.String(maxLength: 50), 16 | Budget = p.Decimal(precision: 19, scale: 4, storeType: "money"), 17 | StartDate = p.DateTime(), 18 | InstructorID = p.Int(), 19 | }, 20 | body: 21 | @"INSERT [dbo].[Department]([Name], [Budget], [StartDate], [InstructorID]) 22 | VALUES (@Name, @Budget, @StartDate, @InstructorID) 23 | 24 | DECLARE @DepartmentID int 25 | SELECT @DepartmentID = [DepartmentID] 26 | FROM [dbo].[Department] 27 | WHERE @@ROWCOUNT > 0 AND [DepartmentID] = scope_identity() 28 | 29 | SELECT t0.[DepartmentID], t0.[RowVersion] 30 | FROM [dbo].[Department] AS t0 31 | WHERE @@ROWCOUNT > 0 AND t0.[DepartmentID] = @DepartmentID" 32 | ); 33 | 34 | AlterStoredProcedure( 35 | "dbo.Department_Update", 36 | p => new 37 | { 38 | DepartmentID = p.Int(), 39 | Name = p.String(maxLength: 50), 40 | Budget = p.Decimal(precision: 19, scale: 4, storeType: "money"), 41 | StartDate = p.DateTime(), 42 | InstructorID = p.Int(), 43 | RowVersion_Original = p.Binary(maxLength: 8, fixedLength: true, storeType: "rowversion"), 44 | }, 45 | body: 46 | @"UPDATE [dbo].[Department] 47 | SET [Name] = @Name, [Budget] = @Budget, [StartDate] = @StartDate, [InstructorID] = @InstructorID 48 | WHERE (([DepartmentID] = @DepartmentID) AND (([RowVersion] = @RowVersion_Original) OR ([RowVersion] IS NULL AND @RowVersion_Original IS NULL))) 49 | 50 | SELECT t0.[RowVersion] 51 | FROM [dbo].[Department] AS t0 52 | WHERE @@ROWCOUNT > 0 AND t0.[DepartmentID] = @DepartmentID" 53 | ); 54 | 55 | AlterStoredProcedure( 56 | "dbo.Department_Delete", 57 | p => new 58 | { 59 | DepartmentID = p.Int(), 60 | RowVersion_Original = p.Binary(maxLength: 8, fixedLength: true, storeType: "rowversion"), 61 | }, 62 | body: 63 | @"DELETE [dbo].[Department] 64 | WHERE (([DepartmentID] = @DepartmentID) AND (([RowVersion] = @RowVersion_Original) OR ([RowVersion] IS NULL AND @RowVersion_Original IS NULL)))" 65 | ); 66 | 67 | } 68 | 69 | public override void Down() 70 | { 71 | DropColumn("dbo.Department", "RowVersion"); 72 | throw new NotSupportedException("Scaffolding create or alter procedure operations is not supported in down methods."); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/ContosoUniversity/Migrations/201411022351064_Inheritance.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | namespace ContosoUniversity.Migrations 3 | { 4 | using System.CodeDom.Compiler; 5 | using System.Data.Entity.Migrations; 6 | using System.Data.Entity.Migrations.Infrastructure; 7 | using System.Resources; 8 | 9 | [GeneratedCode("EntityFramework.Migrations", "6.1.1-30610")] 10 | public sealed partial class Inheritance : IMigrationMetadata 11 | { 12 | private readonly ResourceManager Resources = new ResourceManager(typeof(Inheritance)); 13 | 14 | string IMigrationMetadata.Id 15 | { 16 | get { return "201411022351064_Inheritance"; } 17 | } 18 | 19 | string IMigrationMetadata.Source 20 | { 21 | get { return null; } 22 | } 23 | 24 | string IMigrationMetadata.Target 25 | { 26 | get { return Resources.GetString("Target"); } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/ContosoUniversity/Migrations/201411022351064_Inheritance.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Migrations 2 | { 3 | using System; 4 | using System.Data.Entity.Migrations; 5 | using System.Diagnostics; 6 | 7 | public partial class Inheritance : DbMigration 8 | { 9 | public override void Up() 10 | { 11 | // Drop foreign keys and indexes that point to tables we're going to drop. 12 | Debug.Print("Start"); 13 | DropForeignKey("dbo.Enrollment", "StudentID", "dbo.Student"); 14 | DropIndex("dbo.Enrollment", new[] { "StudentID" }); 15 | 16 | RenameTable(name: "dbo.Instructor", newName: "Person"); 17 | AddColumn("dbo.Person", "EnrollmentDate", c => c.DateTime()); 18 | AddColumn("dbo.Person", "Discriminator", c => c.String(nullable: false, maxLength: 128, defaultValue: "Instructor")); 19 | AlterColumn("dbo.Person", "HireDate", c => c.DateTime()); 20 | AddColumn("dbo.Person", "OldId", c => c.Int(nullable: true)); 21 | 22 | // Copy existing Student data into new Person table. 23 | Sql("INSERT INTO dbo.Person (LastName, FirstName, HireDate, EnrollmentDate, Discriminator, OldId) SELECT LastName, FirstName, null AS HireDate, EnrollmentDate, 'Student' AS Discriminator, ID AS OldId FROM dbo.Student"); 24 | 25 | // Fix up existing relationships to match new PK's. 26 | Sql("UPDATE dbo.Enrollment SET StudentId = (SELECT ID FROM dbo.Person WHERE OldId = Enrollment.StudentId AND Discriminator = 'Student')"); 27 | 28 | // Remove temporary key 29 | DropColumn("dbo.Person", "OldId"); 30 | 31 | DropTable("dbo.Student"); 32 | 33 | // Re-create foreign keys and indexes pointing to new table. 34 | AddForeignKey("dbo.Enrollment", "StudentID", "dbo.Person", "ID", cascadeDelete: true); 35 | CreateIndex("dbo.Enrollment", "StudentID"); 36 | Debug.Print("end"); 37 | } 38 | 39 | public override void Down() 40 | { 41 | CreateTable( 42 | "dbo.Student", 43 | c => new 44 | { 45 | ID = c.Int(nullable: false, identity: true), 46 | LastName = c.String(nullable: false, maxLength: 50), 47 | FirstName = c.String(nullable: false, maxLength: 50), 48 | EnrollmentDate = c.DateTime(nullable: false), 49 | }) 50 | .PrimaryKey(t => t.ID); 51 | 52 | AlterColumn("dbo.Person", "HireDate", c => c.DateTime(nullable: false)); 53 | DropColumn("dbo.Person", "Discriminator"); 54 | DropColumn("dbo.Person", "EnrollmentDate"); 55 | RenameTable(name: "dbo.Person", newName: "Instructor"); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/ContosoUniversity/Models/Course.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | 5 | namespace ContosoUniversity.Models 6 | { 7 | public class Course 8 | { 9 | [DatabaseGenerated(DatabaseGeneratedOption.None)] 10 | [Display(Name = "Number")] 11 | public int CourseID { get; set; } 12 | 13 | [StringLength(50, MinimumLength = 3)] 14 | public string Title { get; set; } 15 | 16 | [Range(0, 5)] 17 | public int Credits { get; set; } 18 | 19 | public int DepartmentID { get; set; } 20 | 21 | public virtual Department Department { get; set; } 22 | public virtual ICollection Enrollments { get; set; } 23 | public virtual ICollection CourseInstructors { get; set; } 24 | } 25 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Models/Department.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.ComponentModel.DataAnnotations.Schema; 5 | 6 | namespace ContosoUniversity.Models 7 | { 8 | public class Department : IEntity 9 | { 10 | public int DepartmentID { get; set; } 11 | 12 | [StringLength(50, MinimumLength = 3)] 13 | public string Name { get; set; } 14 | 15 | [DataType(DataType.Currency)] 16 | [Column(TypeName = "money")] 17 | public decimal Budget { get; set; } 18 | 19 | [DataType(DataType.Date)] 20 | [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)] 21 | [Display(Name = "Start Date")] 22 | public DateTime StartDate { get; set; } 23 | 24 | public int? InstructorID { get; set; } 25 | 26 | [Timestamp] 27 | public byte[] RowVersion { get; set; } 28 | 29 | public virtual Instructor Administrator { get; set; } 30 | public virtual ICollection Courses { get; set; } 31 | } 32 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Models/Enrollment.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace ContosoUniversity.Models 4 | { 5 | public enum Grade 6 | { 7 | A, B, C, D, F 8 | } 9 | 10 | public class Enrollment 11 | { 12 | public int EnrollmentID { get; set; } 13 | public int CourseID { get; set; } 14 | public int StudentID { get; set; } 15 | [DisplayFormat(NullDisplayText = "No grade")] 16 | public Grade? Grade { get; set; } 17 | 18 | public virtual Course Course { get; set; } 19 | public virtual Student Student { get; set; } 20 | } 21 | } 22 | 23 | -------------------------------------------------------------------------------- /src/ContosoUniversity/Models/IEntity.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.Models 2 | { 3 | public interface IEntity 4 | { 5 | 6 | } 7 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Models/Instructor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.ComponentModel.DataAnnotations.Schema; 5 | 6 | namespace ContosoUniversity.Models 7 | { 8 | public class Instructor : Person 9 | { 10 | [DataType(DataType.Date)] 11 | [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)] 12 | [Display(Name = "Hire Date")] 13 | public DateTime HireDate { get; set; } 14 | 15 | public virtual ICollection CourseInstructors { get; set; } = new HashSet(); 16 | public virtual OfficeAssignment OfficeAssignment { get; set; } 17 | } 18 | 19 | public class CourseInstructor 20 | { 21 | public virtual int CourseID { get; set; } 22 | public virtual int InstructorID { get; set; } 23 | public virtual Course Course { get; set; } 24 | public virtual Instructor Instructor { get; set; } 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Models/OfficeAssignment.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using System.ComponentModel.DataAnnotations.Schema; 3 | 4 | namespace ContosoUniversity.Models 5 | { 6 | public class OfficeAssignment 7 | { 8 | [Key] 9 | [ForeignKey("Instructor")] 10 | public int InstructorID { get; set; } 11 | [StringLength(50)] 12 | [Display(Name = "Office Location")] 13 | public string Location { get; set; } 14 | 15 | public virtual Instructor Instructor { get; set; } 16 | } 17 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Models/Person.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using System.ComponentModel.DataAnnotations.Schema; 3 | 4 | namespace ContosoUniversity.Models 5 | { 6 | using DelegateDecompiler; 7 | 8 | public abstract class Person 9 | { 10 | public int ID { get; set; } 11 | 12 | [Required] 13 | [StringLength(50)] 14 | [Display(Name = "Last Name")] 15 | public string LastName { get; set; } 16 | [Required] 17 | [StringLength(50, ErrorMessage = "First name cannot be longer than 50 characters.")] 18 | [Column("FirstName")] 19 | [Display(Name = "First Name")] 20 | public string FirstMidName { get; set; } 21 | 22 | [Display(Name = "Full Name")] 23 | [Computed] 24 | public string FullName 25 | { 26 | get 27 | { 28 | return LastName + ", " + FirstMidName; 29 | } 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/Models/Student.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.ComponentModel.DataAnnotations.Schema; 5 | 6 | namespace ContosoUniversity.Models 7 | { 8 | public class Student : Person 9 | { 10 | [DataType(DataType.Date)] 11 | [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)] 12 | [Display(Name = "Enrollment Date")] 13 | public DateTime EnrollmentDate { get; set; } 14 | 15 | public virtual ICollection Enrollments { get; set; } 16 | } 17 | } -------------------------------------------------------------------------------- /src/ContosoUniversity/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: AssemblyTitle("ContosoUniversity")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Microsoft Corp.")] 12 | [assembly: AssemblyProduct("ContosoUniversity")] 13 | [assembly: AssemblyCopyright("Copyright © Microsoft Corp. 2014")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("0d6e9993-c2b5-420d-a732-c42696a44472")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /src/ContosoUniversity/Scripts/_references.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jbogard/ContosoUniversity/5c4e4ec11395172f82606f95ec520f0a93508541/src/ContosoUniversity/Scripts/_references.js -------------------------------------------------------------------------------- /src/ContosoUniversity/Web.Debug.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/ContosoUniversity/Web.Release.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/ContosoUniversity/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jbogard/ContosoUniversity/5c4e4ec11395172f82606f95ec520f0a93508541/src/ContosoUniversity/favicon.ico -------------------------------------------------------------------------------- /src/ContosoUniversity/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jbogard/ContosoUniversity/5c4e4ec11395172f82606f95ec520f0a93508541/src/ContosoUniversity/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /src/ContosoUniversity/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jbogard/ContosoUniversity/5c4e4ec11395172f82606f95ec520f0a93508541/src/ContosoUniversity/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /src/ContosoUniversity/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jbogard/ContosoUniversity/5c4e4ec11395172f82606f95ec520f0a93508541/src/ContosoUniversity/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /src/ContosoUniversity/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jbogard/ContosoUniversity/5c4e4ec11395172f82606f95ec520f0a93508541/src/ContosoUniversity/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /src/DBDeployment/DBDeployment.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {92616CCC-80EB-4C45-83DC-12FEA110EBA6} 8 | Library 9 | Properties 10 | DBDeployment 11 | DBDeployment 12 | v4.8 13 | 512 14 | 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | DatabaseMigration\%(RecursiveDir)%(FileName)%(Extension) 48 | Always 49 | 50 | 51 | DatabaseMigration\up\000002.Initial_Data.sql 52 | 53 | 54 | 55 | 62 | -------------------------------------------------------------------------------- /src/DBDeployment/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: AssemblyTitle("DBDeployment")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("DBDeployment")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("351ef46f-fd70-4121-93fe-d433a6e1c41c")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/DatabaseMigration/up/000001.Initial_Schema.sql: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jbogard/ContosoUniversity/5c4e4ec11395172f82606f95ec520f0a93508541/src/DatabaseMigration/up/000001.Initial_Schema.sql -------------------------------------------------------------------------------- /src/IntegrationTests/AutoFixtureCustomization.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.IntegrationTests 2 | { 3 | using Ploeh.AutoFixture; 4 | 5 | public abstract class AutoFixtureCustomization : ICustomization 6 | { 7 | public void Customize(IFixture fixture) 8 | { 9 | fixture.Customizations.Add(new IdOmitterBuilder()); 10 | fixture.Customizations.Add(new OmitListBuilder()); 11 | 12 | CustomizeFixture(fixture); 13 | 14 | fixture.Behaviors.Remove(new ThrowingRecursionBehavior()); 15 | fixture.Behaviors.Add(new OmitOnRecursionBehavior()); 16 | } 17 | 18 | protected abstract void CustomizeFixture(IFixture fixture); 19 | } 20 | } -------------------------------------------------------------------------------- /src/IntegrationTests/AutoFixtureFactory.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.IntegrationTests 2 | { 3 | using System; 4 | using System.Collections.Concurrent; 5 | using Ploeh.AutoFixture; 6 | 7 | public class AutoFixtureFactory 8 | { 9 | private static readonly Lazy Factory = new Lazy(() => new AutoFixtureFactory()); 10 | 11 | private readonly ConcurrentDictionary autoFixtureCache; 12 | 13 | private AutoFixtureFactory() 14 | { 15 | autoFixtureCache = new ConcurrentDictionary(); 16 | } 17 | 18 | public static AutoFixtureFactory Instance 19 | { 20 | get { return Factory.Value; } 21 | } 22 | 23 | public IFixture BuildWith(ICustomization autoFixtureCustomization) 24 | { 25 | return autoFixtureCache.GetOrAdd(autoFixtureCustomization.GetType(), type => new Fixture().Customize(autoFixtureCustomization)); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /src/IntegrationTests/ContainerBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using ContosoUniversity.DependencyResolution; 3 | using Ploeh.AutoFixture.Kernel; 4 | 5 | namespace ContosoUniversity.IntegrationTests 6 | { 7 | public class ContainerBuilder : ISpecimenBuilder 8 | { 9 | private readonly StructureMapDependencyScope scope; 10 | 11 | public ContainerBuilder(StructureMapDependencyScope scope) 12 | { 13 | this.scope = scope; 14 | } 15 | 16 | public object Create(object request, ISpecimenContext context) 17 | { 18 | var type = request as Type; 19 | 20 | if (type == null || type.IsPrimitive) 21 | { 22 | return new NoSpecimen(request); 23 | } 24 | 25 | var service = (scope.CurrentNestedContainer ?? scope.Container).TryGetInstance(type); 26 | 27 | return service ?? new NoSpecimen(request); 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /src/IntegrationTests/DeleteData.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.IntegrationTests 2 | { 3 | using System; 4 | using System.Data.SqlClient; 5 | using Fixie; 6 | using Respawn; 7 | 8 | public class DeleteData : FixtureBehavior, ClassBehavior 9 | { 10 | private static Checkpoint checkpoint = new Checkpoint 11 | { 12 | TablesToIgnore = new[] 13 | { 14 | "sysdiagrams", 15 | }, 16 | SchemasToExclude = new[] 17 | { 18 | "RoundhousE" 19 | } 20 | }; 21 | 22 | public void Execute(Fixture context, Action next) 23 | { 24 | DeleteAllData(); 25 | next(); 26 | } 27 | 28 | public void Execute(Class context, Action next) 29 | { 30 | DeleteAllData(); 31 | next(); 32 | } 33 | 34 | private static void DeleteAllData() 35 | { 36 | var localDbInstance = LocalDbFactory.Instance; 37 | var builder = localDbInstance.CreateConnectionStringBuilder(); 38 | builder.InitialCatalog = localDbInstance.Name; 39 | 40 | checkpoint.Reset(builder.ConnectionString); 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /src/IntegrationTests/Features/Course/CreateTests.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.IntegrationTests.Features.Course 2 | { 3 | using System.Linq; 4 | using ContosoUniversity.Features.Course; 5 | using Models; 6 | using Shouldly; 7 | 8 | public class CreateTests 9 | { 10 | public void Should_create(TestContextFixture fixture, Department dept) 11 | { 12 | fixture.SaveAll(dept); 13 | 14 | var command = new Create.Command 15 | { 16 | Title = "Blarg", 17 | Credits = 10, 18 | Department = dept 19 | }; 20 | 21 | fixture.Send(command); 22 | 23 | Course course = null; 24 | 25 | fixture.DoClean(ctx => course = ctx.Set().FirstOrDefault(c => c.Title == command.Title)); 26 | 27 | course.Title.ShouldBe(command.Title); 28 | course.Credits.ShouldBe(command.Credits); 29 | course.DepartmentID.ShouldBe(dept.DepartmentID); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /src/IntegrationTests/Features/FooTests.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.IntegrationTests.Features 2 | { 3 | public class FooTests 4 | { 5 | public void Blarg() 6 | { 7 | 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /src/IntegrationTests/FixieConvention.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.IntegrationTests 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Reflection; 6 | using Fixie; 7 | using Ploeh.AutoFixture; 8 | using Ploeh.AutoFixture.Kernel; 9 | 10 | public abstract class FixieConvention : Convention 11 | { 12 | public FixieConvention() 13 | { 14 | Classes 15 | .NameEndsWith("Tests"); 16 | 17 | ClassExecution 18 | .UsingFactory(CustomFactory); 19 | 20 | Parameters 21 | .Add(GetParameters); 22 | } 23 | 24 | protected abstract ICustomization AutoFixtureCustomization { get; } 25 | 26 | protected IFixture AutoFixture 27 | { 28 | get { return AutoFixtureFactory.Instance.BuildWith(AutoFixtureCustomization); } 29 | } 30 | 31 | private IEnumerable GetParameters(MethodInfo method) 32 | { 33 | return method.ResolveParametersWith(AutoFixture); 34 | } 35 | 36 | private object CustomFactory(Type t) 37 | { 38 | return new SpecimenContext(AutoFixture).Resolve(t); 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /src/IntegrationTests/FixieExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.IntegrationTests 2 | { 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Reflection; 6 | using Fixie.Conventions; 7 | using Ploeh.AutoFixture; 8 | using Ploeh.AutoFixture.Kernel; 9 | 10 | public static class FixieExtensions 11 | { 12 | public static IEnumerable ResolveParametersWith(this MethodInfo methodInfo, IFixture fixture) 13 | { 14 | return Enumerable.Repeat( 15 | methodInfo 16 | .GetParameters() 17 | .Select(parameterInfo => new SpecimenContext(fixture).Resolve(parameterInfo)) 18 | .ToArray(), 19 | 1); 20 | } 21 | 22 | public static ClassExpression IsInNamespaceOf(this ClassExpression expr) 23 | { 24 | return expr.InTheSameNamespaceAs(typeof(T)); 25 | } 26 | 27 | public static ClassExpression AreInIntegrationTestNamespace(this ClassExpression expr) 28 | { 29 | return expr.Where(type => type.Namespace.Contains("IntegrationTests")); 30 | } 31 | 32 | public static ClassExpression ConstructorHasArguments(this ClassExpression filter) 33 | { 34 | return filter.Where(t => t.GetConstructors(BindingFlags.Public | BindingFlags.Instance) 35 | .Any(x => x.GetParameters().Any())); 36 | } 37 | 38 | public static ClassExpression ConstructorDoesntHaveArguments(this ClassExpression filter) 39 | { 40 | return filter.Where(t => t.GetConstructors(BindingFlags.Public | BindingFlags.Instance) 41 | .All(x => x.GetParameters().Length == 0)); 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /src/IntegrationTests/FixturePerClassConvention.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.IntegrationTests 2 | { 3 | public class FixturePerClassConvention : IntegrationTestConvention 4 | { 5 | public FixturePerClassConvention() 6 | { 7 | Classes 8 | .ConstructorHasArguments(); 9 | 10 | ClassExecution 11 | .CreateInstancePerClass() 12 | .Wrap(); 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /src/IntegrationTests/FixturePerMethodConvention.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.IntegrationTests 2 | { 3 | public class FixturePerMethodConvention : IntegrationTestConvention 4 | { 5 | public FixturePerMethodConvention() 6 | { 7 | Classes 8 | .ConstructorDoesntHaveArguments(); 9 | 10 | ClassExecution 11 | .CreateInstancePerCase(); 12 | 13 | FixtureExecution 14 | .Wrap(); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /src/IntegrationTests/IdOmitterBuilder.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.IntegrationTests 2 | { 3 | using System; 4 | using System.Reflection; 5 | using Ploeh.AutoFixture.Kernel; 6 | 7 | public class IdOmitterBuilder : ISpecimenBuilder 8 | { 9 | public object Create(object request, ISpecimenContext context) 10 | { 11 | var property = request as PropertyInfo; 12 | 13 | if (property == null) 14 | { 15 | return new NoSpecimen(request); 16 | } 17 | 18 | if (IsId(property)) 19 | { 20 | return Activator.CreateInstance(property.PropertyType); 21 | } 22 | 23 | return new NoSpecimen(request); 24 | } 25 | 26 | private static bool IsId(PropertyInfo property) 27 | { 28 | return property.Name.EndsWith("Id") && (property.PropertyType == typeof(int) || property.PropertyType == typeof(int?)); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /src/IntegrationTests/IntegrationTestContainerFactory.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.IntegrationTests 2 | { 3 | using System; 4 | using DAL; 5 | using DependencyResolution; 6 | using StructureMap; 7 | 8 | public class IntegrationTestContainerFactory 9 | { 10 | private static readonly Lazy LazyInnerFactory = new Lazy(() => new InnerFactory()); 11 | 12 | public static IContainer Container 13 | { 14 | get { return LazyInnerFactory.Value.Container; } 15 | } 16 | 17 | private class InnerFactory 18 | { 19 | public InnerFactory() 20 | { 21 | var container = IoC.Initialize(); 22 | var connString = LocalDbFactory.Instance.CreateConnectionStringBuilder(); 23 | connString.InitialCatalog = "ContosoUniversity"; 24 | container.Configure(cfg => cfg.For().Use(() => new SchoolContext(connString.ToString())).Transient()); 25 | Container = container; 26 | } 27 | 28 | public IContainer Container { get; private set; } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /src/IntegrationTests/IntegrationTestConvention.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.IntegrationTests 2 | { 3 | using Ploeh.AutoFixture; 4 | 5 | public abstract class IntegrationTestConvention : FixieConvention 6 | { 7 | public IntegrationTestConvention() 8 | { 9 | Classes 10 | .AreInIntegrationTestNamespace(); 11 | } 12 | 13 | protected override ICustomization AutoFixtureCustomization 14 | { 15 | get { return new IntegrationTestsFixtureCustomization(); } 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /src/IntegrationTests/IntegrationTestsFixtureCustomization.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.IntegrationTests 2 | { 3 | using DependencyResolution; 4 | using Infrastructure.Mapping; 5 | using Ploeh.AutoFixture; 6 | 7 | public class IntegrationTestsFixtureCustomization : AutoFixtureCustomization 8 | { 9 | protected override void CustomizeFixture(IFixture fixture) 10 | { 11 | var scope = new StructureMapDependencyScope(IntegrationTestContainerFactory.Container); 12 | var contextFixture = new TestContextFixture(scope); 13 | contextFixture.SetUp(); 14 | 15 | //fixture.Customizations.Add(scope.GetInstance()); 16 | fixture.Register(() => contextFixture); 17 | fixture.Customizations.Add(new ContainerBuilder(scope)); // always last 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /src/IntegrationTests/LocalDbFactory.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.IntegrationTests 2 | { 3 | using System; 4 | using System.Data.SqlClient; 5 | using System.Data.SqlLocalDb; 6 | using System.IO; 7 | using roundhouse; 8 | using Logger = roundhouse.infrastructure.logging.Logger; 9 | 10 | public static class LocalDbFactory 11 | { 12 | private static readonly Lazy _instance = new Lazy(ValueFactory); 13 | 14 | public static TemporarySqlLocalDbInstance Instance 15 | { 16 | get { return _instance.Value; } 17 | } 18 | 19 | private static TemporarySqlLocalDbInstance ValueFactory() 20 | { 21 | var instance = TemporarySqlLocalDbInstance.Create(true); 22 | var builder = instance.CreateConnectionStringBuilder(); 23 | 24 | var databaseName = instance.Name; 25 | 26 | using (var conn = instance.CreateConnection()) 27 | { 28 | conn.Open(); 29 | var cmd = conn.CreateCommand(); 30 | 31 | var fileName = Path.Combine(Environment.CurrentDirectory, databaseName + ".mdf"); 32 | cmd.CommandText = string.Format("CREATE DATABASE [{0}] on (name='{0}', filename='{1}')", databaseName, fileName); 33 | cmd.ExecuteNonQuery(); 34 | } 35 | 36 | Console.WriteLine(instance.Name); 37 | 38 | builder.InitialCatalog = databaseName; 39 | 40 | var connectionString = builder.ConnectionString; 41 | 42 | var migrate = new Migrate().Set(c => 43 | { 44 | c.ConnectionString = connectionString; 45 | c.DatabaseName = databaseName; 46 | c.Silent = true; 47 | c.WithTransaction = true; 48 | c.SqlFilesDirectory = Path.Combine(Environment.CurrentDirectory, "DatabaseMigration"); 49 | }); 50 | migrate.Run(); 51 | 52 | return instance; 53 | } 54 | 55 | private class ConsoleLogger : Logger 56 | { 57 | public void log_a_debug_event_containing(string message, params object[] args) 58 | { 59 | Console.WriteLine(message, args); 60 | } 61 | 62 | public void log_an_info_event_containing(string message, params object[] args) 63 | { 64 | Console.WriteLine(message, args); 65 | } 66 | 67 | public void log_a_warning_event_containing(string message, params object[] args) 68 | { 69 | Console.WriteLine(message, args); 70 | } 71 | 72 | public void log_an_error_event_containing(string message, params object[] args) 73 | { 74 | Console.WriteLine(message, args); 75 | } 76 | 77 | public void log_a_fatal_event_containing(string message, params object[] args) 78 | { 79 | Console.WriteLine(message, args); 80 | } 81 | 82 | public object underlying_type { get { return typeof (ConsoleLogger); } } 83 | } 84 | } 85 | } -------------------------------------------------------------------------------- /src/IntegrationTests/OmitListBuilder.cs: -------------------------------------------------------------------------------- 1 | namespace ContosoUniversity.IntegrationTests 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Reflection; 7 | using Ploeh.AutoFixture.Kernel; 8 | 9 | public class OmitListBuilder : ISpecimenBuilder 10 | { 11 | public object Create(object request, ISpecimenContext context) 12 | { 13 | var pi = request as PropertyInfo; 14 | 15 | if (pi != null) 16 | { 17 | var isIEnumerable = pi.PropertyType 18 | .GetInterfaces() 19 | .Any(t => t.IsGenericType 20 | && t.GetGenericTypeDefinition() == typeof(IList<>)); 21 | 22 | if (isIEnumerable) 23 | { 24 | if (pi.PropertyType.IsArray) 25 | { 26 | return Array.CreateInstance(pi.PropertyType.GetElementType(), 0); 27 | } 28 | 29 | var genericArguments = pi.PropertyType.GetGenericArguments(); 30 | var concreteType = typeof(List<>).MakeGenericType(genericArguments); 31 | var instance = Activator.CreateInstance(concreteType); 32 | return instance; 33 | } 34 | } 35 | 36 | return new NoSpecimen(request); 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /src/IntegrationTests/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: AssemblyTitle("IntegrationTests")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("IntegrationTests")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("1036d859-a078-4751-bcf9-5cc73cf3c67c")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/IntegrationTests/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | 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 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /src/IntegrationTests/log4net.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jbogard/ContosoUniversity/5c4e4ec11395172f82606f95ec520f0a93508541/src/IntegrationTests/log4net.dll -------------------------------------------------------------------------------- /src/IntegrationTests/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /tools/fixie/Fixie.Console.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jbogard/ContosoUniversity/5c4e4ec11395172f82606f95ec520f0a93508541/tools/fixie/Fixie.Console.exe -------------------------------------------------------------------------------- /tools/fixie/Fixie.Console.exe.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /tools/fixie/Fixie.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jbogard/ContosoUniversity/5c4e4ec11395172f82606f95ec520f0a93508541/tools/fixie/Fixie.dll -------------------------------------------------------------------------------- /tools/nuget/nuget.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jbogard/ContosoUniversity/5c4e4ec11395172f82606f95ec520f0a93508541/tools/nuget/nuget.exe -------------------------------------------------------------------------------- /tools/roundhouse/output/migrations/ContosoUniversity/SQL2014/20150302_142703_4853/itemsRan/up/000001.Initial_Schema.sql: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jbogard/ContosoUniversity/5c4e4ec11395172f82606f95ec520f0a93508541/tools/roundhouse/output/migrations/ContosoUniversity/SQL2014/20150302_142703_4853/itemsRan/up/000001.Initial_Schema.sql -------------------------------------------------------------------------------- /tools/roundhouse/output/migrations/ContosoUniversity/SQL2014/20150302_142707_3495/itemsRan/up/000001.Initial_Schema.sql: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jbogard/ContosoUniversity/5c4e4ec11395172f82606f95ec520f0a93508541/tools/roundhouse/output/migrations/ContosoUniversity/SQL2014/20150302_142707_3495/itemsRan/up/000001.Initial_Schema.sql -------------------------------------------------------------------------------- /tools/roundhouse/output/migrations/ContosoUniversity/mssqllocaldb/20230616_203715_3800/itemsRan/up/000001.Initial_Schema.sql: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jbogard/ContosoUniversity/5c4e4ec11395172f82606f95ec520f0a93508541/tools/roundhouse/output/migrations/ContosoUniversity/mssqllocaldb/20230616_203715_3800/itemsRan/up/000001.Initial_Schema.sql -------------------------------------------------------------------------------- /tools/roundhouse/output/migrations/ContosoUniversity/mssqllocaldb/20230616_203725_6147/itemsRan/up/000001.Initial_Schema.sql: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jbogard/ContosoUniversity/5c4e4ec11395172f82606f95ec520f0a93508541/tools/roundhouse/output/migrations/ContosoUniversity/mssqllocaldb/20230616_203725_6147/itemsRan/up/000001.Initial_Schema.sql -------------------------------------------------------------------------------- /tools/roundhouse/rh.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jbogard/ContosoUniversity/5c4e4ec11395172f82606f95ec520f0a93508541/tools/roundhouse/rh.exe --------------------------------------------------------------------------------