From 4a88cff1858389960a78ae82c13165f95fad1cd4 Mon Sep 17 00:00:00 2001 From: Ajay Bhargav Baaskaran Date: Fri, 27 May 2016 12:37:17 -0700 Subject: [PATCH] [Fixes #3255] Added a web template to dotnet new --- .gitignore | 3 + .../dotnet-cli-build/PrepareTargets.cs | 38 +- .../update-dependencies/UpdateFilesTargets.cs | 3 +- src/dotnet/README.md | 2 +- .../commands/dotnet-new/CSharp_Web/.bowerrc | 3 + .../commands/dotnet-new/CSharp_Web/.gitignore | 234 +++++++++ .../Controllers/AccountController.cs | 468 ++++++++++++++++++ .../CSharp_Web/Controllers/HomeController.cs | 35 ++ .../Controllers/ManageController.cs | 347 +++++++++++++ .../CSharp_Web/Data/ApplicationDbContext.cs | 26 + ...000000000_CreateIdentitySchema.Designer.cs | 212 ++++++++ .../00000000000000_CreateIdentitySchema.cs | 215 ++++++++ .../ApplicationDbContextModelSnapshot.cs | 211 ++++++++ .../ExternalLoginConfirmationViewModel.cs | 15 + .../ForgotPasswordViewModel.cs | 15 + .../AccountViewModels/LoginViewModel.cs | 22 + .../AccountViewModels/RegisterViewModel.cs | 27 + .../ResetPasswordViewModel.cs | 27 + .../AccountViewModels/SendCodeViewModel.cs | 19 + .../AccountViewModels/VerifyCodeViewModel.cs | 25 + .../CSharp_Web/Models/ApplicationUser.cs | 13 + .../AddPhoneNumberViewModel.cs | 16 + .../ChangePasswordViewModel.cs | 27 + .../ConfigureTwoFactorViewModel.cs | 15 + .../ManageViewModels/FactorViewModel.cs | 12 + .../Models/ManageViewModels/IndexViewModel.cs | 21 + .../ManageViewModels/ManageLoginsViewModel.cs | 16 + .../ManageViewModels/RemoveLoginViewModel.cs | 14 + .../ManageViewModels/SetPasswordViewModel.cs | 22 + .../VerifyPhoneNumberViewModel.cs | 19 + .../commands/dotnet-new/CSharp_Web/Program.cs | 24 + .../commands/dotnet-new/CSharp_Web/README.md | 39 ++ .../CSharp_Web/Services/IEmailSender.cs | 12 + .../CSharp_Web/Services/ISmsSender.cs | 12 + .../CSharp_Web/Services/MessageServices.cs | 25 + .../commands/dotnet-new/CSharp_Web/Startup.cs | 88 ++++ .../Views/Account/ConfirmEmail.cshtml | 10 + .../Account/ExternalLoginConfirmation.cshtml | 35 ++ .../Views/Account/ExternalLoginFailure.cshtml | 8 + .../Views/Account/ForgotPassword.cshtml | 31 ++ .../Account/ForgotPasswordConfirmation.cshtml | 8 + .../CSharp_Web/Views/Account/Lockout.cshtml | 8 + .../CSharp_Web/Views/Account/Login.cshtml | 92 ++++ .../CSharp_Web/Views/Account/Register.cshtml | 42 ++ .../Views/Account/ResetPassword.cshtml | 43 ++ .../Account/ResetPasswordConfirmation.cshtml | 8 + .../CSharp_Web/Views/Account/SendCode.cshtml | 21 + .../Views/Account/VerifyCode.cshtml | 38 ++ .../CSharp_Web/Views/Home/About.cshtml | 7 + .../CSharp_Web/Views/Home/Contact.cshtml | 17 + .../CSharp_Web/Views/Home/Index.cshtml | 109 ++++ .../Views/Manage/AddPhoneNumber.cshtml | 27 + .../Views/Manage/ChangePassword.cshtml | 42 ++ .../CSharp_Web/Views/Manage/Index.cshtml | 71 +++ .../Views/Manage/ManageLogins.cshtml | 54 ++ .../Views/Manage/SetPassword.cshtml | 38 ++ .../Views/Manage/VerifyPhoneNumber.cshtml | 30 ++ .../CSharp_Web/Views/Shared/Error.cshtml | 14 + .../CSharp_Web/Views/Shared/_Layout.cshtml | 68 +++ .../Views/Shared/_LoginPartial.cshtml | 26 + .../Shared/_ValidationScriptsPartial.cshtml | 14 + .../CSharp_Web/Views/_ViewImports.cshtml | 6 + .../CSharp_Web/Views/_ViewStart.cshtml | 3 + .../dotnet-new/CSharp_Web/appsettings.json | 13 + .../commands/dotnet-new/CSharp_Web/bower.json | 10 + .../dotnet-new/CSharp_Web/gulpfile.js | 45 ++ .../dotnet-new/CSharp_Web/package.json | 12 + .../CSharp_Web/project.json.template | 110 ++++ .../commands/dotnet-new/CSharp_Web/web.config | 14 + .../CSharp_Web/wwwroot/css/site.css | 44 ++ .../CSharp_Web/wwwroot/css/site.min.css | 1 + .../dotnet-new/CSharp_Web/wwwroot/favicon.ico | Bin 0 -> 32038 bytes .../CSharp_Web/wwwroot/images/banner1.svg | 1 + .../CSharp_Web/wwwroot/images/banner2.svg | 1 + .../CSharp_Web/wwwroot/images/banner3.svg | 1 + .../CSharp_Web/wwwroot/images/banner4.svg | 1 + .../dotnet-new/CSharp_Web/wwwroot/js/site.js | 1 + .../CSharp_Web/wwwroot/js/site.min.js | 0 src/dotnet/commands/dotnet-new/Program.cs | 40 +- src/dotnet/commands/dotnet-new/README.md | 2 +- src/dotnet/project.json | 12 +- 81 files changed, 3459 insertions(+), 41 deletions(-) create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/.bowerrc create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/.gitignore create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Controllers/AccountController.cs create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Controllers/HomeController.cs create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Controllers/ManageController.cs create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Data/ApplicationDbContext.cs create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Data/Migrations/00000000000000_CreateIdentitySchema.Designer.cs create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Data/Migrations/00000000000000_CreateIdentitySchema.cs create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Data/Migrations/ApplicationDbContextModelSnapshot.cs create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Models/AccountViewModels/ExternalLoginConfirmationViewModel.cs create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Models/AccountViewModels/ForgotPasswordViewModel.cs create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Models/AccountViewModels/LoginViewModel.cs create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Models/AccountViewModels/RegisterViewModel.cs create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Models/AccountViewModels/ResetPasswordViewModel.cs create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Models/AccountViewModels/SendCodeViewModel.cs create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Models/AccountViewModels/VerifyCodeViewModel.cs create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Models/ApplicationUser.cs create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Models/ManageViewModels/AddPhoneNumberViewModel.cs create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Models/ManageViewModels/ChangePasswordViewModel.cs create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Models/ManageViewModels/ConfigureTwoFactorViewModel.cs create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Models/ManageViewModels/FactorViewModel.cs create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Models/ManageViewModels/IndexViewModel.cs create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Models/ManageViewModels/ManageLoginsViewModel.cs create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Models/ManageViewModels/RemoveLoginViewModel.cs create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Models/ManageViewModels/SetPasswordViewModel.cs create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Models/ManageViewModels/VerifyPhoneNumberViewModel.cs create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Program.cs create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/README.md create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Services/IEmailSender.cs create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Services/ISmsSender.cs create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Services/MessageServices.cs create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Startup.cs create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/ConfirmEmail.cshtml create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/ExternalLoginConfirmation.cshtml create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/ExternalLoginFailure.cshtml create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/ForgotPassword.cshtml create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/ForgotPasswordConfirmation.cshtml create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/Lockout.cshtml create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/Login.cshtml create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/Register.cshtml create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/ResetPassword.cshtml create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/ResetPasswordConfirmation.cshtml create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/SendCode.cshtml create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/VerifyCode.cshtml create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Views/Home/About.cshtml create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Views/Home/Contact.cshtml create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Views/Home/Index.cshtml create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Views/Manage/AddPhoneNumber.cshtml create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Views/Manage/ChangePassword.cshtml create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Views/Manage/Index.cshtml create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Views/Manage/ManageLogins.cshtml create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Views/Manage/SetPassword.cshtml create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Views/Manage/VerifyPhoneNumber.cshtml create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Views/Shared/Error.cshtml create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Views/Shared/_Layout.cshtml create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Views/Shared/_LoginPartial.cshtml create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Views/Shared/_ValidationScriptsPartial.cshtml create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Views/_ViewImports.cshtml create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/Views/_ViewStart.cshtml create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/appsettings.json create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/bower.json create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/gulpfile.js create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/package.json create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/project.json.template create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/web.config create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/wwwroot/css/site.css create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/wwwroot/css/site.min.css create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/wwwroot/favicon.ico create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/wwwroot/images/banner1.svg create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/wwwroot/images/banner2.svg create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/wwwroot/images/banner3.svg create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/wwwroot/images/banner4.svg create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/wwwroot/js/site.js create mode 100644 src/dotnet/commands/dotnet-new/CSharp_Web/wwwroot/js/site.min.js diff --git a/.gitignore b/.gitignore index 193640562..cca89b49e 100644 --- a/.gitignore +++ b/.gitignore @@ -34,6 +34,9 @@ cmake/ # stage0 install directory .dotnet_stage0 +# `dotnet new` template zip files are generated by a pre-build step. +/src/dotnet/commands/dotnet-new/*.zip + ### VisualStudio.gitignore from https://raw.githubusercontent.com/github/gitignore/master/VisualStudio.gitignore ### ## Ignore Visual Studio temporary files, build results, and diff --git a/build_projects/dotnet-cli-build/PrepareTargets.cs b/build_projects/dotnet-cli-build/PrepareTargets.cs index b31827060..4353addbf 100644 --- a/build_projects/dotnet-cli-build/PrepareTargets.cs +++ b/build_projects/dotnet-cli-build/PrepareTargets.cs @@ -18,7 +18,7 @@ namespace Microsoft.DotNet.Cli.Build { public class PrepareTargets { - [Target(nameof(Init), nameof(DownloadHostAndSharedFxArtifacts), nameof(RestorePackages))] + [Target(nameof(Init), nameof(DownloadHostAndSharedFxArtifacts), nameof(RestorePackages), nameof(ZipTemplates))] public static BuildTargetResult Prepare(BuildTargetContext c) => c.Success(); [Target(nameof(CheckPrereqCmakePresent), nameof(CheckPlatformDependencies))] @@ -35,9 +35,9 @@ namespace Microsoft.DotNet.Cli.Build // All major targets will depend on this in order to ensure variables are set up right if they are run independently [Target( - nameof(GenerateVersions), - nameof(CheckPrereqs), - nameof(LocateStage0), + nameof(GenerateVersions), + nameof(CheckPrereqs), + nameof(LocateStage0), nameof(ExpectedBuildArtifacts), nameof(SetTelemetryProfile))] public static BuildTargetResult Init(BuildTargetContext c) @@ -75,7 +75,7 @@ namespace Microsoft.DotNet.Cli.Build ReleaseSuffix = branchInfo["RELEASE_SUFFIX"], CommitCount = commitCount }; - + c.BuildContext["BuildVersion"] = buildVersion; c.BuildContext["CommitHash"] = commitHash; @@ -86,6 +86,26 @@ namespace Microsoft.DotNet.Cli.Build return c.Success(); } + [Target] + public static BuildTargetResult ZipTemplates(BuildTargetContext c) + { + var templateDirectories = Directory.GetDirectories( + Path.Combine(Dirs.RepoRoot, "src", "dotnet", "commands", "dotnet-new")); + + foreach (var directory in templateDirectories) + { + var zipFile = Path.Combine(Path.GetDirectoryName(directory), Path.GetFileName(directory) + ".zip"); + if (File.Exists(zipFile)) + { + File.Delete(zipFile); + } + + ZipFile.CreateFromDirectory(directory, zipFile); + } + + return c.Success(); + } + [Target] public static BuildTargetResult LocateStage0(BuildTargetContext c) { @@ -137,8 +157,8 @@ namespace Microsoft.DotNet.Cli.Build } [Target( - nameof(ExpectedBuildArtifacts), - nameof(DownloadHostAndSharedFxArchives), + nameof(ExpectedBuildArtifacts), + nameof(DownloadHostAndSharedFxArchives), nameof(DownloadHostAndSharedFxInstallers))] public static BuildTargetResult DownloadHostAndSharedFxArtifacts(BuildTargetContext c) => c.Success(); @@ -487,8 +507,8 @@ cmake is required to build the native host 'corehost'"; } private static void AddInstallerArtifactToContext( - BuildTargetContext c, - string artifactPrefix, + BuildTargetContext c, + string artifactPrefix, string contextPrefix, string version) { diff --git a/build_projects/update-dependencies/UpdateFilesTargets.cs b/build_projects/update-dependencies/UpdateFilesTargets.cs index f29a2a133..1156c0b2e 100644 --- a/build_projects/update-dependencies/UpdateFilesTargets.cs +++ b/build_projects/update-dependencies/UpdateFilesTargets.cs @@ -93,7 +93,8 @@ namespace Microsoft.DotNet.Scripts IEnumerable projectJsonFiles = Enumerable.Union( Directory.GetFiles(Dirs.RepoRoot, "project.json", SearchOption.AllDirectories), Directory.GetFiles(Path.Combine(Dirs.RepoRoot, @"src\dotnet\commands\dotnet-new"), "project.json.template", SearchOption.AllDirectories)) - .Where(p => !File.Exists(Path.Combine(Path.GetDirectoryName(p), noUpdateFileName))); + .Where(p => !File.Exists(Path.Combine(Path.GetDirectoryName(p), noUpdateFileName)) && + !Path.GetDirectoryName(p).EndsWith("CSharp_Web", StringComparison.Ordinal)); JObject projectRoot; foreach (string projectJsonFile in projectJsonFiles) diff --git a/src/dotnet/README.md b/src/dotnet/README.md index 4675e732c..bbfd423f9 100644 --- a/src/dotnet/README.md +++ b/src/dotnet/README.md @@ -65,7 +65,7 @@ The following commands exist for dotnet. `dotnet new` - Initializes a sample .NET Core console application that can be compiled and ran. + Initializes sample applications that can be compiled and run. `dotnet restore` diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/.bowerrc b/src/dotnet/commands/dotnet-new/CSharp_Web/.bowerrc new file mode 100644 index 000000000..6406626ab --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/.bowerrc @@ -0,0 +1,3 @@ +{ + "directory": "wwwroot/lib" +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/.gitignore b/src/dotnet/commands/dotnet-new/CSharp_Web/.gitignore new file mode 100644 index 000000000..0ca27f04e --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/.gitignore @@ -0,0 +1,234 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +build/ +bld/ +[Bb]in/ +[Oo]bj/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Microsoft Azure ApplicationInsights config file +ApplicationInsights.config + +# Windows Store app package directory +AppPackages/ +BundleArtifacts/ + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe + +# FAKE - F# Make +.fake/ diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Controllers/AccountController.cs b/src/dotnet/commands/dotnet-new/CSharp_Web/Controllers/AccountController.cs new file mode 100644 index 000000000..035638af9 --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Controllers/AccountController.cs @@ -0,0 +1,468 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Rendering; +using Microsoft.Extensions.Logging; +using WebApplication.Models; +using WebApplication.Models.AccountViewModels; +using WebApplication.Services; + +namespace WebApplication.Controllers +{ + [Authorize] + public class AccountController : Controller + { + private readonly UserManager _userManager; + private readonly SignInManager _signInManager; + private readonly IEmailSender _emailSender; + private readonly ISmsSender _smsSender; + private readonly ILogger _logger; + + public AccountController( + UserManager userManager, + SignInManager signInManager, + IEmailSender emailSender, + ISmsSender smsSender, + ILoggerFactory loggerFactory) + { + _userManager = userManager; + _signInManager = signInManager; + _emailSender = emailSender; + _smsSender = smsSender; + _logger = loggerFactory.CreateLogger(); + } + + // + // GET: /Account/Login + [HttpGet] + [AllowAnonymous] + public IActionResult Login(string returnUrl = null) + { + ViewData["ReturnUrl"] = returnUrl; + return View(); + } + + // + // POST: /Account/Login + [HttpPost] + [AllowAnonymous] + [ValidateAntiForgeryToken] + public async Task Login(LoginViewModel model, string returnUrl = null) + { + ViewData["ReturnUrl"] = returnUrl; + if (ModelState.IsValid) + { + // This doesn't count login failures towards account lockout + // To enable password failures to trigger account lockout, set lockoutOnFailure: true + var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false); + if (result.Succeeded) + { + _logger.LogInformation(1, "User logged in."); + return RedirectToLocal(returnUrl); + } + if (result.RequiresTwoFactor) + { + return RedirectToAction(nameof(SendCode), new { ReturnUrl = returnUrl, RememberMe = model.RememberMe }); + } + if (result.IsLockedOut) + { + _logger.LogWarning(2, "User account locked out."); + return View("Lockout"); + } + else + { + ModelState.AddModelError(string.Empty, "Invalid login attempt."); + return View(model); + } + } + + // If we got this far, something failed, redisplay form + return View(model); + } + + // + // GET: /Account/Register + [HttpGet] + [AllowAnonymous] + public IActionResult Register(string returnUrl = null) + { + ViewData["ReturnUrl"] = returnUrl; + return View(); + } + + // + // POST: /Account/Register + [HttpPost] + [AllowAnonymous] + [ValidateAntiForgeryToken] + public async Task Register(RegisterViewModel model, string returnUrl = null) + { + ViewData["ReturnUrl"] = returnUrl; + if (ModelState.IsValid) + { + var user = new ApplicationUser { UserName = model.Email, Email = model.Email }; + var result = await _userManager.CreateAsync(user, model.Password); + if (result.Succeeded) + { + // For more information on how to enable account confirmation and password reset please visit https://go.microsoft.com/fwlink/?LinkID=532713 + // Send an email with this link + //var code = await _userManager.GenerateEmailConfirmationTokenAsync(user); + //var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: HttpContext.Request.Scheme); + //await _emailSender.SendEmailAsync(model.Email, "Confirm your account", + // $"Please confirm your account by clicking this link: link"); + await _signInManager.SignInAsync(user, isPersistent: false); + _logger.LogInformation(3, "User created a new account with password."); + return RedirectToLocal(returnUrl); + } + AddErrors(result); + } + + // If we got this far, something failed, redisplay form + return View(model); + } + + // + // POST: /Account/LogOff + [HttpPost] + [ValidateAntiForgeryToken] + public async Task LogOff() + { + await _signInManager.SignOutAsync(); + _logger.LogInformation(4, "User logged out."); + return RedirectToAction(nameof(HomeController.Index), "Home"); + } + + // + // POST: /Account/ExternalLogin + [HttpPost] + [AllowAnonymous] + [ValidateAntiForgeryToken] + public IActionResult ExternalLogin(string provider, string returnUrl = null) + { + // Request a redirect to the external login provider. + var redirectUrl = Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl }); + var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl); + return Challenge(properties, provider); + } + + // + // GET: /Account/ExternalLoginCallback + [HttpGet] + [AllowAnonymous] + public async Task ExternalLoginCallback(string returnUrl = null, string remoteError = null) + { + if (remoteError != null) + { + ModelState.AddModelError(string.Empty, $"Error from external provider: {remoteError}"); + return View(nameof(Login)); + } + var info = await _signInManager.GetExternalLoginInfoAsync(); + if (info == null) + { + return RedirectToAction(nameof(Login)); + } + + // Sign in the user with this external login provider if the user already has a login. + var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false); + if (result.Succeeded) + { + _logger.LogInformation(5, "User logged in with {Name} provider.", info.LoginProvider); + return RedirectToLocal(returnUrl); + } + if (result.RequiresTwoFactor) + { + return RedirectToAction(nameof(SendCode), new { ReturnUrl = returnUrl }); + } + if (result.IsLockedOut) + { + return View("Lockout"); + } + else + { + // If the user does not have an account, then ask the user to create an account. + ViewData["ReturnUrl"] = returnUrl; + ViewData["LoginProvider"] = info.LoginProvider; + var email = info.Principal.FindFirstValue(ClaimTypes.Email); + return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = email }); + } + } + + // + // POST: /Account/ExternalLoginConfirmation + [HttpPost] + [AllowAnonymous] + [ValidateAntiForgeryToken] + public async Task ExternalLoginConfirmation(ExternalLoginConfirmationViewModel model, string returnUrl = null) + { + if (ModelState.IsValid) + { + // Get the information about the user from the external login provider + var info = await _signInManager.GetExternalLoginInfoAsync(); + if (info == null) + { + return View("ExternalLoginFailure"); + } + var user = new ApplicationUser { UserName = model.Email, Email = model.Email }; + var result = await _userManager.CreateAsync(user); + if (result.Succeeded) + { + result = await _userManager.AddLoginAsync(user, info); + if (result.Succeeded) + { + await _signInManager.SignInAsync(user, isPersistent: false); + _logger.LogInformation(6, "User created an account using {Name} provider.", info.LoginProvider); + return RedirectToLocal(returnUrl); + } + } + AddErrors(result); + } + + ViewData["ReturnUrl"] = returnUrl; + return View(model); + } + + // GET: /Account/ConfirmEmail + [HttpGet] + [AllowAnonymous] + public async Task ConfirmEmail(string userId, string code) + { + if (userId == null || code == null) + { + return View("Error"); + } + var user = await _userManager.FindByIdAsync(userId); + if (user == null) + { + return View("Error"); + } + var result = await _userManager.ConfirmEmailAsync(user, code); + return View(result.Succeeded ? "ConfirmEmail" : "Error"); + } + + // + // GET: /Account/ForgotPassword + [HttpGet] + [AllowAnonymous] + public IActionResult ForgotPassword() + { + return View(); + } + + // + // POST: /Account/ForgotPassword + [HttpPost] + [AllowAnonymous] + [ValidateAntiForgeryToken] + public async Task ForgotPassword(ForgotPasswordViewModel model) + { + if (ModelState.IsValid) + { + var user = await _userManager.FindByNameAsync(model.Email); + if (user == null || !(await _userManager.IsEmailConfirmedAsync(user))) + { + // Don't reveal that the user does not exist or is not confirmed + return View("ForgotPasswordConfirmation"); + } + + // For more information on how to enable account confirmation and password reset please visit https://go.microsoft.com/fwlink/?LinkID=532713 + // Send an email with this link + //var code = await _userManager.GeneratePasswordResetTokenAsync(user); + //var callbackUrl = Url.Action("ResetPassword", "Account", new { userId = user.Id, code = code }, protocol: HttpContext.Request.Scheme); + //await _emailSender.SendEmailAsync(model.Email, "Reset Password", + // $"Please reset your password by clicking here: link"); + //return View("ForgotPasswordConfirmation"); + } + + // If we got this far, something failed, redisplay form + return View(model); + } + + // + // GET: /Account/ForgotPasswordConfirmation + [HttpGet] + [AllowAnonymous] + public IActionResult ForgotPasswordConfirmation() + { + return View(); + } + + // + // GET: /Account/ResetPassword + [HttpGet] + [AllowAnonymous] + public IActionResult ResetPassword(string code = null) + { + return code == null ? View("Error") : View(); + } + + // + // POST: /Account/ResetPassword + [HttpPost] + [AllowAnonymous] + [ValidateAntiForgeryToken] + public async Task ResetPassword(ResetPasswordViewModel model) + { + if (!ModelState.IsValid) + { + return View(model); + } + var user = await _userManager.FindByNameAsync(model.Email); + if (user == null) + { + // Don't reveal that the user does not exist + return RedirectToAction(nameof(AccountController.ResetPasswordConfirmation), "Account"); + } + var result = await _userManager.ResetPasswordAsync(user, model.Code, model.Password); + if (result.Succeeded) + { + return RedirectToAction(nameof(AccountController.ResetPasswordConfirmation), "Account"); + } + AddErrors(result); + return View(); + } + + // + // GET: /Account/ResetPasswordConfirmation + [HttpGet] + [AllowAnonymous] + public IActionResult ResetPasswordConfirmation() + { + return View(); + } + + // + // GET: /Account/SendCode + [HttpGet] + [AllowAnonymous] + public async Task SendCode(string returnUrl = null, bool rememberMe = false) + { + var user = await _signInManager.GetTwoFactorAuthenticationUserAsync(); + if (user == null) + { + return View("Error"); + } + var userFactors = await _userManager.GetValidTwoFactorProvidersAsync(user); + var factorOptions = userFactors.Select(purpose => new SelectListItem { Text = purpose, Value = purpose }).ToList(); + return View(new SendCodeViewModel { Providers = factorOptions, ReturnUrl = returnUrl, RememberMe = rememberMe }); + } + + // + // POST: /Account/SendCode + [HttpPost] + [AllowAnonymous] + [ValidateAntiForgeryToken] + public async Task SendCode(SendCodeViewModel model) + { + if (!ModelState.IsValid) + { + return View(); + } + + var user = await _signInManager.GetTwoFactorAuthenticationUserAsync(); + if (user == null) + { + return View("Error"); + } + + // Generate the token and send it + var code = await _userManager.GenerateTwoFactorTokenAsync(user, model.SelectedProvider); + if (string.IsNullOrWhiteSpace(code)) + { + return View("Error"); + } + + var message = "Your security code is: " + code; + if (model.SelectedProvider == "Email") + { + await _emailSender.SendEmailAsync(await _userManager.GetEmailAsync(user), "Security Code", message); + } + else if (model.SelectedProvider == "Phone") + { + await _smsSender.SendSmsAsync(await _userManager.GetPhoneNumberAsync(user), message); + } + + return RedirectToAction(nameof(VerifyCode), new { Provider = model.SelectedProvider, ReturnUrl = model.ReturnUrl, RememberMe = model.RememberMe }); + } + + // + // GET: /Account/VerifyCode + [HttpGet] + [AllowAnonymous] + public async Task VerifyCode(string provider, bool rememberMe, string returnUrl = null) + { + // Require that the user has already logged in via username/password or external login + var user = await _signInManager.GetTwoFactorAuthenticationUserAsync(); + if (user == null) + { + return View("Error"); + } + return View(new VerifyCodeViewModel { Provider = provider, ReturnUrl = returnUrl, RememberMe = rememberMe }); + } + + // + // POST: /Account/VerifyCode + [HttpPost] + [AllowAnonymous] + [ValidateAntiForgeryToken] + public async Task VerifyCode(VerifyCodeViewModel model) + { + if (!ModelState.IsValid) + { + return View(model); + } + + // The following code protects for brute force attacks against the two factor codes. + // If a user enters incorrect codes for a specified amount of time then the user account + // will be locked out for a specified amount of time. + var result = await _signInManager.TwoFactorSignInAsync(model.Provider, model.Code, model.RememberMe, model.RememberBrowser); + if (result.Succeeded) + { + return RedirectToLocal(model.ReturnUrl); + } + if (result.IsLockedOut) + { + _logger.LogWarning(7, "User account locked out."); + return View("Lockout"); + } + else + { + ModelState.AddModelError(string.Empty, "Invalid code."); + return View(model); + } + } + + #region Helpers + + private void AddErrors(IdentityResult result) + { + foreach (var error in result.Errors) + { + ModelState.AddModelError(string.Empty, error.Description); + } + } + + private Task GetCurrentUserAsync() + { + return _userManager.GetUserAsync(HttpContext.User); + } + + private IActionResult RedirectToLocal(string returnUrl) + { + if (Url.IsLocalUrl(returnUrl)) + { + return Redirect(returnUrl); + } + else + { + return RedirectToAction(nameof(HomeController.Index), "Home"); + } + } + + #endregion + } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Controllers/HomeController.cs b/src/dotnet/commands/dotnet-new/CSharp_Web/Controllers/HomeController.cs new file mode 100644 index 000000000..4b21d0cce --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Controllers/HomeController.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; + +namespace WebApplication.Controllers +{ + public class HomeController : Controller + { + public IActionResult Index() + { + return View(); + } + + public IActionResult About() + { + ViewData["Message"] = "Your application description page."; + + return View(); + } + + public IActionResult Contact() + { + ViewData["Message"] = "Your contact page."; + + return View(); + } + + public IActionResult Error() + { + return View(); + } + } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Controllers/ManageController.cs b/src/dotnet/commands/dotnet-new/CSharp_Web/Controllers/ManageController.cs new file mode 100644 index 000000000..8d04fe58b --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Controllers/ManageController.cs @@ -0,0 +1,347 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; +using WebApplication.Models; +using WebApplication.Models.ManageViewModels; +using WebApplication.Services; + +namespace WebApplication.Controllers +{ + [Authorize] + public class ManageController : Controller + { + private readonly UserManager _userManager; + private readonly SignInManager _signInManager; + private readonly IEmailSender _emailSender; + private readonly ISmsSender _smsSender; + private readonly ILogger _logger; + + public ManageController( + UserManager userManager, + SignInManager signInManager, + IEmailSender emailSender, + ISmsSender smsSender, + ILoggerFactory loggerFactory) + { + _userManager = userManager; + _signInManager = signInManager; + _emailSender = emailSender; + _smsSender = smsSender; + _logger = loggerFactory.CreateLogger(); + } + + // + // GET: /Manage/Index + [HttpGet] + public async Task Index(ManageMessageId? message = null) + { + ViewData["StatusMessage"] = + message == ManageMessageId.ChangePasswordSuccess ? "Your password has been changed." + : message == ManageMessageId.SetPasswordSuccess ? "Your password has been set." + : message == ManageMessageId.SetTwoFactorSuccess ? "Your two-factor authentication provider has been set." + : message == ManageMessageId.Error ? "An error has occurred." + : message == ManageMessageId.AddPhoneSuccess ? "Your phone number was added." + : message == ManageMessageId.RemovePhoneSuccess ? "Your phone number was removed." + : ""; + + var user = await GetCurrentUserAsync(); + var model = new IndexViewModel + { + HasPassword = await _userManager.HasPasswordAsync(user), + PhoneNumber = await _userManager.GetPhoneNumberAsync(user), + TwoFactor = await _userManager.GetTwoFactorEnabledAsync(user), + Logins = await _userManager.GetLoginsAsync(user), + BrowserRemembered = await _signInManager.IsTwoFactorClientRememberedAsync(user) + }; + return View(model); + } + + // + // POST: /Manage/RemoveLogin + [HttpPost] + [ValidateAntiForgeryToken] + public async Task RemoveLogin(RemoveLoginViewModel account) + { + ManageMessageId? message = ManageMessageId.Error; + var user = await GetCurrentUserAsync(); + if (user != null) + { + var result = await _userManager.RemoveLoginAsync(user, account.LoginProvider, account.ProviderKey); + if (result.Succeeded) + { + await _signInManager.SignInAsync(user, isPersistent: false); + message = ManageMessageId.RemoveLoginSuccess; + } + } + return RedirectToAction(nameof(ManageLogins), new { Message = message }); + } + + // + // GET: /Manage/AddPhoneNumber + public IActionResult AddPhoneNumber() + { + return View(); + } + + // + // POST: /Manage/AddPhoneNumber + [HttpPost] + [ValidateAntiForgeryToken] + public async Task AddPhoneNumber(AddPhoneNumberViewModel model) + { + if (!ModelState.IsValid) + { + return View(model); + } + // Generate the token and send it + var user = await GetCurrentUserAsync(); + var code = await _userManager.GenerateChangePhoneNumberTokenAsync(user, model.PhoneNumber); + await _smsSender.SendSmsAsync(model.PhoneNumber, "Your security code is: " + code); + return RedirectToAction(nameof(VerifyPhoneNumber), new { PhoneNumber = model.PhoneNumber }); + } + + // + // POST: /Manage/EnableTwoFactorAuthentication + [HttpPost] + [ValidateAntiForgeryToken] + public async Task EnableTwoFactorAuthentication() + { + var user = await GetCurrentUserAsync(); + if (user != null) + { + await _userManager.SetTwoFactorEnabledAsync(user, true); + await _signInManager.SignInAsync(user, isPersistent: false); + _logger.LogInformation(1, "User enabled two-factor authentication."); + } + return RedirectToAction(nameof(Index), "Manage"); + } + + // + // POST: /Manage/DisableTwoFactorAuthentication + [HttpPost] + [ValidateAntiForgeryToken] + public async Task DisableTwoFactorAuthentication() + { + var user = await GetCurrentUserAsync(); + if (user != null) + { + await _userManager.SetTwoFactorEnabledAsync(user, false); + await _signInManager.SignInAsync(user, isPersistent: false); + _logger.LogInformation(2, "User disabled two-factor authentication."); + } + return RedirectToAction(nameof(Index), "Manage"); + } + + // + // GET: /Manage/VerifyPhoneNumber + [HttpGet] + public async Task VerifyPhoneNumber(string phoneNumber) + { + var code = await _userManager.GenerateChangePhoneNumberTokenAsync(await GetCurrentUserAsync(), phoneNumber); + // Send an SMS to verify the phone number + return phoneNumber == null ? View("Error") : View(new VerifyPhoneNumberViewModel { PhoneNumber = phoneNumber }); + } + + // + // POST: /Manage/VerifyPhoneNumber + [HttpPost] + [ValidateAntiForgeryToken] + public async Task VerifyPhoneNumber(VerifyPhoneNumberViewModel model) + { + if (!ModelState.IsValid) + { + return View(model); + } + var user = await GetCurrentUserAsync(); + if (user != null) + { + var result = await _userManager.ChangePhoneNumberAsync(user, model.PhoneNumber, model.Code); + if (result.Succeeded) + { + await _signInManager.SignInAsync(user, isPersistent: false); + return RedirectToAction(nameof(Index), new { Message = ManageMessageId.AddPhoneSuccess }); + } + } + // If we got this far, something failed, redisplay the form + ModelState.AddModelError(string.Empty, "Failed to verify phone number"); + return View(model); + } + + // + // POST: /Manage/RemovePhoneNumber + [HttpPost] + [ValidateAntiForgeryToken] + public async Task RemovePhoneNumber() + { + var user = await GetCurrentUserAsync(); + if (user != null) + { + var result = await _userManager.SetPhoneNumberAsync(user, null); + if (result.Succeeded) + { + await _signInManager.SignInAsync(user, isPersistent: false); + return RedirectToAction(nameof(Index), new { Message = ManageMessageId.RemovePhoneSuccess }); + } + } + return RedirectToAction(nameof(Index), new { Message = ManageMessageId.Error }); + } + + // + // GET: /Manage/ChangePassword + [HttpGet] + public IActionResult ChangePassword() + { + return View(); + } + + // + // POST: /Manage/ChangePassword + [HttpPost] + [ValidateAntiForgeryToken] + public async Task ChangePassword(ChangePasswordViewModel model) + { + if (!ModelState.IsValid) + { + return View(model); + } + var user = await GetCurrentUserAsync(); + if (user != null) + { + var result = await _userManager.ChangePasswordAsync(user, model.OldPassword, model.NewPassword); + if (result.Succeeded) + { + await _signInManager.SignInAsync(user, isPersistent: false); + _logger.LogInformation(3, "User changed their password successfully."); + return RedirectToAction(nameof(Index), new { Message = ManageMessageId.ChangePasswordSuccess }); + } + AddErrors(result); + return View(model); + } + return RedirectToAction(nameof(Index), new { Message = ManageMessageId.Error }); + } + + // + // GET: /Manage/SetPassword + [HttpGet] + public IActionResult SetPassword() + { + return View(); + } + + // + // POST: /Manage/SetPassword + [HttpPost] + [ValidateAntiForgeryToken] + public async Task SetPassword(SetPasswordViewModel model) + { + if (!ModelState.IsValid) + { + return View(model); + } + + var user = await GetCurrentUserAsync(); + if (user != null) + { + var result = await _userManager.AddPasswordAsync(user, model.NewPassword); + if (result.Succeeded) + { + await _signInManager.SignInAsync(user, isPersistent: false); + return RedirectToAction(nameof(Index), new { Message = ManageMessageId.SetPasswordSuccess }); + } + AddErrors(result); + return View(model); + } + return RedirectToAction(nameof(Index), new { Message = ManageMessageId.Error }); + } + + //GET: /Manage/ManageLogins + [HttpGet] + public async Task ManageLogins(ManageMessageId? message = null) + { + ViewData["StatusMessage"] = + message == ManageMessageId.RemoveLoginSuccess ? "The external login was removed." + : message == ManageMessageId.AddLoginSuccess ? "The external login was added." + : message == ManageMessageId.Error ? "An error has occurred." + : ""; + var user = await GetCurrentUserAsync(); + if (user == null) + { + return View("Error"); + } + var userLogins = await _userManager.GetLoginsAsync(user); + var otherLogins = _signInManager.GetExternalAuthenticationSchemes().Where(auth => userLogins.All(ul => auth.AuthenticationScheme != ul.LoginProvider)).ToList(); + ViewData["ShowRemoveButton"] = user.PasswordHash != null || userLogins.Count > 1; + return View(new ManageLoginsViewModel + { + CurrentLogins = userLogins, + OtherLogins = otherLogins + }); + } + + // + // POST: /Manage/LinkLogin + [HttpPost] + [ValidateAntiForgeryToken] + public IActionResult LinkLogin(string provider) + { + // Request a redirect to the external login provider to link a login for the current user + var redirectUrl = Url.Action("LinkLoginCallback", "Manage"); + var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl, _userManager.GetUserId(User)); + return Challenge(properties, provider); + } + + // + // GET: /Manage/LinkLoginCallback + [HttpGet] + public async Task LinkLoginCallback() + { + var user = await GetCurrentUserAsync(); + if (user == null) + { + return View("Error"); + } + var info = await _signInManager.GetExternalLoginInfoAsync(await _userManager.GetUserIdAsync(user)); + if (info == null) + { + return RedirectToAction(nameof(ManageLogins), new { Message = ManageMessageId.Error }); + } + var result = await _userManager.AddLoginAsync(user, info); + var message = result.Succeeded ? ManageMessageId.AddLoginSuccess : ManageMessageId.Error; + return RedirectToAction(nameof(ManageLogins), new { Message = message }); + } + + #region Helpers + + private void AddErrors(IdentityResult result) + { + foreach (var error in result.Errors) + { + ModelState.AddModelError(string.Empty, error.Description); + } + } + + public enum ManageMessageId + { + AddPhoneSuccess, + AddLoginSuccess, + ChangePasswordSuccess, + SetTwoFactorSuccess, + SetPasswordSuccess, + RemoveLoginSuccess, + RemovePhoneSuccess, + Error + } + + private Task GetCurrentUserAsync() + { + return _userManager.GetUserAsync(HttpContext.User); + } + + #endregion + } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Data/ApplicationDbContext.cs b/src/dotnet/commands/dotnet-new/CSharp_Web/Data/ApplicationDbContext.cs new file mode 100644 index 000000000..336e6d466 --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Data/ApplicationDbContext.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Identity.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using WebApplication.Models; + +namespace WebApplication.Data +{ + public class ApplicationDbContext : IdentityDbContext + { + public ApplicationDbContext(DbContextOptions options) + : base(options) + { + } + + protected override void OnModelCreating(ModelBuilder builder) + { + base.OnModelCreating(builder); + // Customize the ASP.NET Identity model and override the defaults if needed. + // For example, you can rename the ASP.NET Identity table names and more. + // Add your customizations after calling base.OnModelCreating(builder); + } + } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Data/Migrations/00000000000000_CreateIdentitySchema.Designer.cs b/src/dotnet/commands/dotnet-new/CSharp_Web/Data/Migrations/00000000000000_CreateIdentitySchema.Designer.cs new file mode 100644 index 000000000..bb12d2bbb --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Data/Migrations/00000000000000_CreateIdentitySchema.Designer.cs @@ -0,0 +1,212 @@ +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using WebApplication.Data; + +namespace WebApplication.Data.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("00000000000000_CreateIdentitySchema")] + partial class CreateIdentitySchema + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { + modelBuilder + .HasAnnotation("ProductVersion", "1.0.0-rc2-20901"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole", b => + { + b.Property("Id"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Name") + .HasAnnotation("MaxLength", 256); + + b.Property("NormalizedName") + .HasAnnotation("MaxLength", 256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .HasName("RoleNameIndex"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("RoleId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserLogin", b => + { + b.Property("LoginProvider"); + + b.Property("ProviderKey"); + + b.Property("ProviderDisplayName"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserRole", b => + { + b.Property("UserId"); + + b.Property("RoleId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserToken", b => + { + b.Property("UserId"); + + b.Property("LoginProvider"); + + b.Property("Name"); + + b.Property("Value"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("WebApplication.Models.ApplicationUser", b => + { + b.Property("Id"); + + b.Property("AccessFailedCount"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Email") + .HasAnnotation("MaxLength", 256); + + b.Property("EmailConfirmed"); + + b.Property("LockoutEnabled"); + + b.Property("LockoutEnd"); + + b.Property("NormalizedEmail") + .HasAnnotation("MaxLength", 256); + + b.Property("NormalizedUserName") + .HasAnnotation("MaxLength", 256); + + b.Property("PasswordHash"); + + b.Property("PhoneNumber"); + + b.Property("PhoneNumberConfirmed"); + + b.Property("SecurityStamp"); + + b.Property("TwoFactorEnabled"); + + b.Property("UserName") + .HasAnnotation("MaxLength", 256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .HasName("UserNameIndex"); + + b.ToTable("AspNetUsers"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserClaim", b => + { + b.HasOne("WebApplication.Models.ApplicationUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserLogin", b => + { + b.HasOne("WebApplication.Models.ApplicationUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("WebApplication.Models.ApplicationUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + } + } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Data/Migrations/00000000000000_CreateIdentitySchema.cs b/src/dotnet/commands/dotnet-new/CSharp_Web/Data/Migrations/00000000000000_CreateIdentitySchema.cs new file mode 100644 index 000000000..e6f038f8e --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Data/Migrations/00000000000000_CreateIdentitySchema.cs @@ -0,0 +1,215 @@ +using System; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace WebApplication.Data.Migrations +{ + public partial class CreateIdentitySchema : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "AspNetRoles", + columns: table => new + { + Id = table.Column(nullable: false), + ConcurrencyStamp = table.Column(nullable: true), + Name = table.Column(nullable: true), + NormalizedName = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetRoles", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserTokens", + columns: table => new + { + UserId = table.Column(nullable: false), + LoginProvider = table.Column(nullable: false), + Name = table.Column(nullable: false), + Value = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); + }); + + migrationBuilder.CreateTable( + name: "AspNetUsers", + columns: table => new + { + Id = table.Column(nullable: false), + AccessFailedCount = table.Column(nullable: false), + ConcurrencyStamp = table.Column(nullable: true), + Email = table.Column(nullable: true), + EmailConfirmed = table.Column(nullable: false), + LockoutEnabled = table.Column(nullable: false), + LockoutEnd = table.Column(nullable: true), + NormalizedEmail = table.Column(nullable: true), + NormalizedUserName = table.Column(nullable: true), + PasswordHash = table.Column(nullable: true), + PhoneNumber = table.Column(nullable: true), + PhoneNumberConfirmed = table.Column(nullable: false), + SecurityStamp = table.Column(nullable: true), + TwoFactorEnabled = table.Column(nullable: false), + UserName = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUsers", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AspNetRoleClaims", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Autoincrement", true), + ClaimType = table.Column(nullable: true), + ClaimValue = table.Column(nullable: true), + RoleId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id); + table.ForeignKey( + name: "FK_AspNetRoleClaims_AspNetRoles_RoleId", + column: x => x.RoleId, + principalTable: "AspNetRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserClaims", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Autoincrement", true), + ClaimType = table.Column(nullable: true), + ClaimValue = table.Column(nullable: true), + UserId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserClaims", x => x.Id); + table.ForeignKey( + name: "FK_AspNetUserClaims_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserLogins", + columns: table => new + { + LoginProvider = table.Column(nullable: false), + ProviderKey = table.Column(nullable: false), + ProviderDisplayName = table.Column(nullable: true), + UserId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey }); + table.ForeignKey( + name: "FK_AspNetUserLogins_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserRoles", + columns: table => new + { + UserId = table.Column(nullable: false), + RoleId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId }); + table.ForeignKey( + name: "FK_AspNetUserRoles_AspNetRoles_RoleId", + column: x => x.RoleId, + principalTable: "AspNetRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AspNetUserRoles_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "RoleNameIndex", + table: "AspNetRoles", + column: "NormalizedName"); + + migrationBuilder.CreateIndex( + name: "IX_AspNetRoleClaims_RoleId", + table: "AspNetRoleClaims", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "IX_AspNetUserClaims_UserId", + table: "AspNetUserClaims", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_AspNetUserLogins_UserId", + table: "AspNetUserLogins", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_AspNetUserRoles_RoleId", + table: "AspNetUserRoles", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "IX_AspNetUserRoles_UserId", + table: "AspNetUserRoles", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "EmailIndex", + table: "AspNetUsers", + column: "NormalizedEmail"); + + migrationBuilder.CreateIndex( + name: "UserNameIndex", + table: "AspNetUsers", + column: "NormalizedUserName"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AspNetRoleClaims"); + + migrationBuilder.DropTable( + name: "AspNetUserClaims"); + + migrationBuilder.DropTable( + name: "AspNetUserLogins"); + + migrationBuilder.DropTable( + name: "AspNetUserRoles"); + + migrationBuilder.DropTable( + name: "AspNetUserTokens"); + + migrationBuilder.DropTable( + name: "AspNetRoles"); + + migrationBuilder.DropTable( + name: "AspNetUsers"); + } + } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Data/Migrations/ApplicationDbContextModelSnapshot.cs b/src/dotnet/commands/dotnet-new/CSharp_Web/Data/Migrations/ApplicationDbContextModelSnapshot.cs new file mode 100644 index 000000000..cb459319d --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Data/Migrations/ApplicationDbContextModelSnapshot.cs @@ -0,0 +1,211 @@ +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using WebApplication.Data; + +namespace WebApplication.Data.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + partial class ApplicationDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { + modelBuilder + .HasAnnotation("ProductVersion", "1.0.0-rc2-20901"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole", b => + { + b.Property("Id"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Name") + .HasAnnotation("MaxLength", 256); + + b.Property("NormalizedName") + .HasAnnotation("MaxLength", 256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .HasName("RoleNameIndex"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("RoleId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserLogin", b => + { + b.Property("LoginProvider"); + + b.Property("ProviderKey"); + + b.Property("ProviderDisplayName"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserRole", b => + { + b.Property("UserId"); + + b.Property("RoleId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserToken", b => + { + b.Property("UserId"); + + b.Property("LoginProvider"); + + b.Property("Name"); + + b.Property("Value"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("WebApplication.Models.ApplicationUser", b => + { + b.Property("Id"); + + b.Property("AccessFailedCount"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Email") + .HasAnnotation("MaxLength", 256); + + b.Property("EmailConfirmed"); + + b.Property("LockoutEnabled"); + + b.Property("LockoutEnd"); + + b.Property("NormalizedEmail") + .HasAnnotation("MaxLength", 256); + + b.Property("NormalizedUserName") + .HasAnnotation("MaxLength", 256); + + b.Property("PasswordHash"); + + b.Property("PhoneNumber"); + + b.Property("PhoneNumberConfirmed"); + + b.Property("SecurityStamp"); + + b.Property("TwoFactorEnabled"); + + b.Property("UserName") + .HasAnnotation("MaxLength", 256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .HasName("UserNameIndex"); + + b.ToTable("AspNetUsers"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserClaim", b => + { + b.HasOne("WebApplication.Models.ApplicationUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserLogin", b => + { + b.HasOne("WebApplication.Models.ApplicationUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("WebApplication.Models.ApplicationUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + } + } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Models/AccountViewModels/ExternalLoginConfirmationViewModel.cs b/src/dotnet/commands/dotnet-new/CSharp_Web/Models/AccountViewModels/ExternalLoginConfirmationViewModel.cs new file mode 100644 index 000000000..a60894ce8 --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Models/AccountViewModels/ExternalLoginConfirmationViewModel.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Threading.Tasks; + +namespace WebApplication.Models.AccountViewModels +{ + public class ExternalLoginConfirmationViewModel + { + [Required] + [EmailAddress] + public string Email { get; set; } + } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Models/AccountViewModels/ForgotPasswordViewModel.cs b/src/dotnet/commands/dotnet-new/CSharp_Web/Models/AccountViewModels/ForgotPasswordViewModel.cs new file mode 100644 index 000000000..70fab0c9f --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Models/AccountViewModels/ForgotPasswordViewModel.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Threading.Tasks; + +namespace WebApplication.Models.AccountViewModels +{ + public class ForgotPasswordViewModel + { + [Required] + [EmailAddress] + public string Email { get; set; } + } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Models/AccountViewModels/LoginViewModel.cs b/src/dotnet/commands/dotnet-new/CSharp_Web/Models/AccountViewModels/LoginViewModel.cs new file mode 100644 index 000000000..7dc974b6b --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Models/AccountViewModels/LoginViewModel.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Threading.Tasks; + +namespace WebApplication.Models.AccountViewModels +{ + public class LoginViewModel + { + [Required] + [EmailAddress] + public string Email { get; set; } + + [Required] + [DataType(DataType.Password)] + public string Password { get; set; } + + [Display(Name = "Remember me?")] + public bool RememberMe { get; set; } + } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Models/AccountViewModels/RegisterViewModel.cs b/src/dotnet/commands/dotnet-new/CSharp_Web/Models/AccountViewModels/RegisterViewModel.cs new file mode 100644 index 000000000..bc86f2aed --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Models/AccountViewModels/RegisterViewModel.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Threading.Tasks; + +namespace WebApplication.Models.AccountViewModels +{ + public class RegisterViewModel + { + [Required] + [EmailAddress] + [Display(Name = "Email")] + public string Email { get; set; } + + [Required] + [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] + [DataType(DataType.Password)] + [Display(Name = "Password")] + public string Password { get; set; } + + [DataType(DataType.Password)] + [Display(Name = "Confirm password")] + [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] + public string ConfirmPassword { get; set; } + } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Models/AccountViewModels/ResetPasswordViewModel.cs b/src/dotnet/commands/dotnet-new/CSharp_Web/Models/AccountViewModels/ResetPasswordViewModel.cs new file mode 100644 index 000000000..43198b7e5 --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Models/AccountViewModels/ResetPasswordViewModel.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Threading.Tasks; + +namespace WebApplication.Models.AccountViewModels +{ + public class ResetPasswordViewModel + { + [Required] + [EmailAddress] + public string Email { get; set; } + + [Required] + [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] + [DataType(DataType.Password)] + public string Password { get; set; } + + [DataType(DataType.Password)] + [Display(Name = "Confirm password")] + [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] + public string ConfirmPassword { get; set; } + + public string Code { get; set; } + } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Models/AccountViewModels/SendCodeViewModel.cs b/src/dotnet/commands/dotnet-new/CSharp_Web/Models/AccountViewModels/SendCodeViewModel.cs new file mode 100644 index 000000000..b8ed8f1d4 --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Models/AccountViewModels/SendCodeViewModel.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc.Rendering; + +namespace WebApplication.Models.AccountViewModels +{ + public class SendCodeViewModel + { + public string SelectedProvider { get; set; } + + public ICollection Providers { get; set; } + + public string ReturnUrl { get; set; } + + public bool RememberMe { get; set; } + } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Models/AccountViewModels/VerifyCodeViewModel.cs b/src/dotnet/commands/dotnet-new/CSharp_Web/Models/AccountViewModels/VerifyCodeViewModel.cs new file mode 100644 index 000000000..394db8c59 --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Models/AccountViewModels/VerifyCodeViewModel.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Threading.Tasks; + +namespace WebApplication.Models.AccountViewModels +{ + public class VerifyCodeViewModel + { + [Required] + public string Provider { get; set; } + + [Required] + public string Code { get; set; } + + public string ReturnUrl { get; set; } + + [Display(Name = "Remember this browser?")] + public bool RememberBrowser { get; set; } + + [Display(Name = "Remember me?")] + public bool RememberMe { get; set; } + } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Models/ApplicationUser.cs b/src/dotnet/commands/dotnet-new/CSharp_Web/Models/ApplicationUser.cs new file mode 100644 index 000000000..4642ef2c3 --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Models/ApplicationUser.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Identity.EntityFrameworkCore; + +namespace WebApplication.Models +{ + // Add profile data for application users by adding properties to the ApplicationUser class + public class ApplicationUser : IdentityUser + { + } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Models/ManageViewModels/AddPhoneNumberViewModel.cs b/src/dotnet/commands/dotnet-new/CSharp_Web/Models/ManageViewModels/AddPhoneNumberViewModel.cs new file mode 100644 index 000000000..d2baaf7e0 --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Models/ManageViewModels/AddPhoneNumberViewModel.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Threading.Tasks; + +namespace WebApplication.Models.ManageViewModels +{ + public class AddPhoneNumberViewModel + { + [Required] + [Phone] + [Display(Name = "Phone number")] + public string PhoneNumber { get; set; } + } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Models/ManageViewModels/ChangePasswordViewModel.cs b/src/dotnet/commands/dotnet-new/CSharp_Web/Models/ManageViewModels/ChangePasswordViewModel.cs new file mode 100644 index 000000000..421b91a03 --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Models/ManageViewModels/ChangePasswordViewModel.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Threading.Tasks; + +namespace WebApplication.Models.ManageViewModels +{ + public class ChangePasswordViewModel + { + [Required] + [DataType(DataType.Password)] + [Display(Name = "Current password")] + public string OldPassword { get; set; } + + [Required] + [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] + [DataType(DataType.Password)] + [Display(Name = "New password")] + public string NewPassword { get; set; } + + [DataType(DataType.Password)] + [Display(Name = "Confirm new password")] + [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")] + public string ConfirmPassword { get; set; } + } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Models/ManageViewModels/ConfigureTwoFactorViewModel.cs b/src/dotnet/commands/dotnet-new/CSharp_Web/Models/ManageViewModels/ConfigureTwoFactorViewModel.cs new file mode 100644 index 000000000..beb1fd1a4 --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Models/ManageViewModels/ConfigureTwoFactorViewModel.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc.Rendering; + +namespace WebApplication.Models.ManageViewModels +{ + public class ConfigureTwoFactorViewModel + { + public string SelectedProvider { get; set; } + + public ICollection Providers { get; set; } + } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Models/ManageViewModels/FactorViewModel.cs b/src/dotnet/commands/dotnet-new/CSharp_Web/Models/ManageViewModels/FactorViewModel.cs new file mode 100644 index 000000000..b2d4f9e2f --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Models/ManageViewModels/FactorViewModel.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace WebApplication.Models.ManageViewModels +{ + public class FactorViewModel + { + public string Purpose { get; set; } + } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Models/ManageViewModels/IndexViewModel.cs b/src/dotnet/commands/dotnet-new/CSharp_Web/Models/ManageViewModels/IndexViewModel.cs new file mode 100644 index 000000000..e0b69f2df --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Models/ManageViewModels/IndexViewModel.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Identity; + +namespace WebApplication.Models.ManageViewModels +{ + public class IndexViewModel + { + public bool HasPassword { get; set; } + + public IList Logins { get; set; } + + public string PhoneNumber { get; set; } + + public bool TwoFactor { get; set; } + + public bool BrowserRemembered { get; set; } + } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Models/ManageViewModels/ManageLoginsViewModel.cs b/src/dotnet/commands/dotnet-new/CSharp_Web/Models/ManageViewModels/ManageLoginsViewModel.cs new file mode 100644 index 000000000..fc03a0c27 --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Models/ManageViewModels/ManageLoginsViewModel.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http.Authentication; +using Microsoft.AspNetCore.Identity; + +namespace WebApplication.Models.ManageViewModels +{ + public class ManageLoginsViewModel + { + public IList CurrentLogins { get; set; } + + public IList OtherLogins { get; set; } + } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Models/ManageViewModels/RemoveLoginViewModel.cs b/src/dotnet/commands/dotnet-new/CSharp_Web/Models/ManageViewModels/RemoveLoginViewModel.cs new file mode 100644 index 000000000..394df34a0 --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Models/ManageViewModels/RemoveLoginViewModel.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Threading.Tasks; + +namespace WebApplication.Models.ManageViewModels +{ + public class RemoveLoginViewModel + { + public string LoginProvider { get; set; } + public string ProviderKey { get; set; } + } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Models/ManageViewModels/SetPasswordViewModel.cs b/src/dotnet/commands/dotnet-new/CSharp_Web/Models/ManageViewModels/SetPasswordViewModel.cs new file mode 100644 index 000000000..76c1b4bb4 --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Models/ManageViewModels/SetPasswordViewModel.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Threading.Tasks; + +namespace WebApplication.Models.ManageViewModels +{ + public class SetPasswordViewModel + { + [Required] + [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] + [DataType(DataType.Password)] + [Display(Name = "New password")] + public string NewPassword { get; set; } + + [DataType(DataType.Password)] + [Display(Name = "Confirm new password")] + [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")] + public string ConfirmPassword { get; set; } + } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Models/ManageViewModels/VerifyPhoneNumberViewModel.cs b/src/dotnet/commands/dotnet-new/CSharp_Web/Models/ManageViewModels/VerifyPhoneNumberViewModel.cs new file mode 100644 index 000000000..3c8c08c87 --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Models/ManageViewModels/VerifyPhoneNumberViewModel.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Threading.Tasks; + +namespace WebApplication.Models.ManageViewModels +{ + public class VerifyPhoneNumberViewModel + { + [Required] + public string Code { get; set; } + + [Required] + [Phone] + [Display(Name = "Phone number")] + public string PhoneNumber { get; set; } + } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Program.cs b/src/dotnet/commands/dotnet-new/CSharp_Web/Program.cs new file mode 100644 index 000000000..74e9753fb --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Program.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Hosting; + +namespace WebApplication +{ + public class Program + { + public static void Main(string[] args) + { + var host = new WebHostBuilder() + .UseKestrel() + .UseContentRoot(Directory.GetCurrentDirectory()) + .UseIISIntegration() + .UseStartup() + .Build(); + + host.Run(); + } + } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/README.md b/src/dotnet/commands/dotnet-new/CSharp_Web/README.md new file mode 100644 index 000000000..d8ba0b382 --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/README.md @@ -0,0 +1,39 @@ +# Welcome to ASP.NET Core + +We've made some big updates in this release, so it’s **important** that you spend a few minutes to learn what’s new. + +You've created a new ASP.NET Core project. [Learn what's new](https://go.microsoft.com/fwlink/?LinkId=518016) + +## This application consists of: + +* Sample pages using ASP.NET Core MVC +* [Gulp](https://go.microsoft.com/fwlink/?LinkId=518007) and [Bower](https://go.microsoft.com/fwlink/?LinkId=518004) for managing client-side libraries +* Theming using [Bootstrap](https://go.microsoft.com/fwlink/?LinkID=398939) + +## How to + +* [Add a Controller and View](https://go.microsoft.com/fwlink/?LinkID=398600) +* [Add an appsetting in config and access it in app.](https://go.microsoft.com/fwlink/?LinkID=699562) +* [Manage User Secrets using Secret Manager.](https://go.microsoft.com/fwlink/?LinkId=699315) +* [Use logging to log a message.](https://go.microsoft.com/fwlink/?LinkId=699316) +* [Add packages using NuGet.](https://go.microsoft.com/fwlink/?LinkId=699317) +* [Add client packages using Bower.](https://go.microsoft.com/fwlink/?LinkId=699318) +* [Target development, staging or production environment.](https://go.microsoft.com/fwlink/?LinkId=699319) + +## Overview + +* [Conceptual overview of what is ASP.NET Core](https://go.microsoft.com/fwlink/?LinkId=518008) +* [Fundamentals of ASP.NET Core such as Startup and middleware.](https://go.microsoft.com/fwlink/?LinkId=699320) +* [Working with Data](https://go.microsoft.com/fwlink/?LinkId=398602) +* [Security](https://go.microsoft.com/fwlink/?LinkId=398603) +* [Client side development](https://go.microsoft.com/fwlink/?LinkID=699321) +* [Develop on different platforms](https://go.microsoft.com/fwlink/?LinkID=699322) +* [Read more on the documentation site](https://go.microsoft.com/fwlink/?LinkID=699323) + +## Run & Deploy + +* [Run your app](https://go.microsoft.com/fwlink/?LinkID=517851) +* [Run tools such as EF migrations and more](https://go.microsoft.com/fwlink/?LinkID=517853) +* [Publish to Microsoft Azure Web Apps](https://go.microsoft.com/fwlink/?LinkID=398609) + +We would love to hear your [feedback](https://go.microsoft.com/fwlink/?LinkId=518015) diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Services/IEmailSender.cs b/src/dotnet/commands/dotnet-new/CSharp_Web/Services/IEmailSender.cs new file mode 100644 index 000000000..08fb35bad --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Services/IEmailSender.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace WebApplication.Services +{ + public interface IEmailSender + { + Task SendEmailAsync(string email, string subject, string message); + } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Services/ISmsSender.cs b/src/dotnet/commands/dotnet-new/CSharp_Web/Services/ISmsSender.cs new file mode 100644 index 000000000..8e57a2343 --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Services/ISmsSender.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace WebApplication.Services +{ + public interface ISmsSender + { + Task SendSmsAsync(string number, string message); + } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Services/MessageServices.cs b/src/dotnet/commands/dotnet-new/CSharp_Web/Services/MessageServices.cs new file mode 100644 index 000000000..de54bfc79 --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Services/MessageServices.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace WebApplication.Services +{ + // This class is used by the application to send Email and SMS + // when you turn on two-factor authentication in ASP.NET Identity. + // For more details see this link https://go.microsoft.com/fwlink/?LinkID=532713 + public class AuthMessageSender : IEmailSender, ISmsSender + { + public Task SendEmailAsync(string email, string subject, string message) + { + // Plug in your email service here to send an email. + return Task.FromResult(0); + } + + public Task SendSmsAsync(string number, string message) + { + // Plug in your SMS service here to send a text message. + return Task.FromResult(0); + } + } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Startup.cs b/src/dotnet/commands/dotnet-new/CSharp_Web/Startup.cs new file mode 100644 index 000000000..2fa7ae51b --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Startup.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Identity.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using WebApplication.Data; +using WebApplication.Models; +using WebApplication.Services; + +namespace WebApplication +{ + public class Startup + { + public Startup(IHostingEnvironment env) + { + var builder = new ConfigurationBuilder() + .SetBasePath(env.ContentRootPath) + .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) + .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true); + + if (env.IsDevelopment()) + { + // For more details on using the user secret store see https://go.microsoft.com/fwlink/?LinkID=532709 + builder.AddUserSecrets(); + } + + builder.AddEnvironmentVariables(); + Configuration = builder.Build(); + } + + public IConfigurationRoot Configuration { get; } + + // This method gets called by the runtime. Use this method to add services to the container. + public void ConfigureServices(IServiceCollection services) + { + // Add framework services. + services.AddDbContext(options => + options.UseSqlite(Configuration.GetConnectionString("DefaultConnection"))); + + services.AddIdentity() + .AddEntityFrameworkStores() + .AddDefaultTokenProviders(); + + services.AddMvc(); + + // Add application services. + services.AddTransient(); + services.AddTransient(); + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) + { + loggerFactory.AddConsole(Configuration.GetSection("Logging")); + loggerFactory.AddDebug(); + + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + app.UseDatabaseErrorPage(); + app.UseBrowserLink(); + } + else + { + app.UseExceptionHandler("/Home/Error"); + } + + app.UseStaticFiles(); + + app.UseIdentity(); + + // Add external authentication middleware below. To configure them please see https://go.microsoft.com/fwlink/?LinkID=532715 + + app.UseMvc(routes => + { + routes.MapRoute( + name: "default", + template: "{controller=Home}/{action=Index}/{id?}"); + }); + } + } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/ConfirmEmail.cshtml b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/ConfirmEmail.cshtml new file mode 100644 index 000000000..8e8088d44 --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/ConfirmEmail.cshtml @@ -0,0 +1,10 @@ +@{ + ViewData["Title"] = "Confirm Email"; +} + +

@ViewData["Title"].

+
+

+ Thank you for confirming your email. Please Click here to Log in. +

+
diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/ExternalLoginConfirmation.cshtml b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/ExternalLoginConfirmation.cshtml new file mode 100644 index 000000000..eb3612b55 --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/ExternalLoginConfirmation.cshtml @@ -0,0 +1,35 @@ +@model ExternalLoginConfirmationViewModel +@{ + ViewData["Title"] = "Register"; +} + +

@ViewData["Title"].

+

Associate your @ViewData["LoginProvider"] account.

+ +
+

Association Form

+
+
+ +

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

+
+ +
+ + +
+
+
+
+ +
+
+
+ +@section Scripts { + @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/ExternalLoginFailure.cshtml b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/ExternalLoginFailure.cshtml new file mode 100644 index 000000000..2509746be --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/ExternalLoginFailure.cshtml @@ -0,0 +1,8 @@ +@{ + ViewData["Title"] = "Login Failure"; +} + +
+

@ViewData["Title"].

+

Unsuccessful login with service.

+
diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/ForgotPassword.cshtml b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/ForgotPassword.cshtml new file mode 100644 index 000000000..9d748023f --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/ForgotPassword.cshtml @@ -0,0 +1,31 @@ +@model ForgotPasswordViewModel +@{ + ViewData["Title"] = "Forgot your password?"; +} + +

@ViewData["Title"]

+

+ For more information on how to enable reset password please see this article. +

+ +@*
+

Enter your email.

+
+
+
+ +
+ + +
+
+
+
+ +
+
+
*@ + +@section Scripts { + @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/ForgotPasswordConfirmation.cshtml b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/ForgotPasswordConfirmation.cshtml new file mode 100644 index 000000000..4877fc83a --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/ForgotPasswordConfirmation.cshtml @@ -0,0 +1,8 @@ +@{ + ViewData["Title"] = "Forgot Password Confirmation"; +} + +

@ViewData["Title"].

+

+ Please check your email to reset your password. +

diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/Lockout.cshtml b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/Lockout.cshtml new file mode 100644 index 000000000..34ac56ff3 --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/Lockout.cshtml @@ -0,0 +1,8 @@ +@{ + ViewData["Title"] = "Locked out"; +} + +
+

Locked out.

+

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

+
diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/Login.cshtml b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/Login.cshtml new file mode 100644 index 000000000..95430a12e --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/Login.cshtml @@ -0,0 +1,92 @@ +@using System.Collections.Generic +@using Microsoft.AspNetCore.Http +@using Microsoft.AspNetCore.Http.Authentication +@model LoginViewModel +@inject SignInManager SignInManager + +@{ + ViewData["Title"] = "Log in"; +} + +

@ViewData["Title"].

+
+
+
+
+

Use a local account to log in.

+
+
+
+ +
+ + +
+
+
+ +
+ + +
+
+
+
+
+ +
+
+
+
+
+ +
+
+

+ Register as a new user? +

+

+ Forgot your password? +

+
+
+
+
+
+

Use another service to log in.

+
+ @{ + var loginProviders = SignInManager.GetExternalAuthenticationSchemes().ToList(); + if (loginProviders.Count == 0) + { +
+

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

+
+ } + else + { +
+
+

+ @foreach (var provider in loginProviders) + { + + } +

+
+
+ } + } +
+
+
+ +@section Scripts { + @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/Register.cshtml b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/Register.cshtml new file mode 100644 index 000000000..2090f900e --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/Register.cshtml @@ -0,0 +1,42 @@ +@model RegisterViewModel +@{ + ViewData["Title"] = "Register"; +} + +

@ViewData["Title"].

+ +
+

Create a new account.

+
+
+
+ +
+ + +
+
+
+ +
+ + +
+
+
+ +
+ + +
+
+
+
+ +
+
+
+ +@section Scripts { + @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/ResetPassword.cshtml b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/ResetPassword.cshtml new file mode 100644 index 000000000..dd716d735 --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/ResetPassword.cshtml @@ -0,0 +1,43 @@ +@model ResetPasswordViewModel +@{ + ViewData["Title"] = "Reset password"; +} + +

@ViewData["Title"].

+ +
+

Reset your password.

+
+
+ +
+ +
+ + +
+
+
+ +
+ + +
+
+
+ +
+ + +
+
+
+
+ +
+
+
+ +@section Scripts { + @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/ResetPasswordConfirmation.cshtml b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/ResetPasswordConfirmation.cshtml new file mode 100644 index 000000000..6321d858e --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/ResetPasswordConfirmation.cshtml @@ -0,0 +1,8 @@ +@{ + ViewData["Title"] = "Reset password confirmation"; +} + +

@ViewData["Title"].

+

+ Your password has been reset. Please Click here to log in. +

diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/SendCode.cshtml b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/SendCode.cshtml new file mode 100644 index 000000000..e85ca3c2b --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/SendCode.cshtml @@ -0,0 +1,21 @@ +@model SendCodeViewModel +@{ + ViewData["Title"] = "Send Verification Code"; +} + +

@ViewData["Title"].

+ +
+ +
+
+ Select Two-Factor Authentication Provider: + + +
+
+
+ +@section Scripts { + @{await Html.RenderPartialAsync("_ValidationScriptsPartial"); } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/VerifyCode.cshtml b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/VerifyCode.cshtml new file mode 100644 index 000000000..60afb361d --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Account/VerifyCode.cshtml @@ -0,0 +1,38 @@ +@model VerifyCodeViewModel +@{ + ViewData["Title"] = "Verify"; +} + +

@ViewData["Title"].

+ +
+
+ + +

@ViewData["Status"]

+
+
+ +
+ + +
+
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ +@section Scripts { + @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Home/About.cshtml b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Home/About.cshtml new file mode 100644 index 000000000..b653a26f1 --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Home/About.cshtml @@ -0,0 +1,7 @@ +@{ + ViewData["Title"] = "About"; +} +

@ViewData["Title"].

+

@ViewData["Message"]

+ +

Use this area to provide additional information.

diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Home/Contact.cshtml b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Home/Contact.cshtml new file mode 100644 index 000000000..f953aa63d --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Home/Contact.cshtml @@ -0,0 +1,17 @@ +@{ + ViewData["Title"] = "Contact"; +} +

@ViewData["Title"].

+

@ViewData["Message"]

+ +
+ One Microsoft Way
+ Redmond, WA 98052-6399
+ P: + 425.555.0100 +
+ +
+ Support: Support@example.com
+ Marketing: Marketing@example.com +
diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Home/Index.cshtml b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Home/Index.cshtml new file mode 100644 index 000000000..957b8c1da --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Home/Index.cshtml @@ -0,0 +1,109 @@ +@{ + ViewData["Title"] = "Home Page"; +} + + + + diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Manage/AddPhoneNumber.cshtml b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Manage/AddPhoneNumber.cshtml new file mode 100644 index 000000000..2feb93b22 --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Manage/AddPhoneNumber.cshtml @@ -0,0 +1,27 @@ +@model AddPhoneNumberViewModel +@{ + ViewData["Title"] = "Add Phone Number"; +} + +

@ViewData["Title"].

+
+

Add a phone number.

+
+
+
+ +
+ + +
+
+
+
+ +
+
+
+ +@section Scripts { + @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Manage/ChangePassword.cshtml b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Manage/ChangePassword.cshtml new file mode 100644 index 000000000..41c7960c8 --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Manage/ChangePassword.cshtml @@ -0,0 +1,42 @@ +@model ChangePasswordViewModel +@{ + ViewData["Title"] = "Change Password"; +} + +

@ViewData["Title"].

+ +
+

Change Password Form

+
+
+
+ +
+ + +
+
+
+ +
+ + +
+
+
+ +
+ + +
+
+
+
+ +
+
+
+ +@section Scripts { + @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Manage/Index.cshtml b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Manage/Index.cshtml new file mode 100644 index 000000000..8419b2429 --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Manage/Index.cshtml @@ -0,0 +1,71 @@ +@model IndexViewModel +@{ + ViewData["Title"] = "Manage your account"; +} + +

@ViewData["Title"].

+

@ViewData["StatusMessage"]

+ +
+

Change your account settings

+
+
+
Password:
+
+ @if (Model.HasPassword) + { + Change + } + else + { + Create + } +
+
External Logins:
+
+ + @Model.Logins.Count Manage +
+
Phone Number:
+
+

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

+ @*@(Model.PhoneNumber ?? "None") + @if (Model.PhoneNumber != null) + { +
+ Change +
+ [] +
+ } + else + { + Add + }*@ +
+ +
Two-Factor Authentication:
+
+

+ There are no two-factor authentication providers configured. See this article + for setting up this application to support two-factor authentication. +

+ @*@if (Model.TwoFactor) + { +
+ Enabled +
+ } + else + { +
+ Disabled +
+ }*@ +
+
+
diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Manage/ManageLogins.cshtml b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Manage/ManageLogins.cshtml new file mode 100644 index 000000000..35e12da68 --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Manage/ManageLogins.cshtml @@ -0,0 +1,54 @@ +@model ManageLoginsViewModel +@using Microsoft.AspNetCore.Http.Authentication +@{ + ViewData["Title"] = "Manage your external logins"; +} + +

@ViewData["Title"].

+ +

@ViewData["StatusMessage"]

+@if (Model.CurrentLogins.Count > 0) +{ +

Registered Logins

+ + + @for (var index = 0; index < Model.CurrentLogins.Count; index++) + { + + + + + } + +
@Model.CurrentLogins[index].LoginProvider + @if ((bool)ViewData["ShowRemoveButton"]) + { +
+
+ + + +
+
+ } + else + { + @:   + } +
+} +@if (Model.OtherLogins.Count > 0) +{ +

Add another service to log in.

+
+
+
+

+ @foreach (var provider in Model.OtherLogins) + { + + } +

+
+
+} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Manage/SetPassword.cshtml b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Manage/SetPassword.cshtml new file mode 100644 index 000000000..cfa779160 --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Manage/SetPassword.cshtml @@ -0,0 +1,38 @@ +@model SetPasswordViewModel +@{ + ViewData["Title"] = "Set Password"; +} + +

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

+ +
+

Set your password

+
+
+
+ +
+ + +
+
+
+ +
+ + +
+
+
+
+ +
+
+
+ +@section Scripts { + @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Manage/VerifyPhoneNumber.cshtml b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Manage/VerifyPhoneNumber.cshtml new file mode 100644 index 000000000..af7cd0b1f --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Manage/VerifyPhoneNumber.cshtml @@ -0,0 +1,30 @@ +@model VerifyPhoneNumberViewModel +@{ + ViewData["Title"] = "Verify Phone Number"; +} + +

@ViewData["Title"].

+ +
+ +

Add a phone number.

+
@ViewData["Status"]
+
+
+
+ +
+ + +
+
+
+
+ +
+
+
+ +@section Scripts { + @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Shared/Error.cshtml b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Shared/Error.cshtml new file mode 100644 index 000000000..229c2dead --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Shared/Error.cshtml @@ -0,0 +1,14 @@ +@{ + ViewData["Title"] = "Error"; +} + +

Error.

+

An error occurred while processing your request.

+ +

Development Mode

+

+ Swapping to Development environment will display more detailed information about the error that occurred. +

+

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

diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Shared/_Layout.cshtml b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Shared/_Layout.cshtml new file mode 100644 index 000000000..56827ca52 --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Shared/_Layout.cshtml @@ -0,0 +1,68 @@ + + + + + + @ViewData["Title"] - WebApplication + + + + + + + + + + + + +
+ @RenderBody() +
+
+

© 2016 - WebApplication

+
+
+ + + + + + + + + + + + + @RenderSection("scripts", required: false) + + diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Shared/_LoginPartial.cshtml b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Shared/_LoginPartial.cshtml new file mode 100644 index 000000000..f50d5e89e --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Shared/_LoginPartial.cshtml @@ -0,0 +1,26 @@ +@using Microsoft.AspNetCore.Identity +@using WebApplication.Models + +@inject SignInManager SignInManager +@inject UserManager UserManager + +@if (SignInManager.IsSignedIn(User)) +{ + +} +else +{ + +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Shared/_ValidationScriptsPartial.cshtml b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Shared/_ValidationScriptsPartial.cshtml new file mode 100644 index 000000000..289b22064 --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/Shared/_ValidationScriptsPartial.cshtml @@ -0,0 +1,14 @@ + + + + + + + + diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Views/_ViewImports.cshtml b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/_ViewImports.cshtml new file mode 100644 index 000000000..dcca16cb0 --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/_ViewImports.cshtml @@ -0,0 +1,6 @@ +@using WebApplication +@using WebApplication.Models +@using WebApplication.Models.AccountViewModels +@using WebApplication.Models.ManageViewModels +@using Microsoft.AspNetCore.Identity +@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/Views/_ViewStart.cshtml b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/_ViewStart.cshtml new file mode 100644 index 000000000..820a2f6e0 --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/Views/_ViewStart.cshtml @@ -0,0 +1,3 @@ +@{ + Layout = "_Layout"; +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/appsettings.json b/src/dotnet/commands/dotnet-new/CSharp_Web/appsettings.json new file mode 100644 index 000000000..53b17ae04 --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/appsettings.json @@ -0,0 +1,13 @@ +{ + "ConnectionStrings": { + "DefaultConnection": "Data Source=WebApplication.db" + }, + "Logging": { + "IncludeScopes": false, + "LogLevel": { + "Default": "Debug", + "System": "Information", + "Microsoft": "Information" + } + } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/bower.json b/src/dotnet/commands/dotnet-new/CSharp_Web/bower.json new file mode 100644 index 000000000..3891fce13 --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/bower.json @@ -0,0 +1,10 @@ +{ + "name": "webapplication", + "private": true, + "dependencies": { + "bootstrap": "3.3.6", + "jquery": "2.2.3", + "jquery-validation": "1.15.0", + "jquery-validation-unobtrusive": "3.2.6" + } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/gulpfile.js b/src/dotnet/commands/dotnet-new/CSharp_Web/gulpfile.js new file mode 100644 index 000000000..faf295540 --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/gulpfile.js @@ -0,0 +1,45 @@ +/// +"use strict"; + +var gulp = require("gulp"), + rimraf = require("rimraf"), + concat = require("gulp-concat"), + cssmin = require("gulp-cssmin"), + uglify = require("gulp-uglify"); + +var webroot = "./wwwroot/"; + +var paths = { + js: webroot + "js/**/*.js", + minJs: webroot + "js/**/*.min.js", + css: webroot + "css/**/*.css", + minCss: webroot + "css/**/*.min.css", + concatJsDest: webroot + "js/site.min.js", + concatCssDest: webroot + "css/site.min.css" +}; + +gulp.task("clean:js", function (cb) { + rimraf(paths.concatJsDest, cb); +}); + +gulp.task("clean:css", function (cb) { + rimraf(paths.concatCssDest, cb); +}); + +gulp.task("clean", ["clean:js", "clean:css"]); + +gulp.task("min:js", function () { + return gulp.src([paths.js, "!" + paths.minJs], { base: "." }) + .pipe(concat(paths.concatJsDest)) + .pipe(uglify()) + .pipe(gulp.dest(".")); +}); + +gulp.task("min:css", function () { + return gulp.src([paths.css, "!" + paths.minCss]) + .pipe(concat(paths.concatCssDest)) + .pipe(cssmin()) + .pipe(gulp.dest(".")); +}); + +gulp.task("min", ["min:js", "min:css"]); diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/package.json b/src/dotnet/commands/dotnet-new/CSharp_Web/package.json new file mode 100644 index 000000000..4bb6c884c --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/package.json @@ -0,0 +1,12 @@ +{ + "name": "webapplication", + "version": "0.0.0", + "private": true, + "devDependencies": { + "gulp": "3.9.1", + "gulp-concat": "2.6.0", + "gulp-cssmin": "0.1.7", + "gulp-uglify": "1.5.3", + "rimraf": "2.5.2" + } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/project.json.template b/src/dotnet/commands/dotnet-new/CSharp_Web/project.json.template new file mode 100644 index 000000000..e355cb2d8 --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/project.json.template @@ -0,0 +1,110 @@ +{ + "userSecretsId": "aspnet-WebApplication-0799fe3e-6eaf-4c5f-b40e-7c6bfd5dfa9a", + + "dependencies": { + "Microsoft.NETCore.App": { + "version": "1.0.0", + "type": "platform" + }, + "Microsoft.AspNetCore.Authentication.Cookies": "1.0.0", + "Microsoft.AspNetCore.Diagnostics": "1.0.0", + "Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore": "1.0.0", + "Microsoft.AspNetCore.Identity.EntityFrameworkCore": "1.0.0", + "Microsoft.AspNetCore.Mvc": "1.0.0", + "Microsoft.AspNetCore.Razor.Tools": { + "version": "1.0.0-preview2-final", + "type": "build" + }, + "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0", + "Microsoft.AspNetCore.Server.Kestrel": "1.0.0", + "Microsoft.AspNetCore.StaticFiles": "1.0.0", + "Microsoft.EntityFrameworkCore.Sqlite": "1.0.0", + "Microsoft.EntityFrameworkCore.Tools": { + "version": "1.0.0-preview2-final", + "type": "build" + }, + "Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0", + "Microsoft.Extensions.Configuration.Json": "1.0.0", + "Microsoft.Extensions.Configuration.UserSecrets": "1.0.0", + "Microsoft.Extensions.Logging": "1.0.0", + "Microsoft.Extensions.Logging.Console": "1.0.0", + "Microsoft.Extensions.Logging.Debug": "1.0.0", + "Microsoft.VisualStudio.Web.BrowserLink.Loader": "14.0.0", + "Microsoft.VisualStudio.Web.CodeGeneration.Tools": { + "version": "1.0.0-preview2-final", + "type": "build" + }, + "Microsoft.VisualStudio.Web.CodeGenerators.Mvc": { + "version": "1.0.0-preview2-final", + "type": "build" + } + }, + + "tools": { + "Microsoft.AspNetCore.Razor.Tools": { + "version": "1.0.0-preview2-final", + "imports": "portable-net45+win8+dnxcore50" + }, + "Microsoft.AspNetCore.Server.IISIntegration.Tools": { + "version": "1.0.0-preview2-final", + "imports": "portable-net45+win8+dnxcore50" + }, + "Microsoft.EntityFrameworkCore.Tools": { + "version": "1.0.0-preview2-final", + "imports": [ + "portable-net45+win8+dnxcore50", + "portable-net45+win8" + ] + }, + "Microsoft.Extensions.SecretManager.Tools": { + "version": "1.0.0-preview2-final", + "imports": "portable-net45+win8+dnxcore50" + }, + "Microsoft.VisualStudio.Web.CodeGeneration.Tools": { + "version": "1.0.0-preview2-final", + "imports": [ + "portable-net45+win8+dnxcore50", + "portable-net45+win8" + ] + } + }, + + "frameworks": { + "netcoreapp1.0": { + "imports": [ + "dotnet5.6", + "dnxcore50", + "portable-net45+win8" + ] + } + }, + + "buildOptions": { + "emitEntryPoint": true, + "preserveCompilationContext": true + }, + + "runtimeOptions": { + "configProperties": { + "System.GC.Server": true + } + }, + + "publishOptions": { + "include": [ + "wwwroot", + "Views", + "appsettings.json", + "web.config" + ] + }, + + "scripts": { + "prepublish": [ "npm install", "bower install", "gulp clean", "gulp min" ], + "postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ] + }, + + "tooling": { + "defaultNamespace": "WebApplication" + } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/web.config b/src/dotnet/commands/dotnet-new/CSharp_Web/web.config new file mode 100644 index 000000000..a8d667275 --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/web.config @@ -0,0 +1,14 @@ + + + + + + + + + + + + diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/wwwroot/css/site.css b/src/dotnet/commands/dotnet-new/CSharp_Web/wwwroot/css/site.css new file mode 100644 index 000000000..6baa84da1 --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/wwwroot/css/site.css @@ -0,0 +1,44 @@ +body { + padding-top: 50px; + padding-bottom: 20px; +} + +/* Wrapping element */ +/* Set some basic padding to keep content from hitting the edges */ +.body-content { + padding-left: 15px; + padding-right: 15px; +} + +/* Set widths on the form inputs since otherwise they're 100% wide */ +input, +select, +textarea { + max-width: 280px; +} + +/* Carousel */ +.carousel-caption p { + font-size: 20px; + line-height: 1.4; +} + +/* buttons and links extension to use brackets: [ click me ] */ +.btn-bracketed::before { + display:inline-block; + content: "["; + padding-right: 0.5em; +} +.btn-bracketed::after { + display:inline-block; + content: "]"; + padding-left: 0.5em; +} + +/* Hide/rearrange for smaller screens */ +@media screen and (max-width: 767px) { + /* Hide captions */ + .carousel-caption { + display: none + } +} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/wwwroot/css/site.min.css b/src/dotnet/commands/dotnet-new/CSharp_Web/wwwroot/css/site.min.css new file mode 100644 index 000000000..c8f600ac5 --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/wwwroot/css/site.min.css @@ -0,0 +1 @@ +body{padding-top:50px;padding-bottom:20px}.body-content{padding-left:15px;padding-right:15px}input,select,textarea{max-width:280px}.carousel-caption p{font-size:20px;line-height:1.4}.btn-bracketed::before{display:inline-block;content:"[";padding-right:.5em}.btn-bracketed::after{display:inline-block;content:"]";padding-left:.5em}@media screen and (max-width:767px){.carousel-caption{display:none}} diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/wwwroot/favicon.ico b/src/dotnet/commands/dotnet-new/CSharp_Web/wwwroot/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..a3a799985c43bc7309d701b2cad129023377dc71 GIT binary patch literal 32038 zcmeHwX>eTEbtY7aYbrGrkNjgie?1jXjZ#zP%3n{}GObKv$BxI7Sl;Bwl5E+Qtj&t8 z*p|m4DO#HoJC-FyvNnp8NP<{Na0LMnTtO21(rBP}?EAiNjWgeO?z`{3ZoURUQlV2d zY1Pqv{m|X_oO91|?^z!6@@~od!@OH>&BN;>c@O+yUfy5w>LccTKJJ&`-k<%M^Zvi( z<$dKp=jCnNX5Qa+M_%6g|IEv~4R84q9|7E=|Ho(Wz3f-0wPjaRL;W*N^>q%^KGRr7 zxbjSORb_c&eO;oV_DZ7ua!sPH=0c+W;`vzJ#j~-x3uj};50#vqo*0w4!LUqs*UCh9 zvy2S%$#8$K4EOa&e@~aBS65_hc~Mpu=454VT2^KzWqEpBA=ME|O;1cn?8p<+{MKJf zbK#@1wzL44m$k(?85=Obido7=C|xWKe%66$z)NrzRwR>?hK?_bbwT z@Da?lBrBL}Zemo1@!9pYRau&!ld17h{f+UV0sY(R{ET$PBB|-=Nr@l-nY6w8HEAw* zRMIQU`24Jl_IFEPcS=_HdrOP5yf81z_?@M>83Vv65$QFr9nPg(wr`Ke8 zaY4ogdnMA*F7a4Q1_uXadTLUpCk;$ZPRRJ^sMOch;rlbvUGc1R9=u;dr9YANbQ<4Z z#P|Cp9BP$FXNPolgyr1XGt$^lFPF}rmBF5rj1Kh5%dforrP8W}_qJL$2qMBS-#%-|s#BPZBSETsn_EBYcr(W5dq( z@f%}C|iN7)YN`^)h7R?Cg}Do*w-!zwZb9=BMp%Wsh@nb22hA zA{`wa8Q;yz6S)zfo%sl08^GF`9csI9BlGnEy#0^Y3b);M+n<(}6jziM7nhe57a1rj zC@(2ISYBL^UtWChKzVWgf%4LW2Tqg_^7jMw`C$KvU+mcakFjV(BGAW9g%CzSyM;Df z143=mq0oxaK-H;o>F3~zJ<(3-j&?|QBn)WJfP#JR zRuA;`N?L83wQt78QIA$(Z)lGQY9r^SFal;LB^qi`8%8@y+mwcGsf~nv)bBy2S7z~9 z=;X@Gglk)^jpbNz?1;`!J3QUfAOp4U$Uxm5>92iT`mek#$>s`)M>;e4{#%HAAcb^8_Ax%ersk|}# z0bd;ZPu|2}18KtvmIo8`1@H~@2ejwo(5rFS`Z4&O{$$+ch2hC0=06Jh`@p+p8LZzY z&2M~8T6X^*X?yQ$3N5EzRv$(FtSxhW>>ABUyp!{484f8(%C1_y)3D%Qgfl_!sz`LTXOjR&L!zPA0qH_iNS!tY{!^2WfD%uT}P zI<~&?@&))5&hPPHVRl9);TPO>@UI2d!^ksb!$9T96V(F){puTsn(}qt_WXNw4VvHj zf;6A_XCvE`Z@}E-IOaG0rs>K>^=Sr&OgT_p;F@v0VCN0Y$r|Lw1?Wjt`AKK~RT*kJ z2>QPuVgLNcF+XKno;WBv$yj@d_WFJbl*#*V_Cwzo@%3n5%z4g21G*PVZ)wM5$A{klYozmGlB zT@u2+s}=f}25%IA!yNcXUr!!1)z(Nqbhojg0lv@7@0UlvUMT)*r;M$d0-t)Z?B1@qQk()o!4fqvfr_I0r7 zy1(NdkHEj#Yu{K>T#We#b#FD=c1XhS{hdTh9+8gy-vkcdkk*QS@y(xxEMb1w6z<^~ zYcETGfB#ibR#ql0EiD;PR$L&Vrh2uRv5t_$;NxC;>7_S5_OXxsi8udY3BUUdi55Sk zcyKM+PQ9YMA%D1kH1q48OFG(Gbl=FmV;yk8o>k%0$rJ8%-IYsHclnYuTskkaiCGkUlkMY~mx&K}XRlKIW;odWIeuKjtbc^8bBOTqK zjj(ot`_j?A6y_h%vxE9o*ntx#PGrnK7AljD_r58ylE*oy@{IY%+mA^!|2vW_`>`aC{#3`#3;D_$^S^cM zRcF+uTO2sICledvFgNMU@A%M)%8JbSLq{dD|2|2Sg8vvh_uV6*Q?F&rKaV{v_qz&y z`f;stIb?Cb2!Cg7CG91Bhu@D@RaIrq-+o+T2fwFu#|j>lD6ZS9-t^5cx>p|?flqUA z;Cgs#V)O#`Aw4$Kr)L5?|7f4izl!;n0jux}tEW$&&YBXz9o{+~HhoiYDJ`w5BVTl&ARya=M7zdy$FEe}iGBur8XE>rhLj&_yDk5D4n2GJZ07u7%zyAfNtOLn;)M?h*Py-Xtql5aJOtL4U8e|!t? z((sc6&OJXrPdVef^wZV&x=Z&~uA7^ix8rly^rEj?#d&~pQ{HN8Yq|fZ#*bXn-26P^ z5!)xRzYO9{u6vx5@q_{FE4#7BipS#{&J7*>y}lTyV94}dfE%Yk>@@pDe&F7J09(-0|wuI|$of-MRfK51#t@t2+U|*s=W; z!Y&t{dS%!4VEEi$efA!#<<7&04?kB}Soprd8*jYv;-Qj~h~4v>{XX~kjF+@Z7<t?^|i z#>_ag2i-CRAM8Ret^rZt*^K?`G|o>1o(mLkewxyA)38k93`<~4VFI?5VB!kBh%NNU zxb8K(^-MU1ImWQxG~nFB-Un;6n{lQz_FfsW9^H$Xcn{;+W^ZcG$0qLM#eNV=vGE@# z1~k&!h4@T|IiI<47@pS|i?Qcl=XZJL#$JKve;booMqDUYY{(xcdj6STDE=n?;fsS1 ze`h~Q{CT$K{+{t+#*I1=&&-UU8M&}AwAxD-rMa=e!{0gQXP@6azBq9(ji11uJF%@5 zCvV`#*?;ZguQ7o|nH%bm*s&jLej#@B35gy32ZAE0`Pz@#j6R&kN5w{O4~1rhDoU zEBdU)%Nl?8zi|DR((u|gg~r$aLYmGMyK%FO*qLvwxK5+cn*`;O`16c!&&XT{$j~5k zXb^fbh1GT-CI*Nj{-?r7HNg=e3E{6rxuluPXY z5Nm8ktc$o4-^SO0|Es_sp!A$8GVwOX+%)cH<;=u#R#nz;7QsHl;J@a{5NUAmAHq4D zIU5@jT!h?kUp|g~iN*!>jM6K!W5ar0v~fWrSHK@})@6Lh#h)C6F6@)&-+C3(zO! z8+kV|B7LctM3DpI*~EYo>vCj>_?x&H;>y0*vKwE0?vi$CLt zfSJB##P|M2dEUDBPKW=9cY-F;L;h3Fs4E2ERdN#NSL7ctAC z?-}_a{*L@GA7JHJudxtDVA{K5Yh*k(%#x4W7w+^ zcb-+ofbT5ieG+@QG2lx&7!MyE2JWDP@$k`M;0`*d+oQmJ2A^de!3c53HFcfW_Wtv< zKghQ;*FifmI}kE4dc@1y-u;@qs|V75Z^|Q0l0?teobTE8tGl@EB?k#q_wUjypJ*R zyEI=DJ^Z+d*&}B_xoWvs27LtH7972qqMxVFcX9}c&JbeNCXUZM0`nQIkf&C}&skSt z^9fw@b^Hb)!^hE2IJq~~GktG#ZWwWG<`@V&ckVR&r=JAO4YniJewVcG`HF;59}=bf zLyz0uxf6MhuSyH#-^!ZbHxYl^mmBVrx) zyrb8sQ*qBd_WXm9c~Of$&ZP$b^)<~0%nt#7y$1Jg$e}WCK>TeUB{P>|b1FAB?%K7>;XiOfd}JQ`|IP#Vf%kVy zXa4;XFZ+>n;F>uX&3|4zqWK2u3c<>q;tzjsb1;d{u;L$-hq3qe@82(ob<3qom#%`+ z;vzYAs7TIMl_O75BXu|r`Qhc4UT*vN$3Oo0kAC!{f2#HexDy|qUpgTF;k{o6|L>7l z=?`=*LXaow1o;oNNLXsGTrvC)$R&{m=94Tf+2iTT3Y_Or z-!;^0a{kyWtO4vksG_3cyc7HQ0~detf0+2+qxq(e1NS251N}w5iTSrM)`0p8rem!j zZ56hGD=pHI*B+dd)2B`%|9f0goozCSeXPw3 z+58k~sI02Yz#lOneJzYcG)EB0|F+ggC6D|B`6}d0khAK-gz7U3EGT|M_9$ZINqZjwf>P zJCZ=ogSoE`=yV5YXrcTQZx@Un(64*AlLiyxWnCJ9I<5Nc*eK6eV1Mk}ci0*NrJ=t| zCXuJG`#7GBbPceFtFEpl{(lTm`LX=B_!H+& z>$*Hf}}y zkt@nLXFG9%v**s{z&{H4e?aqp%&l#oU8lxUxk2o%K+?aAe6jLojA& z_|J0<-%u^<;NT*%4)n2-OdqfctSl6iCHE?W_Q2zpJken#_xUJlidzs249H=b#g z?}L4-Tnp6)t_5X?_$v)vz`s9@^BME2X@w<>sKZ3=B{%*B$T5Nj%6!-Hr;I!Scj`lH z&2dHFlOISwWJ&S2vf~@I4i~(0*T%OFiuX|eD*nd2utS4$1_JM?zmp>a#CsVy6Er^z zeNNZZDE?R3pM?>~e?H_N`C`hy%m4jb;6L#8=a7l>3eJS2LGgEUxsau-Yh9l~o7=Yh z2mYg3`m5*3Ik|lKQf~euzZlCWzaN&=vHuHtOwK!2@W6)hqq$Zm|7`Nmu%9^F6UH?+ z@2ii+=iJ;ZzhiUKu$QB()nKk3FooI>Jr_IjzY6=qxYy;&mvi7BlQ?t4kRjIhb|2q? zd^K~{-^cxjVSj?!Xs=Da5IHmFzRj!Kzh~b!?`P7c&T9s77VLYB?8_?F zauM^)p;qFG!9PHLfIsnt43UnmV?Wn?Ki7aXSosgq;f?MYUuSIYwOn(5vWhb{f%$pn z4ySN-z}_%7|B);A@PA5k*7kkdr4xZ@s{e9j+9w;*RFm;XPDQwx%~;8iBzSKTIGKO z{53ZZU*OLr@S5=k;?CM^i#zkxs3Sj%z0U`L%q`qM+tP zX$aL;*^g$7UyM2Go+_4A+f)IQcy^G$h2E zb?nT$XlgTEFJI8GN6NQf%-eVn9mPilRqUbT$pN-|;FEjq@Ao&TxpZg=mEgBHB zU@grU;&sfmqlO=6|G3sU;7t8rbK$?X0y_v9$^{X`m4jZ_BR|B|@?ZCLSPPEzz`w1n zP5nA;4(kQFKm%$enjkkBxM%Y}2si&d|62L)U(dCzCGn56HN+i#6|nV-TGIo0;W;`( zW-y=1KF4dp$$mC_|6}pbb>IHoKQeZajXQB>jVR?u`R>%l1o54?6NnS*arpVopdEF; zeC5J3*M0p`*8lif;!irrcjC?(uExejsi~>4wKYwstGY^N@KY}TujLx`S=Cu+T=!dx zKWlPm->I**E{A*q-Z^FFT5$G%7Ij0_*Mo4-y6~RmyTzUB&lfae(WZfO>um}mnsDXPEbau-!13!!xd!qh*{C)6&bz0j1I{>y$D-S)b*)JMCPk!=~KL&6Ngin0p6MCOxF2L_R9t8N!$2Wpced<#`y!F;w zKTi5V_kX&X09wAIJ#anfg9Dhn0s7(C6Nj3S-mVn(i|C6ZAVq0$hE)874co};g z^hR7pe4lU$P;*ggYc4o&UTQC%liCXooIfkI3TNaBV%t~FRr}yHu7kjQ2J*3;e%;iW zvDVCh8=G80KAeyhCuY2LjrC!Od1rvF7h}zszxGV)&!)6ChP5WAjv-zQAMNJIG!JHS zwl?pLxC-V5II#(hQ`l)ZAp&M0xd4%cxmco*MIk?{BD=BK`1vpc}D39|XlV z{c&0oGdDa~TL2FT4lh=~1NL5O-P~0?V2#ie`v^CnANfGUM!b4F=JkCwd7Q`c8Na2q zJGQQk^?6w}Vg9-{|2047((lAV84uN%sK!N2?V(!_1{{v6rdgZl56f0zDMQ+q)jKzzu^ztsVken;=DjAh6G`Cw`Q4G+BjS+n*=KI~^K{W=%t zbD-rN)O4|*Q~@<#@1Vx$E!0W9`B~IZeFn87sHMXD>$M%|Bh93rdGf1lKoX3K651t&nhsl= zXxG|%@8}Bbrlp_u#t*DZX<}_0Yb{A9*1Pd_)LtqNwy6xT4pZrOY{s?N4)pPwT(i#y zT%`lRi8U#Ken4fw>H+N`{f#FF?ZxFlLZg7z7#cr4X>id z{9kUD`d2=w_Zlb{^c`5IOxWCZ1k<0T1D1Z31IU0Q2edsZ1K0xv$pQVYq2KEp&#v#Z z?{m@Lin;*Str(C2sfF^L>{R3cjY`~#)m>Wm$Y|1fzeS0-$(Q^z@} zEO*vlb-^XK9>w&Ef^=Zzo-1AFSP#9zb~X5_+){$(eB4K z8gtW+nl{q+CTh+>v(gWrsP^DB*ge(~Q$AGxJ-eYc1isti%$%nM<_&Ev?%|??PK`$p z{f-PM{Ym8k<$$)(F9)tqzFJ?h&Dk@D?Dt{4CHKJWLs8$zy6+(R)pr@0ur)xY{=uXFFzH_> z-F^tN1y(2hG8V)GpDg%wW0Px_ep~nIjD~*HCSxDi0y`H!`V*~RHs^uQsb1*bK1qGpmd zB1m`Cjw0`nLBF2|umz+a#2X$c?Lj;M?Lj;MUp*d>7j~ayNAyj@SLpeH`)BgRH}byy zyQSat!;U{@O(<<2fp&oQkIy$z`_CQ-)O@RN;QD9T4y|wIJ^%U#(BF%=`i49}j!D-) zkOwPSJaG03SMkE~BzW}b_v>LA&y)EEYO6sbdnTX*$>UF|JhZ&^MSb4}Tgbne_4n+C zwI8U4i~PI>7a3{kVa8|))*%C0|K+bIbmV~a`|G#+`TU#g zXW;bWIcWsQi9c4X*RUDpIfyoPY)2bI-r9)xulm1CJDkQd6u+f)_N=w1ElgEBjprPF z3o?Ly0RVeY_{3~fPVckRMxe2lM8hj!B8F)JO z!`AP6>u>5Y&3o9t0QxBpNE=lJx#NyIbp1gD zzUYBIPYHIv9ngk-Zt~<)62^1Zs1LLYMh@_tP^I7EX-9)Ed0^@y{k65Gp0KRcTmMWw zU|+)qx{#q0SL+4q?Q`i0>COIIF8a0Cf&C`hbMj?LmG9K&iW-?PJt*u)38tTXAP>@R zZL6uH^!RYNq$p>PKz7f-zvg>OKXcZ8h!%Vo@{VUZp|+iUD_xb(N~G|6c#oQK^nHZU zKg#F6<)+`rf~k*Xjjye+syV{bwU2glMMMs-^ss4`bYaVroXzn`YQUd__UlZL_mLs z(vO}k!~(mi|L+(5&;>r<;|OHnbXBE78LruP;{yBxZ6y7K3)nMo-{6PCI7gQi6+rF_ zkPod!Z8n}q46ykrlQS|hVB(}(2Kf7BCZ>Vc;V>ccbk2~NGaf6wGQH@W9&?Zt3v(h*P4xDrN>ex7+jH*+Qg z%^jH$&+*!v{sQ!xkWN4+>|b}qGvEd6ANzgqoVy5Qfws}ef2QqF{iiR5{pT}PS&yjo z>lron#va-p=v;m>WB+XVz|o;UJFdjo5_!RRD|6W{4}A2a#bZv)gS_`b|KsSH)Sd_JIr%<%n06TX&t{&!H#{)?4W9hlJ`R1>FyugOh3=D_{einr zu(Wf`qTkvED+gEULO0I*Hs%f;&=`=X4;N8Ovf28x$A*11`dmfy2=$+PNqX>XcG`h% zJY&A6@&)*WT^rC(Caj}2+|X|6cICm5h0OK0cGB_!wEKFZJU)OQ+TZ1q2bTx9hxnq& z$9ee|f9|0M^)#E&Pr4)f?o&DMM4w>Ksb{hF(0|wh+5_{vPow{V%TFzU2za&gjttNi zIyR9qA56dX52Qbv2aY^g`U7R43-p`#sO1A=KS2aKgfR+Yu^bQ*i-qu z%0mP;Ap)B~zZgO9lG^`325gOf?iUHF{~7jyGC)3L(eL(SQ70VzR~wLN18tnx(Cz2~ zctBl1kI)wAe+cxWHw*NW-d;=pd+>+wd$a@GBju*wFvabSaPtHiT!o#QFC+wBVwYo3s=y;z1jM+M=Fj!FZM>UzpL-eZzOT( zhmZmEfWa=%KE#V3-ZK5#v!Hzd{zc^{ctF~- z>DT-U`}5!fk$aj24`#uGdB7r`>oX5tU|d*b|N3V1lXmv%MGrvE(dXG)^-J*LA>$LE z7kut4`zE)v{@Op|(|@i#c>tM!12FQh?}PfA0`Bp%=%*RiXVzLDXnXtE@4B)5uR}a> zbNU}q+712pIrM`k^odG8dKtG$zwHmQI^c}tfjx5?egx3!e%JRm_64e+>`Ra1IRfLb z1KQ`SxmH{cZfyVS5m(&`{V}Y4j6J{b17`h6KWqZ&hfc(oR zxM%w!$F(mKy05kY&lco3%zvLCxBW+t*rxO+i=qGMvobx0-<7`VUu)ka`){=ew+Ovt zg%52_{&UbkUA8aJPWsk)gYWV4`dnxI%s?7^fGpq{ZQuu=VH{-t7w~K%_E<8`zS;V- zKTho*>;UQQul^1GT^HCt@I-q?)&4!QDgBndn?3sNKYKCQFU4LGKJ$n@Je$&w9@E$X z^p@iJ(v&`1(tq~1zc>0Vow-KR&vm!GUzT?Eqgnc)leZ9p)-Z*C!zqb=-$XG0 z^!8RfuQs5s>Q~qcz92(a_Q+KH?C*vCTr~UdTiR`JGuNH8v(J|FTiSEcPrBpmHRtmd zI2Jng0J=bXK);YY^rM?jzn?~X-Pe`GbAy{D)Y6D&1GY-EBcy%Bq?bKh?A>DD9DD!p z?{q02wno2sraGUkZv5dx+J8)&K$)No43Zr(*S`FEdL!4C)}WE}vJd%{S6-3VUw>Wp z?Aasv`T0^%P$2vE?L+Qhj~qB~K%eW)xH(=b_jU}TLD&BP*Pc9hz@Z=e0nkpLkWl}> z_5J^i(9Z7$(XG9~I3sY)`OGZ#_L06+Dy4E>UstcP-rU@xJ$&rxvo!n1Ao`P~KLU-8 z{zDgN4-&A6N!kPSYbQ&7sLufi`YtE2uN$S?e&5n>Y4(q#|KP!cc1j)T^QrUXMPFaP z_SoYO8S8G}Z$?AL4`;pE?7J5K8yWqy23>cCT2{=-)+A$X^-I9=e!@J@A&-;Ufc)`H}c(VI&;0x zrrGv()5mjP%jXzS{^|29?bLNXS0bC%p!YXI!;O457rjCEEzMkGf~B3$T}dXBO23tP z+Ci>;5UoM?C@bU@f9G1^X3=ly&ZeFH<@|RnOG--A&)fd)AUgjw?%izq{p(KJ`EP0v z2mU)P!+3t@X14DA=E2RR-|p${GZ9ETX=d+kJRZL$nSa0daI@&oUUxnZg0xd_xu>Vz lzF#z5%kSKX?YLH3ll^(hI(_`L*t#Iva2Ede*Z;>H_ \ No newline at end of file diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/wwwroot/images/banner2.svg b/src/dotnet/commands/dotnet-new/CSharp_Web/wwwroot/images/banner2.svg new file mode 100644 index 000000000..9679c604d --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/wwwroot/images/banner2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/wwwroot/images/banner3.svg b/src/dotnet/commands/dotnet-new/CSharp_Web/wwwroot/images/banner3.svg new file mode 100644 index 000000000..9be2c2503 --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/wwwroot/images/banner3.svg @@ -0,0 +1 @@ +banner3b \ No newline at end of file diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/wwwroot/images/banner4.svg b/src/dotnet/commands/dotnet-new/CSharp_Web/wwwroot/images/banner4.svg new file mode 100644 index 000000000..38b3d7cd1 --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/wwwroot/images/banner4.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/wwwroot/js/site.js b/src/dotnet/commands/dotnet-new/CSharp_Web/wwwroot/js/site.js new file mode 100644 index 000000000..e069226a1 --- /dev/null +++ b/src/dotnet/commands/dotnet-new/CSharp_Web/wwwroot/js/site.js @@ -0,0 +1 @@ +// Write your Javascript code. diff --git a/src/dotnet/commands/dotnet-new/CSharp_Web/wwwroot/js/site.min.js b/src/dotnet/commands/dotnet-new/CSharp_Web/wwwroot/js/site.min.js new file mode 100644 index 000000000..e69de29bb diff --git a/src/dotnet/commands/dotnet-new/Program.cs b/src/dotnet/commands/dotnet-new/Program.cs index 969dccdd0..ff7f30916 100644 --- a/src/dotnet/commands/dotnet-new/Program.cs +++ b/src/dotnet/commands/dotnet-new/Program.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; +using System.IO.Compression; namespace Microsoft.DotNet.Tools.New { @@ -19,12 +20,6 @@ namespace Microsoft.DotNet.Tools.New return null; } - // filename.extension.template - if (parts.Length > 2 && string.Equals("template", parts[parts.Length - 1], StringComparison.OrdinalIgnoreCase)) - { - return parts[parts.Length - 3] + "." + parts[parts.Length - 2]; - } - // filename.extension return parts[parts.Length - 2] + "." + parts[parts.Length - 1]; } @@ -42,11 +37,23 @@ namespace Microsoft.DotNet.Tools.New { string fileName = GetFileNameFromResourceName(resourceName); - resourceNameToFileName.Add(resourceName, fileName); - if (File.Exists(fileName)) + using (var resource = thisAssembly.GetManifestResourceStream(resourceName)) { - Reporter.Error.WriteLine($"Creating new {languageName} project would override file {fileName}."); - hasFilesToOverride = true; + var archive = new ZipArchive(resource); + + try + { + archive.ExtractToDirectory(Directory.GetCurrentDirectory()); + + File.Move( + Path.Combine(Directory.GetCurrentDirectory(), "project.json.template"), + Path.Combine(Directory.GetCurrentDirectory(), "project.json")); + } + catch (IOException ex) + { + Reporter.Error.WriteLine(ex.Message); + hasFilesToOverride = true; + } } } @@ -56,17 +63,6 @@ namespace Microsoft.DotNet.Tools.New return 1; } - foreach (var kv in resourceNameToFileName) - { - using (var fileStream = File.Create(kv.Value)) - { - using (var resource = thisAssembly.GetManifestResourceStream(kv.Key)) - { - resource.CopyTo(fileStream); - } - } - } - Reporter.Output.WriteLine($"Created new {languageName} project in {Directory.GetCurrentDirectory()}."); return 0; @@ -88,7 +84,7 @@ namespace Microsoft.DotNet.Tools.New var dotnetNew = new NewCommand(); app.OnExecute(() => { - var csharp = new { Name = "C#", Alias = new[] { "c#", "cs", "csharp" }, TemplatePrefix = "CSharp", Templates = new[] { "Console" } }; + var csharp = new { Name = "C#", Alias = new[] { "c#", "cs", "csharp" }, TemplatePrefix = "CSharp", Templates = new[] { "Console", "Web" } }; var fsharp = new { Name = "F#", Alias = new[] { "f#", "fs", "fsharp" }, TemplatePrefix = "FSharp", Templates = new[] { "Console" } }; string languageValue = lang.Value() ?? csharp.Name; diff --git a/src/dotnet/commands/dotnet-new/README.md b/src/dotnet/commands/dotnet-new/README.md index 05592ad73..8968d1f9a 100644 --- a/src/dotnet/commands/dotnet-new/README.md +++ b/src/dotnet/commands/dotnet-new/README.md @@ -29,7 +29,7 @@ Language of project. Defaults to `C##`. Also `csharp` ( `fsharp` ) or `cs` ( `fs `-t`, `--type` -Type of the project. Valid value is "console". +Type of the project. Valid values are "console" and "web". ## EXAMPLES diff --git a/src/dotnet/project.json b/src/dotnet/project.json index 3a1595060..387fe5c73 100644 --- a/src/dotnet/project.json +++ b/src/dotnet/project.json @@ -4,18 +4,16 @@ "emitEntryPoint": true, "embed": { "include": [ - "commands/dotnet-new/CSharp_Console/NuGet.Config", - "commands/dotnet-new/CSharp_Console/Program.cs", - "commands/dotnet-new/CSharp_Console/project.json.template", - "commands/dotnet-new/FSharp_Console/NuGet.config", - "commands/dotnet-new/FSharp_Console/Program.fs", - "commands/dotnet-new/FSharp_Console/project.json.template" + "commands/dotnet-new/CSharp_Console.zip", + "commands/dotnet-new/FSharp_Console.zip", + "commands/dotnet-new/CSharp_Web.zip" ] }, "compile": { "exclude": [ "commands/dotnet-new/CSharp_Console/**", - "commands/dotnet-new/FSharp_Console/**" + "commands/dotnet-new/FSharp_Console/**", + "commands/dotnet-new/CSharp_Web/**" ] } },