Tags { get; internal set; }
+ }
+}
diff --git a/FoneDynamics/FoneDynamics/Pages/Error.cshtml b/FoneDynamics/FoneDynamics/Pages/Error.cshtml
new file mode 100644
index 0000000..6f92b95
--- /dev/null
+++ b/FoneDynamics/FoneDynamics/Pages/Error.cshtml
@@ -0,0 +1,26 @@
+@page
+@model ErrorModel
+@{
+ ViewData["Title"] = "Error";
+}
+
+Error.
+An error occurred while processing your request.
+
+@if (Model.ShowRequestId)
+{
+
+ Request ID: @Model.RequestId
+
+}
+
+Development Mode
+
+ Swapping to the Development environment displays detailed information about the error that occurred.
+
+
+ The Development environment shouldn't be enabled for deployed applications.
+ It can result in displaying sensitive information from exceptions to end users.
+ For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development
+ and restarting the app.
+
diff --git a/FoneDynamics/FoneDynamics/Pages/Error.cshtml.cs b/FoneDynamics/FoneDynamics/Pages/Error.cshtml.cs
new file mode 100644
index 0000000..931a810
--- /dev/null
+++ b/FoneDynamics/FoneDynamics/Pages/Error.cshtml.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.RazorPages;
+using Microsoft.Extensions.Logging;
+
+namespace FoneDynamics.Pages
+{
+ [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
+ public class ErrorModel : PageModel
+ {
+ private readonly ILogger _logger;
+
+ public ErrorModel(ILogger logger)
+ {
+ _logger = logger;
+ }
+
+ public string RequestId { get; set; }
+
+ public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
+
+ public void OnGet()
+ {
+ RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
+ }
+ }
+}
diff --git a/FoneDynamics/FoneDynamics/Pages/_ViewImports.cshtml b/FoneDynamics/FoneDynamics/Pages/_ViewImports.cshtml
new file mode 100644
index 0000000..f4223e8
--- /dev/null
+++ b/FoneDynamics/FoneDynamics/Pages/_ViewImports.cshtml
@@ -0,0 +1,3 @@
+@using FoneDynamics
+@namespace FoneDynamics.Pages
+@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
diff --git a/FoneDynamics/FoneDynamics/Program.cs b/FoneDynamics/FoneDynamics/Program.cs
new file mode 100644
index 0000000..cf841c3
--- /dev/null
+++ b/FoneDynamics/FoneDynamics/Program.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Hosting;
+using Microsoft.Extensions.Logging;
+
+namespace FoneDynamics
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ CreateHostBuilder(args).Build().Run();
+ }
+
+ public static IHostBuilder CreateHostBuilder(string[] args) =>
+ Host.CreateDefaultBuilder(args)
+ .ConfigureWebHostDefaults(webBuilder =>
+ {
+ webBuilder.UseStartup();
+ });
+ }
+}
diff --git a/FoneDynamics/FoneDynamics/Properties/launchSettings.json b/FoneDynamics/FoneDynamics/Properties/launchSettings.json
new file mode 100644
index 0000000..7189537
--- /dev/null
+++ b/FoneDynamics/FoneDynamics/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:59267",
+ "sslPort": 44363
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "FoneDynamics": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:5001;http://localhost:5000",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/FoneDynamics/FoneDynamics/Startup.cs b/FoneDynamics/FoneDynamics/Startup.cs
new file mode 100644
index 0000000..6f81a0a
--- /dev/null
+++ b/FoneDynamics/FoneDynamics/Startup.cs
@@ -0,0 +1,88 @@
+using FoneDynamics.Helpers;
+using Microsoft.AspNetCore.Authentication.JwtBearer;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.HttpsPolicy;
+using Microsoft.AspNetCore.SpaServices.AngularCli;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Microsoft.IdentityModel.Tokens;
+
+namespace FoneDynamics
+{
+ public class Startup
+ {
+ public Startup(IConfiguration configuration)
+ {
+ Configuration = configuration;
+ }
+
+ public IConfiguration Configuration { get; }
+
+ // This method gets called by the runtime. Use this method to add services to the container.
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
+ .AddJwtBearer(options => {
+ options.TokenValidationParameters = new TokenValidationParameters
+ {
+ ValidateIssuer = true,
+ ValidateAudience = true,
+ ValidateIssuerSigningKey = true,
+ ValidIssuer = AuthConfiguration.ValidIssuer,
+ ValidAudience = AuthConfiguration.ValidAudience,
+ IssuerSigningKey = AuthConfiguration.SymmetricSecurityKey
+ };
+ });
+ services.AddControllersWithViews();
+
+ services.AddSpaStaticFiles(configuration =>
+ {
+ configuration.RootPath = "ClientApp/dist";
+ });
+ }
+
+ // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ {
+ if (env.IsDevelopment())
+ {
+ app.UseDeveloperExceptionPage();
+ }
+ else
+ {
+ app.UseExceptionHandler("/Home/Error");
+ // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
+ app.UseHsts();
+ }
+
+ app.UseAuthentication();
+ app.UseHttpsRedirection();
+ app.UseStaticFiles();
+ app.UseRouting();
+
+ app.UseAuthorization();
+
+ app.UseEndpoints(endpoints =>
+ {
+ endpoints.MapControllerRoute(
+ name: "default",
+ pattern: "{controller=Home}/{action=Index}/{id?}");
+ });
+
+ app.UseSpa(spa =>
+ {
+ // To learn more about options for serving an Angular SPA from ASP.NET Core,
+ // see https://go.microsoft.com/fwlink/?linkid=864501
+
+ spa.Options.SourcePath = "ClientApp";
+
+ if (env.IsDevelopment())
+ {
+ spa.UseAngularCliServer(npmScript: "start");
+ }
+ });
+ }
+ }
+}
diff --git a/FoneDynamics/FoneDynamics/WeatherForecast.cs b/FoneDynamics/FoneDynamics/WeatherForecast.cs
new file mode 100644
index 0000000..f2f0d2b
--- /dev/null
+++ b/FoneDynamics/FoneDynamics/WeatherForecast.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace FoneDynamics
+{
+ public class WeatherForecast
+ {
+ public DateTime Date { get; set; }
+
+ public int TemperatureC { get; set; }
+
+ public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
+
+ public string Summary { get; set; }
+ }
+}
diff --git a/FoneDynamics/FoneDynamics/appsettings.Development.json b/FoneDynamics/FoneDynamics/appsettings.Development.json
new file mode 100644
index 0000000..8983e0f
--- /dev/null
+++ b/FoneDynamics/FoneDynamics/appsettings.Development.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ }
+}
diff --git a/FoneDynamics/FoneDynamics/appsettings.json b/FoneDynamics/FoneDynamics/appsettings.json
new file mode 100644
index 0000000..ad75fee
--- /dev/null
+++ b/FoneDynamics/FoneDynamics/appsettings.json
@@ -0,0 +1,10 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ },
+"AllowedHosts": "*"
+}
diff --git a/FoneDynamics/FoneDynamics/exercise.yaml b/FoneDynamics/FoneDynamics/exercise.yaml
new file mode 100644
index 0000000..58affcc
--- /dev/null
+++ b/FoneDynamics/FoneDynamics/exercise.yaml
@@ -0,0 +1,92 @@
+---
+auth:
+ - password: password123
+ username: john
+ - password: 149037y5
+ username: jane
+ - password: idfs9302ks2012
+ username: nick
+ - password: kd93jkd832jd
+ username: james
+customers:
+ - id: f312b57e-a655-4a35-b27f-416c464c3730
+ num_employees: 4
+ name: Fancy Pants
+ tags:
+ - commercial
+ - clothing
+ - pants
+ - id: 999d1860-d809-4296-a206-bb8ee114e3c5
+ name: Jimmys Bar
+ num_employees: 3
+ tags:
+ - commercial
+ - bar
+ - alcohol
+ - id: 41fe1ef3-717f-4f2d-9f77-11eb6b9a0e40
+ name: Tabletop Adventures
+ num_employees: 43
+ tags:
+ - commercial
+ - clothing
+ - id: 333314c1-cfa1-4caa-942c-41cc9e54902c
+ name: Sports Store
+ num_employees: 34
+ tags:
+ - commercial
+ - sports
+ - clothing
+ - id: dab6f5d2-6067-49ab-b82a-53b48a319a15
+ name: Peters Plants
+ num_employees: 32
+ tags:
+ - commercial
+ - gardening
+ - id: 682269e6-a8c9-4406-a1b6-656d163ab248
+ name: Potsys Pots
+ num_employees: 29
+ tags:
+ - industrial
+ - gardening
+ - pottery
+ - id: f5da32de-cb97-4a35-961d-230e4e20b6bf
+ name: Shirts n More
+ num_employees: 3834
+ tags:
+ - commercial
+ - clothing
+ - shirts
+ - id: 397feee7-fc37-4e88-87e1-0378019dfc70
+ name: Bernies Furniture
+ num_employees: 3
+ tags:
+ - commercial
+ - furniture
+ - hardware
+ - id: b13bc3f3-95e8-4c79-81fc-8d32c5bea9e9
+ name: Hardware R Us
+ num_employees: 10
+ tags:
+ - commercial
+ - hardware
+ - tools
+ - id: 97ab21b3-9192-4bd5-af3e-f03ed6a329d9
+ name: Mixy's Power Tools
+ num_employees: 4
+ tags:
+ - commercial
+ - hardware
+ - tools
+ - id: 4e9f7c0f-3473-4307-b27d-08f3af08d15d
+ name: Fred's Clothing
+ num_employees: 1
+ tags:
+ - commercial
+ - clothing
+ - shirts
+ - id: 95684d39-37c2-41ef-ba00-dc974d9f49a0
+ name: Jims Gyms
+ num_employees: 7
+ tags:
+ - commercial
+ - sports
diff --git a/FoneDynamics/FoneDynamics/wwwroot/favicon.ico b/FoneDynamics/FoneDynamics/wwwroot/favicon.ico
new file mode 100644
index 0000000..a3a7999
Binary files /dev/null and b/FoneDynamics/FoneDynamics/wwwroot/favicon.ico differ