forked from khellang/Middleware
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathProgram.cs
148 lines (122 loc) · 5.11 KB
/
Program.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
namespace Hellang.Middleware.ProblemDetails.Sample
{
public class Startup : StartupBase
{
public Startup(IHostingEnvironment environment)
{
Environment = environment;
}
private IHostingEnvironment Environment { get; }
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args)
{
return WebHost.CreateDefaultBuilder(args)
.UseEnvironment(EnvironmentName.Development)
//.UseEnvironment(EnvironmentName.Production) // Uncomment to remove exception details from responses.
.UseStartup<Startup>();
}
public override void ConfigureServices(IServiceCollection services)
{
services.AddProblemDetails(ConfigureProblemDetails).AddMvcCore().AddJsonFormatters(x => x.NullValueHandling = NullValueHandling.Ignore);
}
public override void Configure(IApplicationBuilder app)
{
app.UseProblemDetails();
app.Use(CustomMiddleware);
app.UseMvc();
}
private void ConfigureProblemDetails(ProblemDetailsOptions options)
{
// This is the default behavior; only include exception details in a development environment.
options.IncludeExceptionDetails = ctx => Environment.IsDevelopment();
// This will map NotImplementedException to the 501 Not Implemented status code.
options.Map<NotImplementedException>(ex => new ExceptionProblemDetails(ex, StatusCodes.Status501NotImplemented));
// This will map HttpRequestException to the 503 Service Unavailable status code.
options.Map<HttpRequestException>(ex => new ExceptionProblemDetails(ex, StatusCodes.Status503ServiceUnavailable));
// Because exceptions are handled polymorphically, this will act as a "catch all" mapping, which is why it's added last.
// If an exception other than NotImplementedException and HttpRequestException is thrown, this will handle it.
options.Map<Exception>(ex => new ExceptionProblemDetails(ex, StatusCodes.Status500InternalServerError));
}
private Task CustomMiddleware(HttpContext context, Func<Task> next)
{
if (context.Request.Path.StartsWithSegments("/middleware", out _, out var remaining))
{
if (remaining.StartsWithSegments("/error"))
{
throw new Exception("This is an exception thrown from middleware.");
}
if (remaining.StartsWithSegments("/status", out _, out remaining))
{
var statusCodeString = remaining.Value.Trim('/');
if (int.TryParse(statusCodeString, out var statusCode))
{
context.Response.StatusCode = statusCode;
return Task.CompletedTask;
}
}
}
return next();
}
}
[Route("mvc")]
public class MvcController : ControllerBase
{
[HttpGet("status/{statusCode}")]
public IActionResult Status([FromRoute] int statusCode)
{
return StatusCode(statusCode);
}
[HttpGet("error")]
public IActionResult Error()
{
throw new NotImplementedException("This is an exception thrown from an MVC controller.");
}
[HttpGet("error/details")]
public IActionResult ErrorDetails()
{
ModelState.AddModelError("someProperty", "This property failed validation.");
var validation = new ValidationProblemDetails(ModelState)
{
Status = StatusCodes.Status422UnprocessableEntity
};
throw new ProblemDetailsException(validation);
}
[HttpGet("result")]
public IActionResult Result()
{
var problem = new OutOfCreditProblemDetails
{
Type = "https://example.com/probs/out-of-credit",
Title = "You do not have enough credit.",
Detail = "Your current balance is 30, but that costs 50.",
Instance = "/account/12345/msgs/abc",
Balance = 30.0m,
Accounts = { "/account/12345","/account/67890" }
};
return BadRequest(problem);
}
}
public class OutOfCreditProblemDetails : Microsoft.AspNetCore.Mvc.ProblemDetails
{
public OutOfCreditProblemDetails()
{
Accounts = new List<string>();
}
public decimal Balance { get; set; }
public ICollection<string> Accounts { get; }
}
}