Skip to content

Commit ff045f3

Browse files
authored
Merge pull request #1 from NetCoreStack/test
Full improvement, http content native supports, performance, multipartformdata, binders
2 parents bfdf626 + 4d2adc6 commit ff045f3

File tree

221 files changed

+3649
-31038
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

221 files changed

+3649
-31038
lines changed

NetCoreStack.Proxy.sln

Lines changed: 10 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
Microsoft Visual Studio Solution File, Format Version 12.00
33
# Visual Studio 15
4-
VisualStudioVersion = 15.0.26403.7
4+
VisualStudioVersion = 15.0.27130.2020
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{9754E8AD-F544-4C44-939D-95164DC29671}"
77
EndProject
@@ -19,15 +19,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetCoreStack.Proxy.Tests",
1919
EndProject
2020
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetCoreStack.Proxy.Test.Contracts", "test\NetCoreStack.Proxy.Test.Contracts\NetCoreStack.Proxy.Test.Contracts.csproj", "{65CF1A10-0E97-479E-9D8A-2C7741BF608C}"
2121
EndProject
22-
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetCoreStack.Api.Hosting", "test\NetCoreStack.Api.Hosting\NetCoreStack.Api.Hosting.csproj", "{8BD1F907-921F-44BD-A06A-C77F58F82B8F}"
23-
EndProject
24-
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetCoreStack.WebClient.Hosting", "test\NetCoreStack.WebClient.Hosting\NetCoreStack.WebClient.Hosting.csproj", "{7C186FB4-EA93-470F-9552-CDF2A0C5F20D}"
25-
EndProject
26-
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetCoreStack.Domain.Contracts", "test\NetCoreStack.Domain.Contracts\NetCoreStack.Domain.Contracts.csproj", "{E0D0DB64-3A8F-46A8-95BE-C2A559041BD8}"
27-
EndProject
28-
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetCoreStack.Proxy.ServerApp", "test\NetCoreStack.Proxy.ServerApp\NetCoreStack.Proxy.ServerApp.csproj", "{0847A55D-050B-4F99-A694-6D3F640B99EE}"
29-
EndProject
30-
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetCoreStack.Proxy.WebClient", "test\NetCoreStack.Proxy.WebClient\NetCoreStack.Proxy.WebClient.csproj", "{EE267E71-A7A8-44C2-B0A1-7E093D702A5F}"
22+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetCoreStack.Proxy.Mvc.Hosting", "test\NetCoreStack.Proxy.Mvc.Hosting\NetCoreStack.Proxy.Mvc.Hosting.csproj", "{76748B9C-AC8D-49C2-BE89-F427EC4BD20A}"
3123
EndProject
3224
Global
3325
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -47,26 +39,10 @@ Global
4739
{65CF1A10-0E97-479E-9D8A-2C7741BF608C}.Debug|Any CPU.Build.0 = Debug|Any CPU
4840
{65CF1A10-0E97-479E-9D8A-2C7741BF608C}.Release|Any CPU.ActiveCfg = Release|Any CPU
4941
{65CF1A10-0E97-479E-9D8A-2C7741BF608C}.Release|Any CPU.Build.0 = Release|Any CPU
50-
{8BD1F907-921F-44BD-A06A-C77F58F82B8F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
51-
{8BD1F907-921F-44BD-A06A-C77F58F82B8F}.Debug|Any CPU.Build.0 = Debug|Any CPU
52-
{8BD1F907-921F-44BD-A06A-C77F58F82B8F}.Release|Any CPU.ActiveCfg = Release|Any CPU
53-
{8BD1F907-921F-44BD-A06A-C77F58F82B8F}.Release|Any CPU.Build.0 = Release|Any CPU
54-
{7C186FB4-EA93-470F-9552-CDF2A0C5F20D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
55-
{7C186FB4-EA93-470F-9552-CDF2A0C5F20D}.Debug|Any CPU.Build.0 = Debug|Any CPU
56-
{7C186FB4-EA93-470F-9552-CDF2A0C5F20D}.Release|Any CPU.ActiveCfg = Release|Any CPU
57-
{7C186FB4-EA93-470F-9552-CDF2A0C5F20D}.Release|Any CPU.Build.0 = Release|Any CPU
58-
{E0D0DB64-3A8F-46A8-95BE-C2A559041BD8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
59-
{E0D0DB64-3A8F-46A8-95BE-C2A559041BD8}.Debug|Any CPU.Build.0 = Debug|Any CPU
60-
{E0D0DB64-3A8F-46A8-95BE-C2A559041BD8}.Release|Any CPU.ActiveCfg = Release|Any CPU
61-
{E0D0DB64-3A8F-46A8-95BE-C2A559041BD8}.Release|Any CPU.Build.0 = Release|Any CPU
62-
{0847A55D-050B-4F99-A694-6D3F640B99EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
63-
{0847A55D-050B-4F99-A694-6D3F640B99EE}.Debug|Any CPU.Build.0 = Debug|Any CPU
64-
{0847A55D-050B-4F99-A694-6D3F640B99EE}.Release|Any CPU.ActiveCfg = Release|Any CPU
65-
{0847A55D-050B-4F99-A694-6D3F640B99EE}.Release|Any CPU.Build.0 = Release|Any CPU
66-
{EE267E71-A7A8-44C2-B0A1-7E093D702A5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
67-
{EE267E71-A7A8-44C2-B0A1-7E093D702A5F}.Debug|Any CPU.Build.0 = Debug|Any CPU
68-
{EE267E71-A7A8-44C2-B0A1-7E093D702A5F}.Release|Any CPU.ActiveCfg = Release|Any CPU
69-
{EE267E71-A7A8-44C2-B0A1-7E093D702A5F}.Release|Any CPU.Build.0 = Release|Any CPU
42+
{76748B9C-AC8D-49C2-BE89-F427EC4BD20A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
43+
{76748B9C-AC8D-49C2-BE89-F427EC4BD20A}.Debug|Any CPU.Build.0 = Debug|Any CPU
44+
{76748B9C-AC8D-49C2-BE89-F427EC4BD20A}.Release|Any CPU.ActiveCfg = Release|Any CPU
45+
{76748B9C-AC8D-49C2-BE89-F427EC4BD20A}.Release|Any CPU.Build.0 = Release|Any CPU
7046
EndGlobalSection
7147
GlobalSection(SolutionProperties) = preSolution
7248
HideSolutionNode = FALSE
@@ -75,10 +51,9 @@ Global
7551
{80583F01-4793-4A33-9945-09397C1FCBA8} = {9754E8AD-F544-4C44-939D-95164DC29671}
7652
{00CEA1AF-05CC-4D39-9118-267683DEDCD1} = {E65756E9-13C3-4F24-8818-A6CD2E5E99D8}
7753
{65CF1A10-0E97-479E-9D8A-2C7741BF608C} = {E65756E9-13C3-4F24-8818-A6CD2E5E99D8}
78-
{8BD1F907-921F-44BD-A06A-C77F58F82B8F} = {E65756E9-13C3-4F24-8818-A6CD2E5E99D8}
79-
{7C186FB4-EA93-470F-9552-CDF2A0C5F20D} = {E65756E9-13C3-4F24-8818-A6CD2E5E99D8}
80-
{E0D0DB64-3A8F-46A8-95BE-C2A559041BD8} = {E65756E9-13C3-4F24-8818-A6CD2E5E99D8}
81-
{0847A55D-050B-4F99-A694-6D3F640B99EE} = {E65756E9-13C3-4F24-8818-A6CD2E5E99D8}
82-
{EE267E71-A7A8-44C2-B0A1-7E093D702A5F} = {E65756E9-13C3-4F24-8818-A6CD2E5E99D8}
54+
{76748B9C-AC8D-49C2-BE89-F427EC4BD20A} = {E65756E9-13C3-4F24-8818-A6CD2E5E99D8}
55+
EndGlobalSection
56+
GlobalSection(ExtensibilityGlobals) = postSolution
57+
SolutionGuid = {1E0B4A17-1DEE-4EDF-979F-4C1B12D95CC8}
8358
EndGlobalSection
8459
EndGlobal

README.md

Lines changed: 80 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,79 @@
1-
### Cross-Platform .NET Core HTTP Base Flying Proxy
1+
### Cross-Platform .NET Standard HTTP Base Flying Proxy
22

3-
This project is demonstrating manage and consume distributed API - Micro Service
4-
from different regions (endpoints) with ease.
3+
This project is demonstrating manage and consume distributed HTTP APIs and Micro Services
4+
from different regions (hosts) with ease.
55

6-
Flying Proxy allows the management of scalable applications, trigger many operations at the same time from your clients (SPA Web App or Mobile App) and
7-
start to consume your new resource (Backend Instance, APIs) that you can simply add.
6+
Flying Proxy allows the management of scalable applications, trigger many operations at the same time from your clients (Desktop, Web or Mobile App) and start to consume your new resources that you can simply add.
87

98
Flying Proxy aims to:
109
- Simple scalability
1110
- Effective and type-safe management of distributed architecture
1211
- Better performance
1312
- Maintainability
14-
- Provide updated API or SDK usage
1513

16-
[Latest release on Nuget](https://www.nuget.org/packages/NetCoreStack.Proxy/)
14+
## Sample Client (Web)
15+
16+
### Add ProxySettings section to the appsettings.json
17+
```json
18+
"ProxySettings": {
19+
"RegionKeys": {
20+
"Main": "http://localhost:5000/,http://localhost:5001/",
21+
"Authorization": "http://localhost:5002/",
22+
"Integrations": "http://localhost:5003/"
23+
}
24+
}
25+
```
26+
27+
### APIs Definitions
28+
```csharp
29+
// This API expose methods from localhost:5000 and localhost:5001 as configured on ProxySettings
30+
[ApiRoute("api/[controller]", regionKey: "Main")]
31+
public interface IGuidelineApi : IApiContract
32+
{
33+
[HttpHeaders("X-Method-Header: Some Value")]
34+
Task TaskOperation();
35+
36+
int PrimitiveReturn(int i, string s, long l, DateTime dt);
37+
38+
Task<IEnumerable<SampleModel>> GetEnumerableModels();
1739

18-
### Usage for Client Side
40+
Task GetWithReferenceType(SimpleModel model);
41+
42+
/// <summary>
43+
/// Default Content-Type is ModelAware.
44+
/// If the any parameter(s) has FormFile type property that will be MultipartFormData
45+
/// if not will be JSON
46+
/// </summary>
47+
/// <param name="model"></param>
48+
/// <returns></returns>
49+
[HttpPostMarker]
50+
Task TaskActionPost(ComplexTypeModel model);
51+
52+
[HttpPostMarker(ContentType = ContentType.MultipartFormData)]
53+
Task TaskActionBarMultipartFormData(Bar model);
54+
55+
[HttpPostMarker(ContentType = ContentType.Xml)]
56+
Task TaskActionBarSimpleXml(BarSimple model);
57+
58+
/// <summary>
59+
/// Template and parameter usage, key parameter will be part of the request Url
60+
/// and extracting it as api/guideline/kv/<key>
61+
/// </summary>
62+
/// <param name="key"></param>
63+
/// <param name="body"></param>
64+
/// <returns></returns>
65+
[HttpPutMarker(Template = "kv/{key}")]
66+
Task<bool> CreateOrUpdateKey(string key, Bar body);
67+
}
68+
```
1969

20-
#### Startup ConfigureServices
70+
### Startup ConfigureServices
2171
```csharp
2272
public void ConfigureServices(IServiceCollection services)
2373
{
24-
// Add NetCoreProxy Dependencies and Configuration
2574
services.AddNetCoreProxy(Configuration, options =>
2675
{
27-
// Register the API to use as Proxy
76+
// Register the API to use as a Proxy
2877
options.Register<IGuidelineApi>();
2978
});
3079

@@ -33,9 +82,9 @@ public void ConfigureServices(IServiceCollection services)
3382
}
3483
```
3584

36-
#### Example dependency injection
85+
### Proxy Usage (DI)
3786
```csharp
38-
public class TestController : Controller
87+
public class HomeController : Controller
3988
{
4089
private readonly IGuidelineApi _api;
4190

@@ -44,133 +93,47 @@ public class TestController : Controller
4493
_api = api;
4594
}
4695

47-
public async Task<IActionResult> GetPostsAsync()
96+
public async Task<IEnumerable<SampleModel>> GetModels()
4897
{
49-
var items = await _api.GetPostsAsync();
50-
return Json(items);
98+
var items = await _api.GetEnumerableModels();
99+
return items;
51100
}
52101
}
53102
```
54103

55-
#### Add configuration section to the appsettings.json file (or your configuration file)
56-
##### Example:
57-
```json
58-
"ProxySettings": {
59-
"RegionKeys": {
60-
"Main": "http://localhost:5000/,http://localhost:5001/",
61-
"Authorization": "http://localhost:5002/",
62-
"Integrations": "http://localhost:5003/"
63-
}
64-
}
65-
```
66-
67-
### Usage for Contracts (Common) Side
68-
69-
#### API Contract Definition (Default HttpMethod is HttpGet)
70-
```csharp
71-
// This API expose methods from localhost:5000 and localhost:5001 as configured on ProxySettings
72-
[ApiRoute("api/[controller]", regionKey: "Main")]
73-
public interface IGuidelineApi : IApiContract
74-
{
75-
void VoidOperation();
76-
77-
int PrimitiveReturn(int i, string s, long l, DateTime dt);
78-
79-
Task TaskOperation();
80-
81-
Task<IEnumerable<Post>> GetPostsAsync();
82-
83-
Task GetWithReferenceType(SimpleModel model);
84-
85-
[HttpPostMarker]
86-
Task TaskActionPost(SimpleModel model);
87-
}
88-
```
89-
90-
### Backend - Server Side
91-
#### API Contract Implementation
104+
## Sample Server
105+
### API Implementation
92106
```csharp
93107
[Route("api/[controller]")]
94108
public class GuidelineController : Controller, IGuidelineApi
95109
{
96-
private readonly ILoggerFactory _loggerFactory;
97-
98-
protected ILogger Logger { get; }
99-
100-
public GuidelineController(ILoggerFactory loggerFactory)
110+
[HttpGet(nameof(GetEnumerableModels))]
111+
public Task<IEnumerable<SampleModel>> GetEnumerableModels()
101112
{
102-
_loggerFactory = loggerFactory;
103-
Logger = _loggerFactory.CreateLogger<GuidelineController>();
104-
}
105-
106-
[HttpGet(nameof(GetPostsAsync))]
107-
public async Task<IEnumerable<Post>> GetPostsAsync()
108-
{
109-
var httpRequest = new HttpRequestMessage(HttpMethod.Get, new Uri("https://jsonplaceholder.typicode.com/posts"));
110-
var response = await Factory.Client.SendAsync(httpRequest);
111-
var content = await response.Content.ReadAsStringAsync();
112-
var items = JsonConvert.DeserializeObject<List<Post>>(content);
113-
Logger.LogDebug($"{nameof(GetPostsAsync)}, PostsCount:{items.Count}");
113+
...
114114
return items;
115115
}
116116

117-
[HttpGet(nameof(GetWithReferenceType))]
118-
public async Task GetWithReferenceType([FromQuery]SimpleModel model)
117+
[HttpPost(nameof(TaskComplexTypeModel))]
118+
public async Task TaskComplexTypeModel([FromBody]ComplexTypeModel model)
119119
{
120-
var serializedModel = JsonConvert.SerializeObject(model);
121-
Logger.LogDebug($"{nameof(GetWithReferenceType)}, Model: {serializedModel}");
122-
await Task.Delay(900);
120+
...
123121
}
124122

125-
[HttpGet(nameof(PrimitiveReturn))]
126-
public int PrimitiveReturn(int i, string s, long l, DateTime dt)
123+
[HttpPost(nameof(TaskActionBarMultipartFormData))]
124+
public Task TaskActionBarMultipartFormData(Bar model)
127125
{
128-
Logger.LogDebug($"{nameof(PrimitiveReturn)}, i:{i}, s:{s}, l:{l}, dt:{dt}");
129-
return i + 10;
130-
}
131-
132-
[HttpPost(nameof(TaskActionPost))]
133-
public async Task TaskActionPost([FromBody]SimpleModel model)
134-
{
135-
var serializedModel = JsonConvert.SerializeObject(model);
136-
Logger.LogDebug($"{nameof(TaskActionPost)}, Model: {serializedModel}");
137-
await Task.Delay(900);
138-
}
139-
140-
[HttpGet(nameof(TaskOperation))]
141-
public async Task TaskOperation()
142-
{
143-
await Task.Delay(2000);
144-
Logger.LogDebug($"{nameof(TaskOperation)}, long running process completed!");
145-
}
146-
147-
[HttpGet(nameof(VoidOperation))]
148-
public void VoidOperation()
149-
{
150-
var str = "Hello World!";
151-
Logger.LogDebug($"{nameof(VoidOperation)}, {str}");
126+
...
152127
}
153128
}
154129
```
155130

156-
#### Multipart form data:
157-
Proxy sends all POST methods as JSON but if the method parameter model contains IFormFile type property it converts the content-type to multipart/form-data. In this case, use any model to POST multipart/form-data to API without [FromBody] attribute on action parameter. For example:
158-
159-
```csharp
160-
// Interface
161-
[HttpPostMarker]
162-
Task<AlbumViewModel> SaveAlbumSubmitAsync(AlbumViewModelSubmit model)
163-
```
164-
165-
```csharp
166-
// API Controller
167-
[HttpPost(nameof(SaveAlbumSubmitAsync))]
168-
public async Task<AlbumViewModel> SaveAlbumSubmitAsync(AlbumViewModelSubmit model)
169-
```
170-
171-
131+
### Unit Testing
132+
Use [HttpLive](https://github.com/gencebay/httplive)
172133

134+
httplive -p 5003,5004 -d test/NetCoreStack.Proxy.Tests/httplive.db
173135

136+
[Latest release on Nuget](https://www.nuget.org/packages/NetCoreStack.Proxy/)
174137

175138
### Prerequisites
176139
> [ASP.NET Core](https://github.com/aspnet/Home)

0 commit comments

Comments
 (0)