├── CoreStarter
├── CoreStarter.Vsix
│ ├── logo-lazybyte.png
│ ├── bak
│ │ ├── logo-lazybyte.ico
│ │ ├── MyTemplate.vstemplate
│ │ └── API.vstemplate
│ ├── ProjectTemplates
│ │ └── CoreStarter.Api.zip
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── source.extension.vsixmanifest
│ └── CoreStarter.Vsix.csproj
├── CoreStarter.Api
│ ├── Configuration
│ │ └── ConnectionStrings.cs
│ ├── appsettings.development.json
│ ├── Models
│ │ ├── FooFile.cs
│ │ └── Foo.cs
│ ├── appsettings.json
│ ├── Program.cs
│ ├── CoreStarter.Api.csproj
│ ├── Midlleware
│ │ └── RequestValidationMiddleware.cs
│ ├── Observability
│ │ ├── BasicHealthCheck.cs
│ │ └── HealthReportWriter.cs
│ ├── Services
│ │ ├── FooService.cs
│ │ └── IFooService.cs
│ ├── Controllers
│ │ └── FooController.cs
│ └── Startup.cs
└── CoreStarter.sln
├── release-notes.md
├── .github
└── ISSUE_TEMPLATE
│ ├── feature_request.md
│ └── bug_report.md
├── README.md
└── .gitignore
/CoreStarter/CoreStarter.Vsix/logo-lazybyte.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MirzaMerdovic/DotNetCore-WebApiStarter/HEAD/CoreStarter/CoreStarter.Vsix/logo-lazybyte.png
--------------------------------------------------------------------------------
/CoreStarter/CoreStarter.Vsix/bak/logo-lazybyte.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MirzaMerdovic/DotNetCore-WebApiStarter/HEAD/CoreStarter/CoreStarter.Vsix/bak/logo-lazybyte.ico
--------------------------------------------------------------------------------
/CoreStarter/CoreStarter.Vsix/ProjectTemplates/CoreStarter.Api.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MirzaMerdovic/DotNetCore-WebApiStarter/HEAD/CoreStarter/CoreStarter.Vsix/ProjectTemplates/CoreStarter.Api.zip
--------------------------------------------------------------------------------
/CoreStarter/CoreStarter.Api/Configuration/ConnectionStrings.cs:
--------------------------------------------------------------------------------
1 | namespace CoreStarter.Api.Configuration
2 | {
3 | public class ConnectionStrings
4 | {
5 | public string ApiDb { get; set; }
6 |
7 | public string Api2Db { get; set; }
8 | }
9 | }
--------------------------------------------------------------------------------
/CoreStarter/CoreStarter.Api/appsettings.development.json:
--------------------------------------------------------------------------------
1 | {
2 | "ConnectionStrings": {
3 | "apiDb": "Server=localhost;Initial Catalog={database};Integrated Security=SSPI;",
4 | "api2Db": "Server=localhost;Initial Catalog={database};Integrated Security=SSPI;"
5 | }
6 | }
--------------------------------------------------------------------------------
/release-notes.md:
--------------------------------------------------------------------------------
1 | Release Notes
2 |
3 | # 1.0.0 - October 25th, 2018
4 | - Initial version.
5 |
6 | # 2.0.0 - December 4th, 2019
7 | - Upgraded to ASPNet Core 3.1
8 | - Added liveness and readiness health checks
9 | - Fixed file upload so it supports POCO + File combination in models
10 | - Removed Swagger examples
--------------------------------------------------------------------------------
/CoreStarter/CoreStarter.Api/Models/FooFile.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using Microsoft.AspNetCore.Http;
3 |
4 | namespace CoreStarter.Api.Models
5 | {
6 | public class FooFile : Foo
7 | {
8 | ///
9 | /// Gets or set the file content.
10 | ///
11 | public IFormFile File { get; set; }
12 | }
13 | }
--------------------------------------------------------------------------------
/CoreStarter/CoreStarter.Api/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "DatabaseConfiguration": {
3 | "apiDb": "Server={localhost};Initial Catalog={database};User ID={userName};Password={password};",
4 | "api2Db": "Server={localhost};Initial Catalog={database};User ID={userName};Password={password};"
5 | },
6 | "Logging": {
7 | "LogLevel": {
8 | "Default": "Trace",
9 | "System": "Information",
10 | "Microsoft": "Information"
11 | },
12 | "Console": {
13 | "IncludeScopes": true
14 | }
15 | }
16 | }
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 |
5 | ---
6 |
7 | **Is your feature request related to a problem? Please describe.**
8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
9 |
10 | **Describe the solution you'd like**
11 | A clear and concise description of what you want to happen.
12 |
13 | **Describe alternatives you've considered**
14 | A clear and concise description of any alternative solutions or features you've considered.
15 |
16 | **Additional context**
17 | Add any other context or screenshots about the feature request here.
18 |
--------------------------------------------------------------------------------
/CoreStarter/CoreStarter.Api/Models/Foo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace CoreStarter.Api.Models
4 | {
5 | ///
6 | /// The Foo
7 | ///
8 | public class Foo
9 | {
10 | ///
11 | /// Gets the creation time.
12 | ///
13 | public DateTime CreateAd => DateTime.UtcNow;
14 |
15 | ///
16 | /// Gets or sets unique identifier.
17 | ///
18 | public int Id { get; set; }
19 |
20 | ///
21 | /// Gets or sets the Foo value.
22 | ///
23 | public string Value { get; set; }
24 | }
25 | }
--------------------------------------------------------------------------------
/CoreStarter/CoreStarter.Api/Program.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Hosting;
2 | using Microsoft.Extensions.Hosting;
3 | using System.Threading.Tasks;
4 |
5 | namespace CoreStarter.Api
6 | {
7 | ///
8 | /// Where all begins.
9 | ///
10 | public static class Program
11 | {
12 | ///
13 | /// The main method.
14 | ///
15 | /// Arguments
16 | /// A task.
17 | public static Task Main(string[] args)
18 | {
19 | return CreateHostBuilder(args).Build().RunAsync();
20 | }
21 |
22 | private static IHostBuilder CreateHostBuilder(string[] args) =>
23 | Host.CreateDefaultBuilder(args)
24 | .ConfigureWebHostDefaults(webBuilder =>
25 | {
26 | webBuilder.UseStartup();
27 | });
28 | }
29 | }
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 |
5 | ---
6 |
7 | **Describe the bug**
8 | A clear and concise description of what the bug is.
9 |
10 | **To Reproduce**
11 | Steps to reproduce the behavior:
12 | 1. Go to '...'
13 | 2. Click on '....'
14 | 3. Scroll down to '....'
15 | 4. See error
16 |
17 | **Expected behavior**
18 | A clear and concise description of what you expected to happen.
19 |
20 | **Screenshots**
21 | If applicable, add screenshots to help explain your problem.
22 |
23 | **Desktop (please complete the following information):**
24 | - OS: [e.g. iOS]
25 | - Browser [e.g. chrome, safari]
26 | - Version [e.g. 22]
27 |
28 | **Smartphone (please complete the following information):**
29 | - Device: [e.g. iPhone6]
30 | - OS: [e.g. iOS8.1]
31 | - Browser [e.g. stock browser, safari]
32 | - Version [e.g. 22]
33 |
34 | **Additional context**
35 | Add any other context about the problem here.
36 |
--------------------------------------------------------------------------------
/CoreStarter/CoreStarter.Api/CoreStarter.Api.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 | 2.0.0
6 | true
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | all
20 | runtime; build; native; contentfiles; analyzers; buildtransitive
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/CoreStarter/CoreStarter.Api/Midlleware/RequestValidationMiddleware.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics;
2 | using System.Threading.Tasks;
3 | using Microsoft.AspNetCore.Http;
4 | using Microsoft.Extensions.Logging;
5 |
6 | namespace CoreStarter.Api.Middleware
7 | {
8 | public class RequestValidationMiddleware
9 | {
10 | private readonly RequestDelegate _next;
11 | private readonly ILogger _logger;
12 |
13 | public RequestValidationMiddleware(RequestDelegate next, ILogger logger)
14 | {
15 | _next = next;
16 | _logger = logger;
17 | }
18 |
19 | public async Task Invoke(HttpContext context)
20 | {
21 | var stopwatch = new Stopwatch();
22 | stopwatch.Restart();
23 |
24 | await _next(context);
25 |
26 | stopwatch.Stop();
27 |
28 | _logger.LogTrace($"Method: {context.Request.Method}; Path: {context.Request.Path} Execution time: {stopwatch.ElapsedMilliseconds}[ms]");
29 | }
30 | }
31 | }
--------------------------------------------------------------------------------
/CoreStarter/CoreStarter.Api/Observability/BasicHealthCheck.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Diagnostics.HealthChecks;
2 | using System;
3 | using System.Threading;
4 | using System.Threading.Tasks;
5 |
6 | namespace CoreStarter.Api.Observability
7 | {
8 | ///
9 | /// Basic health check implementation.
10 | ///
11 | public class BasicHealthCheck : IHealthCheck
12 | {
13 | ///
14 | /// Executes the health check logic
15 | ///
16 | /// Instance of .
17 | /// Instance of .
18 | /// An instance of .
19 | public Task CheckHealthAsync(
20 | HealthCheckContext context,
21 | CancellationToken cancellationToken = default(CancellationToken))
22 | {
23 | var shoredinger = new Random().Next();
24 |
25 | return
26 | shoredinger % 2 == 0
27 | ? Task.FromResult(HealthCheckResult.Healthy("Alive."))
28 | : Task.FromResult(HealthCheckResult.Unhealthy("Dead"));
29 | }
30 | }
31 | }
--------------------------------------------------------------------------------
/CoreStarter/CoreStarter.Vsix/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("CoreStarter.Vsix")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("CoreStarter.Vsix")]
13 | [assembly: AssemblyCopyright("")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // Version information for an assembly consists of the following four values:
23 | //
24 | // Major Version
25 | // Minor Version
26 | // Build Number
27 | // Revision
28 | //
29 | // You can specify all the values or you can default the Build and Revision Numbers
30 | // by using the '*' as shown below:
31 | // [assembly: AssemblyVersion("1.0.*")]
32 | [assembly: AssemblyVersion("1.0.0.0")]
33 | [assembly: AssemblyFileVersion("1.0.0.0")]
34 |
--------------------------------------------------------------------------------
/CoreStarter/CoreStarter.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.29509.3
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CoreStarter.Api", "CoreStarter.Api\CoreStarter.Api.csproj", "{9760BCAC-02F4-440A-BBD4-319A397ADC3D}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CoreStarter.Vsix", "CoreStarter.Vsix\CoreStarter.Vsix.csproj", "{CFB65B2F-BCBD-4422-AAE7-7309103B1636}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Release|Any CPU = Release|Any CPU
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {9760BCAC-02F4-440A-BBD4-319A397ADC3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17 | {9760BCAC-02F4-440A-BBD4-319A397ADC3D}.Debug|Any CPU.Build.0 = Debug|Any CPU
18 | {9760BCAC-02F4-440A-BBD4-319A397ADC3D}.Release|Any CPU.ActiveCfg = Release|Any CPU
19 | {9760BCAC-02F4-440A-BBD4-319A397ADC3D}.Release|Any CPU.Build.0 = Release|Any CPU
20 | {CFB65B2F-BCBD-4422-AAE7-7309103B1636}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {CFB65B2F-BCBD-4422-AAE7-7309103B1636}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {CFB65B2F-BCBD-4422-AAE7-7309103B1636}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {CFB65B2F-BCBD-4422-AAE7-7309103B1636}.Release|Any CPU.Build.0 = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {F783D03C-2A68-4C3B-AF91-03E530BBABDF}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/CoreStarter/CoreStarter.Api/Services/FooService.cs:
--------------------------------------------------------------------------------
1 | using CoreStarter.Api.Configuration;
2 | using CoreStarter.Api.Models;
3 | using Microsoft.Extensions.Options;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Threading.Tasks;
7 |
8 | namespace CoreStarter.Api.Services
9 | {
10 | public sealed class FooService : IFooService
11 | {
12 | private readonly ConnectionStrings _connectionStrings;
13 |
14 | public FooService(IOptionsMonitor connectionStrings)
15 | {
16 | _connectionStrings = connectionStrings.CurrentValue;
17 | }
18 |
19 | public Task Create(Foo foo)
20 | {
21 | return Task.FromResult(new Random().Next());
22 | }
23 |
24 | public Task> Get()
25 | {
26 | return Task.FromResult>(new List
27 | {
28 | new Foo {Id = 1, Value = Guid.NewGuid().ToString().Remove(5)},
29 | new Foo {Id = 3, Value = Guid.NewGuid().ToString().Remove(5)}
30 | });
31 | }
32 |
33 | public Task Get(int id)
34 | {
35 | if (id == 0)
36 | return Task.FromResult(null);
37 |
38 | return Task.FromResult(new Foo { Id = id, Value = Guid.NewGuid().ToString().Remove(5) });
39 | }
40 |
41 | public Task Update(Foo foo)
42 | {
43 | return Task.CompletedTask;
44 | }
45 |
46 | public Task Delete(int id)
47 | {
48 | return Task.CompletedTask;
49 | }
50 |
51 | public void Throw()
52 | {
53 | throw new ApplicationException("Here is an error for you");
54 | }
55 | }
56 | }
--------------------------------------------------------------------------------
/CoreStarter/CoreStarter.Vsix/source.extension.vsixmanifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | AspNetCore Web Api Starter Template
6 | AspNet Core Web API starter template that includes: swagger, configuration reading, exception handling, examples of routing with proper HTTP responses.
7 |
8 | https://github.com/MirzaMerdovic/DotNetCore-Starter.git
9 | https://github.com/MirzaMerdovic/DotNetCore-WebApiStarter/wiki
10 | https://github.com/MirzaMerdovic/DotNetCore-WebApiStarter/blob/master/release-notes.md
11 | logo-lazybyte.png
12 | web api, rest, webapi, swagger, cors
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/CoreStarter/CoreStarter.Api/Services/IFooService.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Threading.Tasks;
3 | using CoreStarter.Api.Models;
4 |
5 | namespace CoreStarter.Api.Services
6 | {
7 | ///
8 | /// Represents the set of methods for Foo manipulation.
9 | ///
10 | public interface IFooService
11 | {
12 | ///
13 | /// Tries to create new Foo.
14 | ///
15 | /// Instance of
16 | /// Unique identifier.
17 | Task Create(Foo foo);
18 |
19 | ///
20 | /// Tries to retrieve all Foo objects.
21 | ///
22 | /// A collection of Foo objects (collection might be empty, but never null).
23 | Task> Get();
24 |
25 | ///
26 | /// Tries to retrieve specified Foo object if exists.
27 | ///
28 | /// Unique identifier.
29 | /// A object, or null.
30 | Task Get(int id);
31 |
32 | ///
33 | /// Tries to perform update.
34 | ///
35 | /// Instance of that holds values that we want updated.
36 | /// An awaitable task.
37 | Task Update(Foo foo);
38 |
39 | ///
40 | /// Tries to delete specified Foo.
41 | ///
42 | /// Unique identifier.
43 | /// An awaitable task.
44 | Task Delete(int id);
45 |
46 | ///
47 | /// Throws an exception to demonstrate exception handling.
48 | ///
49 | void Throw();
50 | }
51 | }
--------------------------------------------------------------------------------
/CoreStarter/CoreStarter.Api/Observability/HealthReportWriter.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Http;
2 | using Microsoft.Extensions.Diagnostics.HealthChecks;
3 | using Newtonsoft.Json;
4 | using System;
5 | using System.Linq;
6 | using System.Threading.Tasks;
7 |
8 | namespace CoreStarter.Api.Observability
9 | {
10 | ///
11 | /// Contains utility methods for configuring health checks
12 | ///
13 | public static class HealthReportWriter
14 | {
15 | ///
16 | /// Tries to write the health check result data into HTTP response message.
17 | ///
18 | /// Instance of .
19 | /// Instance of .
20 | /// A task.
21 | public static Task WriteResponse(HttpContext httpContext, HealthReport result)
22 | {
23 | _ = httpContext ?? throw new ArgumentNullException(nameof(httpContext));
24 | _ = result ?? throw new ArgumentNullException(nameof(result));
25 |
26 | httpContext.Response.ContentType = "application/json";
27 |
28 | var payload = new
29 | {
30 | Status = result.Status.ToString(),
31 | HealthChecks = result.Entries.Select(pair => new
32 | {
33 | Name = pair.Key,
34 | Report = new
35 | {
36 | Status = pair.Value.Status.ToString(),
37 | Descriptions = pair.Value.Description,
38 | ElapsedMilliseconds = pair.Value.Duration.TotalMilliseconds,
39 | Tags = pair.Value.Tags,
40 | Data = pair.Value.Data.Select(kvp => new
41 | {
42 | Key = kvp.Key,
43 | Value = kvp.Value
44 | })
45 | }
46 | })
47 | };
48 |
49 | return httpContext.Response.WriteAsync(JsonConvert.SerializeObject(payload, Formatting.Indented));
50 | }
51 | }
52 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ASPNet Core Api Template
2 |
3 | [](https://ci.appveyor.com/project/MirzaMerdovic/dotnetcore-webapistarter/branch/master) [](https://www.codefactor.io/repository/github/mirzamerdovic/dotnetcore-webapistarter) [](https://app.fossa.io/projects/git%2Bgithub.com%2FMirzaMerdovic%2FDotNetCore-WebApiStarter?ref=badge_shield)
4 |
5 | # Introduction
6 |
7 | A thin template that should give you benefit of having the common stuff setup and couple of extra things that might be useful to people who are learning.
8 |
9 | # Where can I get it?
10 |
11 | The template is available on [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=lazybyte.LazyByte-AspNetCore-WebApiStarterTemplate)
12 |
13 | # Why do I need it?
14 | In all honesty you don't it's just a template after all, but in case you are frequently building Web APIs you may found it useful, or may found parts that you can re-use to build one for yourself.
15 |
16 | In case you are still reading this is what template brings on the table:
17 | * Configuration setup which includes appsettings.{env}.json transformation and reading the data using the [Options pattern](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/options?view=aspnetcore-3.1)
18 | * [CORS](https://docs.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-3.1) that is configure to allow everyhting, but it should be very easy to configure it for a real world scenario.
19 | * [Response caching](https://docs.microsoft.com/en-us/aspnet/core/performance/caching/middleware?view=aspnetcore-3.1)
20 | * Health check implementation using [readiness and liveness probes](https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/health-checks?view=aspnetcore-3.1#separate-readiness-and-liveness-probes)
21 | * Swagger
22 | * FooController - a simple API controller:
23 | * Routing
24 | * HTTP response messages using IActionResult
25 | * File upload example that support complex models so that you can have metadata around IFormFile property that carries the file content
26 | * Custom middleware example
27 |
28 | # Feedback
29 | If you have any issues or suggestion that you believe might make the template better please don't hestitate to let me know and if it's not a big bother please use one of the templates: [bug](https://github.com/MirzaMerdovic/DotNetCore-WebApiStarter/issues/new?template=bug_report.md)/[new feature](https://github.com/MirzaMerdovic/DotNetCore-WebApiStarter/issues/new?template=feature_request.md)
30 |
--------------------------------------------------------------------------------
/CoreStarter/CoreStarter.Vsix/bak/MyTemplate.vstemplate:
--------------------------------------------------------------------------------
1 |
2 |
3 | CoreStarter.Api
4 | Starter template for developing Web APIs with ASPNet Core 3+
5 | CSharp
6 | Web
7 | C#
8 | Windows
9 | Linux
10 | macOS
11 | Web
12 | 1
13 | 10
14 | true
15 | WebApi
16 | true
17 | Enabled
18 | true
19 | true
20 | __TemplateIcon.ico
21 |
22 |
23 |
24 |
25 | launchSettings.json
26 |
27 |
28 | ConnectionStrings.cs
29 |
30 |
31 | FooController.cs
32 |
33 |
34 | RequestValidationMiddleware.cs
35 |
36 |
37 | Foo.cs
38 | FooFile.cs
39 |
40 |
41 | BasicHealthCheck.cs
42 | HealthReportWriter.cs
43 |
44 |
45 | FooService.cs
46 | IFooService.cs
47 |
48 | appsettings.json
49 | appsettings.development.json
50 | Program.cs
51 | Startup.cs
52 |
53 |
54 |
--------------------------------------------------------------------------------
/CoreStarter/CoreStarter.Vsix/CoreStarter.Vsix.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 15.0
5 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
6 |
7 |
8 |
9 | Debug
10 | AnyCPU
11 | 2.0
12 | {82b43b9b-a64c-4715-b499-d71e9ca2bd60};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
13 | {CFB65B2F-BCBD-4422-AAE7-7309103B1636}
14 | Library
15 | Properties
16 | CoreStarter.Vsix
17 | CoreStarter.Vsix
18 | v4.7.2
19 | false
20 | false
21 | false
22 | false
23 | false
24 | false
25 | Program
26 | $(DevEnvDir)devenv.exe
27 | /rootsuffix Exp
28 |
29 |
30 | true
31 | full
32 | false
33 | bin\Debug\
34 | DEBUG;TRACE
35 | prompt
36 | 4
37 |
38 |
39 | pdbonly
40 | true
41 | bin\Release\
42 | TRACE
43 | prompt
44 | 4
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 | Always
53 | true
54 |
55 |
56 | Designer
57 |
58 |
59 |
60 |
61 |
62 | Always
63 | true
64 |
65 |
66 |
67 |
68 |
69 |
76 |
--------------------------------------------------------------------------------
/CoreStarter/CoreStarter.Vsix/bak/API.vstemplate:
--------------------------------------------------------------------------------
1 |
2 |
3 | Service.API
4 | <No description available>
5 | CSharp
6 |
7 |
8 | 1000
9 | true
10 | Service.API
11 | true
12 | Enabled
13 | true
14 | true
15 | __TemplateIcon.ico
16 | true
17 |
18 |
19 |
20 |
21 |
22 | launchSettings.json
23 |
24 |
25 |
26 | CarsV0Controller.cs
27 |
28 | CarsController.cs
29 | TodosController.cs
30 | TokenController.cs
31 |
32 |
33 |
34 | CarsViewMappingProfile.cs
35 | TodoViewMappingProfile.cs
36 |
37 |
38 | HttpContextMiddleware.cs
39 | HttpContextMiddlewareExtensions.cs
40 |
41 |
42 | AppSettings.cs
43 | Car.cs
44 | CarType.cs
45 | Todo.cs
46 |
47 |
48 | CarModelExample.cs
49 | SwaggerDefaultValues.cs
50 |
51 | appsettings.json
52 | appsettings.Development.json
53 | Program.cs
54 | Service.API.xml
55 | Startup.cs
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/CoreStarter/CoreStarter.Api/Controllers/FooController.cs:
--------------------------------------------------------------------------------
1 | using CoreStarter.Api.Models;
2 | using CoreStarter.Api.Services;
3 | using Microsoft.AspNetCore.Mvc;
4 | using Microsoft.Extensions.Logging;
5 | using System;
6 | using System.Collections.Generic;
7 | using System.IO;
8 | using System.Threading.Tasks;
9 |
10 | namespace CoreStarter.Api.Controllers
11 | {
12 | ///
13 | /// Foo controller.
14 | ///
15 | [Route("api/[controller]")]
16 | public class FooController : ControllerBase
17 | {
18 | private readonly IFooService _service;
19 | private readonly ILogger _logger;
20 |
21 | ///
22 | /// Creates new instance of .
23 | ///
24 | /// Instance of
25 | ///
26 | public FooController(IFooService service, ILogger logger)
27 | {
28 | _service = service ?? throw new ArgumentNullException(nameof(service));
29 | _logger = logger ?? throw new ArgumentNullException(nameof(logger));
30 | }
31 |
32 | ///
33 | /// Tries to create a new Foo.
34 | ///
35 | /// Instance of .
36 | /// Foo created.
37 | /// Internal server error.
38 | [HttpPost]
39 | [ProducesResponseType(typeof(int), 201)]
40 | [ProducesResponseType(500)]
41 | public async Task Post([FromBody] Foo foo)
42 | {
43 | var response = await _service.Create(foo);
44 |
45 | return CreatedAtRoute("getById", new { id = response }, response);
46 | }
47 |
48 | ///
49 | /// Tries to create a new foo file.
50 | ///
51 | /// Instance of .
52 | /// A file content
53 | ///
54 | [HttpPost("content")]
55 | [ProducesResponseType(typeof(int), 201)]
56 | [ProducesResponseType(500)]
57 | public async Task PostFile([FromForm] FooFile foo)
58 | {
59 | using (var memoryStream = new MemoryStream())
60 | {
61 | await foo.File.OpenReadStream().CopyToAsync(memoryStream);
62 | var fileName = Guid.NewGuid().ToString("N");
63 | var path = Path.Combine(Path.GetTempPath(), fileName);
64 | await System.IO.File.WriteAllBytesAsync(path, memoryStream.ToArray());
65 | }
66 |
67 | var response = await _service.Create(foo);
68 |
69 | return CreatedAtRoute("getById", new { id = response }, response);
70 | }
71 |
72 | ///
73 | /// Tries to retrieve all Foo objects.
74 | ///
75 | /// All available Foo objects retrieved.
76 | /// Internal server error.
77 | [HttpGet, ResponseCache(CacheProfileName = "default")]
78 | [ProducesResponseType(typeof(IEnumerable), 200)]
79 | public async Task Get()
80 | {
81 | var response = await _service.Get();
82 |
83 | return Ok(response);
84 | }
85 |
86 |
87 | [HttpPost("throw")]
88 | [ProducesResponseType(500)]
89 | public async Task Throw([FromBody] Foo foo)
90 | {
91 | _ = foo ?? throw new ArgumentNullException(nameof(foo));
92 |
93 | _service.Throw();
94 |
95 | return Ok(foo);
96 | }
97 |
98 | ///
99 | /// Tries to retrieve specified Foo.
100 | ///
101 | /// Unique identifier.
102 | /// Foo successfully retrieved.
103 | /// Specified Foo doesn't exist.
104 | /// Internal server error.
105 | [HttpGet("{id:int:min(1)}", Name = "getById")]
106 | [ProducesResponseType(typeof(Foo), 200)]
107 | [ProducesResponseType(404)]
108 | public async Task Get(int id)
109 | {
110 | var response = await _service.Get(id);
111 |
112 | if (response == null)
113 | return NotFound(id);
114 |
115 | return Ok(response);
116 | }
117 |
118 | ///
119 | /// Tries to update the Foo.
120 | ///
121 | /// Instance of that holds values that we want updated.
122 | /// Foo updated successfully.
123 | /// Internal server error.
124 | [HttpPut]
125 | public async Task Patch([FromBody] Foo foo)
126 | {
127 | await _service.Update(foo);
128 |
129 | return Ok();
130 | }
131 |
132 | ///
133 | /// Tires to delete specified Foo.
134 | ///
135 | /// Unique identifier.
136 | /// Foo deleted successfully.
137 | /// Internal server error.
138 | [HttpDelete("{id:int:min(1)}")]
139 | public async Task Delete(int id)
140 | {
141 | await _service.Delete(id);
142 |
143 | return Ok();
144 | }
145 | }
146 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.suo
8 | *.user
9 | *.userosscache
10 | *.sln.docstates
11 |
12 | # User-specific files (MonoDevelop/Xamarin Studio)
13 | *.userprefs
14 |
15 | # Build results
16 | [Dd]ebug/
17 | [Dd]ebugPublic/
18 | [Rr]elease/
19 | [Rr]eleases/
20 | x64/
21 | x86/
22 | bld/
23 | [Bb]in/
24 | [Oo]bj/
25 | [Ll]og/
26 |
27 | # Visual Studio 2015 cache/options directory
28 | .vs/
29 | # Uncomment if you have tasks that create the project's static files in wwwroot
30 | #wwwroot/
31 |
32 | # MSTest test Results
33 | [Tt]est[Rr]esult*/
34 | [Bb]uild[Ll]og.*
35 |
36 | # NUNIT
37 | *.VisualState.xml
38 | TestResult.xml
39 |
40 | # Build Results of an ATL Project
41 | [Dd]ebugPS/
42 | [Rr]eleasePS/
43 | dlldata.c
44 |
45 | # .NET Core
46 | project.lock.json
47 | project.fragment.lock.json
48 | artifacts/
49 | **/Properties/launchSettings.json
50 |
51 | *_i.c
52 | *_p.c
53 | *_i.h
54 | *.ilk
55 | *.meta
56 | *.obj
57 | *.pch
58 | *.pdb
59 | *.pgc
60 | *.pgd
61 | *.rsp
62 | *.sbr
63 | *.tlb
64 | *.tli
65 | *.tlh
66 | *.tmp
67 | *.tmp_proj
68 | *.log
69 | *.vspscc
70 | *.vssscc
71 | .builds
72 | *.pidb
73 | *.svclog
74 | *.scc
75 |
76 | # Chutzpah Test files
77 | _Chutzpah*
78 |
79 | # Visual C++ cache files
80 | ipch/
81 | *.aps
82 | *.ncb
83 | *.opendb
84 | *.opensdf
85 | *.sdf
86 | *.cachefile
87 | *.VC.db
88 | *.VC.VC.opendb
89 |
90 | # Visual Studio profiler
91 | *.psess
92 | *.vsp
93 | *.vspx
94 | *.sap
95 |
96 | # TFS 2012 Local Workspace
97 | $tf/
98 |
99 | # Guidance Automation Toolkit
100 | *.gpState
101 |
102 | # ReSharper is a .NET coding add-in
103 | _ReSharper*/
104 | *.[Rr]e[Ss]harper
105 | *.DotSettings.user
106 |
107 | # JustCode is a .NET coding add-in
108 | .JustCode
109 |
110 | # TeamCity is a build add-in
111 | _TeamCity*
112 |
113 | # DotCover is a Code Coverage Tool
114 | *.dotCover
115 |
116 | # Visual Studio code coverage results
117 | *.coverage
118 | *.coveragexml
119 |
120 | # NCrunch
121 | _NCrunch_*
122 | .*crunch*.local.xml
123 | nCrunchTemp_*
124 |
125 | # MightyMoose
126 | *.mm.*
127 | AutoTest.Net/
128 |
129 | # Web workbench (sass)
130 | .sass-cache/
131 |
132 | # Installshield output folder
133 | [Ee]xpress/
134 |
135 | # DocProject is a documentation generator add-in
136 | DocProject/buildhelp/
137 | DocProject/Help/*.HxT
138 | DocProject/Help/*.HxC
139 | DocProject/Help/*.hhc
140 | DocProject/Help/*.hhk
141 | DocProject/Help/*.hhp
142 | DocProject/Help/Html2
143 | DocProject/Help/html
144 |
145 | # Click-Once directory
146 | publish/
147 |
148 | # Publish Web Output
149 | *.[Pp]ublish.xml
150 | *.azurePubxml
151 | # TODO: Comment the next line if you want to checkin your web deploy settings
152 | # but database connection strings (with potential passwords) will be unencrypted
153 | *.pubxml
154 | *.publishproj
155 |
156 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
157 | # checkin your Azure Web App publish settings, but sensitive information contained
158 | # in these scripts will be unencrypted
159 | PublishScripts/
160 |
161 | # NuGet Packages
162 | *.nupkg
163 | # The packages folder can be ignored because of Package Restore
164 | **/packages/*
165 | # except build/, which is used as an MSBuild target.
166 | !**/packages/build/
167 | # Uncomment if necessary however generally it will be regenerated when needed
168 | #!**/packages/repositories.config
169 | # NuGet v3's project.json files produces more ignorable files
170 | *.nuget.props
171 | *.nuget.targets
172 |
173 | # Microsoft Azure Build Output
174 | csx/
175 | *.build.csdef
176 |
177 | # Microsoft Azure Emulator
178 | ecf/
179 | rcf/
180 |
181 | # Windows Store app package directories and files
182 | AppPackages/
183 | BundleArtifacts/
184 | Package.StoreAssociation.xml
185 | _pkginfo.txt
186 |
187 | # Visual Studio cache files
188 | # files ending in .cache can be ignored
189 | *.[Cc]ache
190 | # but keep track of directories ending in .cache
191 | !*.[Cc]ache/
192 |
193 | # Others
194 | ClientBin/
195 | ~$*
196 | *~
197 | *.dbmdl
198 | *.dbproj.schemaview
199 | *.jfm
200 | *.pfx
201 | *.publishsettings
202 | orleans.codegen.cs
203 |
204 | # Since there are multiple workflows, uncomment next line to ignore bower_components
205 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
206 | #bower_components/
207 |
208 | # RIA/Silverlight projects
209 | Generated_Code/
210 |
211 | # Backup & report files from converting an old project file
212 | # to a newer Visual Studio version. Backup files are not needed,
213 | # because we have git ;-)
214 | _UpgradeReport_Files/
215 | Backup*/
216 | UpgradeLog*.XML
217 | UpgradeLog*.htm
218 |
219 | # SQL Server files
220 | *.mdf
221 | *.ldf
222 | *.ndf
223 |
224 | # Business Intelligence projects
225 | *.rdl.data
226 | *.bim.layout
227 | *.bim_*.settings
228 |
229 | # Microsoft Fakes
230 | FakesAssemblies/
231 |
232 | # GhostDoc plugin setting file
233 | *.GhostDoc.xml
234 |
235 | # Node.js Tools for Visual Studio
236 | .ntvs_analysis.dat
237 | node_modules/
238 |
239 | # Typescript v1 declaration files
240 | typings/
241 |
242 | # Visual Studio 6 build log
243 | *.plg
244 |
245 | # Visual Studio 6 workspace options file
246 | *.opt
247 |
248 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
249 | *.vbw
250 |
251 | # Visual Studio LightSwitch build output
252 | **/*.HTMLClient/GeneratedArtifacts
253 | **/*.DesktopClient/GeneratedArtifacts
254 | **/*.DesktopClient/ModelManifest.xml
255 | **/*.Server/GeneratedArtifacts
256 | **/*.Server/ModelManifest.xml
257 | _Pvt_Extensions
258 |
259 | # Paket dependency manager
260 | .paket/paket.exe
261 | paket-files/
262 |
263 | # FAKE - F# Make
264 | .fake/
265 |
266 | # JetBrains Rider
267 | .idea/
268 | *.sln.iml
269 |
270 | # CodeRush
271 | .cr/
272 |
273 | # Python Tools for Visual Studio (PTVS)
274 | __pycache__/
275 | *.pyc
276 |
277 | # Cake - Uncomment if you are using it
278 | # tools/**
279 | # !tools/packages.config
280 |
281 | # Telerik's JustMock configuration file
282 | *.jmconfig
283 |
284 | # BizTalk build output
285 | *.btp.cs
286 | *.btm.cs
287 | *.odx.cs
288 | *.xsd.cs
289 |
--------------------------------------------------------------------------------
/CoreStarter/CoreStarter.Api/Startup.cs:
--------------------------------------------------------------------------------
1 | using CoreStarter.Api.Configuration;
2 | using CoreStarter.Api.Middleware;
3 | using CoreStarter.Api.Observability;
4 | using CoreStarter.Api.Services;
5 | using Microsoft.AspNetCore.Builder;
6 | using Microsoft.AspNetCore.Cors.Infrastructure;
7 | using Microsoft.AspNetCore.Diagnostics;
8 | using Microsoft.AspNetCore.Diagnostics.HealthChecks;
9 | using Microsoft.AspNetCore.Hosting;
10 | using Microsoft.AspNetCore.Http;
11 | using Microsoft.AspNetCore.Mvc;
12 | using Microsoft.Extensions.Configuration;
13 | using Microsoft.Extensions.DependencyInjection;
14 | using Microsoft.Extensions.Logging;
15 | using Microsoft.OpenApi.Models;
16 | using Newtonsoft.Json.Serialization;
17 | using System;
18 | using System.Buffers;
19 | using System.IO;
20 | using System.Text;
21 | using System.Text.Json;
22 |
23 | namespace CoreStarter.Api
24 | {
25 | ///
26 | /// OWIN configuration and setup.
27 | ///
28 | public class Startup
29 | {
30 | private readonly IWebHostEnvironment _env;
31 |
32 | ///
33 | /// Initializes new instance of
34 | ///
35 | ///
36 | public Startup(IWebHostEnvironment env)
37 | {
38 | _env = env;
39 | }
40 |
41 | ///
42 | ///
43 | ///
44 | ///
45 | ///
46 | public void ConfigureServices(IServiceCollection services)
47 | {
48 | IConfigurationRoot configuration =
49 | new ConfigurationBuilder()
50 | .SetBasePath(_env.ContentRootPath)
51 | .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
52 | .AddJsonFile($"appsettings.{_env.EnvironmentName}.json", optional: true, reloadOnChange: true)
53 | .AddEnvironmentVariables()
54 | .Build();
55 |
56 | services.Configure(configuration.GetSection("ConnectionStrings"));
57 |
58 | services.AddLogging(x => x.AddConsole());
59 |
60 | services.AddHealthChecks().AddCheck("basic", tags: new[] { "ready", "live" });
61 |
62 | // Register your types
63 | services.AddTransient();
64 |
65 | // Refer to this article if you require more information on CORS
66 | // https://docs.microsoft.com/en-us/aspnet/core/security/cors
67 | void build(CorsPolicyBuilder b) { b.WithOrigins("*").WithMethods("*").WithHeaders("*").Build(); };
68 | services.AddCors(options => { options.AddPolicy("AllowAllPolicy", build); });
69 |
70 | services
71 | .AddMvc(
72 | options =>
73 | {
74 | // Refer to this article for more details on how to properly set the caching for your needs
75 | // https://docs.microsoft.com/en-us/aspnet/core/performance/caching/response
76 | options.CacheProfiles.Add(
77 | "default",
78 | new CacheProfile
79 | {
80 | Duration = 600,
81 | Location = ResponseCacheLocation.None
82 | });
83 | })
84 | .AddNewtonsoftJson(options =>
85 | {
86 | options.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented;
87 | options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
88 | options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
89 | });
90 |
91 | services.AddResponseCaching(options =>
92 | {
93 | options.MaximumBodySize = 2048;
94 | options.UseCaseSensitivePaths = false;
95 | });
96 |
97 | services.AddSwaggerGen(c =>
98 | {
99 | c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
100 | });
101 | }
102 |
103 | ///
104 | ///
105 | ///
106 | ///
107 | public void Configure(IApplicationBuilder app)
108 | {
109 | app.UseExceptionHandler(builder =>
110 | {
111 | builder.Run(
112 | async context =>
113 | {
114 |
115 | var loggerFactory = context.RequestServices.GetService();
116 | var exceptionHandler = context.Features.Get();
117 | loggerFactory.CreateLogger("ExceptionHandler").LogError(exceptionHandler.Error, exceptionHandler.Error.Message, null);
118 | });
119 | });
120 |
121 | app.UseCors("AllowAllPolicy");
122 |
123 | app.UseMiddleware();
124 | app.UseResponseCaching();
125 |
126 | app.Use(async (context, next) =>
127 | {
128 | context.Response.GetTypedHeaders().CacheControl =
129 | new Microsoft.Net.Http.Headers.CacheControlHeaderValue()
130 | {
131 | Public = true,
132 | MaxAge = TimeSpan.FromSeconds(10)
133 | };
134 |
135 | context.Response.Headers[Microsoft.Net.Http.Headers.HeaderNames.Vary] = new[] { "Accept-Encoding" };
136 |
137 | await next();
138 | });
139 |
140 | app.UseRouting();
141 |
142 | app.UseEndpoints(endpoints =>
143 | {
144 | endpoints.MapControllers();
145 |
146 | endpoints.MapHealthChecks("/health/ready", new HealthCheckOptions()
147 | {
148 | AllowCachingResponses = false,
149 | Predicate = (check) => check.Tags.Contains("ready"),
150 | ResponseWriter = HealthReportWriter.WriteResponse
151 | });
152 |
153 | endpoints.MapHealthChecks("/health/live", new HealthCheckOptions()
154 | {
155 | AllowCachingResponses = false,
156 | Predicate = (check) => check.Tags.Contains("ready"),
157 | ResponseWriter = HealthReportWriter.WriteResponse
158 | });
159 | });
160 |
161 | app.UseSwagger();
162 | app.UseSwaggerUI(c =>
163 | {
164 | c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
165 | });
166 | }
167 | }
168 | }
169 |
--------------------------------------------------------------------------------