Skip to content

Commit 26abf6c

Browse files
authored
Merge pull request #2 from lreb/development
Add OData
2 parents ae95521 + ca21bfa commit 26abf6c

16 files changed

+460
-7
lines changed
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
using System.Data.Entity;
2+
using System.Linq;
3+
using FacwareBase.API.Helpers.Domain.POCO;
4+
using Microsoft.AspNet.OData;
5+
using Microsoft.AspNet.OData.Routing;
6+
using Microsoft.AspNetCore.Mvc;
7+
8+
namespace FacwareBase.API.Controllers
9+
{
10+
//[ODataRoutePrefix("Albums")]
11+
public class AlbumController : ODataController
12+
{
13+
private readonly MusicContext _context;
14+
public AlbumController(MusicContext context)
15+
{
16+
_context = context;
17+
if(!context.Albums.Any())
18+
{
19+
_context.Database.EnsureCreated();
20+
}
21+
}
22+
23+
[EnableQuery]
24+
public IActionResult Get()
25+
{
26+
var albums = _context.Albums;
27+
return Ok(albums);
28+
}
29+
30+
[EnableQuery]
31+
public IActionResult Get(int key)
32+
{
33+
if(!ModelState.IsValid)
34+
{
35+
return BadRequest();
36+
}
37+
var album = _context.Albums.Include(a => a.Songs).Where(a => a.Id == key);
38+
if(album == null)
39+
{
40+
return NotFound();
41+
}
42+
return Ok(album);
43+
}
44+
}
45+
}

FacwareBase.API/Controllers/WeatherForecastController.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ public class WeatherForecastController : ControllerBase
1818

1919
private readonly ILogger<WeatherForecastController> _logger;
2020

21+
2122
public WeatherForecastController(ILogger<WeatherForecastController> logger)
2223
{
2324
_logger = logger;
@@ -27,6 +28,12 @@ public WeatherForecastController(ILogger<WeatherForecastController> logger)
2728
public IEnumerable<WeatherForecast> Get()
2829
{
2930
var rng = new Random();
31+
_logger.LogInformation("Information");
32+
_logger.LogTrace("Trace");
33+
_logger.LogDebug("Debug");
34+
_logger.LogWarning("Warning");
35+
_logger.LogError("Error");
36+
_logger.LogCritical("Critical");
3037
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
3138
{
3239
Date = DateTime.Now.AddDays(index),

FacwareBase.API/Extensions/Database/DatabaseExtension.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Data;
2+
using FacwareBase.API.Helpers.Domain.POCO;
23
using Microsoft.EntityFrameworkCore;
34
using Microsoft.Extensions.DependencyInjection;
45
// using QSS.DataAccess.DataContext;
@@ -11,6 +12,17 @@ namespace FacwareBase.Api.Extensions
1112
/// <seealso cref="IServiceCollection"/>
1213
public static class ServiceCollectionExtensions
1314
{
15+
/// <summary>
16+
/// Set up the Service SQL DB Context
17+
/// </summary>
18+
/// <param name="serviceCollection">The <see cref="IServiceCollection"/></param>
19+
public static void UseInMemoryDatabase(this IServiceCollection serviceCollection)
20+
{
21+
// TODO: use your context
22+
serviceCollection.AddDbContext<MusicContext>(opts => opts.UseInMemoryDatabase("AlbumsDB"));
23+
// https://medium.com/@sddkal/using-odata-controller-in-net-core-apis-63b688585eaf
24+
}
25+
1426
/// <summary>
1527
/// Set up the Service SQL DB Context
1628
/// </summary>
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
using System;
2+
using FacwareBase.API.Helpers.Domain.POCO;
3+
using Microsoft.AspNet.OData.Builder;
4+
using Microsoft.AspNetCore.Builder;
5+
using Microsoft.OData.Edm;
6+
7+
namespace FacwareBase.Api.Extensions.OData
8+
{
9+
/// <summary>
10+
/// OData extension
11+
/// </summary>
12+
public static class ODataExtension
13+
{
14+
/// <summary>
15+
/// Generates the OData IEdm Models based on the DB Tables/Models
16+
/// </summary>
17+
/// <param name="serviceProvider"></param>
18+
/// <returns><see cref="IEdmModel"/></returns>
19+
public static IEdmModel GetODataModels(IServiceProvider serviceProvider)
20+
{
21+
ODataModelBuilder builder = new ODataConventionModelBuilder(serviceProvider).EnableLowerCamelCase();
22+
23+
builder.EntitySet<Song>("Songs").EntityType.Filter();
24+
builder.EntitySet<Album>("Albums");
25+
26+
return builder.GetEdmModel();
27+
}
28+
29+
/// <summary>
30+
/// Generates the OData IEdm Models based on the DB Tables/Models extension method
31+
/// </summary>
32+
/// <param name="app"></param>
33+
/// <returns><see cref="IEdmModel"/></returns>
34+
public static IEdmModel GetODataModels(this IApplicationBuilder app)
35+
{
36+
ODataModelBuilder builder = new ODataConventionModelBuilder(app.ApplicationServices).EnableLowerCamelCase();
37+
38+
builder.EntitySet<Song>("Songs");
39+
builder.EntitySet<Album>("Album");
40+
41+
return builder.GetEdmModel();
42+
}
43+
}
44+
}

FacwareBase.API/FacwareBase.API.csproj

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,17 @@
1111
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="3.1.1" />
1212
<PackageReference Include="EntityFramework6.Npgsql" Version="6.4.1" />
1313
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.8" />
14+
<PackageReference Include="Microsoft.AspNetCore.OData" Version="7.4.1" />
15+
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="3.1.8" />
1416
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.8">
1517
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
1618
<PrivateAssets>all</PrivateAssets>
1719
</PackageReference>
1820
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
1921
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="3.1.4" />
22+
<PackageReference Include="Serilog.AspNetCore" Version="3.4.0" />
23+
<PackageReference Include="Serilog.Extensions.Logging" Version="3.0.1" />
24+
<PackageReference Include="Serilog.Sinks.ColoredConsole" Version="3.0.1" />
2025
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.5.0" />
2126
</ItemGroup>
2227

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
{
2+
"info": {
3+
"_postman_id": "23ed4a9e-d63d-46dd-b1e7-6c7f2dccd783",
4+
"name": "FacwareBase",
5+
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
6+
},
7+
"item": [
8+
{
9+
"name": "Demo",
10+
"item": [
11+
{
12+
"name": "Album",
13+
"item": [
14+
{
15+
"name": "Odata Album",
16+
"request": {
17+
"method": "GET",
18+
"header": [],
19+
"url": {
20+
"raw": "https://localhost:5001/OData/Album?$expand=Songs($select=name;$orderby=name desc;$filter=startswith(name, '21');$count=true)&$count=true",
21+
"protocol": "https",
22+
"host": [
23+
"localhost"
24+
],
25+
"port": "5001",
26+
"path": [
27+
"OData",
28+
"Album"
29+
],
30+
"query": [
31+
{
32+
"key": "$select",
33+
"value": "name",
34+
"disabled": true
35+
},
36+
{
37+
"key": "$expand",
38+
"value": "Songs($select=name;$skip=1)",
39+
"disabled": true
40+
},
41+
{
42+
"key": "$expand",
43+
"value": "Songs($select=name;$top=1)",
44+
"disabled": true
45+
},
46+
{
47+
"key": "$expand",
48+
"value": "Songs($select=name;$orderby=name desc;$filter=startswith(name, '21');$count=true)"
49+
},
50+
{
51+
"key": "$count",
52+
"value": "true"
53+
}
54+
]
55+
}
56+
},
57+
"response": []
58+
}
59+
],
60+
"protocolProfileBehavior": {},
61+
"_postman_isSubFolder": true
62+
}
63+
],
64+
"protocolProfileBehavior": {}
65+
}
66+
],
67+
"protocolProfileBehavior": {}
68+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using System.Collections.Generic;
2+
3+
namespace FacwareBase.API.Helpers.Domain.POCO
4+
{
5+
public class Album
6+
{
7+
public Album()
8+
{
9+
Songs = new List<Song>();
10+
}
11+
public int Id { get; set; }
12+
public string Name { get; set; }
13+
public ICollection<Song> Songs { get; set; }
14+
}
15+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using Microsoft.EntityFrameworkCore;
2+
3+
namespace FacwareBase.API.Helpers.Domain.POCO
4+
{
5+
6+
public class MusicContext: DbContext
7+
{
8+
public DbSet<Album> Albums{get; set;}
9+
public DbSet<Song> Songs { get; set; }
10+
11+
public MusicContext(): base() { }
12+
public MusicContext(DbContextOptions opts): base(opts) { }
13+
14+
protected override void OnModelCreating(ModelBuilder builder)
15+
{
16+
builder.Entity<Album>().HasMany(a => a.Songs).WithOne(s => s.Album); // One-To-Many
17+
builder.Entity<Album>().HasData(new Album{
18+
Id = 1, Name = "The Court of the Crimson King"
19+
});
20+
// https://wildermuth.com/2018/08/12/Seeding-Related-Entities-in-EF-Core-2-1-s-HasData()
21+
builder.Entity<Song>().HasData(
22+
new {Id = 1, AlbumId = 1, Name = "21st Century Schzoid Man"},
23+
new {Id = 2, AlbumId = 1, Name = "I Talk to the Wind"}
24+
);
25+
}
26+
}
27+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
namespace FacwareBase.API.Helpers.Domain.POCO
2+
{
3+
public class Song
4+
{
5+
public int Id { get; set; }
6+
public string Name { get; set; }
7+
public Album Album { get; set; }
8+
}
9+
}

FacwareBase.API/Program.cs

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,62 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.IO;
34
using System.Linq;
45
using System.Threading.Tasks;
56
using Microsoft.AspNetCore.Hosting;
67
using Microsoft.Extensions.Configuration;
78
using Microsoft.Extensions.Hosting;
89
using Microsoft.Extensions.Logging;
10+
using Serilog;
11+
using Serilog.Events;
912

1013
namespace FacwareBase.API
1114
{
1215
public class Program
1316
{
17+
/// <summary>
18+
/// App settings
19+
/// </summary>
20+
public static IConfiguration configuration = new ConfigurationBuilder()
21+
.SetBasePath(Directory.GetCurrentDirectory())
22+
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
23+
.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", optional: true)
24+
.AddEnvironmentVariables()
25+
.Build();
26+
1427
public static void Main(string[] args)
1528
{
16-
CreateHostBuilder(args).Build().Run();
29+
Log.Logger = new LoggerConfiguration()
30+
.Enrich.FromLogContext()
31+
.ReadFrom.Configuration(configuration)
32+
.WriteTo.Debug()
33+
.WriteTo.ColoredConsole(
34+
LogEventLevel.Verbose,
35+
"{NewLine}{Timestamp:HH:mm:ss} [{Level}] ({CorrelationToken}) {Message}{NewLine}{Exception}")
36+
// TODO: Write to db or AWS cloud watch
37+
.CreateLogger();
38+
39+
try
40+
{
41+
Log.Information("Staring up");
42+
CreateHostBuilder(args).Build().Run();
43+
}
44+
catch (System.Exception exception)
45+
{
46+
Log.Fatal(exception, "Application fatils to start");
47+
}
48+
finally
49+
{
50+
Log.CloseAndFlush();
51+
}
1752
}
1853

1954
public static IHostBuilder CreateHostBuilder(string[] args) =>
2055
Host.CreateDefaultBuilder(args)
21-
.ConfigureWebHostDefaults(webBuilder =>
22-
{
23-
webBuilder.UseStartup<Startup>();
24-
});
56+
.UseSerilog()
57+
.ConfigureWebHostDefaults(webBuilder =>
58+
{
59+
webBuilder.UseStartup<Startup>();
60+
});
2561
}
2662
}

0 commit comments

Comments
 (0)