├── .gitattributes
├── .gitignore
├── README.md
├── ShapingAPI.sln
├── global.json
├── licence
└── src
└── ShapingAPI
├── .bowerrc
├── Controllers
├── AlbumsController.cs
├── ArtistsController.cs
├── CustomersController.cs
├── HomeController.cs
├── InvoicesController.cs
└── TracksController.cs
├── Entities
├── Album.cs
├── Artist.cs
├── ChinookContext.cs
├── Customer.cs
├── Employee.cs
├── Genre.cs
├── Invoice.cs
├── InvoiceLine.cs
├── MediaType.cs
├── Playlist.cs
├── PlaylistTrack.cs
├── Track.cs
└── sysdiagrams.cs
├── Infrastructure
├── Core
│ ├── Expressions.cs
│ ├── TokenService.cs
│ └── Utils.cs
├── Data
│ ├── IRepository.cs
│ ├── Repositories
│ │ ├── IRepositories.cs
│ │ └── Repositories.cs
│ └── Repository.cs
└── Mappings
│ ├── AutoMapperConfiguration.cs
│ └── DomainToViewModelMappingProfile.cs
├── Project_Readme.html
├── Properties
└── launchSettings.json
├── SQL
└── Chinook_SqlServer_AutoIncrementPKs.sql
├── ShapingAPI.xproj
├── Startup.cs
├── ViewModels
├── AddressViewModel.cs
├── AlbumViewModel.cs
├── ArtistViewModel.cs
├── ContactViewModel.cs
├── CustomerViewModel.cs
├── InvoiceLineViewModel.cs
├── InvoiceViewModel.cs
└── TrackViewModel.cs
├── Views
├── Home
│ ├── Albums.cshtml
│ ├── Artists.cshtml
│ ├── Customers.cshtml
│ └── Index.cshtml
├── Shared
│ └── _Layout.cshtml
└── _ViewStart.cshtml
├── appsettings.json
├── bower.json
├── project.json
└── wwwroot
├── app
├── app.js
└── controllers
│ ├── albumsCtrl.js
│ ├── artistsCtrl.js
│ ├── customersCtrl.js
│ └── tracksCtrl.js
├── images
├── facebook.png
├── github.png
├── spinner.gif
└── twitter.png
├── styles
└── site.css
└── web.config
/.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 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | x64/
19 | x86/
20 | build/
21 | bld/
22 | [Bb]in/
23 | [Oo]bj/
24 |
25 | # Visual Studio 2015 cache/options directory
26 | .vs/
27 |
28 | # MSTest test Results
29 | [Tt]est[Rr]esult*/
30 | [Bb]uild[Ll]og.*
31 |
32 | # NUNIT
33 | *.VisualState.xml
34 | TestResult.xml
35 |
36 | # Build Results of an ATL Project
37 | [Dd]ebugPS/
38 | [Rr]eleasePS/
39 | dlldata.c
40 |
41 | # DNX
42 | project.lock.json
43 | artifacts/
44 |
45 | *_i.c
46 | *_p.c
47 | *_i.h
48 | *.ilk
49 | *.meta
50 | *.obj
51 | *.pch
52 | *.pdb
53 | *.pgc
54 | *.pgd
55 | *.rsp
56 | *.sbr
57 | *.tlb
58 | *.tli
59 | *.tlh
60 | *.tmp
61 | *.tmp_proj
62 | *.log
63 | *.vspscc
64 | *.vssscc
65 | .builds
66 | *.pidb
67 | *.svclog
68 | *.scc
69 |
70 | # Chutzpah Test files
71 | _Chutzpah*
72 |
73 | # Visual C++ cache files
74 | ipch/
75 | *.aps
76 | *.ncb
77 | *.opensdf
78 | *.sdf
79 | *.cachefile
80 |
81 | # Visual Studio profiler
82 | *.psess
83 | *.vsp
84 | *.vspx
85 |
86 | # TFS 2012 Local Workspace
87 | $tf/
88 |
89 | # Guidance Automation Toolkit
90 | *.gpState
91 |
92 | # ReSharper is a .NET coding add-in
93 | _ReSharper*/
94 | *.[Rr]e[Ss]harper
95 | *.DotSettings.user
96 |
97 | # JustCode is a .NET coding add-in
98 | .JustCode
99 |
100 | # TeamCity is a build add-in
101 | _TeamCity*
102 |
103 | # DotCover is a Code Coverage Tool
104 | *.dotCover
105 |
106 | # NCrunch
107 | _NCrunch_*
108 | .*crunch*.local.xml
109 |
110 | # MightyMoose
111 | *.mm.*
112 | AutoTest.Net/
113 |
114 | # Web workbench (sass)
115 | .sass-cache/
116 |
117 | # Installshield output folder
118 | [Ee]xpress/
119 |
120 | # DocProject is a documentation generator add-in
121 | DocProject/buildhelp/
122 | DocProject/Help/*.HxT
123 | DocProject/Help/*.HxC
124 | DocProject/Help/*.hhc
125 | DocProject/Help/*.hhk
126 | DocProject/Help/*.hhp
127 | DocProject/Help/Html2
128 | DocProject/Help/html
129 |
130 | # Click-Once directory
131 | publish/
132 |
133 | # Publish Web Output
134 | *.[Pp]ublish.xml
135 | *.azurePubxml
136 | ## TODO: Comment the next line if you want to checkin your
137 | ## web deploy settings but do note that will include unencrypted
138 | ## passwords
139 | #*.pubxml
140 |
141 | *.publishproj
142 |
143 | # NuGet Packages
144 | *.nupkg
145 | # The packages folder can be ignored because of Package Restore
146 | **/packages/*
147 | # except build/, which is used as an MSBuild target.
148 | !**/packages/build/
149 | # Uncomment if necessary however generally it will be regenerated when needed
150 | #!**/packages/repositories.config
151 |
152 | # Windows Azure Build Output
153 | csx/
154 | *.build.csdef
155 |
156 | # Windows Store app package directory
157 | AppPackages/
158 |
159 | # Visual Studio cache files
160 | # files ending in .cache can be ignored
161 | *.[Cc]ache
162 | # but keep track of directories ending in .cache
163 | !*.[Cc]ache/
164 |
165 | # Others
166 | ClientBin/
167 | [Ss]tyle[Cc]op.*
168 | ~$*
169 | *~
170 | *.dbmdl
171 | *.dbproj.schemaview
172 | *.pfx
173 | *.publishsettings
174 | node_modules/
175 | orleans.codegen.cs
176 |
177 | # RIA/Silverlight projects
178 | Generated_Code/
179 |
180 | # Backup & report files from converting an old project file
181 | # to a newer Visual Studio version. Backup files are not needed,
182 | # because we have git ;-)
183 | _UpgradeReport_Files/
184 | Backup*/
185 | UpgradeLog*.XML
186 | UpgradeLog*.htm
187 |
188 | # SQL Server files
189 | *.mdf
190 | *.ldf
191 |
192 | # Business Intelligence projects
193 | *.rdl.data
194 | *.bim.layout
195 | *.bim_*.settings
196 |
197 | # Microsoft Fakes
198 | FakesAssemblies/
199 |
200 | # Node.js Tools for Visual Studio
201 | .ntvs_analysis.dat
202 |
203 | # Visual Studio 6 build log
204 | *.plg
205 |
206 | # Visual Studio 6 workspace options file
207 | *.opt
208 |
209 | # LightSwitch generated files
210 | GeneratedArtifacts/
211 | _Pvt_Extensions/
212 | ModelManifest.xml
213 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
Building multi-client APIs in ASP.NET
2 |
3 |
4 | The project introduces a method that processes JTokens in order to return only the properties requested by the client.
5 |
8 | Assuming the result of the resource uri /api/tracks/1 is the following:
9 |
10 | ```javascript
11 | {
12 | "TrackId": 1,
13 | "AlbumId": 1,
14 | "Bytes": 11170334,
15 | "Composer": "Angus Young, Malcolm Young, Brian Johnson",
16 | "GenreId": 1,
17 | "MediaTypeId": 1,
18 | "Milliseconds": 343719,
19 | "Name": "For Those About To Rock (We Salute You)",
20 | "UnitPrice": 0.99
21 | }
22 | ```
23 | You can request only specific properties of that resource by making the request /api/tracks/1?props=bytes,milliseconds,name
24 | ```javascript
25 | {
26 | "Bytes": 11170334,
27 | "Milliseconds": 343719,
28 | "Name": "For Those About To Rock (We Salute You)"
29 | }
30 | ```
31 | The algorithm supports nested navigation properties as well. If /api/albums/1 returns..
32 | ```javascript
33 | {
34 | "AlbumId": 1,
35 | "ArtistName": "AC/DC",
36 | "Title": "For Those About To Rock We Salute You",
37 | "Track": [
38 | {
39 | "TrackId": 1,
40 | "AlbumId": 1,
41 | "Bytes": 11170334,
42 | "Composer": "Angus Young, Malcolm Young, Brian Johnson",
43 | "GenreId": 1,
44 | "MediaTypeId": 1,
45 | "Milliseconds": 343719,
46 | "Name": "For Those About To Rock (We Salute You)",
47 | "UnitPrice": 0.99
48 | },
49 | {
50 | "TrackId": 6,
51 | "AlbumId": 1,
52 | "Bytes": 6713451,
53 | "Composer": "Angus Young, Malcolm Young, Brian Johnson",
54 | "GenreId": 1,
55 | "MediaTypeId": 1,
56 | "Milliseconds": 205662,
57 | "Name": "Put The Finger On You",
58 | "UnitPrice": 0.99
59 | }
60 | ]
61 | }
62 | ```
63 | Then /api/albums/1?props=artistname,title,track(composer;name) should return the following:
64 | ```javascript
65 | {
66 | "ArtistName": "AC/DC",
67 | "Title": "For Those About To Rock We Salute You",
68 | "Track": [
69 | {
70 | "Composer": "Angus Young, Malcolm Young, Brian Johnson",
71 | "Name": "For Those About To Rock (We Salute You)"
72 | },
73 | {
74 | "Composer": "Angus Young, Malcolm Young, Brian Johnson",
75 | "Name": "Put The Finger On You"
76 | }
77 | ]
78 | }
79 | ```
80 | Properties in navigations should be semicolon (;) separated inside parethensis.
81 |
82 | Example in API Controller
83 |
84 |
85 | ```javascript
86 | var _tracks = _trackRepository.GetAll(includeProperties).Skip(page).Take(pageSize);
87 |
88 | var _tracksVM = Mapper.Map, IEnumerable>(_tracks);
89 |
90 | string _serializedTracks = JsonConvert.SerializeObject(_tracksVM, Formatting.None,
91 | new JsonSerializerSettings()
92 | {
93 | ReferenceLoopHandling = ReferenceLoopHandling.Ignore
94 | });
95 |
96 | JToken _jtoken = JToken.Parse(_serializedTracks);
97 | if (!string.IsNullOrEmpty(props))
98 | Utils.FilterProperties(_jtoken, props.ToLower().Split(',').ToList());
99 |
100 | return Ok(_jtoken);
101 | ```
102 |
103 | The project is built in Visual Studio 2015 and ASP.NET Core but the technique and the method can be easily integrated in any version of ASP.NET API. In case you want to run the ShapingAPI application:
104 |
105 |
106 | Download the source code and open the solution in Visual Studio 2015
107 |
108 |
109 | Restore Nuget and Bower packages
110 |
111 |
112 | Install the Chinook database in your SQL Server by running the script inside the SQL folder.
113 |
114 |
115 | Alter the appsettings.json file to reflect your database environment.
116 |
117 |
118 | Run the application
119 |
120 |
121 |
122 |
123 | Donations
124 | For being part of open source projects and documenting my work here and on chsakell's blog I really do not charge anything. I try to avoid any type of ads also.
125 |
126 | If you think that any information you obtained here is worth of some money and are willing to pay for it, feel free to send any amount through paypal.
127 |
128 |
129 | Paypal
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 | Follow chsakell's Blog
140 |
141 |
142 |
143 | Facebook
144 | Twitter
145 |
146 |
147 |
148 |
149 | Microsoft Web Application Development
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 | License
164 | Code released under the MIT license .
165 |
--------------------------------------------------------------------------------
/ShapingAPI.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.24720.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{B1752202-EC14-4A1F-A52C-0FE85D891D2B}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{2B8F9A03-FA1B-494C-BD99-562248B190D3}"
9 | ProjectSection(SolutionItems) = preProject
10 | global.json = global.json
11 | EndProjectSection
12 | EndProject
13 | Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ShapingAPI", "src\ShapingAPI\ShapingAPI.xproj", "{6C8D22BC-4F3B-4F8F-947D-F9CDEB82F3DE}"
14 | EndProject
15 | Global
16 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
17 | Debug|Any CPU = Debug|Any CPU
18 | Release|Any CPU = Release|Any CPU
19 | EndGlobalSection
20 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
21 | {6C8D22BC-4F3B-4F8F-947D-F9CDEB82F3DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
22 | {6C8D22BC-4F3B-4F8F-947D-F9CDEB82F3DE}.Debug|Any CPU.Build.0 = Debug|Any CPU
23 | {6C8D22BC-4F3B-4F8F-947D-F9CDEB82F3DE}.Release|Any CPU.ActiveCfg = Release|Any CPU
24 | {6C8D22BC-4F3B-4F8F-947D-F9CDEB82F3DE}.Release|Any CPU.Build.0 = Release|Any CPU
25 | EndGlobalSection
26 | GlobalSection(SolutionProperties) = preSolution
27 | HideSolutionNode = FALSE
28 | EndGlobalSection
29 | GlobalSection(NestedProjects) = preSolution
30 | {6C8D22BC-4F3B-4F8F-947D-F9CDEB82F3DE} = {B1752202-EC14-4A1F-A52C-0FE85D891D2B}
31 | EndGlobalSection
32 | EndGlobal
33 |
--------------------------------------------------------------------------------
/global.json:
--------------------------------------------------------------------------------
1 | {
2 | "projects": [ "src", "test" ],
3 | "sdk": {
4 | "version": "1.0.0-rc1-update1"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/licence:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016
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.
22 |
--------------------------------------------------------------------------------
/src/ShapingAPI/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory": "wwwroot/lib"
3 | }
4 |
--------------------------------------------------------------------------------
/src/ShapingAPI/Controllers/AlbumsController.cs:
--------------------------------------------------------------------------------
1 | using AutoMapper;
2 | using Microsoft.AspNet.Mvc;
3 | using Newtonsoft.Json;
4 | using Newtonsoft.Json.Linq;
5 | using ShapingAPI.Entities;
6 | using ShapingAPI.Infrastructure.Core;
7 | using ShapingAPI.Infrastructure.Data.Repositories;
8 | using ShapingAPI.ViewModels;
9 | using System;
10 | using System.Collections.Generic;
11 | using System.Linq;
12 | using System.Linq.Expressions;
13 | using System.Threading.Tasks;
14 |
15 | namespace ShapingAPI.Controllers
16 | {
17 | [Route("api/[controller]")]
18 | public class AlbumsController : Controller
19 | {
20 | #region Properties
21 | private readonly IAlbumRepository _albumRepository;
22 | private Expression>[] includeProperties;
23 | private const int maxSize = 50;
24 | #endregion
25 |
26 | #region Constructor
27 | public AlbumsController(IAlbumRepository albumRepository)
28 | {
29 | _albumRepository = albumRepository;
30 |
31 | includeProperties = Expressions.LoadAlbumNavigations();
32 | }
33 | #endregion
34 |
35 | #region Actions
36 | public ActionResult Get(string props = null, int page = 1, int pageSize = maxSize)
37 | {
38 | try
39 | {
40 | var _albums = _albumRepository.LoadAll().Skip((page - 1) * pageSize).Take(pageSize);
41 |
42 | var test = _albums.ToList();
43 |
44 | var _albumsVM = Mapper.Map, IEnumerable>(_albums);
45 |
46 | JToken _jtoken = TokenService.CreateJToken(_albumsVM, props);
47 |
48 | return Ok(_jtoken);
49 | }
50 | catch (Exception ex)
51 | {
52 | return new HttpStatusCodeResult(500);
53 | }
54 | }
55 |
56 | [Route("{albumId}")]
57 | public ActionResult Get(int albumId, string props = null)
58 | {
59 | try
60 | {
61 | var _album = _albumRepository.Get(t => t.AlbumId == albumId, includeProperties);
62 |
63 | if (_album == null)
64 | {
65 | return HttpNotFound();
66 | }
67 |
68 | var _albumVM = Mapper.Map(_album);
69 |
70 | JToken _jtoken = TokenService.CreateJToken(_albumVM, props);
71 |
72 | return Ok(_jtoken);
73 | }
74 | catch (Exception ex)
75 | {
76 | return new HttpStatusCodeResult(500);
77 | }
78 | }
79 | #endregion
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/ShapingAPI/Controllers/ArtistsController.cs:
--------------------------------------------------------------------------------
1 | using AutoMapper;
2 | using Microsoft.AspNet.Mvc;
3 | using Newtonsoft.Json;
4 | using Newtonsoft.Json.Linq;
5 | using ShapingAPI.Entities;
6 | using ShapingAPI.Infrastructure.Core;
7 | using ShapingAPI.Infrastructure.Data.Repositories;
8 | using ShapingAPI.ViewModels;
9 | using System;
10 | using System.Collections.Generic;
11 | using System.Linq;
12 | using System.Threading.Tasks;
13 |
14 | namespace ShapingAPI.Controllers
15 | {
16 | [Route("api/[controller]")]
17 | public class ArtistsController : Controller
18 | {
19 | #region Properties
20 | private readonly IArtistRepository _artistRepository;
21 | private const int maxSize = 50;
22 | #endregion
23 |
24 | #region Constructor
25 | public ArtistsController(IArtistRepository artistRepository)
26 | {
27 | _artistRepository = artistRepository;
28 | }
29 | #endregion
30 |
31 | #region Actions
32 | public ActionResult Get(string props = null, int page = 1, int pageSize = maxSize)
33 | {
34 | try
35 | {
36 | var _artists = _artistRepository.LoadAll().Skip((page - 1) * pageSize).Take(pageSize);
37 |
38 | var _artistsVM = Mapper.Map, IEnumerable>(_artists);
39 |
40 | JToken _jtoken = TokenService.CreateJToken(_artistsVM, props);
41 |
42 | return Ok(_jtoken);
43 | }
44 | catch (Exception ex)
45 | {
46 | return new HttpStatusCodeResult(500);
47 | }
48 | }
49 |
50 | [Route("{artistId}")]
51 | public ActionResult Get(int artistId, string props = null)
52 | {
53 | try
54 | {
55 | var _artist = _artistRepository.Load(artistId);
56 |
57 | if (_artist == null)
58 | {
59 | return HttpNotFound();
60 | }
61 |
62 | var _artistVM = Mapper.Map(_artist);
63 |
64 | JToken _jtoken = TokenService.CreateJToken(_artistVM, props);
65 |
66 | return Ok(_jtoken);
67 | }
68 | catch (Exception ex)
69 | {
70 | return new HttpStatusCodeResult(500);
71 | }
72 | }
73 | #endregion
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/ShapingAPI/Controllers/CustomersController.cs:
--------------------------------------------------------------------------------
1 | using AutoMapper;
2 | using Microsoft.AspNet.Mvc;
3 | using Newtonsoft.Json;
4 | using Newtonsoft.Json.Linq;
5 | using ShapingAPI.Entities;
6 | using ShapingAPI.Infrastructure.Core;
7 | using ShapingAPI.Infrastructure.Data.Repositories;
8 | using ShapingAPI.ViewModels;
9 | using System;
10 | using System.Collections.Generic;
11 | using System.Linq;
12 | using System.Linq.Expressions;
13 | using System.Threading.Tasks;
14 |
15 | namespace ShapingAPI.Controllers
16 | {
17 | [Route("api/[controller]")]
18 | public class CustomersController : Controller
19 | {
20 | #region Properties
21 | private readonly ICustomerRepository _customerRepository;
22 | private const int maxSize = 50;
23 | #endregion
24 |
25 | #region Constructor
26 | public CustomersController(ICustomerRepository customerRepository)
27 | {
28 | _customerRepository = customerRepository;
29 | }
30 | #endregion
31 |
32 | #region Actions
33 | public ActionResult Get(string props = null, int page = 1, int pageSize = maxSize)
34 | {
35 | try
36 | {
37 | var _customers = _customerRepository.LoadAll().Skip((page - 1) * pageSize).Take(pageSize);
38 |
39 | var _customersVM = Mapper.Map, IEnumerable>(_customers);
40 |
41 | JToken _jtoken = TokenService.CreateJToken(_customersVM, props);
42 |
43 | return Ok(_jtoken);
44 | }
45 | catch (Exception ex)
46 | {
47 | return new HttpStatusCodeResult(500);
48 | }
49 | }
50 |
51 | [Route("{customerId}")]
52 | public ActionResult Get(int customerId, string props = null)
53 | {
54 | try
55 | {
56 | var _customer = _customerRepository.Load(customerId);
57 |
58 | if (_customer == null)
59 | {
60 | return HttpNotFound();
61 | }
62 |
63 | var _customerVM = Mapper.Map(_customer);
64 |
65 | JToken _jtoken = TokenService.CreateJToken(_customerVM, props);
66 |
67 | return Ok(_jtoken);
68 | }
69 | catch (Exception ex)
70 | {
71 | return new HttpStatusCodeResult(500);
72 | }
73 | }
74 | #endregion
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/ShapingAPI/Controllers/HomeController.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNet.Mvc;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 |
7 | namespace ShapingAPI.Controllers
8 | {
9 | public class HomeController : Controller
10 | {
11 | // GET: //
12 | public IActionResult Index()
13 | {
14 | return View();
15 | }
16 |
17 | public IActionResult Albums()
18 | {
19 | return View();
20 | }
21 |
22 | public IActionResult Artists()
23 | {
24 | return View();
25 | }
26 |
27 | public IActionResult Customers()
28 | {
29 | return View();
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/ShapingAPI/Controllers/InvoicesController.cs:
--------------------------------------------------------------------------------
1 | using AutoMapper;
2 | using Microsoft.AspNet.Mvc;
3 | using Newtonsoft.Json;
4 | using Newtonsoft.Json.Linq;
5 | using ShapingAPI.Entities;
6 | using ShapingAPI.Infrastructure.Core;
7 | using ShapingAPI.Infrastructure.Data.Repositories;
8 | using ShapingAPI.ViewModels;
9 | using System;
10 | using System.Collections.Generic;
11 | using System.Linq;
12 | using System.Linq.Expressions;
13 | using System.Threading.Tasks;
14 |
15 | namespace ShapingAPI.Controllers
16 | {
17 | [Route("api/[controller]")]
18 | public class InvoicesController : Controller
19 | {
20 | #region Properties
21 | private readonly IInvoiceRepository _invoiceRepository;
22 | private const int maxSize = 50;
23 | #endregion
24 |
25 | #region Constructor
26 | public InvoicesController(IInvoiceRepository invoiceRepository)
27 | {
28 | _invoiceRepository = invoiceRepository;
29 | }
30 | #endregion
31 |
32 | #region Actions
33 | public ActionResult Get(string props = null, int page = 1, int pageSize = maxSize)
34 | {
35 | try
36 | {
37 | var _invoices = _invoiceRepository.LoadAll().Skip((page - 1) * pageSize).Take(pageSize);
38 |
39 | var _invoicesVM = Mapper.Map, IEnumerable>(_invoices);
40 |
41 | JToken _jtoken = TokenService.CreateJToken(_invoicesVM, props);
42 |
43 | return Ok(_jtoken);
44 | }
45 | catch (Exception ex)
46 | {
47 | return new HttpStatusCodeResult(500);
48 | }
49 | }
50 |
51 | [Route("{invoiceId}")]
52 | public ActionResult Get(int invoiceId, string props = null)
53 | {
54 | try
55 | {
56 | var _invoice = _invoiceRepository.Load(invoiceId);
57 |
58 | if (_invoice == null)
59 | {
60 | return HttpNotFound();
61 | }
62 |
63 | var _invoiceVM = Mapper.Map(_invoice);
64 |
65 | JToken _jtoken = TokenService.CreateJToken(_invoiceVM, props);
66 |
67 | return Ok(_jtoken);
68 | }
69 | catch (Exception ex)
70 | {
71 | return new HttpStatusCodeResult(500);
72 | }
73 | }
74 | #endregion
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/ShapingAPI/Controllers/TracksController.cs:
--------------------------------------------------------------------------------
1 | using AutoMapper;
2 | using Microsoft.AspNet.Mvc;
3 | using Newtonsoft.Json;
4 | using Newtonsoft.Json.Linq;
5 | using ShapingAPI.Entities;
6 | using ShapingAPI.Infrastructure.Core;
7 | using ShapingAPI.Infrastructure.Data.Repositories;
8 | using ShapingAPI.ViewModels;
9 | using System;
10 | using System.Collections.Generic;
11 | using System.Linq;
12 | using System.Linq.Expressions;
13 | using System.Threading.Tasks;
14 |
15 | namespace ShapingAPI.Controllers
16 | {
17 | [Route("api/[controller]")]
18 | public class TracksController : Controller
19 | {
20 | #region Properties
21 | private readonly ITrackRepository _trackRepository;
22 | private Expression>[] includeProperties;
23 | private const int maxSize = 50;
24 | #endregion
25 |
26 | #region Constructor
27 | public TracksController(ITrackRepository trackRepository)
28 | {
29 | _trackRepository = trackRepository;
30 |
31 | includeProperties = Expressions.LoadTrackNavigations();
32 | }
33 | #endregion
34 |
35 | #region Actions
36 | public ActionResult Get(string props = null, int page = 1, int pageSize = maxSize)
37 | {
38 | try
39 | {
40 | var _tracks = _trackRepository.GetAll(includeProperties).Skip((page - 1) * pageSize).Take(pageSize);
41 |
42 | var _tracksVM = Mapper.Map, IEnumerable>(_tracks);
43 |
44 | JToken _jtoken = TokenService.CreateJToken(_tracksVM, props);
45 |
46 | return Ok(_jtoken);
47 | }
48 | catch (Exception ex)
49 | {
50 | return new HttpStatusCodeResult(500);
51 | }
52 | }
53 |
54 | [Route("{trackId}")]
55 | public ActionResult Get(int trackId, string props = null)
56 | {
57 | try
58 | {
59 |
60 |
61 | var _track = _trackRepository.Get(t => t.TrackId == trackId, includeProperties);
62 |
63 | if (_track == null)
64 | {
65 | return HttpNotFound();
66 | }
67 |
68 | var _trackVM = Mapper.Map(_track);
69 |
70 | JToken _jtoken = TokenService.CreateJToken(_trackVM, props);
71 |
72 | return Ok(_jtoken);
73 | }
74 | catch (Exception ex)
75 | {
76 | return new HttpStatusCodeResult(500);
77 | }
78 | }
79 | #endregion
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/ShapingAPI/Entities/Album.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace ShapingAPI.Entities
5 | {
6 | public partial class Album
7 | {
8 | public Album()
9 | {
10 | Track = new HashSet();
11 | }
12 |
13 | public int AlbumId { get; set; }
14 | public int ArtistId { get; set; }
15 | public string Title { get; set; }
16 |
17 | public virtual ICollection Track { get; set; }
18 | public virtual Artist Artist { get; set; }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/ShapingAPI/Entities/Artist.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace ShapingAPI.Entities
5 | {
6 | public partial class Artist
7 | {
8 | public Artist()
9 | {
10 | Album = new HashSet();
11 | }
12 |
13 | public int ArtistId { get; set; }
14 | public string Name { get; set; }
15 |
16 | public virtual ICollection Album { get; set; }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/ShapingAPI/Entities/ChinookContext.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Data.Entity;
2 | using Microsoft.Data.Entity.Metadata;
3 |
4 | namespace ShapingAPI.Entities
5 | {
6 | public partial class ChinookContext : DbContext
7 | {
8 | protected override void OnConfiguring(DbContextOptionsBuilder options)
9 | {
10 | //options.UseSqlServer(@"Server=(localdb)\v11.0;Database=Chinook;Trusted_Connection=True;");
11 | }
12 |
13 | protected override void OnModelCreating(ModelBuilder modelBuilder)
14 | {
15 | modelBuilder.Entity(entity =>
16 | {
17 | entity.HasIndex(e => e.ArtistId).HasName("IFK_AlbumArtistId");
18 |
19 | entity.Property(e => e.Title)
20 | .IsRequired()
21 | .HasMaxLength(160);
22 |
23 | entity.HasOne(d => d.Artist).WithMany(p => p.Album).HasForeignKey(d => d.ArtistId).OnDelete(DeleteBehavior.Restrict);
24 | });
25 |
26 | modelBuilder.Entity(entity =>
27 | {
28 | entity.Property(e => e.Name).HasMaxLength(120);
29 | });
30 |
31 | modelBuilder.Entity(entity =>
32 | {
33 | entity.HasIndex(e => e.SupportRepId).HasName("IFK_CustomerSupportRepId");
34 |
35 | entity.Property(e => e.Address).HasMaxLength(70);
36 |
37 | entity.Property(e => e.City).HasMaxLength(40);
38 |
39 | entity.Property(e => e.Company).HasMaxLength(80);
40 |
41 | entity.Property(e => e.Country).HasMaxLength(40);
42 |
43 | entity.Property(e => e.Email)
44 | .IsRequired()
45 | .HasMaxLength(60);
46 |
47 | entity.Property(e => e.Fax).HasMaxLength(24);
48 |
49 | entity.Property(e => e.FirstName)
50 | .IsRequired()
51 | .HasMaxLength(40);
52 |
53 | entity.Property(e => e.LastName)
54 | .IsRequired()
55 | .HasMaxLength(20);
56 |
57 | entity.Property(e => e.Phone).HasMaxLength(24);
58 |
59 | entity.Property(e => e.PostalCode).HasMaxLength(10);
60 |
61 | entity.Property(e => e.State).HasMaxLength(40);
62 |
63 | entity.HasOne(d => d.SupportRep).WithMany(p => p.Customer).HasForeignKey(d => d.SupportRepId);
64 | });
65 |
66 | modelBuilder.Entity(entity =>
67 | {
68 | entity.HasIndex(e => e.ReportsTo).HasName("IFK_EmployeeReportsTo");
69 |
70 | entity.Property(e => e.Address).HasMaxLength(70);
71 |
72 | entity.Property(e => e.BirthDate).HasColumnType("datetime");
73 |
74 | entity.Property(e => e.City).HasMaxLength(40);
75 |
76 | entity.Property(e => e.Country).HasMaxLength(40);
77 |
78 | entity.Property(e => e.Email).HasMaxLength(60);
79 |
80 | entity.Property(e => e.Fax).HasMaxLength(24);
81 |
82 | entity.Property(e => e.FirstName)
83 | .IsRequired()
84 | .HasMaxLength(20);
85 |
86 | entity.Property(e => e.HireDate).HasColumnType("datetime");
87 |
88 | entity.Property(e => e.LastName)
89 | .IsRequired()
90 | .HasMaxLength(20);
91 |
92 | entity.Property(e => e.Phone).HasMaxLength(24);
93 |
94 | entity.Property(e => e.PostalCode).HasMaxLength(10);
95 |
96 | entity.Property(e => e.State).HasMaxLength(40);
97 |
98 | entity.Property(e => e.Title).HasMaxLength(30);
99 |
100 | entity.HasOne(d => d.ReportsToNavigation).WithMany(p => p.InverseReportsToNavigation).HasForeignKey(d => d.ReportsTo);
101 | });
102 |
103 | modelBuilder.Entity(entity =>
104 | {
105 | entity.Property(e => e.Name).HasMaxLength(120);
106 | });
107 |
108 | modelBuilder.Entity(entity =>
109 | {
110 | entity.HasIndex(e => e.CustomerId).HasName("IFK_InvoiceCustomerId");
111 |
112 | entity.Property(e => e.BillingAddress).HasMaxLength(70);
113 |
114 | entity.Property(e => e.BillingCity).HasMaxLength(40);
115 |
116 | entity.Property(e => e.BillingCountry).HasMaxLength(40);
117 |
118 | entity.Property(e => e.BillingPostalCode).HasMaxLength(10);
119 |
120 | entity.Property(e => e.BillingState).HasMaxLength(40);
121 |
122 | entity.Property(e => e.InvoiceDate).HasColumnType("datetime");
123 |
124 | entity.Property(e => e.Total).HasColumnType("numeric");
125 |
126 | entity.HasOne(d => d.Customer).WithMany(p => p.Invoice).HasForeignKey(d => d.CustomerId).OnDelete(DeleteBehavior.Restrict);
127 | });
128 |
129 | modelBuilder.Entity(entity =>
130 | {
131 | entity.HasIndex(e => e.InvoiceId).HasName("IFK_InvoiceLineInvoiceId");
132 |
133 | entity.HasIndex(e => e.TrackId).HasName("IFK_InvoiceLineTrackId");
134 |
135 | entity.Property(e => e.UnitPrice).HasColumnType("numeric");
136 |
137 | entity.HasOne(d => d.Invoice).WithMany(p => p.InvoiceLine).HasForeignKey(d => d.InvoiceId).OnDelete(DeleteBehavior.Restrict);
138 |
139 | entity.HasOne(d => d.Track).WithMany(p => p.InvoiceLine).HasForeignKey(d => d.TrackId).OnDelete(DeleteBehavior.Restrict);
140 | });
141 |
142 | modelBuilder.Entity(entity =>
143 | {
144 | entity.Property(e => e.Name).HasMaxLength(120);
145 | });
146 |
147 | modelBuilder.Entity(entity =>
148 | {
149 | entity.Property(e => e.Name).HasMaxLength(120);
150 | });
151 |
152 | modelBuilder.Entity(entity =>
153 | {
154 | entity.HasKey(e => new { e.PlaylistId, e.TrackId });
155 |
156 | entity.HasIndex(e => e.TrackId).HasName("IFK_PlaylistTrackTrackId");
157 |
158 | entity.HasOne(d => d.Playlist).WithMany(p => p.PlaylistTrack).HasForeignKey(d => d.PlaylistId).OnDelete(DeleteBehavior.Restrict);
159 |
160 | entity.HasOne(d => d.Track).WithMany(p => p.PlaylistTrack).HasForeignKey(d => d.TrackId).OnDelete(DeleteBehavior.Restrict);
161 | });
162 |
163 | modelBuilder.Entity(entity =>
164 | {
165 | entity.HasIndex(e => e.AlbumId).HasName("IFK_TrackAlbumId");
166 |
167 | entity.HasIndex(e => e.GenreId).HasName("IFK_TrackGenreId");
168 |
169 | entity.HasIndex(e => e.MediaTypeId).HasName("IFK_TrackMediaTypeId");
170 |
171 | entity.Property(e => e.Composer).HasMaxLength(220);
172 |
173 | entity.Property(e => e.Name)
174 | .IsRequired()
175 | .HasMaxLength(200);
176 |
177 | entity.Property(e => e.UnitPrice).HasColumnType("numeric");
178 |
179 | entity.HasOne(d => d.Album).WithMany(p => p.Track).HasForeignKey(d => d.AlbumId);
180 |
181 | entity.HasOne(d => d.Genre).WithMany(p => p.Track).HasForeignKey(d => d.GenreId);
182 |
183 | entity.HasOne(d => d.MediaType).WithMany(p => p.Track).HasForeignKey(d => d.MediaTypeId).OnDelete(DeleteBehavior.Restrict);
184 | });
185 |
186 | modelBuilder.Entity(entity =>
187 | {
188 | entity.HasKey(e => e.diagram_id);
189 |
190 | entity.Property(e => e.definition).HasColumnType("varbinary");
191 | });
192 | }
193 |
194 | public virtual DbSet Album { get; set; }
195 | public virtual DbSet Artist { get; set; }
196 | public virtual DbSet Customer { get; set; }
197 | public virtual DbSet Employee { get; set; }
198 | public virtual DbSet Genre { get; set; }
199 | public virtual DbSet Invoice { get; set; }
200 | public virtual DbSet InvoiceLine { get; set; }
201 | public virtual DbSet MediaType { get; set; }
202 | public virtual DbSet Playlist { get; set; }
203 | public virtual DbSet PlaylistTrack { get; set; }
204 | public virtual DbSet Track { get; set; }
205 | public virtual DbSet sysdiagrams { get; set; }
206 | }
207 | }
--------------------------------------------------------------------------------
/src/ShapingAPI/Entities/Customer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace ShapingAPI.Entities
5 | {
6 | public partial class Customer
7 | {
8 | public Customer()
9 | {
10 | Invoice = new HashSet();
11 | }
12 |
13 | public int CustomerId { get; set; }
14 | public string Address { get; set; }
15 | public string City { get; set; }
16 | public string Company { get; set; }
17 | public string Country { get; set; }
18 | public string Email { get; set; }
19 | public string Fax { get; set; }
20 | public string FirstName { get; set; }
21 | public string LastName { get; set; }
22 | public string Phone { get; set; }
23 | public string PostalCode { get; set; }
24 | public string State { get; set; }
25 | public int? SupportRepId { get; set; }
26 |
27 | public virtual ICollection Invoice { get; set; }
28 | public virtual Employee SupportRep { get; set; }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/ShapingAPI/Entities/Employee.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace ShapingAPI.Entities
5 | {
6 | public partial class Employee
7 | {
8 | public Employee()
9 | {
10 | Customer = new HashSet();
11 | }
12 |
13 | public int EmployeeId { get; set; }
14 | public string Address { get; set; }
15 | public DateTime? BirthDate { get; set; }
16 | public string City { get; set; }
17 | public string Country { get; set; }
18 | public string Email { get; set; }
19 | public string Fax { get; set; }
20 | public string FirstName { get; set; }
21 | public DateTime? HireDate { get; set; }
22 | public string LastName { get; set; }
23 | public string Phone { get; set; }
24 | public string PostalCode { get; set; }
25 | public int? ReportsTo { get; set; }
26 | public string State { get; set; }
27 | public string Title { get; set; }
28 |
29 | public virtual ICollection Customer { get; set; }
30 | public virtual Employee ReportsToNavigation { get; set; }
31 | public virtual ICollection InverseReportsToNavigation { get; set; }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/ShapingAPI/Entities/Genre.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace ShapingAPI.Entities
5 | {
6 | public partial class Genre
7 | {
8 | public Genre()
9 | {
10 | Track = new HashSet();
11 | }
12 |
13 | public int GenreId { get; set; }
14 | public string Name { get; set; }
15 |
16 | public virtual ICollection Track { get; set; }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/ShapingAPI/Entities/Invoice.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace ShapingAPI.Entities
5 | {
6 | public partial class Invoice
7 | {
8 | public Invoice()
9 | {
10 | InvoiceLine = new HashSet();
11 | }
12 |
13 | public int InvoiceId { get; set; }
14 | public string BillingAddress { get; set; }
15 | public string BillingCity { get; set; }
16 | public string BillingCountry { get; set; }
17 | public string BillingPostalCode { get; set; }
18 | public string BillingState { get; set; }
19 | public int CustomerId { get; set; }
20 | public DateTime InvoiceDate { get; set; }
21 | public decimal Total { get; set; }
22 |
23 | public virtual ICollection InvoiceLine { get; set; }
24 | public virtual Customer Customer { get; set; }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/ShapingAPI/Entities/InvoiceLine.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace ShapingAPI.Entities
5 | {
6 | public partial class InvoiceLine
7 | {
8 | public int InvoiceLineId { get; set; }
9 | public int InvoiceId { get; set; }
10 | public int Quantity { get; set; }
11 | public int TrackId { get; set; }
12 | public decimal UnitPrice { get; set; }
13 |
14 | public virtual Invoice Invoice { get; set; }
15 | public virtual Track Track { get; set; }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/ShapingAPI/Entities/MediaType.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace ShapingAPI.Entities
5 | {
6 | public partial class MediaType
7 | {
8 | public MediaType()
9 | {
10 | Track = new HashSet();
11 | }
12 |
13 | public int MediaTypeId { get; set; }
14 | public string Name { get; set; }
15 |
16 | public virtual ICollection Track { get; set; }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/ShapingAPI/Entities/Playlist.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace ShapingAPI.Entities
5 | {
6 | public partial class Playlist
7 | {
8 | public Playlist()
9 | {
10 | PlaylistTrack = new HashSet();
11 | }
12 |
13 | public int PlaylistId { get; set; }
14 | public string Name { get; set; }
15 |
16 | public virtual ICollection PlaylistTrack { get; set; }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/ShapingAPI/Entities/PlaylistTrack.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace ShapingAPI.Entities
5 | {
6 | public partial class PlaylistTrack
7 | {
8 | public int PlaylistId { get; set; }
9 | public int TrackId { get; set; }
10 |
11 | public virtual Playlist Playlist { get; set; }
12 | public virtual Track Track { get; set; }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/ShapingAPI/Entities/Track.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace ShapingAPI.Entities
5 | {
6 | public partial class Track
7 | {
8 | public Track()
9 | {
10 | InvoiceLine = new HashSet();
11 | PlaylistTrack = new HashSet();
12 | }
13 |
14 | public int TrackId { get; set; }
15 | public int? AlbumId { get; set; }
16 | public int? Bytes { get; set; }
17 | public string Composer { get; set; }
18 | public int? GenreId { get; set; }
19 | public int MediaTypeId { get; set; }
20 | public int Milliseconds { get; set; }
21 | public string Name { get; set; }
22 | public decimal UnitPrice { get; set; }
23 |
24 | public virtual ICollection InvoiceLine { get; set; }
25 | public virtual ICollection PlaylistTrack { get; set; }
26 | public virtual Album Album { get; set; }
27 | public virtual Genre Genre { get; set; }
28 | public virtual MediaType MediaType { get; set; }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/ShapingAPI/Entities/sysdiagrams.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace ShapingAPI.Entities
5 | {
6 | public partial class sysdiagrams
7 | {
8 | public int diagram_id { get; set; }
9 | public byte[] definition { get; set; }
10 | public int principal_id { get; set; }
11 | public int? version { get; set; }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/ShapingAPI/Infrastructure/Core/Expressions.cs:
--------------------------------------------------------------------------------
1 | using ShapingAPI.Entities;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Diagnostics;
5 | using System.Linq;
6 | using System.Linq.Expressions;
7 | using System.Threading.Tasks;
8 |
9 | namespace ShapingAPI.Infrastructure.Core
10 | {
11 | public class Expressions
12 | {
13 | public static Expression>[] LoadTrackNavigations()
14 | {
15 | Expression>[] _navigations = {
16 | t => t.Album,
17 | t => t.Genre,
18 | t => t.InvoiceLine,
19 | t => t.MediaType
20 | };
21 |
22 | return _navigations;
23 | }
24 |
25 | public static Expression>[] LoadCustomerNavigations()
26 | {
27 | Expression>[] _navigations = {
28 | c => c.Invoice,
29 | c => c.SupportRep
30 | };
31 |
32 | return _navigations;
33 | }
34 |
35 | public static Expression>[] LoadAlbumNavigations()
36 | {
37 | Expression>[] _navigations = {
38 | a => a.Track,
39 | a => a.Artist
40 | };
41 |
42 | return _navigations;
43 | }
44 |
45 | public static Expression>[] LoadArtistNavigations()
46 | {
47 | Expression>[] _navigations = {
48 | a => a.Album
49 | };
50 |
51 | return _navigations;
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/ShapingAPI/Infrastructure/Core/TokenService.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 | using Newtonsoft.Json.Linq;
3 | using System.Linq;
4 |
5 | namespace ShapingAPI.Infrastructure.Core
6 | {
7 | public class TokenService
8 | {
9 | public static JToken CreateJToken(object obj, string props)
10 | {
11 | string _serializedTracks = JsonConvert.SerializeObject(obj, Formatting.None,
12 | new JsonSerializerSettings()
13 | {
14 | ReferenceLoopHandling = ReferenceLoopHandling.Ignore
15 | });
16 |
17 | JToken jtoken = JToken.Parse(_serializedTracks);
18 | if (!string.IsNullOrEmpty(props))
19 | Utils.FilterProperties(jtoken, props.ToLower().Split(',').ToList());
20 |
21 | return jtoken;
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/ShapingAPI/Infrastructure/Core/Utils.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json.Linq;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Dynamic;
5 | using System.Linq;
6 | using System.Linq.Expressions;
7 | using System.Reflection;
8 | using System.Threading.Tasks;
9 |
10 | namespace ShapingAPI.Infrastructure.Core
11 | {
12 | public class Utils
13 | {
14 | public static void FilterProperties(JToken token, List fields)
15 | {
16 | try
17 | {
18 | JContainer container = token as JContainer;
19 | if (container == null) return;
20 |
21 | JProperty jprop = null;
22 | JObject jobj = null;
23 |
24 | JProperty pNested = null;
25 | JObject poNested = null;
26 |
27 | List removeList = new List();
28 | foreach (JToken el in container.Children())
29 | {
30 | if (el is JProperty)
31 | {
32 | jprop = el as JProperty;
33 |
34 | if (fields.Any(f => f.StartsWith(el.Path.ToLower() + "(")))
35 | {
36 | string nestedProperty = fields.First(f => f.StartsWith(el.Path.ToLower() + "("));
37 | int startField = nestedProperty.IndexOf("(");
38 | int lastField = nestedProperty.LastIndexOf(")");
39 | string nestedFields = nestedProperty.Substring(startField + 1, (lastField - 1) - startField);
40 |
41 | List _nestedFieldList = GetNestedFiels(nestedFields);// nestedFields.Split(';').ToList();
42 |
43 | JToken nestedProperties = el.First();
44 | List removeListNested = new List();
45 | foreach (JToken elNested in (nestedProperties as JContainer).Children())
46 | {
47 | if (elNested is JProperty)
48 | {
49 | pNested = elNested as JProperty;
50 | if (!_nestedFieldList.Contains(pNested.Path.ToLower().Substring(pNested.Path.IndexOf('.') + 1)))
51 | removeListNested.Add(pNested);
52 | }
53 | else if (elNested is JObject)
54 | {
55 | poNested = elNested as JObject;
56 |
57 | foreach (JToken _poNested in (poNested as JContainer).Children().OrderBy(order => order.Parent))
58 | {
59 | if (!(_poNested.ToString().Contains('(') && _poNested.ToString().Contains(';') && _poNested.ToString().Contains(')'))
60 | && !_poNested.ToString().Replace(" ", "").Replace("\r\n", "").Contains("[{"))
61 | {
62 | if (!_nestedFieldList.Contains(_poNested.Path.ToLower().Substring(_poNested.Path.IndexOf('.') + 1)))
63 | removeListNested.Add(_poNested);
64 | }
65 | else
66 | {
67 | foreach (JToken el2 in (_poNested as JContainer).Children())
68 | {
69 | if (el2 is JProperty)
70 | {
71 | jprop = el2 as JProperty;
72 |
73 | if (fields.Any(f => f.StartsWith(el2.Path.ToLower() + "(")))
74 | {
75 | string nestedProperty2 = fields.First(f => f.StartsWith(el2.Path.ToLower() + "("));
76 | int startField2 = nestedProperty.IndexOf("(");
77 | int lastField2 = nestedProperty.LastIndexOf(")");
78 | string nestedFields2 = nestedProperty.Substring(startField + 1, (lastField - 1) - startField);
79 | }
80 | }
81 | else if (el2 is JArray)
82 | {
83 | JArray jar = el2 as JArray;
84 |
85 | if (_nestedFieldList.Contains(el2.Path.ToLower().Substring(el2.Path.ToLower().LastIndexOf('.') + 1)))
86 | break;
87 |
88 | foreach (JToken el3 in (jar as JContainer).Children())
89 | {
90 | if (el3 is JObject)
91 | {
92 | string _nestedField = _nestedFieldList.FirstOrDefault(f => f.ToLower().StartsWith(_poNested.Path.ToLower().Substring(_poNested.Path.IndexOf('.') + 1) + "("));
93 |
94 | if (string.IsNullOrEmpty(_nestedField))
95 | {
96 | removeListNested.Add(_poNested);
97 | break;
98 | }
99 |
100 | int startField2 = _nestedField.IndexOf("(");
101 | int lastField2 = _nestedField.LastIndexOf(")");
102 | string nestedFields2 = _nestedField.Substring(startField2 + 1, (lastField2 - 1) - startField2);
103 |
104 | string[] _nestedFields = nestedFields2.Split(',');
105 |
106 | JObject job = el3 as JObject;
107 | foreach (JToken el4 in (job as JContainer).Children())
108 | {
109 | if (!_nestedFields.Contains(el4.Path.ToLower().Substring(el4.Path.ToLower().LastIndexOf('.') + 1)))
110 | removeListNested.Add(el4);
111 | }
112 | }
113 | }
114 | }
115 | }
116 | }
117 | }
118 | }
119 | }
120 | foreach (JToken elNest in removeListNested)
121 | {
122 | elNest.Remove();
123 | }
124 |
125 | if (fields.Contains(nestedProperty))
126 | fields.Remove(nestedProperty);
127 |
128 | if (fields.Contains(el.Path.ToLower()))
129 | fields.Remove(el.Path.ToLower());
130 | }
131 | else if (jprop != null && !fields.Contains(jprop.Name.ToLower()))
132 | {
133 | removeList.Add(el);
134 | }
135 | }
136 | else
137 | {
138 | jobj = el as JObject;
139 |
140 | foreach (JToken _joNested in (jobj as JContainer).Children().OrderBy(order => order.Parent))
141 | {
142 | if (fields.Any(field => field.ToLower().StartsWith(_joNested.Path.ToLower().Substring(_joNested.Path.IndexOf('.') + 1) + "(")))
143 | {
144 | string nestedProperty = fields.First(f => f.StartsWith(_joNested.Path.ToLower().Substring(_joNested.Path.IndexOf('.') + 1) + "("));
145 | int startField = nestedProperty.IndexOf("(");
146 | int lastField = nestedProperty.LastIndexOf(")");
147 | string nestedFields = nestedProperty.Substring(startField + 1, (lastField - 1) - startField);
148 |
149 | List _nestedFieldList = GetNestedFiels(nestedFields); // nestedFields.Split(';').ToList();
150 | JToken nestedProperties = _joNested.First();
151 | List removeListNested = new List();
152 | foreach (JToken elNested in (nestedProperties as JContainer).Children())
153 | {
154 | if (elNested is JProperty)
155 | {
156 | pNested = elNested as JProperty;
157 | if (!_nestedFieldList.Contains(pNested.Path.ToLower().Substring(pNested.Path.IndexOf('.') + 1)))
158 | removeListNested.Add(pNested);
159 | }
160 | else if (elNested is JObject)
161 | {
162 | poNested = elNested as JObject;
163 |
164 | foreach (JToken _poNested in (poNested as JContainer).Children().OrderBy(order => order.Parent))
165 | {
166 | if (_nestedFieldList.Any(f => f.ToLower().StartsWith(_poNested.Path.ToLower().Substring(_poNested.Path.LastIndexOf('.') + 1) + "(")))
167 | {
168 | string field = _nestedFieldList.First(f => f.ToLower().StartsWith(_poNested.Path.ToLower().Substring(_poNested.Path.LastIndexOf('.') + 1) + "("));
169 | int startNestedField = field.IndexOf("(");
170 | int lastNestedField = field.LastIndexOf(")");
171 | string nestedFields2 = field.Substring(startNestedField + 1, (lastNestedField - 1) - startNestedField);
172 |
173 | List _nestedFieldList2 = nestedFields2.Split(',').ToList(); // GetNestedFiels(nestedFields2); // nestedFields.Split(';').ToList();
174 | JToken nestedProperties2 = _poNested.First();
175 | List removeListNested2 = new List();
176 | foreach (JToken elNested2 in (nestedProperties2 as JContainer).Children())
177 | {
178 | if (elNested2 is JProperty)
179 | {
180 | pNested = elNested2 as JProperty;
181 | if (!_nestedFieldList2.Contains(pNested.Path.ToLower().Substring(pNested.Path.IndexOf('.') + 1)))
182 | removeListNested.Add(pNested);
183 | }
184 | else if (elNested2 is JObject)
185 | {
186 | poNested = elNested2 as JObject;
187 |
188 | foreach (JToken _poNested2 in (poNested as JContainer).Children().OrderBy(order => order.Parent))
189 | {
190 | if ((!_nestedFieldList2.Contains(_poNested2.Path.ToLower().Substring(_poNested2.Path.LastIndexOf('.') + 1))))
191 | removeListNested.Add(_poNested2);
192 | }
193 | }
194 | }
195 |
196 | }
197 |
198 | else if ((!_nestedFieldList.Contains(_poNested.Path.ToLower().Substring(_poNested.Path.LastIndexOf('.') + 1))))
199 | removeListNested.Add(_poNested);
200 | }
201 | }
202 | }
203 | foreach (JToken elNest in removeListNested)
204 | {
205 | elNest.Remove();
206 | }
207 |
208 | if (fields.Contains(nestedProperty) && el.Next == null)
209 | fields.Remove(nestedProperty);
210 |
211 | if (fields.Contains(el.Path.ToLower()))
212 | fields.Remove(el.Path.ToLower());
213 | }
214 | else if (!fields.Contains(_joNested.Path.ToLower().Substring(_joNested.Path.IndexOf('.') + 1)))
215 | removeList.Add(_joNested);
216 | }
217 | }
218 | }
219 |
220 | foreach (JToken el in removeList)
221 | {
222 | el.Remove();
223 | }
224 | }
225 | catch (Exception ex)
226 | {
227 | throw ex;
228 | }
229 | }
230 | private static List GetNestedFiels(string fields)
231 | {
232 | if (!fields.Contains('(') && !fields.Contains(')'))
233 | return fields.Split(';').ToList();
234 |
235 | List _fieldList = new List();
236 | string _tempField = string.Empty;
237 | char[] _fieldArray = fields.ToCharArray();
238 | bool _skip = false;
239 |
240 | try
241 | {
242 | for (int i = 0; i < _fieldArray.Length; i++)
243 | {
244 | if (_fieldArray[i] != ';' && _fieldArray[i] != ')')
245 | {
246 | _tempField += _fieldArray[i];
247 |
248 | if (_fieldArray[i] == '(')
249 | {
250 | _skip = true;
251 | }
252 | }
253 | else if (_fieldArray[i] == ';')
254 | {
255 | if (!_skip)
256 | {
257 | _fieldList.Add(_tempField);
258 | _tempField = string.Empty;
259 | }
260 | else
261 | {
262 | _tempField += ',';
263 | }
264 | }
265 | else if (_fieldArray[i] == ')')
266 | {
267 | _tempField += ')';
268 | _fieldList.Add(_tempField);
269 | _tempField = string.Empty;
270 | _skip = false;
271 | }
272 |
273 | }
274 | }
275 | catch (Exception ex)
276 | {
277 | throw ex;
278 | }
279 |
280 | return _fieldList;
281 | }
282 | }
283 | }
284 |
--------------------------------------------------------------------------------
/src/ShapingAPI/Infrastructure/Data/IRepository.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Linq.Expressions;
5 | using System.Threading.Tasks;
6 |
7 | namespace ShapingAPI.Infrastructure.Data
8 | {
9 | public interface IRepository
10 | {
11 | #region READ
12 | TEntity Get(Expression> predicate);
13 | TEntity Get(Expression> predicate, params Expression>[] includeProperties);
14 | IQueryable GetAll();
15 | IQueryable GetAll(params Expression>[] includeProperties);
16 |
17 | #endregion
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/ShapingAPI/Infrastructure/Data/Repositories/IRepositories.cs:
--------------------------------------------------------------------------------
1 | using ShapingAPI.Entities;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 |
7 | namespace ShapingAPI.Infrastructure.Data.Repositories
8 | {
9 | public interface IAlbumRepository : IRepository {
10 | IEnumerable LoadAll();
11 | Album Load(int albumId);
12 | }
13 |
14 | public interface IArtistRepository : IRepository
15 | {
16 | IEnumerable LoadAll();
17 | Artist Load(int artistId);
18 | }
19 |
20 | public interface ICustomerRepository : IRepository
21 | {
22 | IEnumerable LoadAll();
23 | Customer Load(int customerId);
24 | }
25 |
26 | public interface IEmployeeRepository : IRepository { }
27 |
28 | public interface IGenreRepository : IRepository { }
29 |
30 | public interface IInvoiceLineRepository : IRepository { }
31 |
32 | public interface IInvoiceRepository : IRepository
33 | {
34 | IEnumerable LoadAll();
35 | Invoice Load(int invoiceId);
36 | }
37 |
38 | public interface IMediaTypeRepository : IRepository { }
39 |
40 | public interface IPlaylistTrackRepository : IRepository { }
41 |
42 | public interface IPlaylistRepository : IRepository { }
43 |
44 | public interface ITrackRepository : IRepository { }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/src/ShapingAPI/Infrastructure/Data/Repositories/Repositories.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Data.Entity;
2 | using ShapingAPI.Entities;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using System.Threading.Tasks;
7 |
8 | namespace ShapingAPI.Infrastructure.Data.Repositories
9 | {
10 | public class AlbumRepository : Repository, IAlbumRepository
11 | {
12 | public AlbumRepository(ChinookContext context)
13 | : base(context)
14 | { }
15 |
16 | public IEnumerable LoadAll()
17 | {
18 | IQueryable query = this._dbSet;
19 |
20 | query = query.Include(a => a.Track);
21 |
22 | return query.ToList();
23 | }
24 |
25 | public Album Load(int artistId)
26 | {
27 | IQueryable query = this._dbSet;
28 |
29 | query = query.Include(a => a.Track);
30 |
31 | return query.FirstOrDefault(a => a.AlbumId == artistId);
32 | }
33 | }
34 |
35 | public class ArtistRepository : Repository, IArtistRepository
36 | {
37 | public ArtistRepository(ChinookContext context)
38 | : base(context)
39 | {
40 |
41 | }
42 |
43 | public IEnumerable LoadAll()
44 | {
45 | IQueryable query = this._dbSet;
46 |
47 | query = query.Include(a => a.Album).ThenInclude(al => al.Track);
48 |
49 | return query.ToList();
50 | }
51 |
52 | public Artist Load(int artistId)
53 | {
54 | IQueryable query = this._dbSet;
55 |
56 | query = query.Include(a => a.Album).ThenInclude(al => al.Track);
57 |
58 | return query.FirstOrDefault(a => a.ArtistId == artistId);
59 | }
60 | }
61 |
62 | public class CustomerRepository : Repository, ICustomerRepository
63 | {
64 | public CustomerRepository(ChinookContext context)
65 | : base(context)
66 | { }
67 |
68 | public IEnumerable LoadAll()
69 | {
70 | IQueryable query = this._dbSet;
71 |
72 | query = query.Include(c => c.Invoice).ThenInclude(i => i.InvoiceLine);
73 |
74 | return query.ToList();
75 | }
76 |
77 | public Customer Load(int customerId)
78 | {
79 | IQueryable query = this._dbSet;
80 |
81 | query = query.Include(c => c.Invoice).ThenInclude(i => i.InvoiceLine);
82 |
83 | return query.FirstOrDefault(c => c.CustomerId == customerId);
84 | }
85 | }
86 |
87 | public class EmployeeRepository : Repository, IEmployeeRepository
88 | {
89 | public EmployeeRepository(ChinookContext context)
90 | : base(context)
91 | { }
92 | }
93 |
94 | public class GenreRepository : Repository, IGenreRepository
95 | {
96 | public GenreRepository(ChinookContext context)
97 | : base(context)
98 | { }
99 | }
100 |
101 | public class InvoiceLineRepository : Repository, IInvoiceLineRepository
102 | {
103 | public InvoiceLineRepository(ChinookContext context)
104 | : base(context)
105 | { }
106 | }
107 |
108 | public class InvoiceRepository : Repository, IInvoiceRepository
109 | {
110 | public InvoiceRepository(ChinookContext context)
111 | : base(context)
112 | { }
113 |
114 | public IEnumerable LoadAll()
115 | {
116 | IQueryable query = this._dbSet;
117 |
118 | query = query.Include(i => i.Customer).ThenInclude(c => c.Invoice);
119 | query = query.Include(i => i.InvoiceLine);
120 |
121 | return query.ToList();
122 | }
123 |
124 | public Invoice Load(int invoiceId)
125 | {
126 | IQueryable query = this._dbSet;
127 |
128 | query = query.Include(i => i.Customer).ThenInclude(c => c.Invoice);
129 | query = query.Include(i => i.InvoiceLine);
130 |
131 | return query.FirstOrDefault(i => i.InvoiceId == invoiceId);
132 | }
133 | }
134 |
135 | public class MediaTypeRepository : Repository, IMediaTypeRepository
136 | {
137 | public MediaTypeRepository(ChinookContext context)
138 | : base(context)
139 | { }
140 | }
141 |
142 | public class PlaylistTrackRepository : Repository, IPlaylistTrackRepository
143 | {
144 | public PlaylistTrackRepository(ChinookContext context)
145 | : base(context)
146 | { }
147 | }
148 |
149 | public class PlaylistRepository : Repository, IPlaylistRepository
150 | {
151 | public PlaylistRepository(ChinookContext context)
152 | : base(context)
153 | { }
154 | }
155 |
156 | public class TrackRepository : Repository, ITrackRepository
157 | {
158 | public TrackRepository(ChinookContext context)
159 | : base(context)
160 | { }
161 | }
162 | }
--------------------------------------------------------------------------------
/src/ShapingAPI/Infrastructure/Data/Repository.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Data.Entity;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Linq.Expressions;
6 | using System.Threading.Tasks;
7 |
8 | namespace ShapingAPI.Infrastructure.Data
9 | {
10 | public abstract class Repository : IRepository where TEntity : class
11 | {
12 | protected DbContext _context;
13 | protected DbSet _dbSet;
14 |
15 | public Repository(DbContext context)
16 | {
17 | _context = context;
18 | _dbSet = _context.Set();
19 | }
20 |
21 | #region READ
22 | public TEntity Get(Expression> predicate)
23 | {
24 | return _dbSet.FirstOrDefault(predicate);
25 | }
26 |
27 | public TEntity Get(Expression> predicate, params Expression>[] includeProperties)
28 | {
29 | IQueryable query = _dbSet;
30 |
31 | if (includeProperties != null)
32 | foreach (var property in includeProperties)
33 | {
34 | query = query.Include(property);
35 | }
36 |
37 | return query.FirstOrDefault(predicate);
38 | }
39 |
40 | public IQueryable GetAll()
41 | {
42 | return _dbSet.AsQueryable();
43 | }
44 |
45 | public IQueryable GetAll(params Expression>[] includeProperties)
46 | {
47 | IQueryable query = _dbSet.AsQueryable();
48 |
49 | if (includeProperties != null)
50 | foreach (var property in includeProperties)
51 | {
52 | query = query.Include(property);
53 | }
54 |
55 | return query;
56 | }
57 |
58 | #endregion
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/ShapingAPI/Infrastructure/Mappings/AutoMapperConfiguration.cs:
--------------------------------------------------------------------------------
1 | using AutoMapper;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 |
7 | namespace ShapingAPI.Infrastructure.Mappings
8 | {
9 | public class AutoMapperConfiguration
10 | {
11 | public static void Configure()
12 | {
13 | Mapper.Initialize(x =>
14 | {
15 | x.AddProfile();
16 | });
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/ShapingAPI/Infrastructure/Mappings/DomainToViewModelMappingProfile.cs:
--------------------------------------------------------------------------------
1 | using AutoMapper;
2 | using ShapingAPI.Entities;
3 | using ShapingAPI.ViewModels;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Linq;
7 | using System.Threading.Tasks;
8 |
9 | namespace ShapingAPI.Infrastructure.Mappings
10 | {
11 | public class DomainToViewModelMappingProfile : Profile
12 | {
13 | protected override void Configure()
14 | {
15 | Mapper.CreateMap();
16 |
17 | Mapper.CreateMap()
18 | .ForMember(vm => vm.ArtistName, map => map.MapFrom(a => a.Artist.Name));
19 |
20 | Mapper.CreateMap();
21 |
22 | Mapper.CreateMap()
23 | .ForMember(vm => vm.Address, map => map.MapFrom(c => new AddressViewModel()
24 | {
25 | Address = c.Address,
26 | City = c.City,
27 | Country = c.Country,
28 | PostalCode = c.PostalCode,
29 | State = c.State
30 | }))
31 | .ForMember(vm => vm.Contact, map => map.MapFrom(c => new ContactViewModel()
32 | {
33 | Email = c.Email,
34 | Fax = c.Fax,
35 | Phone = c.Phone
36 | }))
37 | .ForMember(vm => vm.TotalInvoices, map => map.MapFrom(c => c.Invoice.Count()));
38 |
39 | //Mapper.CreateMap();
40 |
41 | //Mapper.CreateMap()
42 | // .ForMember(vm => vm.Tracks, map => map.MapFrom(g => g.Track.Select(t => t.TrackId).ToList()));
43 |
44 | Mapper.CreateMap();
45 |
46 | Mapper.CreateMap();
47 |
48 | //Mapper.CreateMap()
49 | // .ForMember(vm => vm.Tracks, map => map.MapFrom(m => m.Track.Select(t => t.TrackId).ToList()));
50 |
51 | //Mapper.CreateMap();
52 |
53 | //Mapper.CreateMap();
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/ShapingAPI/Project_Readme.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Welcome to ASP.NET 5
6 |
127 |
128 |
129 |
130 |
138 |
139 |
140 |
141 |
This application consists of:
142 |
143 | Sample pages using ASP.NET MVC 6
144 | Gulp and Bower for managing client-side libraries
145 | Theming using Bootstrap
146 |
147 |
148 |
160 |
161 |
Overview
162 |
171 |
172 |
173 |
Run & Deploy
174 |
180 |
181 |
182 |
185 |
186 |
187 |
188 |
189 |
--------------------------------------------------------------------------------
/src/ShapingAPI/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "iisSettings": {
3 | "windowsAuthentication": false,
4 | "anonymousAuthentication": true,
5 | "iisExpress": {
6 | "applicationUrl": "http://localhost:22249/",
7 | "sslPort": 0
8 | }
9 | },
10 | "profiles": {
11 | "IIS Express": {
12 | "commandName": "IISExpress",
13 | "launchBrowser": true,
14 | "environmentVariables": {
15 | "Hosting:Environment": "Development"
16 | }
17 | },
18 | "web": {
19 | "commandName": "web",
20 | "environmentVariables": {
21 | "Hosting:Environment": "Development"
22 | }
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/src/ShapingAPI/SQL/Chinook_SqlServer_AutoIncrementPKs.sql:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chsakell/multi-client-api/db6e537563c7adb1f47d269b8e6533793d9d6806/src/ShapingAPI/SQL/Chinook_SqlServer_AutoIncrementPKs.sql
--------------------------------------------------------------------------------
/src/ShapingAPI/ShapingAPI.xproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 14.0
5 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
6 |
7 |
8 |
9 |
10 | 6c8d22bc-4f3b-4f8f-947d-f9cdeb82f3de
11 | ShapingAPI
12 | ..\..\artifacts\obj\$(MSBuildProjectName)
13 | ..\..\artifacts\bin\$(MSBuildProjectName)\
14 |
15 |
16 |
17 | 2.0
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/ShapingAPI/Startup.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using Microsoft.AspNet.Builder;
6 | using Microsoft.AspNet.Hosting;
7 | using Microsoft.AspNet.Http;
8 | using Microsoft.Extensions.DependencyInjection;
9 | using Newtonsoft.Json.Serialization;
10 | using Microsoft.Extensions.Logging;
11 | using ShapingAPI.Entities;
12 | using Microsoft.Data.Entity;
13 | using Microsoft.Extensions.Configuration;
14 | using ShapingAPI.Infrastructure.Data.Repositories;
15 | using ShapingAPI.Infrastructure.Mappings;
16 |
17 | namespace ShapingAPI
18 | {
19 | public class Startup
20 | {
21 | public Startup(IHostingEnvironment env)
22 | {
23 | // Set up configuration sources.
24 | var builder = new ConfigurationBuilder()
25 | .AddJsonFile("appsettings.json");
26 |
27 | if (env.IsEnvironment("Development"))
28 | {
29 | // This will push telemetry data through Application Insights pipeline faster, allowing you to view results immediately.
30 | builder.AddApplicationInsightsSettings(developerMode: true);
31 | }
32 |
33 | builder.AddEnvironmentVariables();
34 | Configuration = builder.Build().ReloadOnChanged("appsettings.json");
35 | }
36 |
37 | public IConfigurationRoot Configuration { get; set; }
38 |
39 | // This method gets called by the runtime. Use this method to add services to the container
40 | public void ConfigureServices(IServiceCollection services)
41 | {
42 | // Add framework services.
43 | services.AddApplicationInsightsTelemetry(Configuration);
44 |
45 | services.AddEntityFramework()
46 | .AddSqlServer()
47 | .AddDbContext(options => options.UseSqlServer(Configuration["Data:ChinookConnection:ConnectionString"]));
48 |
49 | // Repositories
50 | services.AddScoped();
51 | services.AddScoped();
52 | services.AddScoped();
53 | services.AddScoped();
54 | services.AddScoped();
55 | services.AddScoped();
56 | services.AddScoped();
57 | services.AddScoped();
58 | services.AddScoped();
59 | services.AddScoped();
60 | services.AddScoped();
61 |
62 | services.AddMvc()
63 | .AddJsonOptions(options =>
64 | {
65 | options.SerializerSettings.ReferenceLoopHandling =
66 | Newtonsoft.Json.ReferenceLoopHandling.Ignore;
67 | options.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented;
68 | options.SerializerSettings.ContractResolver =
69 | new CamelCasePropertyNamesContractResolver();
70 | });
71 | }
72 |
73 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline
74 | public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
75 | {
76 | loggerFactory.AddConsole(Configuration.GetSection("Logging"));
77 | loggerFactory.AddDebug();
78 |
79 | app.UseIISPlatformHandler();
80 |
81 | app.UseApplicationInsightsRequestTelemetry();
82 |
83 | app.UseApplicationInsightsExceptionTelemetry();
84 |
85 | app.UseStaticFiles();
86 |
87 | AutoMapperConfiguration.Configure();
88 |
89 | app.UseMvc(routes =>
90 | {
91 | routes.MapRoute(
92 | name: "default",
93 | template: "{controller=Home}/{action=Index}/{id?}");
94 |
95 | // Uncomment the following line to add a route for porting Web API 2 controllers.
96 | //routes.MapWebApiRoute("DefaultApi", "api/{controller}/{id?}");
97 | });
98 | }
99 |
100 | // Entry point for the application.
101 | public static void Main(string[] args) => WebApplication.Run(args);
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/src/ShapingAPI/ViewModels/AddressViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace ShapingAPI.ViewModels
7 | {
8 | public class AddressViewModel
9 | {
10 | public string Address { get; set; }
11 | public string City { get; set; }
12 | public string Country { get; set; }
13 | public string PostalCode { get; set; }
14 | public string State { get; set; }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/ShapingAPI/ViewModels/AlbumViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace ShapingAPI.ViewModels
7 | {
8 | public class AlbumViewModel
9 | {
10 | public AlbumViewModel()
11 | {
12 | Track = new HashSet();
13 | }
14 |
15 | public int AlbumId { get; set; }
16 | public string ArtistName { get; set; }
17 | public string Title { get; set; }
18 | public virtual ICollection Track { get; set; }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/ShapingAPI/ViewModels/ArtistViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace ShapingAPI.ViewModels
7 | {
8 | public class ArtistViewModel
9 | {
10 | public ArtistViewModel()
11 | {
12 | Album = new HashSet();
13 | }
14 |
15 | public int ArtistId { get; set; }
16 | public string Name { get; set; }
17 |
18 | public virtual ICollection Album { get; set; }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/ShapingAPI/ViewModels/ContactViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace ShapingAPI.ViewModels
7 | {
8 | public class ContactViewModel
9 | {
10 | public string Email { get; set; }
11 | public string Fax { get; set; }
12 | public string Phone { get; set; }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/ShapingAPI/ViewModels/CustomerViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace ShapingAPI.ViewModels
5 | {
6 | public class CustomerViewModel
7 | {
8 | public CustomerViewModel() { }
9 |
10 | public int CustomerId { get; set; }
11 | public string Company { get; set; }
12 | public string FirstName { get; set; }
13 | public string LastName { get; set; }
14 | public int? SupportRepId { get; set; }
15 | public int TotalInvoices { get; set; }
16 | public ICollection Invoice { get; set; }
17 | public AddressViewModel Address { get; set; }
18 | public ContactViewModel Contact { get; set; }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/ShapingAPI/ViewModels/InvoiceLineViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace ShapingAPI.ViewModels
5 | {
6 | public class InvoiceLineViewModel
7 | {
8 | public int InvoiceLineId { get; set; }
9 | public int InvoiceId { get; set; }
10 | public int Quantity { get; set; }
11 | public int TrackId { get; set; }
12 | public decimal UnitPrice { get; set; }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/ShapingAPI/ViewModels/InvoiceViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace ShapingAPI.ViewModels
5 | {
6 | public class InvoiceViewModel
7 | {
8 | public InvoiceViewModel()
9 | {
10 | InvoiceLine = new HashSet();
11 | }
12 |
13 | public int InvoiceId { get; set; }
14 | public string BillingAddress { get; set; }
15 | public string BillingCity { get; set; }
16 | public string BillingCountry { get; set; }
17 | public string BillingPostalCode { get; set; }
18 | public string BillingState { get; set; }
19 | public int CustomerId { get; set; }
20 | public DateTime InvoiceDate { get; set; }
21 | public decimal Total { get; set; }
22 | public ICollection InvoiceLine { get; set; }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/ShapingAPI/ViewModels/TrackViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace ShapingAPI.ViewModels
7 | {
8 | public class TrackViewModel
9 | {
10 | public TrackViewModel() { }
11 |
12 | public int TrackId { get; set; }
13 | public int? AlbumId { get; set; }
14 | public int? Bytes { get; set; }
15 | public string Composer { get; set; }
16 | public int? GenreId { get; set; }
17 | public int MediaTypeId { get; set; }
18 | public int Milliseconds { get; set; }
19 | public string Name { get; set; }
20 | public decimal UnitPrice { get; set; }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/ShapingAPI/Views/Home/Albums.cshtml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 | @section scripts
97 | {
98 |
99 | }
--------------------------------------------------------------------------------
/src/ShapingAPI/Views/Home/Artists.cshtml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 | @section scripts
83 | {
84 |
85 | }
--------------------------------------------------------------------------------
/src/ShapingAPI/Views/Home/Customers.cshtml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 | @section scripts
97 | {
98 |
99 | }
--------------------------------------------------------------------------------
/src/ShapingAPI/Views/Home/Index.cshtml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 | @section scripts
83 | {
84 |
85 | }
86 |
--------------------------------------------------------------------------------
/src/ShapingAPI/Views/Shared/_Layout.cshtml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Shaping APIs
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
48 |
49 |
50 |
66 | @RenderBody()
67 |
68 | @RenderSection("scripts", required: false)
69 |
72 |
73 |
--------------------------------------------------------------------------------
/src/ShapingAPI/Views/_ViewStart.cshtml:
--------------------------------------------------------------------------------
1 | @{
2 | Layout = "_Layout";
3 | }
4 |
--------------------------------------------------------------------------------
/src/ShapingAPI/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "IncludeScopes": false,
4 | "LogLevel": {
5 | "Default": "Verbose",
6 | "System": "Information",
7 | "Microsoft": "Information"
8 | }
9 | },
10 | "Data": {
11 | "ChinookConnection": {
12 | "ConnectionString": "Server=(localdb)\\v11.0;Database=Chinook;Trusted_Connection=True;MultipleActiveResultSets=true"
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/ShapingAPI/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ASP.NET",
3 | "private": true,
4 | "dependencies": {
5 | "angular": "1.5.0",
6 | "bootstrap": "3.3.6",
7 | "font-awesome": "4.5.0",
8 | "angular-perfect-scrollbar": "0.0.4",
9 | "ng-json-prettifier": "*"
10 | },
11 | "resolutions": {
12 | "angular": "1.5.0"
13 | }
14 | }
--------------------------------------------------------------------------------
/src/ShapingAPI/project.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "1.0.0-*",
3 | "compilationOptions": {
4 | "emitEntryPoint": true
5 | },
6 |
7 | "dependencies": {
8 | "Microsoft.ApplicationInsights.AspNet": "1.0.0-rc1",
9 | "Microsoft.AspNet.IISPlatformHandler": "1.0.0-rc1-final",
10 | "Microsoft.AspNet.Mvc": "6.0.0-rc1-final",
11 | "Microsoft.AspNet.Server.Kestrel": "1.0.0-rc1-final",
12 | "Microsoft.AspNet.StaticFiles": "1.0.0-rc1-final",
13 | "Microsoft.Extensions.Configuration.FileProviderExtensions": "1.0.0-rc1-final",
14 | "Microsoft.Extensions.Configuration.Json": "1.0.0-rc1-final",
15 | "Microsoft.Extensions.Logging": "1.0.0-rc1-final",
16 | "Microsoft.Extensions.Logging.Console": "1.0.0-rc1-final",
17 | "Microsoft.Extensions.Logging.Debug": "1.0.0-rc1-final",
18 | "EntityFramework.MicrosoftSqlServer": "7.0.0-rc1-final",
19 | "EntityFramework.MicrosoftSqlServer.Design": "7.0.0-rc1-final",
20 | "EntityFramework.Commands": "7.0.0-rc1-final",
21 | "AutoMapper.Data": "1.0.0-beta1",
22 | "Newtonsoft.Json": "7.0.1"
23 | },
24 |
25 | "commands": {
26 | "web": "Microsoft.AspNet.Server.Kestrel",
27 | "ef": "EntityFramework.Commands"
28 | },
29 |
30 | "frameworks": {
31 | "dnx451": { },
32 | "dnxcore50": { }
33 | },
34 |
35 | "exclude": [
36 | "wwwroot",
37 | "node_modules"
38 | ],
39 | "publishExclude": [
40 | "**.user",
41 | "**.vspscc"
42 | ]
43 | }
44 |
--------------------------------------------------------------------------------
/src/ShapingAPI/wwwroot/app/app.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | 'use strict';
3 | var app = angular.module("shapeApp", ['perfect_scrollbar','pretty.json']);
4 |
5 | })();
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/ShapingAPI/wwwroot/app/controllers/albumsCtrl.js:
--------------------------------------------------------------------------------
1 | (function (app) {
2 | 'use strict';
3 |
4 | app.controller('albumsCtrl', albumsCtrl);
5 |
6 | albumsCtrl.$inject = ['$scope', '$http'];
7 |
8 | function albumsCtrl($scope, $http) {
9 | // api/albums
10 | $http.get('/api/albums/').
11 | success(function (data, status, headers, config) {
12 | $scope.apiAlbums = data;
13 | }).
14 | error(function (data, status, headers, config) {
15 | console.log(data);
16 | });
17 |
18 |
19 | //api/albums?props=artistname,title,track
20 | $http.get('/api/albums?props=artistname,title,track').
21 | success(function (data, status, headers, config) {
22 | $scope.apiAlbumsPropsAll = data;
23 | }).
24 | error(function (data, status, headers, config) {
25 | console.log(data);
26 | });
27 |
28 | //api/albums?props=artistname,title,track&page=2&pagesize=10
29 | $http.get('/api/albums?props=artistname,title,track&page=2&pagesize=10').
30 | success(function (data, status, headers, config) {
31 | $scope.apiAlbumsPropsAllPaged = data;
32 | }).
33 | error(function (data, status, headers, config) {
34 | console.log(data);
35 | });
36 |
37 | //api/albums?props=artistname,title,track
38 | $http.get('/api/albums?props=artistname,title,track(bytes;name;unitprice)').
39 | success(function (data, status, headers, config) {
40 | $scope.apiAlbumsPropsAllParseTrack = data;
41 | }).
42 | error(function (data, status, headers, config) {
43 | console.log(data);
44 | });
45 |
46 | // api/albums/1
47 | $http.get('/api/albums/1').
48 | success(function (data, status, headers, config) {
49 | $scope.apiAlbumsOne = data;
50 | }).
51 | error(function (data, status, headers, config) {
52 | console.log(data);
53 | });
54 |
55 | // api/albums/1?props=bytes,milliseconds,name
56 | $http.get('/api/albums/1?props=artistname,title,track(composer;name)').
57 | success(function (data, status, headers, config) {
58 | $scope.apiAlbumsOneProps = data;
59 | }).
60 | error(function (data, status, headers, config) {
61 | console.log(data);
62 | });
63 | }
64 | })(angular.module('shapeApp'));
--------------------------------------------------------------------------------
/src/ShapingAPI/wwwroot/app/controllers/artistsCtrl.js:
--------------------------------------------------------------------------------
1 | (function (app) {
2 | 'use strict';
3 |
4 | app.controller('artistsCtrl', artistsCtrl);
5 |
6 | artistsCtrl.$inject = ['$scope', '$http'];
7 |
8 | function artistsCtrl($scope, $http) {
9 | // api/artists
10 | $http.get('/api/artists/').
11 | success(function (data, status, headers, config) {
12 | $scope.apiArtists = data;
13 | }).
14 | error(function (data, status, headers, config) {
15 | console.log(data);
16 | });
17 |
18 |
19 | //api/artists?props=artistname,title,track
20 | $http.get('/api/artists?props=name,album(albumid;title)').
21 | success(function (data, status, headers, config) {
22 | $scope.apiArtistsPropsOne = data;
23 | }).
24 | error(function (data, status, headers, config) {
25 | console.log(data);
26 | });
27 |
28 | //api/artists?props=artistname,title,track
29 | $http.get('/api/artists?props=name,album(albumid;title;track)').
30 | success(function (data, status, headers, config) {
31 | $scope.apiAlbumsPropsTwo = data;
32 | }).
33 | error(function (data, status, headers, config) {
34 | console.log(data);
35 | });
36 |
37 | // api/artists/1
38 | $http.get('/api/artists/1?props=name,album(albumid;title;track)').
39 | success(function (data, status, headers, config) {
40 | $scope.apiArtistsPropsThree = data;
41 | }).
42 | error(function (data, status, headers, config) {
43 | console.log(data);
44 | });
45 |
46 | // api/albums/1?props=bytes,milliseconds,name
47 | $http.get('/api/artists/1?props=name,album(albumid;title;track(bytes;composer;unitprice))').
48 | success(function (data, status, headers, config) {
49 | $scope.apiArtistsPropsFour = data;
50 | }).
51 | error(function (data, status, headers, config) {
52 | console.log(data);
53 | });
54 | }
55 | })(angular.module('shapeApp'));
--------------------------------------------------------------------------------
/src/ShapingAPI/wwwroot/app/controllers/customersCtrl.js:
--------------------------------------------------------------------------------
1 | (function (app) {
2 | 'use strict';
3 |
4 | app.controller('customersCtrl', customersCtrl);
5 |
6 | customersCtrl.$inject = ['$scope', '$http'];
7 |
8 | function customersCtrl($scope, $http) {
9 | // api/customers
10 | $http.get('/api/customers/').
11 | success(function (data, status, headers, config) {
12 | $scope.apiCustomers = data;
13 | }).
14 | error(function (data, status, headers, config) {
15 | console.log(data);
16 | });
17 |
18 |
19 | //api/customers?props=city,company,firstname,lastname,Invoice
20 | $http.get('/api/customers?props=city,company,firstname,lastname,Invoice').
21 | success(function (data, status, headers, config) {
22 | $scope.apiCustomersPropsOne = data;
23 | }).
24 | error(function (data, status, headers, config) {
25 | console.log(data);
26 | });
27 |
28 | //api/customers?props=address,contact
29 | $http.get('/api/customers?props=firstname,lastname,address,contact').
30 | success(function (data, status, headers, config) {
31 | $scope.apiCustomersPropsAddressContact = data;
32 | }).
33 | error(function (data, status, headers, config) {
34 | console.log(data);
35 | });
36 |
37 | //api/customers?props=firstname,lastname,Invoice[billingcity;total]
38 | $http.get('/api/customers?props=firstname,lastname,Invoice(billingcity;total)&page=4&pagesize=5').
39 | success(function (data, status, headers, config) {
40 | $scope.apiCustomersPropsOnePaged = data;
41 | }).
42 | error(function (data, status, headers, config) {
43 | console.log(data);
44 | });
45 |
46 | //api/customers?props=customerid,city,company,firstname,lastname,Invoice[billingaddress;billingcity;total;invoiceline]
47 | $http.get('/api/customers?props=customerid,city,company,firstname,lastname,Invoice(billingaddress;billingcity;total;invoiceline)').
48 | success(function (data, status, headers, config) {
49 | $scope.apiCustomersPropsTwo = data;
50 | }).
51 | error(function (data, status, headers, config) {
52 | console.log(data);
53 | });
54 |
55 | // /api/customers/1?props=customerid,city,company,firstname,lastname,Invoice[billingaddress;billingcity;total;invoiceline[invoicelineid;quantity;trackid]]
56 | $http.get('/api/customers/1?props=customerid,city,company,firstname,lastname,Invoice(billingaddress;billingcity;total;invoiceline(invoicelineid;quantity;trackid))').
57 | success(function (data, status, headers, config) {
58 | $scope.apiCustomersPropsThree = data;
59 | }).
60 | error(function (data, status, headers, config) {
61 | console.log(data);
62 | });
63 | }
64 | })(angular.module('shapeApp'));
--------------------------------------------------------------------------------
/src/ShapingAPI/wwwroot/app/controllers/tracksCtrl.js:
--------------------------------------------------------------------------------
1 | (function (app) {
2 | 'use strict';
3 |
4 | app.controller('tracksCtrl', tracksCtrl);
5 |
6 | tracksCtrl.$inject = ['$scope', '$http'];
7 |
8 | function tracksCtrl($scope, $http) {
9 | // api/tracks
10 | $http.get('api/tracks/').
11 | success(function (data, status, headers, config) {
12 | $scope.apiTracks = data;
13 | }).
14 | error(function (data, status, headers, config) {
15 | console.log(data);
16 | });
17 |
18 | // api/tracks?page=2&pagesize=100
19 | $http.get('api/tracks?page=2&pagesize=100').
20 | success(function (data, status, headers, config) {
21 | $scope.apiTracksPaged = data;
22 | }).
23 | error(function (data, status, headers, config) {
24 | console.log(data);
25 | });
26 |
27 | // api/tracks?props=bytes,composer,milliseconds
28 | $http.get('api/tracks?props=bytes,composer,milliseconds').
29 | success(function (data, status, headers, config) {
30 | $scope.apiTracksAll = data;
31 | }).
32 | error(function (data, status, headers, config) {
33 | console.log(data);
34 | });
35 |
36 | // api/tracks/1
37 | $http.get('api/tracks/1').
38 | success(function (data, status, headers, config) {
39 | $scope.apiTracksOne = data;
40 | }).
41 | error(function (data, status, headers, config) {
42 | console.log(data);
43 | });
44 |
45 | // api/tracks/1?props=bytes,milliseconds,name
46 | $http.get('api/tracks/1?props=bytes,milliseconds,name').
47 | success(function (data, status, headers, config) {
48 | $scope.apiTracksOneProps = data;
49 | }).
50 | error(function (data, status, headers, config) {
51 | console.log(data);
52 | });
53 | }
54 | })(angular.module('shapeApp'));
--------------------------------------------------------------------------------
/src/ShapingAPI/wwwroot/images/facebook.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chsakell/multi-client-api/db6e537563c7adb1f47d269b8e6533793d9d6806/src/ShapingAPI/wwwroot/images/facebook.png
--------------------------------------------------------------------------------
/src/ShapingAPI/wwwroot/images/github.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chsakell/multi-client-api/db6e537563c7adb1f47d269b8e6533793d9d6806/src/ShapingAPI/wwwroot/images/github.png
--------------------------------------------------------------------------------
/src/ShapingAPI/wwwroot/images/spinner.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chsakell/multi-client-api/db6e537563c7adb1f47d269b8e6533793d9d6806/src/ShapingAPI/wwwroot/images/spinner.gif
--------------------------------------------------------------------------------
/src/ShapingAPI/wwwroot/images/twitter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chsakell/multi-client-api/db6e537563c7adb1f47d269b8e6533793d9d6806/src/ShapingAPI/wwwroot/images/twitter.png
--------------------------------------------------------------------------------
/src/ShapingAPI/wwwroot/styles/site.css:
--------------------------------------------------------------------------------
1 | body {
2 | background-color: #31708f;
3 | }
4 |
5 | .api-box {
6 | white-space: pre-line;
7 | height: 200px;
8 | overflow-y: hidden;
9 | position: relative;
10 | background-color: white;
11 | margin: 6px;
12 | }
13 |
14 | pre {
15 | border: none !important;
16 | background-color: white !important;
17 | }
18 |
19 | .spinner {
20 | display: block;
21 | margin-left: auto;
22 | margin-right: auto;
23 | }
24 |
25 | .blog-image {
26 | height: 70px;
27 | }
28 |
29 | .icon::before {
30 | display: inline-block;
31 | margin-right: .5em;
32 | font: normal normal normal 14px/1 FontAwesome;
33 | font-size: inherit;
34 | text-rendering: auto;
35 | -webkit-font-smoothing: antialiased;
36 | -moz-osx-font-smoothing: grayscale;
37 | transform: translate(0, 0);
38 | }
--------------------------------------------------------------------------------
/src/ShapingAPI/wwwroot/web.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------