├── .gitattributes ├── .gitignore ├── .nuget ├── NuGet.Config ├── NuGet.exe └── NuGet.targets ├── CreateDatabaseTables.sql ├── CreateLocalDatabase.sql ├── LICENCE.md ├── MarketFinder.AnalyticsService ├── MarketFinder.AnalyticsService.csproj ├── MarketsDataRepository.cs ├── Properties │ └── AssemblyInfo.cs ├── Rating.cs ├── RecomendationRepository.cs ├── RecommendationsAnalysisController.cs └── packages.config ├── MarketFinder.CommonHost ├── App_Start │ └── WebApiConfig.cs ├── Global.asax ├── Global.asax.cs ├── MarketFinder.CommonHost.csproj ├── Properties │ └── AssemblyInfo.cs ├── Web.Debug.config ├── Web.Release.config ├── Web.config └── packages.config ├── MarketFinder.MakretManagementService ├── App.config ├── Controllers │ ├── MarketsController.cs │ └── RatingsController.cs ├── MarketFinder.MakretManagementService.csproj ├── Models │ ├── Market.cs │ ├── MarketManagementServiceContext.cs │ └── Rating.cs ├── Properties │ └── AssemblyInfo.cs └── packages.config ├── MarketFinder.sln └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bin 2 | obj 3 | *.user 4 | *.suo 5 | /packages -------------------------------------------------------------------------------- /.nuget/NuGet.Config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.nuget/NuGet.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kszabelski/Microservices---ASP.NET-Web-API---Azure/5c49b862f80dacac68cb93a9c01b3395885f6499/.nuget/NuGet.exe -------------------------------------------------------------------------------- /.nuget/NuGet.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildProjectDirectory)\..\ 5 | 6 | 7 | false 8 | 9 | 10 | false 11 | 12 | 13 | true 14 | 15 | 16 | false 17 | 18 | 19 | 20 | 21 | 22 | 26 | 27 | 28 | 29 | 30 | $([System.IO.Path]::Combine($(SolutionDir), ".nuget")) 31 | 32 | 33 | 34 | 35 | $(SolutionDir).nuget 36 | 37 | 38 | 39 | $(MSBuildProjectDirectory)\packages.$(MSBuildProjectName.Replace(' ', '_')).config 40 | $(MSBuildProjectDirectory)\packages.$(MSBuildProjectName).config 41 | 42 | 43 | 44 | $(MSBuildProjectDirectory)\packages.config 45 | $(PackagesProjectConfig) 46 | 47 | 48 | 49 | 50 | $(NuGetToolsPath)\NuGet.exe 51 | @(PackageSource) 52 | 53 | "$(NuGetExePath)" 54 | mono --runtime=v4.0.30319 "$(NuGetExePath)" 55 | 56 | $(TargetDir.Trim('\\')) 57 | 58 | -RequireConsent 59 | -NonInteractive 60 | 61 | "$(SolutionDir) " 62 | "$(SolutionDir)" 63 | 64 | 65 | $(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir $(PaddedSolutionDir) 66 | $(NuGetCommand) pack "$(ProjectPath)" -Properties "Configuration=$(Configuration);Platform=$(Platform)" $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols 67 | 68 | 69 | 70 | RestorePackages; 71 | $(BuildDependsOn); 72 | 73 | 74 | 75 | 76 | $(BuildDependsOn); 77 | BuildPackage; 78 | 79 | 80 | 81 | 82 | 83 | 84 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 99 | 100 | 103 | 104 | 105 | 106 | 108 | 109 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 141 | 142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /CreateDatabaseTables.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE [dbo].[Markets]( 2 | [Id] [int] IDENTITY(1,1) NOT NULL, 3 | [Name] [nvarchar](max) NULL, 4 | [Address] [nvarchar](max) NULL, 5 | [Notes] [nvarchar](max) NULL, 6 | CONSTRAINT [PK_dbo.Markets] PRIMARY KEY CLUSTERED 7 | ( 8 | [Id] ASC 9 | ) 10 | ) 11 | GO 12 | 13 | CREATE TABLE [dbo].[Ratings]( 14 | [Id] [int] IDENTITY(1,1) NOT NULL, 15 | [UserEmail] [nvarchar](max) NULL, 16 | [Comment] [nvarchar](max) NULL, 17 | [Rate] [int] NOT NULL, 18 | [MarketId] [int] NOT NULL, 19 | CONSTRAINT [PK_dbo.Ratings] PRIMARY KEY CLUSTERED 20 | ( 21 | [Id] ASC 22 | ) 23 | ) 24 | GO 25 | 26 | CREATE TABLE [dbo].[Recommendations]( 27 | [Id] [int] IDENTITY(1,1) NOT NULL, 28 | [UserEmail] [nvarchar](max) NOT NULL, 29 | [MarketId] [int] NOT NULL, 30 | CONSTRAINT [PK_Recommendations] PRIMARY KEY CLUSTERED 31 | ( 32 | [Id] ASC 33 | ) 34 | ) 35 | GO -------------------------------------------------------------------------------- /CreateLocalDatabase.sql: -------------------------------------------------------------------------------- 1 | CREATE DATABASE [MarketManagementServiceDb] 2 | GO 3 | -------------------------------------------------------------------------------- /LICENCE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Future Processing Sp. z o.o. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /MarketFinder.AnalyticsService/MarketFinder.AnalyticsService.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {6D2BAC0F-6460-4EC6-9105-58A006ECAD86} 8 | Library 9 | Properties 10 | MarketFinder.AnalyticsService 11 | MarketFinder.AnalyticsService 12 | v4.5 13 | 512 14 | ..\ 15 | true 16 | 17 | 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | ..\packages\Dapper.1.42\lib\net45\Dapper.dll 37 | 38 | 39 | False 40 | ..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll 41 | 42 | 43 | 44 | 45 | 46 | 47 | False 48 | ..\packages\Microsoft.AspNet.WebApi.Client.5.2.2\lib\net45\System.Net.Http.Formatting.dll 49 | 50 | 51 | False 52 | ..\packages\Microsoft.AspNet.WebApi.Core.5.2.2\lib\net45\System.Web.Http.dll 53 | 54 | 55 | False 56 | ..\packages\Microsoft.AspNet.WebApi.WebHost.5.2.2\lib\net45\System.Web.Http.WebHost.dll 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 79 | 80 | 81 | 82 | 89 | -------------------------------------------------------------------------------- /MarketFinder.AnalyticsService/MarketsDataRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Configuration; 3 | using System.Data.SqlClient; 4 | using Dapper; 5 | 6 | namespace MarketFinder.AnalyticsService 7 | { 8 | public class MarketsDataRepository 9 | { 10 | public IEnumerable GetRatings() 11 | { 12 | string connectionString = ConfigurationManager.ConnectionStrings["MarketManagementServiceDb"].ConnectionString; 13 | using (var connection = new SqlConnection(connectionString)) 14 | { 15 | return connection.Query("SELECT * FROM Ratings"); 16 | } 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /MarketFinder.AnalyticsService/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("MarketFinder.AnalyticsService")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("MarketFinder.AnalyticsService")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("d169af8b-e524-4335-90a1-c23cb947efdb")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /MarketFinder.AnalyticsService/Rating.cs: -------------------------------------------------------------------------------- 1 | namespace MarketFinder.AnalyticsService 2 | { 3 | public class Rating 4 | { 5 | public int Id { get; set; } 6 | 7 | public string UserEmail { get; set; } 8 | 9 | public string Comment { get; set; } 10 | 11 | public int Rate { get; set; } 12 | 13 | public int MarketId { get; set; } 14 | } 15 | } -------------------------------------------------------------------------------- /MarketFinder.AnalyticsService/RecomendationRepository.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Configuration; 3 | using System.Data.SqlClient; 4 | using Dapper; 5 | 6 | namespace MarketFinder.AnalyticsService 7 | { 8 | public class RecomendationRepository 9 | { 10 | public void Insert(string userEmail, int marketId) 11 | { 12 | string connectionString = ConfigurationManager.ConnectionStrings["RecommendationsDb"].ConnectionString; 13 | using (var connection = new SqlConnection(connectionString)) 14 | { 15 | connection.Execute( 16 | "INSERT Recommendations (UserEmail, MarketId) VALUES (@userEmail, @marketId)", 17 | new { userEmail, marketId}); 18 | } 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /MarketFinder.AnalyticsService/RecommendationsAnalysisController.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Configuration; 3 | using System.Data.SqlClient; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Web.Http; 8 | using Dapper; 9 | 10 | namespace MarketFinder.AnalyticsService 11 | { 12 | public class RecommendationsAnalysisController : ApiController 13 | { 14 | private readonly MarketsDataRepository _marketsDataRepository = new MarketsDataRepository(); 15 | private readonly RecomendationRepository _recomendationRepository = new RecomendationRepository(); 16 | 17 | [HttpPost] 18 | public void GenerateRecomendations() 19 | { 20 | var ratings = _marketsDataRepository.GetRatings(); 21 | 22 | var userToFavouriteMarkets = new Dictionary>(); 23 | var userRatings = ratings.GroupBy(r=>r.UserEmail); 24 | foreach (var userRating in userRatings) 25 | { 26 | userToFavouriteMarkets[userRating.Key] = userRating.OrderByDescending(r => r.Rate).Take(3).Select(r => r.MarketId).ToList(); 27 | } 28 | 29 | foreach (var userRating in userRatings) 30 | { 31 | var userFavourites = userRating.OrderByDescending(r => r.Rate).Take(5).Select(r => r.MarketId).ToArray(); 32 | var usersWithSimilarRecommendations = userToFavouriteMarkets.Select(u=>u.Value).Where(ufm => ufm.Any(r => userFavourites.Contains(r))); 33 | 34 | var userRecomendations = usersWithSimilarRecommendations.SelectMany(u => u).Distinct().Except(userRating.Select(u=>u.MarketId)).ToList(); 35 | 36 | foreach (var userRecomendation in userRecomendations) 37 | { 38 | _recomendationRepository.Insert(userRating.Key, userRecomendation); 39 | } 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /MarketFinder.AnalyticsService/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /MarketFinder.CommonHost/App_Start/WebApiConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web.Http; 5 | 6 | namespace MarketFinder.CommonHost 7 | { 8 | public static class WebApiConfig 9 | { 10 | public static void Register(HttpConfiguration config) 11 | { 12 | // Web API configuration and services 13 | 14 | // Web API routes 15 | config.MapHttpAttributeRoutes(); 16 | 17 | config.Routes.MapHttpRoute( 18 | name: "DefaultApi", 19 | routeTemplate: "{controller}/{id}", 20 | defaults: new { id = RouteParameter.Optional } 21 | ); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /MarketFinder.CommonHost/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.cs" Inherits="MarketFinder.CommonHost.WebApiApplication" Language="C#" %> 2 | -------------------------------------------------------------------------------- /MarketFinder.CommonHost/Global.asax.cs: -------------------------------------------------------------------------------- 1 | using System.Web; 2 | using System.Web.Http; 3 | 4 | namespace MarketFinder.CommonHost 5 | { 6 | public class WebApiApplication : HttpApplication 7 | { 8 | protected void Application_Start() 9 | { 10 | GlobalConfiguration.Configure(WebApiConfig.Register); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /MarketFinder.CommonHost/MarketFinder.CommonHost.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | 8 | 9 | 2.0 10 | {3D7B8032-D376-4973-8864-AB5D56741C8B} 11 | {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} 12 | Library 13 | Properties 14 | MarketFinder.CommonHost 15 | MarketFinder.CommonHost 16 | v4.5 17 | true 18 | 19 | 20 | 21 | 22 | ..\ 23 | true 24 | 25 | 26 | true 27 | full 28 | false 29 | bin\ 30 | DEBUG;TRACE 31 | prompt 32 | 4 33 | 34 | 35 | pdbonly 36 | true 37 | bin\ 38 | TRACE 39 | prompt 40 | 4 41 | 42 | 43 | 44 | False 45 | ..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.dll 46 | 47 | 48 | ..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.SqlServer.dll 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | ..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll 72 | 73 | 74 | ..\packages\Microsoft.AspNet.WebApi.Client.5.2.2\lib\net45\System.Net.Http.Formatting.dll 75 | 76 | 77 | ..\packages\Microsoft.AspNet.WebApi.Core.5.2.2\lib\net45\System.Web.Http.dll 78 | 79 | 80 | ..\packages\Microsoft.AspNet.WebApi.WebHost.5.2.2\lib\net45\System.Web.Http.WebHost.dll 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | Global.asax 91 | 92 | 93 | 94 | 95 | 96 | Designer 97 | 98 | 99 | Web.config 100 | 101 | 102 | Web.config 103 | 104 | 105 | 106 | 107 | 108 | {6d2bac0f-6460-4ec6-9105-58a006ecad86} 109 | MarketFinder.AnalyticsService 110 | 111 | 112 | {cefe6fb1-4575-43b8-a065-0f098186d5c7} 113 | MarketFinder.MakretManagementService 114 | 115 | 116 | 117 | 10.0 118 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | True 128 | True 129 | 24043 130 | / 131 | http://localhost:24043/ 132 | False 133 | False 134 | 135 | 136 | False 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 145 | 146 | 147 | 148 | 155 | -------------------------------------------------------------------------------- /MarketFinder.CommonHost/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("MarketFinder.CommonHost")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("MarketFinder.CommonHost")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("82e4482c-67a0-4511-a0c8-043de07deb43")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /MarketFinder.CommonHost/Web.Debug.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | -------------------------------------------------------------------------------- /MarketFinder.CommonHost/Web.Release.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | -------------------------------------------------------------------------------- /MarketFinder.CommonHost/Web.config: -------------------------------------------------------------------------------- 1 |  2 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /MarketFinder.CommonHost/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /MarketFinder.MakretManagementService/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /MarketFinder.MakretManagementService/Controllers/MarketsController.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Data.Entity; 3 | using System.Data.Entity.Infrastructure; 4 | using System.Linq; 5 | using System.Net; 6 | using System.Threading.Tasks; 7 | using System.Web.Http; 8 | using System.Web.Http.Description; 9 | using MarketFinder.MakretManagementService.Models; 10 | 11 | namespace MarketFinder.MakretManagementService.Controllers 12 | { 13 | public class MarketsController : ApiController 14 | { 15 | private MarketManagementServiceContext db = new MarketManagementServiceContext(); 16 | 17 | // GET: Markets 18 | public async Task> GetMarkets() 19 | { 20 | return await db.Markets.ToListAsync(); 21 | } 22 | 23 | // GET: Markets/5 24 | [ResponseType(typeof(Market))] 25 | public async Task GetMarket(int id) 26 | { 27 | Market market = await db.Markets.FindAsync(id); 28 | if (market == null) 29 | { 30 | return NotFound(); 31 | } 32 | 33 | return Ok(market); 34 | } 35 | 36 | // PUT: Markets/5 37 | [ResponseType(typeof(void))] 38 | public async Task PutMarket(int id, [FromBody]Market market) 39 | { 40 | if (!ModelState.IsValid) 41 | { 42 | return BadRequest(ModelState); 43 | } 44 | 45 | if (id != market.Id) 46 | { 47 | return BadRequest(); 48 | } 49 | 50 | db.Entry(market).State = EntityState.Modified; 51 | 52 | try 53 | { 54 | await db.SaveChangesAsync(); 55 | } 56 | catch (DbUpdateConcurrencyException) 57 | { 58 | if (!MarketExists(id)) 59 | { 60 | return NotFound(); 61 | } 62 | else 63 | { 64 | throw; 65 | } 66 | } 67 | 68 | return StatusCode(HttpStatusCode.NoContent); 69 | } 70 | 71 | // POST: Markets 72 | [ResponseType(typeof(Market))] 73 | public async Task PostMarket(Market market) 74 | { 75 | if (!ModelState.IsValid) 76 | { 77 | return BadRequest(ModelState); 78 | } 79 | 80 | db.Markets.Add(market); 81 | await db.SaveChangesAsync(); 82 | 83 | return CreatedAtRoute("DefaultApi", new { id = market.Id }, market); 84 | } 85 | 86 | // DELETE: Markets/5 87 | [ResponseType(typeof(Market))] 88 | public async Task DeleteMarket(int id) 89 | { 90 | Market market = await db.Markets.FindAsync(id); 91 | if (market == null) 92 | { 93 | return NotFound(); 94 | } 95 | 96 | db.Markets.Remove(market); 97 | await db.SaveChangesAsync(); 98 | 99 | return Ok(market); 100 | } 101 | 102 | protected override void Dispose(bool disposing) 103 | { 104 | if (disposing) 105 | { 106 | db.Dispose(); 107 | } 108 | base.Dispose(disposing); 109 | } 110 | 111 | private bool MarketExists(int id) 112 | { 113 | return db.Markets.Count(e => e.Id == id) > 0; 114 | } 115 | } 116 | } -------------------------------------------------------------------------------- /MarketFinder.MakretManagementService/Controllers/RatingsController.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Data.Entity; 3 | using System.Data.Entity.Infrastructure; 4 | using System.Linq; 5 | using System.Net; 6 | using System.Threading.Tasks; 7 | using System.Web.Http; 8 | using System.Web.Http.Description; 9 | using MarketFinder.MakretManagementService.Models; 10 | 11 | namespace MarketFinder.MakretManagementService.Controllers 12 | { 13 | public class RatingsController : ApiController 14 | { 15 | private MarketManagementServiceContext db = new MarketManagementServiceContext(); 16 | 17 | // GET: Ratings 18 | public async Task> GetRatings() 19 | { 20 | return await db.Ratings.ToListAsync(); 21 | } 22 | 23 | // GET: Ratings/5 24 | [ResponseType(typeof(Rating))] 25 | public async Task GetRating(int id) 26 | { 27 | Rating rating = await db.Ratings.FindAsync(id); 28 | if (rating == null) 29 | { 30 | return NotFound(); 31 | } 32 | 33 | return Ok(rating); 34 | } 35 | 36 | // PUT: Ratings/5 37 | [ResponseType(typeof(void))] 38 | public async Task PutRating(int id, Rating rating) 39 | { 40 | if (!ModelState.IsValid) 41 | { 42 | return BadRequest(ModelState); 43 | } 44 | 45 | if (id != rating.Id) 46 | { 47 | return BadRequest(); 48 | } 49 | 50 | db.Entry(rating).State = EntityState.Modified; 51 | 52 | try 53 | { 54 | await db.SaveChangesAsync(); 55 | } 56 | catch (DbUpdateConcurrencyException) 57 | { 58 | if (!RatingExists(id)) 59 | { 60 | return NotFound(); 61 | } 62 | else 63 | { 64 | throw; 65 | } 66 | } 67 | 68 | return StatusCode(HttpStatusCode.NoContent); 69 | } 70 | 71 | // POST: Ratings 72 | [ResponseType(typeof(Rating))] 73 | public async Task PostRating(Rating rating) 74 | { 75 | if (!ModelState.IsValid) 76 | { 77 | return BadRequest(ModelState); 78 | } 79 | 80 | db.Ratings.Add(rating); 81 | await db.SaveChangesAsync(); 82 | 83 | return CreatedAtRoute("DefaultApi", new { id = rating.Id }, rating); 84 | } 85 | 86 | // DELETE: Ratings/5 87 | [ResponseType(typeof(Rating))] 88 | public async Task DeleteRating(int id) 89 | { 90 | Rating rating = await db.Ratings.FindAsync(id); 91 | if (rating == null) 92 | { 93 | return NotFound(); 94 | } 95 | 96 | db.Ratings.Remove(rating); 97 | await db.SaveChangesAsync(); 98 | 99 | return Ok(rating); 100 | } 101 | 102 | protected override void Dispose(bool disposing) 103 | { 104 | if (disposing) 105 | { 106 | db.Dispose(); 107 | } 108 | base.Dispose(disposing); 109 | } 110 | 111 | private bool RatingExists(int id) 112 | { 113 | return db.Ratings.Count(e => e.Id == id) > 0; 114 | } 115 | } 116 | } -------------------------------------------------------------------------------- /MarketFinder.MakretManagementService/MarketFinder.MakretManagementService.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {CEFE6FB1-4575-43B8-A065-0F098186D5C7} 8 | Library 9 | Properties 10 | MarketFinder.MakretManagementService 11 | MarketFinder.MakretManagementService 12 | v4.5 13 | 512 14 | ..\ 15 | true 16 | 17 | 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | False 37 | ..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.dll 38 | 39 | 40 | False 41 | ..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.SqlServer.dll 42 | 43 | 44 | False 45 | ..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll 46 | 47 | 48 | 49 | 50 | 51 | 52 | False 53 | ..\packages\Microsoft.AspNet.WebApi.Client.5.2.2\lib\net45\System.Net.Http.Formatting.dll 54 | 55 | 56 | False 57 | ..\packages\Microsoft.AspNet.WebApi.Core.5.2.2\lib\net45\System.Web.Http.dll 58 | 59 | 60 | False 61 | ..\packages\Microsoft.AspNet.WebApi.WebHost.5.2.2\lib\net45\System.Web.Http.WebHost.dll 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 86 | 87 | 88 | 89 | 96 | -------------------------------------------------------------------------------- /MarketFinder.MakretManagementService/Models/Market.cs: -------------------------------------------------------------------------------- 1 | namespace MarketFinder.MakretManagementService.Models 2 | { 3 | public class Market 4 | { 5 | public int? Id { get; set; } 6 | 7 | public string Name { get; set; } 8 | 9 | public string Address { get; set; } 10 | 11 | public string Notes { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /MarketFinder.MakretManagementService/Models/MarketManagementServiceContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Data.Entity; 3 | 4 | namespace MarketFinder.MakretManagementService.Models 5 | { 6 | public class MarketManagementServiceContext : DbContext 7 | { 8 | static MarketManagementServiceContext() 9 | { 10 | // Use CreateDatabase.sql to create Database 11 | Database.SetInitializer(null); 12 | } 13 | 14 | public MarketManagementServiceContext() 15 | : base("name=MarketManagementServiceDb") 16 | { 17 | } 18 | 19 | public System.Data.Entity.DbSet Markets { get; set; } 20 | 21 | public System.Data.Entity.DbSet Ratings { get; set; } 22 | 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /MarketFinder.MakretManagementService/Models/Rating.cs: -------------------------------------------------------------------------------- 1 | namespace MarketFinder.MakretManagementService.Models 2 | { 3 | public class Rating 4 | { 5 | public int Id { get; set; } 6 | 7 | public string UserEmail { get; set; } 8 | 9 | public string Comment { get; set; } 10 | 11 | public int Rate { get; set; } 12 | 13 | // For simplicity of this demo code it lacks Forign Key here 14 | public int MarketId { get; set; } 15 | } 16 | } -------------------------------------------------------------------------------- /MarketFinder.MakretManagementService/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("MarketFinder.MakretManagementService")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("MarketFinder.MakretManagementService")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("c99e758d-a407-48fc-86bd-fb34fc270373")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /MarketFinder.MakretManagementService/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /MarketFinder.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.31101.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MarketFinder.MakretManagementService", "MarketFinder.MakretManagementService\MarketFinder.MakretManagementService.csproj", "{CEFE6FB1-4575-43B8-A065-0F098186D5C7}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{80CB27D5-E79D-47A7-9CD3-709D464DBDD0}" 9 | ProjectSection(SolutionItems) = preProject 10 | .nuget\NuGet.Config = .nuget\NuGet.Config 11 | .nuget\NuGet.exe = .nuget\NuGet.exe 12 | .nuget\NuGet.targets = .nuget\NuGet.targets 13 | EndProjectSection 14 | EndProject 15 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MarketFinder.CommonHost", "MarketFinder.CommonHost\MarketFinder.CommonHost.csproj", "{3D7B8032-D376-4973-8864-AB5D56741C8B}" 16 | EndProject 17 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MarketFinder.AnalyticsService", "MarketFinder.AnalyticsService\MarketFinder.AnalyticsService.csproj", "{6D2BAC0F-6460-4EC6-9105-58A006ECAD86}" 18 | EndProject 19 | Global 20 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 21 | Debug|Any CPU = Debug|Any CPU 22 | Release|Any CPU = Release|Any CPU 23 | EndGlobalSection 24 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 25 | {CEFE6FB1-4575-43B8-A065-0F098186D5C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 26 | {CEFE6FB1-4575-43B8-A065-0F098186D5C7}.Debug|Any CPU.Build.0 = Debug|Any CPU 27 | {CEFE6FB1-4575-43B8-A065-0F098186D5C7}.Release|Any CPU.ActiveCfg = Release|Any CPU 28 | {CEFE6FB1-4575-43B8-A065-0F098186D5C7}.Release|Any CPU.Build.0 = Release|Any CPU 29 | {3D7B8032-D376-4973-8864-AB5D56741C8B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 30 | {3D7B8032-D376-4973-8864-AB5D56741C8B}.Debug|Any CPU.Build.0 = Debug|Any CPU 31 | {3D7B8032-D376-4973-8864-AB5D56741C8B}.Release|Any CPU.ActiveCfg = Release|Any CPU 32 | {3D7B8032-D376-4973-8864-AB5D56741C8B}.Release|Any CPU.Build.0 = Release|Any CPU 33 | {6D2BAC0F-6460-4EC6-9105-58A006ECAD86}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 34 | {6D2BAC0F-6460-4EC6-9105-58A006ECAD86}.Debug|Any CPU.Build.0 = Debug|Any CPU 35 | {6D2BAC0F-6460-4EC6-9105-58A006ECAD86}.Release|Any CPU.ActiveCfg = Release|Any CPU 36 | {6D2BAC0F-6460-4EC6-9105-58A006ECAD86}.Release|Any CPU.Build.0 = Release|Any CPU 37 | EndGlobalSection 38 | GlobalSection(SolutionProperties) = preSolution 39 | HideSolutionNode = FALSE 40 | EndGlobalSection 41 | EndGlobal 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Microservices - ASP.NET Web API - Azure 2 | 3 | This is sample project presenting how to organize system into multiple lightweight, logical, decoupled components, rather that multiple independently hosted services. With this approach we can start with hosting all components in single service and dividing it into multiple ones overtime. 4 | 5 | This code is related to article posted at [Future Processing technical blog](http://www.future-processing.pl/technical-blog/). 6 | 7 | --- 8 | Krzysztof Szabelski 9 | http://krzysztofszabelski.com/ 10 | --------------------------------------------------------------------------------