diff --git a/src/Services/Catalog/Catalog.API/Dockerfile.nanowin b/src/Services/Catalog/Catalog.API/Dockerfile.nanowin index c40d3a4d0..10d8d2ffe 100644 --- a/src/Services/Catalog/Catalog.API/Dockerfile.nanowin +++ b/src/Services/Catalog/Catalog.API/Dockerfile.nanowin @@ -1,4 +1,4 @@ -FROM microsoft/dotnet:1.1-runtime-nanoserver +FROM microsoft/dotnet:1.1-sdk-nanoserver ARG source WORKDIR /app RUN set-itemproperty -path 'HKLM:\SYSTEM\CurrentControlSet\Services\Dnscache\Parameters' -Name ServerPriorityTimeLimit -Value 0 -Type DWord diff --git a/src/Web/Catalog.WebForms/Catalog.WebForms/Catalog.WebForms.csproj b/src/Web/Catalog.WebForms/Catalog.WebForms/Catalog.WebForms.csproj index 40bd7bb2a..e71028818 100644 --- a/src/Web/Catalog.WebForms/Catalog.WebForms/Catalog.WebForms.csproj +++ b/src/Web/Catalog.WebForms/Catalog.WebForms/Catalog.WebForms.csproj @@ -57,6 +57,8 @@ + + @@ -415,6 +417,7 @@ + Site.Master ASPXCodeBehind diff --git a/src/Web/Catalog.WebForms/Catalog.WebForms/Modules/AutoFacHttpModule.cs b/src/Web/Catalog.WebForms/Catalog.WebForms/Modules/AutoFacHttpModule.cs index 471edbd18..53f9c9840 100644 --- a/src/Web/Catalog.WebForms/Catalog.WebForms/Modules/AutoFacHttpModule.cs +++ b/src/Web/Catalog.WebForms/Catalog.WebForms/Modules/AutoFacHttpModule.cs @@ -1,5 +1,6 @@ using Autofac; using eShopOnContainers.Core.Services.Catalog; +using eShopOnContainers.Core.Services.RequestProvider; using System; using System.Collections.Generic; using System.Linq; @@ -34,8 +35,11 @@ namespace eShopOnContainers.Catalog.WebForms.Modules } else { - builder.RegisterType() + builder.RegisterType() .As(); + + builder.RegisterType() + .As(); } var container = builder.Build(); return container; diff --git a/src/Web/Catalog.WebForms/Catalog.WebForms/Services/CatalogService.cs b/src/Web/Catalog.WebForms/Catalog.WebForms/Services/CatalogService.cs index f77eb11d4..cc22a37c4 100644 --- a/src/Web/Catalog.WebForms/Catalog.WebForms/Services/CatalogService.cs +++ b/src/Web/Catalog.WebForms/Catalog.WebForms/Services/CatalogService.cs @@ -23,8 +23,8 @@ namespace eShopOnContainers.Core.Services.Catalog { try { - // TODO: - UriBuilder builder = new UriBuilder("" /* GlobalSetting.Instance.CatalogEndpoint */); + var baseURl = System.Configuration.ConfigurationManager.AppSettings["CatalogURL"]; + UriBuilder builder = new UriBuilder(baseURl); builder.Path = string.Format("api/v1/catalog/items/type/{0}/brand/{1}", catalogTypeId, catalogBrandId); @@ -48,8 +48,8 @@ namespace eShopOnContainers.Core.Services.Catalog { try { - // TODO: - UriBuilder builder = new UriBuilder("" /* GlobalSetting.Instance.CatalogEndpoint */); + var baseURl = System.Configuration.ConfigurationManager.AppSettings["CatalogURL"]; + UriBuilder builder = new UriBuilder(baseURl); builder.Path = "api/v1/catalog/items"; @@ -82,8 +82,8 @@ namespace eShopOnContainers.Core.Services.Catalog { try { - // TODO: - UriBuilder builder = new UriBuilder("" /* GlobalSetting.Instance.CatalogEndpoint */); + var baseURl = System.Configuration.ConfigurationManager.AppSettings["CatalogURL"]; + UriBuilder builder = new UriBuilder(baseURl); builder.Path = "api/v1/catalog/catalogbrands"; @@ -107,8 +107,8 @@ namespace eShopOnContainers.Core.Services.Catalog { try { - // TODO: - UriBuilder builder = new UriBuilder("" /* GlobalSetting.Instance.CatalogEndpoint */); + var baseURl = System.Configuration.ConfigurationManager.AppSettings["CatalogURL"]; + UriBuilder builder = new UriBuilder(baseURl); builder.Path = "api/v1/catalog/catalogtypes"; @@ -130,8 +130,8 @@ namespace eShopOnContainers.Core.Services.Catalog public Task DeleteCatalogItemAsync(string catalogItemId) { - // TODO: - UriBuilder builder = new UriBuilder("" /* GlobalSetting.Instance.CatalogEndpoint */); + var baseURl = System.Configuration.ConfigurationManager.AppSettings["CatalogURL"]; + UriBuilder builder = new UriBuilder(baseURl); builder.Path = $"api/v1/catalog/{catalogItemId}"; @@ -142,8 +142,8 @@ namespace eShopOnContainers.Core.Services.Catalog public Task UpdateCatalogItemAsync(CatalogItem item) { - // TODO: - UriBuilder builder = new UriBuilder("" /* GlobalSetting.Instance.CatalogEndpoint */); + var baseURl = System.Configuration.ConfigurationManager.AppSettings["CatalogURL"]; + UriBuilder builder = new UriBuilder(baseURl); builder.Path = "api/v1/catalog/edit"; @@ -154,8 +154,8 @@ namespace eShopOnContainers.Core.Services.Catalog public Task CreateCatalogItemAsync(CatalogItem item) { - // TODO: - UriBuilder builder = new UriBuilder("" /* GlobalSetting.Instance.CatalogEndpoint */); + var baseURl = System.Configuration.ConfigurationManager.AppSettings["CatalogURL"]; + UriBuilder builder = new UriBuilder(baseURl); builder.Path = "api/v1/catalog/create"; diff --git a/src/Web/Catalog.WebForms/Catalog.WebForms/Services/RequestProvider.cs b/src/Web/Catalog.WebForms/Catalog.WebForms/Services/RequestProvider.cs new file mode 100644 index 000000000..a35417eaa --- /dev/null +++ b/src/Web/Catalog.WebForms/Catalog.WebForms/Services/RequestProvider.cs @@ -0,0 +1,174 @@ +using eShopOnContainers.Core.Exceptions; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Serialization; +using System.Net; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Text; +using System.Threading.Tasks; +using System; + +// Taken from https://raw.githubusercontent.com/dotnet/eShopOnContainers/dev/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/RequestProvider/RequestProvider.cs +// TODO: DRY This + +namespace eShopOnContainers.Core.Services.RequestProvider +{ + public class RequestProvider : IRequestProvider + { + private readonly JsonSerializerSettings _serializerSettings; + + public RequestProvider() + { + _serializerSettings = new JsonSerializerSettings + { + ContractResolver = new CamelCasePropertyNamesContractResolver(), + DateTimeZoneHandling = DateTimeZoneHandling.Utc, + NullValueHandling = NullValueHandling.Ignore + }; + + _serializerSettings.Converters.Add(new StringEnumConverter()); + } + + public async Task GetAsync(string uri, string token = "") + { + HttpClient httpClient = CreateHttpClient(token); + HttpResponseMessage response = await httpClient.GetAsync(uri); + + await HandleResponse(response); + + string serialized = await response.Content.ReadAsStringAsync(); + + TResult result = await Task.Run(() => + JsonConvert.DeserializeObject(serialized, _serializerSettings)); + + return result; + } + + public async Task PostAsync(string uri, TResult data, string token = "", string header = "") + { + HttpClient httpClient = CreateHttpClient(token); + + if (!string.IsNullOrEmpty(header)) + { + AddHeaderParameter(httpClient, header); + } + + var content = new StringContent(JsonConvert.SerializeObject(data)); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + HttpResponseMessage response = await httpClient.PostAsync(uri, content); + + await HandleResponse(response); + + string serialized = await response.Content.ReadAsStringAsync(); + + TResult result = await Task.Run(() => + JsonConvert.DeserializeObject(serialized, _serializerSettings)); + + return result; + } + + public Task PostAsync(string uri, TResult data, string token = "") + { + return PostAsync(uri, data, token); + } + + public async Task PostAsync(string uri, TRequest data, string token = "") + { + HttpClient httpClient = CreateHttpClient(token); + string serialized = await Task.Run(() => JsonConvert.SerializeObject(data, _serializerSettings)); + var content = new StringContent(serialized, Encoding.UTF8, "application/json"); + HttpResponseMessage response = await httpClient.PostAsync(uri, content); + + await HandleResponse(response); + + string responseData = await response.Content.ReadAsStringAsync(); + + return await Task.Run(() => JsonConvert.DeserializeObject(responseData, _serializerSettings)); + } + + public Task PutAsync(string uri, TResult data, string token = "") + { + return PutAsync(uri, data, token); + } + + public async Task PutAsync(string uri, TRequest data, string token = "") + { + HttpClient httpClient = CreateHttpClient(token); + string serialized = await Task.Run(() => JsonConvert.SerializeObject(data, _serializerSettings)); + HttpResponseMessage response = await httpClient.PutAsync(uri, new StringContent(serialized, Encoding.UTF8, "application/json")); + + await HandleResponse(response); + + string responseData = await response.Content.ReadAsStringAsync(); + + return await Task.Run(() => JsonConvert.DeserializeObject(responseData, _serializerSettings)); + } + + public async Task DeleteAsync(string uri, string token = "") + { + HttpClient httpClient = CreateHttpClient(token); + + await httpClient.DeleteAsync(uri); + } + + private HttpClient CreateHttpClient(string token = "") + { + var httpClient = new HttpClient(); + + httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); + + if (!string.IsNullOrEmpty(token)) + { + httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + } + + return httpClient; + } + + private void AddHeaderParameter(HttpClient httpClient, string parameter) + { + if (httpClient == null) + return; + + if (string.IsNullOrEmpty(parameter)) + return; + + httpClient.DefaultRequestHeaders.Add(parameter, Guid.NewGuid().ToString()); + } + + private async Task HandleResponse(HttpResponseMessage response) + { + if (!response.IsSuccessStatusCode) + { + var content = await response.Content.ReadAsStringAsync(); + + if (response.StatusCode == HttpStatusCode.Forbidden + || response.StatusCode == HttpStatusCode.Unauthorized) + { + throw new ServiceAuthenticationException(content); + } + + throw new HttpRequestException(content); + } + } + } +} + +// Taken from: https://raw.githubusercontent.com/dotnet/eShopOnContainers/dev/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Exceptions/ServiceAuthenticationException.cs +namespace eShopOnContainers.Core.Exceptions +{ + public class ServiceAuthenticationException : Exception + { + public string Content { get; } + + public ServiceAuthenticationException() + { + } + + public ServiceAuthenticationException(string content) + { + Content = content; + } + } +} diff --git a/src/Web/Catalog.WebForms/Catalog.WebForms/Web.Debug.config b/src/Web/Catalog.WebForms/Catalog.WebForms/Web.Debug.config index fae9cfefa..15c33a329 100644 --- a/src/Web/Catalog.WebForms/Catalog.WebForms/Web.Debug.config +++ b/src/Web/Catalog.WebForms/Catalog.WebForms/Web.Debug.config @@ -26,5 +26,6 @@ --> + \ No newline at end of file diff --git a/src/Web/Catalog.WebForms/Catalog.WebForms/Web.config b/src/Web/Catalog.WebForms/Catalog.WebForms/Web.config index 46d4ab24e..0e2f9205e 100644 --- a/src/Web/Catalog.WebForms/Catalog.WebForms/Web.config +++ b/src/Web/Catalog.WebForms/Catalog.WebForms/Web.config @@ -9,7 +9,8 @@
- + + diff --git a/src/Web/Catalog.WebForms/docker-compose.override.yml b/src/Web/Catalog.WebForms/docker-compose.override.yml index dc74370aa..fbf3b39ae 100644 --- a/src/Web/Catalog.WebForms/docker-compose.override.yml +++ b/src/Web/Catalog.WebForms/docker-compose.override.yml @@ -11,6 +11,7 @@ services: catalog.api: environment: - ASPNETCORE_ENVIRONMENT=Development + - ASPNETCORE_URLS=http://0.0.0.0:5101 - ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=Pass@word #- ExternalCatalogBaseUrl=http://13.88.8.119:5101 #Remote: VM Needs to have public access at 5105. - ExternalCatalogBaseUrl=http://localhost:5101 #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105. @@ -20,8 +21,3 @@ services: catalog.webforms: ports: - "80:80" - -networks: - default: - external: - name: nat diff --git a/src/Web/Catalog.WebForms/docker-compose.vs.debug.yml b/src/Web/Catalog.WebForms/docker-compose.vs.debug.yml index 4485cb1de..b93037737 100644 --- a/src/Web/Catalog.WebForms/docker-compose.vs.debug.yml +++ b/src/Web/Catalog.WebForms/docker-compose.vs.debug.yml @@ -2,7 +2,7 @@ version: '2.1' services: catalog.webforms: - image: catalog.webforms:dev + image: eshop/catalog.webforms:dev build: args: source: ${DOCKER_BUILD_SOURCE} @@ -11,3 +11,16 @@ services: - ~\msvsmon:C:\msvsmon:ro labels: - "com.microsoft.visualstudio.targetoperatingsystem=windows" + + catalog.api: + image: eshop/catalog.api:dev + build: + args: + source: ${DOCKER_BUILD_SOURCE} + environment: + - DOTNET_USE_POLLING_FILE_WATCHER=1 + volumes: + - ../../Services/Catalog/Catalog.API:C:\app + - ~\msvsmon:C:\msvsmon:ro + labels: + - "com.microsoft.visualstudio.targetoperatingsystem=windows" diff --git a/src/Web/Catalog.WebForms/docker-compose.yml b/src/Web/Catalog.WebForms/docker-compose.yml index 4eb18f0d2..7c13247b1 100644 --- a/src/Web/Catalog.WebForms/docker-compose.yml +++ b/src/Web/Catalog.WebForms/docker-compose.yml @@ -2,7 +2,7 @@ version: '2.1' services: catalog.webforms: - image: catalog.webforms + image: eshop/catalog.webforms build: context: .\Catalog.WebForms dockerfile: Dockerfile @@ -12,10 +12,15 @@ services: catalog.api: image: eshop/catalog.api build: - context: ..\..\Services\Catalog\Catalog.API - dockerfile: Dockerfile.windows + context: ../../Services/Catalog/Catalog.API + dockerfile: Dockerfile.nanowin depends_on: - sql.data sql.data: image: microsoft/mssql-server-windows + +networks: + default: + external: + name: nat