diff --git a/cli-windows/add-firewall-rules-for-sts-auth-thru-docker.ps1 b/cli-windows/add-firewall-rules-for-sts-auth-thru-docker.ps1
index be63d8a25..865f24067 100644
--- a/cli-windows/add-firewall-rules-for-sts-auth-thru-docker.ps1
+++ b/cli-windows/add-firewall-rules-for-sts-auth-thru-docker.ps1
@@ -21,6 +21,6 @@ try {
Write-Host "Rule found"
}
catch [Exception] {
- New-NetFirewallRule -DisplayName eShopOnContainers-Inbound -Confirm -Description "eShopOnContainers Inbound Rule for port range 5100-5105" -LocalAddress Any -LocalPort 5100-5105 -Protocol tcp -RemoteAddress Any -RemotePort Any -Direction Inbound
- New-NetFirewallRule -DisplayName eShopOnContainers-Outbound -Confirm -Description "eShopOnContainers Outbound Rule for port range 5100-5105" -LocalAddress Any -LocalPort 5100-5105 -Protocol tcp -RemoteAddress Any -RemotePort Any -Direction Outbound
+ New-NetFirewallRule -DisplayName eShopOnContainers-Inbound -Confirm -Description "eShopOnContainers Inbound Rule for port range 5100-5105" -LocalAddress Any -LocalPort 5100-5110 -Protocol tcp -RemoteAddress Any -RemotePort Any -Direction Inbound
+ New-NetFirewallRule -DisplayName eShopOnContainers-Outbound -Confirm -Description "eShopOnContainers Outbound Rule for port range 5100-5105" -LocalAddress Any -LocalPort 5100-5110 -Protocol tcp -RemoteAddress Any -RemotePort Any -Direction Outbound
}
\ No newline at end of file
diff --git a/docker-compose.override.yml b/docker-compose.override.yml
index 04d1c4d9c..a96720ba5 100644
--- a/docker-compose.override.yml
+++ b/docker-compose.override.yml
@@ -95,3 +95,13 @@ services:
- spa=http://webspa/hc
ports:
- "5107:80"
+
+ locations.api:
+ environment:
+ - ASPNETCORE_ENVIRONMENT=Development
+ - ASPNETCORE_URLS=http://0.0.0.0:80
+ - ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.LocationsDb;User Id=sa;Password=Pass@word
+ - identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105.
+ - EventBusConnection=rabbitmq
+ ports:
+ - "5109:80"
\ No newline at end of file
diff --git a/docker-compose.vs.debug.yml b/docker-compose.vs.debug.yml
index 2e7145637..50ba68a69 100644
--- a/docker-compose.vs.debug.yml
+++ b/docker-compose.vs.debug.yml
@@ -105,3 +105,18 @@ services:
entrypoint: tail -f /dev/null
labels:
- "com.microsoft.visualstudio.targetoperatingsystem=linux"
+
+ locations.api:
+ image: eshop/locations.api:dev
+ build:
+ args:
+ source: ${DOCKER_BUILD_SOURCE}
+ environment:
+ - DOTNET_USE_POLLING_FILE_WATCHER=1
+ volumes:
+ - ./src/Services/Location/Locations.API:/app
+ - ~/.nuget/packages:/root/.nuget/packages:ro
+ - ~/clrdbg:/clrdbg:ro
+ entrypoint: tail -f /dev/null
+ labels:
+ - "com.microsoft.visualstudio.targetoperatingsystem=linux"
diff --git a/docker-compose.vs.release.yml b/docker-compose.vs.release.yml
index d1ca5b2c6..58c9ffb81 100644
--- a/docker-compose.vs.release.yml
+++ b/docker-compose.vs.release.yml
@@ -70,3 +70,13 @@ services:
entrypoint: tail -f /dev/null
labels:
- "com.microsoft.visualstudio.targetoperatingsystem=linux"
+
+ locations.api:
+ build:
+ args:
+ source: ${DOCKER_BUILD_SOURCE}
+ volumes:
+ - ~/clrdbg:/clrdbg:ro
+ entrypoint: tail -f /dev/null
+ labels:
+ - "com.microsoft.visualstudio.targetoperatingsystem=linux"
diff --git a/docker-compose.yml b/docker-compose.yml
index 21f3972f2..e698992b2 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -74,4 +74,11 @@ services:
build:
context: ./src/Web/WebStatus
dockerfile: Dockerfile
-
\ No newline at end of file
+
+ locations.api:
+ image: locations.api
+ build:
+ context: ./src/Services/Location/Locations.API
+ dockerfile: Dockerfile
+ depends_on:
+ - sql.data
\ No newline at end of file
diff --git a/eShopOnContainers-ServicesAndWebApps.sln b/eShopOnContainers-ServicesAndWebApps.sln
index eb0e83e02..699185133 100644
--- a/eShopOnContainers-ServicesAndWebApps.sln
+++ b/eShopOnContainers-ServicesAndWebApps.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
-VisualStudioVersion = 15.0.26403.3
+VisualStudioVersion = 15.0.26430.6
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{932D8224-11F6-4D07-B109-DA28AD288A63}"
EndProject
@@ -76,6 +76,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Health
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventBus.Tests", "src\BuildingBlocks\EventBus\EventBus.Tests\EventBus.Tests.csproj", "{89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Location", "Location", "{41139F64-4046-4F16-96B7-D941D96FA9C6}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Locations.API", "src\Services\Location\Locations.API\Locations.API.csproj", "{E7581357-FC34-474C-B8F5-307EE3CE05EF}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Ad-Hoc|Any CPU = Ad-Hoc|Any CPU
@@ -1002,6 +1006,54 @@ Global
{89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Release|x64.Build.0 = Release|Any CPU
{89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Release|x86.ActiveCfg = Release|Any CPU
{89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Release|x86.Build.0 = Release|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.AppStore|Any CPU.Build.0 = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.AppStore|ARM.ActiveCfg = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.AppStore|ARM.Build.0 = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.AppStore|iPhone.Build.0 = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.AppStore|x64.ActiveCfg = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.AppStore|x64.Build.0 = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.AppStore|x86.ActiveCfg = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.AppStore|x86.Build.0 = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Debug|ARM.Build.0 = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Debug|x64.Build.0 = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Debug|x86.Build.0 = Debug|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Release|ARM.ActiveCfg = Release|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Release|ARM.Build.0 = Release|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Release|iPhone.Build.0 = Release|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Release|x64.ActiveCfg = Release|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Release|x64.Build.0 = Release|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Release|x86.ActiveCfg = Release|Any CPU
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -1038,5 +1090,7 @@ Global
{22A0F9C1-2D4A-4107-95B7-8459E6688BC5} = {A81ECBC2-6B00-4DCD-8388-469174033379}
{4BD76717-3102-4969-8C2C-BAAA3F0263B6} = {A81ECBC2-6B00-4DCD-8388-469174033379}
{89D80DF1-32E1-4AAF-970F-DA0AA6881F9D} = {807BB76E-B2BB-47A2-A57B-3D1B20FF5E7F}
+ {41139F64-4046-4F16-96B7-D941D96FA9C6} = {91CF7717-08AB-4E65-B10E-0B426F01E2E8}
+ {E7581357-FC34-474C-B8F5-307EE3CE05EF} = {41139F64-4046-4F16-96B7-D941D96FA9C6}
EndGlobalSection
EndGlobal
diff --git a/src/Services/Catalog/Catalog.API/Catalog.API.csproj b/src/Services/Catalog/Catalog.API/Catalog.API.csproj
index 10fe25945..5bea2f22d 100644
--- a/src/Services/Catalog/Catalog.API/Catalog.API.csproj
+++ b/src/Services/Catalog/Catalog.API/Catalog.API.csproj
@@ -30,6 +30,7 @@
+
diff --git a/src/Services/Identity/Identity.API/Configuration/Config.cs b/src/Services/Identity/Identity.API/Configuration/Config.cs
index 260989da4..a07f5d01d 100644
--- a/src/Services/Identity/Identity.API/Configuration/Config.cs
+++ b/src/Services/Identity/Identity.API/Configuration/Config.cs
@@ -12,7 +12,8 @@ namespace Identity.API.Configuration
return new List
{
new ApiResource("orders", "Orders Service"),
- new ApiResource("basket", "Basket Service")
+ new ApiResource("basket", "Basket Service"),
+ new ApiResource("locations", "Locations Service")
};
}
diff --git a/src/Services/Location/Locations.API/.dockerignore b/src/Services/Location/Locations.API/.dockerignore
new file mode 100644
index 000000000..d8f8175f6
--- /dev/null
+++ b/src/Services/Location/Locations.API/.dockerignore
@@ -0,0 +1,3 @@
+*
+!obj/Docker/publish/*
+!obj/Docker/empty/
diff --git a/src/Services/Location/Locations.API/Controllers/HomeController.cs b/src/Services/Location/Locations.API/Controllers/HomeController.cs
new file mode 100644
index 000000000..e7cea3cca
--- /dev/null
+++ b/src/Services/Location/Locations.API/Controllers/HomeController.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Mvc;
+
+// For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
+
+namespace Microsoft.eShopOnContainers.Services.Locations.API.Controllers
+{
+ public class HomeController : Controller
+ {
+ // GET: //
+ public IActionResult Index()
+ {
+ return new RedirectResult("~/swagger");
+ }
+ }
+}
diff --git a/src/Services/Location/Locations.API/Controllers/ValuesController.cs b/src/Services/Location/Locations.API/Controllers/ValuesController.cs
new file mode 100644
index 000000000..e711e221d
--- /dev/null
+++ b/src/Services/Location/Locations.API/Controllers/ValuesController.cs
@@ -0,0 +1,44 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Mvc;
+
+namespace Locations.API.Controllers
+{
+ [Route("api/[controller]")]
+ public class ValuesController : Controller
+ {
+ // GET api/values
+ [HttpGet]
+ public IEnumerable Get()
+ {
+ return new string[] { "value1", "value2" };
+ }
+
+ // GET api/values/5
+ [HttpGet("{id}")]
+ public string Get(int id)
+ {
+ return "value";
+ }
+
+ // POST api/values
+ [HttpPost]
+ public void Post([FromBody]string value)
+ {
+ }
+
+ // PUT api/values/5
+ [HttpPut("{id}")]
+ public void Put(int id, [FromBody]string value)
+ {
+ }
+
+ // DELETE api/values/5
+ [HttpDelete("{id}")]
+ public void Delete(int id)
+ {
+ }
+ }
+}
diff --git a/src/Services/Location/Locations.API/Dockerfile b/src/Services/Location/Locations.API/Dockerfile
new file mode 100644
index 000000000..3d00f01a9
--- /dev/null
+++ b/src/Services/Location/Locations.API/Dockerfile
@@ -0,0 +1,6 @@
+FROM microsoft/aspnetcore:1.1
+ARG source
+WORKDIR /app
+EXPOSE 80
+COPY ${source:-obj/Docker/publish} .
+ENTRYPOINT ["dotnet", "Locations.API.dll"]
diff --git a/src/Services/Location/Locations.API/Infrastructure/LocationsContext.cs b/src/Services/Location/Locations.API/Infrastructure/LocationsContext.cs
new file mode 100644
index 000000000..42c3f7900
--- /dev/null
+++ b/src/Services/Location/Locations.API/Infrastructure/LocationsContext.cs
@@ -0,0 +1,55 @@
+namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure
+{
+ using Microsoft.EntityFrameworkCore;
+ using Microsoft.EntityFrameworkCore.Metadata.Builders;
+ using Microsoft.eShopOnContainers.Services.Locations.API.Model;
+
+ public class LocationsContext : DbContext
+ {
+ public LocationsContext(DbContextOptions options) : base(options)
+ {
+ }
+
+ public DbSet Locations { get; set; }
+
+ protected override void OnModelCreating(ModelBuilder builder)
+ {
+ builder.Entity(ConfigureLocations);
+ builder.Entity(ConfigureFrontierPoints);
+ }
+
+ void ConfigureLocations(EntityTypeBuilder builder)
+ {
+ builder.ToTable("Locations");
+
+ builder.HasKey(cl => cl.Id);
+
+ builder.Property(cl => cl.Id)
+ .ForSqlServerUseSequenceHiLo("locations_hilo")
+ .IsRequired();
+
+ builder.Property(cb => cb.Code)
+ .IsRequired()
+ .HasColumnName("LocationCode")
+ .HasMaxLength(15);
+
+ builder.HasMany(f => f.Polygon)
+ .WithOne(l => l.Location)
+ .IsRequired();
+
+ builder.Property(cb => cb.Description)
+ .HasMaxLength(100);
+ }
+
+ void ConfigureFrontierPoints(EntityTypeBuilder builder)
+ {
+ builder.ToTable("FrontierPoints");
+
+ builder.HasKey(fp => fp.Id);
+
+ builder.Property(fp => fp.Id)
+ .ForSqlServerUseSequenceHiLo("frontier_hilo")
+ .IsRequired();
+ }
+ }
+}
diff --git a/src/Services/Location/Locations.API/Infrastructure/LocationsContextSeed.cs b/src/Services/Location/Locations.API/Infrastructure/LocationsContextSeed.cs
new file mode 100644
index 000000000..67673719b
--- /dev/null
+++ b/src/Services/Location/Locations.API/Infrastructure/LocationsContextSeed.cs
@@ -0,0 +1,131 @@
+namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure
+{
+ using Microsoft.AspNetCore.Builder;
+ using Microsoft.EntityFrameworkCore;
+ using Microsoft.Extensions.Logging;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Threading.Tasks;
+ using Microsoft.eShopOnContainers.Services.Locations.API.Model;
+ using System.Text;
+
+ public class LocationsContextSeed
+ {
+ public static async Task SeedAsync(IApplicationBuilder applicationBuilder, ILoggerFactory loggerFactory)
+ {
+ var context = (LocationsContext)applicationBuilder
+ .ApplicationServices.GetService(typeof(LocationsContext));
+
+ context.Database.Migrate();
+
+ if (!context.Locations.Any())
+ {
+ context.Locations.AddRange(
+ GetPreconfiguredLocations());
+
+ await context.SaveChangesAsync();
+ }
+ }
+
+ static Locations GetPreconfiguredLocations()
+ {
+ var ww = new Locations() { Code = "WW", Description = "WorldWide", Latitude = -1, Longitude = -1 };
+ ww.ChildLocations.Add(GetUSLocations());
+ return ww;
+ }
+
+ static Locations GetUSLocations()
+ {
+ var us = new Locations() { Code = "US", Description = "United States", Latitude = 41.650455, Longitude = -101.357386, Polygon = GetUSPoligon() };
+ us.ChildLocations.Add(GetWashingtonLocations());
+ return us;
+ }
+
+ static Locations GetWashingtonLocations()
+ {
+ var wht = new Locations() { Code = "WHT", Description = "Washington", Latitude = 47.223652, Longitude = -119.542781, Polygon = GetWashingtonPoligon() };
+ wht.ChildLocations.Add(GetSeattleLocations());
+ wht.ChildLocations.Add(GetRedmondLocations());
+ return wht;
+ }
+
+ static Locations GetSeattleLocations()
+ {
+ var bcn = new Locations() { Code = "SEAT", Description = "Seattle", Latitude = 47.603111, Longitude = -122.330747, Polygon = GetSeattlePoligon() };
+ bcn.ChildLocations.Add(new Locations() { Code = "SEAT-PioneerSqr", Description = "Seattle Pioneer Square Shop" , Latitude = 47.602053, Longitude= -122.333884, Polygon = GetSeattlePioneerSqrPoligon() });
+ return bcn;
+ }
+
+ static Locations GetRedmondLocations()
+ {
+ var bcn = new Locations() { Code = "REDM", Description = "Redmond", Latitude = 47.674961, Longitude = -122.122887, Polygon = GetRedmondPoligon() };
+ bcn.ChildLocations.Add(new Locations() { Code = "REDM-DWNTWP", Description = "Redmond Downtown Central Park Shop", Latitude = 47.674433, Longitude = -122.125006, Polygon = GetRedmondDowntownParkPoligon() });
+ return bcn;
+ }
+
+ static List GetUSPoligon()
+ {
+ var poligon = new List();
+ poligon.Add(new FrontierPoints() { Latitude = 48.7985, Longitude = -62.88205 });
+ poligon.Add(new FrontierPoints() { Latitude = 48.76513, Longitude = -129.31329 });
+ poligon.Add(new FrontierPoints() { Latitude = 30.12256, Longitude = -120.9496 });
+ poligon.Add(new FrontierPoints() { Latitude = 30.87114, Longitude = -111.39442 });
+ poligon.Add(new FrontierPoints() { Latitude = 24.24979, Longitude = -78.11975 });
+ return poligon;
+ }
+
+ static List GetWashingtonPoligon()
+ {
+ var poligon = new List();
+ poligon.Add(new FrontierPoints() { Latitude = 48.8943, Longitude = -124.68633 });
+ poligon.Add(new FrontierPoints() { Latitude = 45.66613, Longitude = -124.32962 });
+ poligon.Add(new FrontierPoints() { Latitude = 45.93384, Longitude = -116.73824 });
+ poligon.Add(new FrontierPoints() { Latitude = 49.04282, Longitude = -116.96912 });
+ return poligon;
+ }
+
+ static List GetSeattlePoligon()
+ {
+ var poligon = new List();
+ poligon.Add(new FrontierPoints() { Latitude = 47.82929, Longitude = -122.36238 });
+ poligon.Add(new FrontierPoints() { Latitude = 47.6337, Longitude = -122.42091 });
+ poligon.Add(new FrontierPoints() { Latitude = 47.45224, Longitude = -122.37371 });
+ poligon.Add(new FrontierPoints() { Latitude = 47.50259, Longitude = -122.20788 });
+ poligon.Add(new FrontierPoints() { Latitude = 47.73644, Longitude = -122.26934 });
+ return poligon;
+ }
+
+ static List GetRedmondPoligon()
+ {
+ var poligon = new List();
+ poligon.Add(new FrontierPoints() { Latitude = 47.73148, Longitude = -122.15432 });
+ poligon.Add(new FrontierPoints() { Latitude = 47.72559, Longitude = -122.17673 });
+ poligon.Add(new FrontierPoints() { Latitude = 47.67851, Longitude = -122.16904 });
+ poligon.Add(new FrontierPoints() { Latitude = 47.65036, Longitude = -122.16136 });
+ poligon.Add(new FrontierPoints() { Latitude = 47.62746, Longitude = -122.15604 });
+ poligon.Add(new FrontierPoints() { Latitude = 47.63463, Longitude = -122.01562 });
+ poligon.Add(new FrontierPoints() { Latitude = 47.74244, Longitude = -122.04961 });
+ return poligon;
+ }
+
+ static List GetSeattlePioneerSqrPoligon()
+ {
+ var poligon = new List();
+ poligon.Add(new FrontierPoints() { Latitude = 47.60338, Longitude = -122.3327 });
+ poligon.Add(new FrontierPoints() { Latitude = 47.60192, Longitude = -122.33665 });
+ poligon.Add(new FrontierPoints() { Latitude = 47.60096, Longitude = -122.33456 });
+ poligon.Add(new FrontierPoints() { Latitude = 47.60136, Longitude = -122.33186 });
+ return poligon;
+ }
+
+ static List GetRedmondDowntownParkPoligon()
+ {
+ var poligon = new List();
+ poligon.Add(new FrontierPoints() { Latitude = 47.67595, Longitude = -122.12467 });
+ poligon.Add(new FrontierPoints() { Latitude = 47.67449, Longitude = -122.12862 });
+ poligon.Add(new FrontierPoints() { Latitude = 47.67353, Longitude = -122.12653 });
+ poligon.Add(new FrontierPoints() { Latitude = 47.67368, Longitude = -122.12197 });
+ return poligon;
+ }
+ }
+}
diff --git a/src/Services/Location/Locations.API/Infrastructure/Migrations/20170529174524_Initial.Designer.cs b/src/Services/Location/Locations.API/Infrastructure/Migrations/20170529174524_Initial.Designer.cs
new file mode 100644
index 000000000..0623edc4e
--- /dev/null
+++ b/src/Services/Location/Locations.API/Infrastructure/Migrations/20170529174524_Initial.Designer.cs
@@ -0,0 +1,87 @@
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure;
+
+namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Migrations
+{
+ [DbContext(typeof(LocationsContext))]
+ [Migration("20170529174524_Initial")]
+ partial class Initial
+ {
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+ modelBuilder
+ .HasAnnotation("ProductVersion", "1.1.2")
+ .HasAnnotation("SqlServer:Sequence:.frontier_hilo", "'frontier_hilo', '', '1', '10', '', '', 'Int64', 'False'")
+ .HasAnnotation("SqlServer:Sequence:.locations_hilo", "'locations_hilo', '', '1', '10', '', '', 'Int64', 'False'")
+ .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
+
+ modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Locations.API.Model.FrontierPoints", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasAnnotation("SqlServer:HiLoSequenceName", "frontier_hilo")
+ .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo);
+
+ b.Property("Latitude");
+
+ b.Property("LocationId")
+ .IsRequired();
+
+ b.Property("Longitude");
+
+ b.HasKey("Id");
+
+ b.HasIndex("LocationId");
+
+ b.ToTable("FrontierPoints");
+ });
+
+ modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Locations.API.Model.Locations", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasAnnotation("SqlServer:HiLoSequenceName", "locations_hilo")
+ .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo);
+
+ b.Property("Code")
+ .IsRequired()
+ .HasColumnName("LocationCode")
+ .HasMaxLength(15);
+
+ b.Property("Description")
+ .HasMaxLength(100);
+
+ b.Property("Latitude");
+
+ b.Property("Longitude");
+
+ b.Property("ParentId");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ParentId");
+
+ b.ToTable("Locations");
+ });
+
+ modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Locations.API.Model.FrontierPoints", b =>
+ {
+ b.HasOne("Microsoft.eShopOnContainers.Services.Locations.API.Model.Locations", "Location")
+ .WithMany("FrontierPoints")
+ .HasForeignKey("LocationId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Locations.API.Model.Locations", b =>
+ {
+ b.HasOne("Microsoft.eShopOnContainers.Services.Locations.API.Model.Locations")
+ .WithMany("ChildLocations")
+ .HasForeignKey("ParentId");
+ });
+ }
+ }
+}
diff --git a/src/Services/Location/Locations.API/Infrastructure/Migrations/20170529174524_Initial.cs b/src/Services/Location/Locations.API/Infrastructure/Migrations/20170529174524_Initial.cs
new file mode 100644
index 000000000..d2352312f
--- /dev/null
+++ b/src/Services/Location/Locations.API/Infrastructure/Migrations/20170529174524_Initial.cs
@@ -0,0 +1,129 @@
+using System;
+using System.Collections.Generic;
+using Microsoft.EntityFrameworkCore.Migrations;
+using System.Text;
+
+namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Migrations
+{
+ public partial class Initial : Migration
+ {
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.CreateSequence(
+ name: "frontier_hilo",
+ incrementBy: 10);
+
+ migrationBuilder.CreateSequence(
+ name: "locations_hilo",
+ incrementBy: 10);
+
+ migrationBuilder.CreateTable(
+ name: "Locations",
+ columns: table => new
+ {
+ Id = table.Column(nullable: false),
+ LocationCode = table.Column(maxLength: 15, nullable: false),
+ Description = table.Column(maxLength: 100, nullable: true),
+ Latitude = table.Column(nullable: false),
+ Longitude = table.Column(nullable: false),
+ ParentId = table.Column(nullable: true)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Locations", x => x.Id);
+ table.ForeignKey(
+ name: "FK_Locations_Locations_ParentId",
+ column: x => x.ParentId,
+ principalTable: "Locations",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Restrict);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "FrontierPoints",
+ columns: table => new
+ {
+ Id = table.Column(nullable: false),
+ Latitude = table.Column(nullable: false),
+ LocationId = table.Column(nullable: false),
+ Longitude = table.Column(nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_FrontierPoints", x => x.Id);
+ table.ForeignKey(
+ name: "FK_FrontierPoints_Locations_LocationId",
+ column: x => x.LocationId,
+ principalTable: "Locations",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateIndex(
+ name: "IX_FrontierPoints_LocationId",
+ table: "FrontierPoints",
+ column: "LocationId");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_Locations_ParentId",
+ table: "Locations",
+ column: "ParentId");
+
+ migrationBuilder.Sql(CreateGetDistanceFunction());
+ migrationBuilder.Sql(CreateLocationsNearSP());
+ }
+
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropTable(
+ name: "FrontierPoints");
+
+ migrationBuilder.DropTable(
+ name: "Locations");
+
+ migrationBuilder.DropSequence(
+ name: "frontier_hilo");
+
+ migrationBuilder.DropSequence(
+ name: "locations_hilo");
+
+ migrationBuilder.Sql(@"DROP PROCEDURE IF EXISTS pLocationsNear");
+ migrationBuilder.Sql(@"DROP FUNCTION IF EXISTS dbo.GetDistanceFromLocation");
+ }
+
+ private string CreateLocationsNearSP()
+ {
+ var sb = new StringBuilder();
+ sb.AppendLine(@"CREATE PROCEDURE [dbo].[pLocationsNear]");
+ sb.AppendLine(@"@latitude float,");
+ sb.AppendLine(@"@longitude float,");
+ sb.AppendLine(@"@size int = 500");
+ sb.AppendLine(@"AS");
+ sb.AppendLine(@"BEGIN");
+ sb.AppendLine(@"SELECT TOP( @size) location.*");
+ sb.AppendLine(@"FROM [dbo].[Locations] AS location");
+ sb.AppendLine(@"ORDER BY dbo.[GetDistanceFromLocation](location.Latitude, location.Longitude, @latitude, @longitude)");
+ sb.AppendLine(@"END");
+ return sb.ToString();
+ }
+
+ private string CreateGetDistanceFunction()
+ {
+ var sb = new StringBuilder();
+ sb.AppendLine(@"CREATE FUNCTION [dbo].[GetDistanceFromLocation](");
+ sb.AppendLine(@"@CurrentLatitude float,");
+ sb.AppendLine(@"@CurrentLongitude float,");
+ sb.AppendLine(@"@latitude float,");
+ sb.AppendLine(@"@longitude float)");
+ sb.AppendLine(@"RETURNS int");
+ sb.AppendLine(@"AS");
+ sb.AppendLine(@"BEGIN");
+ sb.AppendLine(@"DECLARE @geo1 geography = geography::Point(@CurrentLatitude, @CurrentLongitude, 4268),@geo2 geography = geography::Point(@latitude, @longitude, 4268)");
+ sb.AppendLine(@"DECLARE @distance int");
+ sb.AppendLine(@"SELECT @distance = @geo1.STDistance(@geo2)");
+ sb.AppendLine(@"RETURN @distance");
+ sb.AppendLine(@"END");
+ return sb.ToString();
+ }
+ }
+}
diff --git a/src/Services/Location/Locations.API/Infrastructure/Migrations/LocationsContextModelSnapshot.cs b/src/Services/Location/Locations.API/Infrastructure/Migrations/LocationsContextModelSnapshot.cs
new file mode 100644
index 000000000..02f77cdd0
--- /dev/null
+++ b/src/Services/Location/Locations.API/Infrastructure/Migrations/LocationsContextModelSnapshot.cs
@@ -0,0 +1,86 @@
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure;
+
+namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Migrations
+{
+ [DbContext(typeof(LocationsContext))]
+ partial class LocationsContextModelSnapshot : ModelSnapshot
+ {
+ protected override void BuildModel(ModelBuilder modelBuilder)
+ {
+ modelBuilder
+ .HasAnnotation("ProductVersion", "1.1.2")
+ .HasAnnotation("SqlServer:Sequence:.frontier_hilo", "'frontier_hilo', '', '1', '10', '', '', 'Int64', 'False'")
+ .HasAnnotation("SqlServer:Sequence:.locations_hilo", "'locations_hilo', '', '1', '10', '', '', 'Int64', 'False'")
+ .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
+
+ modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Locations.API.Model.FrontierPoints", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasAnnotation("SqlServer:HiLoSequenceName", "frontier_hilo")
+ .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo);
+
+ b.Property("Latitude");
+
+ b.Property("LocationId")
+ .IsRequired();
+
+ b.Property("Longitude");
+
+ b.HasKey("Id");
+
+ b.HasIndex("LocationId");
+
+ b.ToTable("FrontierPoints");
+ });
+
+ modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Locations.API.Model.Locations", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasAnnotation("SqlServer:HiLoSequenceName", "locations_hilo")
+ .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo);
+
+ b.Property("Code")
+ .IsRequired()
+ .HasColumnName("LocationCode")
+ .HasMaxLength(15);
+
+ b.Property("Description")
+ .HasMaxLength(100);
+
+ b.Property("Latitude");
+
+ b.Property("Longitude");
+
+ b.Property("ParentId");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ParentId");
+
+ b.ToTable("Locations");
+ });
+
+ modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Locations.API.Model.FrontierPoints", b =>
+ {
+ b.HasOne("Microsoft.eShopOnContainers.Services.Locations.API.Model.Locations", "Location")
+ .WithMany("FrontierPoints")
+ .HasForeignKey("LocationId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Locations.API.Model.Locations", b =>
+ {
+ b.HasOne("Microsoft.eShopOnContainers.Services.Locations.API.Model.Locations")
+ .WithMany("ChildLocations")
+ .HasForeignKey("ParentId");
+ });
+ }
+ }
+}
diff --git a/src/Services/Location/Locations.API/Locations.API.csproj b/src/Services/Location/Locations.API/Locations.API.csproj
new file mode 100644
index 000000000..b00054921
--- /dev/null
+++ b/src/Services/Location/Locations.API/Locations.API.csproj
@@ -0,0 +1,39 @@
+
+
+
+ netcoreapp1.1
+ ..\..\..\..\docker-compose.dcproj
+ Microsoft.eShopOnContainers.Services.Locations.API
+ aspnet-Locations.API-20161122013619
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Services/Location/Locations.API/Model/FrontierPoints.cs b/src/Services/Location/Locations.API/Model/FrontierPoints.cs
new file mode 100644
index 000000000..4a9112e5e
--- /dev/null
+++ b/src/Services/Location/Locations.API/Model/FrontierPoints.cs
@@ -0,0 +1,11 @@
+namespace Microsoft.eShopOnContainers.Services.Locations.API.Model
+{
+ public class FrontierPoints
+ {
+ public int Id { get; set; }
+ public double Latitude { get; set; }
+ public double Longitude { get; set; }
+
+ public Locations Location { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Services/Location/Locations.API/Model/Locations.cs b/src/Services/Location/Locations.API/Model/Locations.cs
new file mode 100644
index 000000000..ec21ac34f
--- /dev/null
+++ b/src/Services/Location/Locations.API/Model/Locations.cs
@@ -0,0 +1,62 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations.Schema;
+
+
+namespace Microsoft.eShopOnContainers.Services.Locations.API.Model
+{
+ public class Locations
+ {
+ public int Id { get; set; }
+ public string Code { get; set; }
+ public int? ParentId { get; set; }
+ public string Description { get; set; }
+ public double Latitude { get; set; }
+ public double Longitude { get; set; }
+ public bool IsPointInPolygon(double lat, double lon) => CheckIsPointInPolygon(lat, lon);
+
+ public Locations()
+ {
+ ChildLocations = new List();
+ }
+
+ public virtual List Polygon { get; set; }
+
+ [ForeignKey("ParentId")]
+ public virtual List ChildLocations { get; set; }
+
+
+ private bool CheckIsPointInPolygon(double lat, double lon)
+ {
+ double minX = Polygon[0].Latitude;
+ double maxX = Polygon[0].Latitude;
+ double minY = Polygon[0].Longitude;
+ double maxY = Polygon[0].Longitude;
+ for (int i = 1; i < Polygon.Count; i++)
+ {
+ FrontierPoints q = Polygon[i];
+ minX = Math.Min(q.Latitude, minX);
+ maxX = Math.Max(q.Latitude, maxX);
+ minY = Math.Min(q.Longitude, minY);
+ maxY = Math.Max(q.Longitude, maxY);
+ }
+
+ if (lat < minX || lat > maxX || lon < minY || lon > maxY)
+ {
+ return false;
+ }
+
+ bool inside = false;
+ for (int i = 0, j = Polygon.Count - 1; i < Polygon.Count; j = i++)
+ {
+ if ((Polygon[i].Longitude > lon) != (Polygon[j].Latitude > lat) &&
+ lat < (Polygon[j].Longitude - Polygon[i].Latitude) * (lon - Polygon[i].Longitude) / (Polygon[j].Longitude - Polygon[i].Longitude) + Polygon[i].Latitude)
+ {
+ inside = !inside;
+ }
+ }
+
+ return inside;
+ }
+ }
+}
diff --git a/src/Services/Location/Locations.API/Program.cs b/src/Services/Location/Locations.API/Program.cs
new file mode 100644
index 000000000..345956401
--- /dev/null
+++ b/src/Services/Location/Locations.API/Program.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+
+namespace Microsoft.eShopOnContainers.Services.Locations.API
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ var host = new WebHostBuilder()
+ .UseKestrel()
+ .UseContentRoot(Directory.GetCurrentDirectory())
+ .UseStartup()
+ .UseApplicationInsights()
+ .Build();
+
+ host.Run();
+ }
+ }
+}
diff --git a/src/Services/Location/Locations.API/Properties/launchSettings.json b/src/Services/Location/Locations.API/Properties/launchSettings.json
new file mode 100644
index 000000000..45b637914
--- /dev/null
+++ b/src/Services/Location/Locations.API/Properties/launchSettings.json
@@ -0,0 +1,29 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:3278/",
+ "sslPort": 0
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "launchUrl": "api/values",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "Locations.API": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "launchUrl": "api/values",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ },
+ "applicationUrl": "http://localhost:3279"
+ }
+ }
+}
diff --git a/src/Services/Location/Locations.API/Startup.cs b/src/Services/Location/Locations.API/Startup.cs
new file mode 100644
index 000000000..1a42679a6
--- /dev/null
+++ b/src/Services/Location/Locations.API/Startup.cs
@@ -0,0 +1,115 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+using System.Reflection;
+using System;
+
+namespace Microsoft.eShopOnContainers.Services.Locations.API
+{
+ public class Startup
+ {
+ public IConfigurationRoot Configuration { get; }
+
+ public Startup(IHostingEnvironment env)
+ {
+ var builder = new ConfigurationBuilder()
+ .SetBasePath(env.ContentRootPath)
+ .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
+ .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);
+
+ if (env.IsDevelopment())
+ {
+ builder.AddUserSecrets(typeof(Startup).GetTypeInfo().Assembly);
+ }
+
+ builder.AddEnvironmentVariables();
+
+ Configuration = builder.Build();
+ }
+
+ // 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.AddMvc();
+
+ services.AddDbContext(options =>
+ {
+ options.UseSqlServer(Configuration["ConnectionString"],
+ sqlServerOptionsAction: sqlOptions =>
+ {
+ sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name);
+ //Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency
+ sqlOptions.EnableRetryOnFailure(maxRetryCount: 5, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
+ });
+
+ // Changing default behavior when client evaluation occurs to throw.
+ // Default in EF Core would be to log a warning when client evaluation is performed.
+ options.ConfigureWarnings(warnings => warnings.Throw(RelationalEventId.QueryClientEvaluationWarning));
+ //Check Client vs. Server evaluation: https://docs.microsoft.com/en-us/ef/core/querying/client-eval
+ });
+
+ // Add framework services.
+ services.AddSwaggerGen(options =>
+ {
+ options.DescribeAllEnumsAsStrings();
+ options.SwaggerDoc("v1", new Swashbuckle.AspNetCore.Swagger.Info
+ {
+ Title = "eShopOnContainers - Location HTTP API",
+ Version = "v1",
+ Description = "The Location Microservice HTTP API. This is a Data-Driven/CRUD microservice sample",
+ TermsOfService = "Terms Of Service"
+ });
+ });
+
+ services.AddCors(options =>
+ {
+ options.AddPolicy("CorsPolicy",
+ builder => builder.AllowAnyOrigin()
+ .AllowAnyMethod()
+ .AllowAnyHeader()
+ .AllowCredentials());
+ });
+ }
+
+ // 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)
+ {
+ //Configure logs
+
+ loggerFactory.AddConsole(Configuration.GetSection("Logging"));
+ loggerFactory.AddDebug();
+
+ app.UseCors("CorsPolicy");
+
+ ConfigureAuth(app);
+
+ app.UseMvcWithDefaultRoute();
+
+ app.UseSwagger()
+ .UseSwaggerUI(c =>
+ {
+ c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
+ });
+
+ LocationsContextSeed.SeedAsync(app, loggerFactory)
+ .Wait();
+ }
+
+ protected virtual void ConfigureAuth(IApplicationBuilder app)
+ {
+ var identityUrl = Configuration.GetValue("IdentityUrl");
+ app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
+ {
+ Authority = identityUrl.ToString(),
+ ApiName = "locations",
+ RequireHttpsMetadata = false
+ });
+ }
+ }
+}
diff --git a/src/Services/Location/Locations.API/appsettings.Development.json b/src/Services/Location/Locations.API/appsettings.Development.json
new file mode 100644
index 000000000..fa8ce71a9
--- /dev/null
+++ b/src/Services/Location/Locations.API/appsettings.Development.json
@@ -0,0 +1,10 @@
+{
+ "Logging": {
+ "IncludeScopes": false,
+ "LogLevel": {
+ "Default": "Debug",
+ "System": "Information",
+ "Microsoft": "Information"
+ }
+ }
+}
diff --git a/src/Services/Location/Locations.API/appsettings.json b/src/Services/Location/Locations.API/appsettings.json
new file mode 100644
index 000000000..812cce207
--- /dev/null
+++ b/src/Services/Location/Locations.API/appsettings.json
@@ -0,0 +1,12 @@
+{
+ "ConnectionString": "Server=tcp:127.0.0.1,5433;Database=Microsoft.eShopOnContainers.Services.LocationsDb;User Id=sa;Password=Pass@word;",
+ "IdentityUrl": "http://localhost:5105",
+ "Logging": {
+ "IncludeScopes": false,
+ "LogLevel": {
+ "Default": "Debug",
+ "System": "Information",
+ "Microsoft": "Information"
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/Services/FunctionalTests/FunctionalTests.csproj b/test/Services/FunctionalTests/FunctionalTests.csproj
index 2b8ee1f44..54a74beda 100644
--- a/test/Services/FunctionalTests/FunctionalTests.csproj
+++ b/test/Services/FunctionalTests/FunctionalTests.csproj
@@ -38,4 +38,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/test/Services/IntegrationTests/IntegrationTests.csproj b/test/Services/IntegrationTests/IntegrationTests.csproj
index b71e1d4c4..60911dd4d 100644
--- a/test/Services/IntegrationTests/IntegrationTests.csproj
+++ b/test/Services/IntegrationTests/IntegrationTests.csproj
@@ -46,4 +46,8 @@
+
+
+
+
diff --git a/test/Services/UnitTest/UnitTest.csproj b/test/Services/UnitTest/UnitTest.csproj
index 3a80e594b..8955e4a45 100644
--- a/test/Services/UnitTest/UnitTest.csproj
+++ b/test/Services/UnitTest/UnitTest.csproj
@@ -28,4 +28,8 @@
+
+
+
+