Skip to content

Commit 11d4b31

Browse files
committed
model resolvers, files dictionary result, tests
1 parent d53c082 commit 11d4b31

26 files changed

+440
-70
lines changed

src/NetCoreStack.Proxy/Binders/BodyContentBinder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ protected virtual StringContent SerializeToString(object value)
3232
return new StringContent(JsonConvert.SerializeObject(value), Encoding.UTF8, "application/json");
3333
}
3434

35-
protected virtual MultipartFormDataContent GetMultipartFormDataContent(ResolvedContentResult contentResult)
35+
protected virtual MultipartFormDataContent GetMultipartFormDataContent(ModelDictionaryResult contentResult)
3636
{
3737
MultipartFormDataContent multipartFormDataContent = new MultipartFormDataContent();
3838
foreach (KeyValuePair<string, string> entry in contentResult.Dictionary)

src/NetCoreStack.Proxy/Binders/ContentBinderFactory.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,6 @@ namespace NetCoreStack.Proxy
55
{
66
public static class ContentBinderFactory
77
{
8-
static ContentBinderFactory()
9-
{
10-
11-
}
12-
138
public static IContentModelBinder GetContentModelBinder(HttpMethod httpMethod)
149
{
1510
if (httpMethod == HttpMethod.Get)
Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,21 @@
1-
namespace NetCoreStack.Proxy
1+
using NetCoreStack.Proxy.Extensions;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Net.Http;
5+
6+
namespace NetCoreStack.Proxy
27
{
38
public class HttpDeleteContentBinder : ContentModelBinder
49
{
10+
HttpMethod HttpMethod => HttpMethod.Delete;
11+
512
public override void BindContent(ContentModelBindingContext bindingContext)
613
{
14+
ModelDictionaryResult result = bindingContext.GetResolvedContentResult();
15+
List<string> keys = result.Dictionary.Keys.ToList();
16+
EnsureTemplate(bindingContext.MethodMarkerTemplate, bindingContext.Args, bindingContext.UriDefinition, result.Dictionary, keys);
17+
18+
bindingContext.TryUpdateUri(result.Dictionary);
719
}
820
}
921
}

src/NetCoreStack.Proxy/Binders/HttpGetContentBinder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public class HttpGetContentBinder : ContentModelBinder
1111

1212
public override void BindContent(ContentModelBindingContext bindingContext)
1313
{
14-
ResolvedContentResult result = bindingContext.GetResolvedContentResult();
14+
ModelDictionaryResult result = bindingContext.GetResolvedContentResult();
1515
List<string> keys = result.Dictionary.Keys.ToList();
1616
EnsureTemplate(bindingContext.MethodMarkerTemplate, bindingContext.Args, bindingContext.UriDefinition, result.Dictionary, keys);
1717

src/NetCoreStack.Proxy/Binders/HttpPostContentBinder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ public override void BindContent(ContentModelBindingContext bindingContext)
1212
var isMultiPartFormData = bindingContext.IsMultiPartFormData;
1313
if (isMultiPartFormData)
1414
{
15-
ResolvedContentResult result = bindingContext.GetResolvedContentResult();
15+
ModelDictionaryResult result = bindingContext.GetResolvedContentResult();
1616
var content = GetMultipartFormDataContent(result);
1717
bindingContext.ContentResult = ContentModelBindingResult.Success(content);
1818
return;

src/NetCoreStack.Proxy/Binders/HttpPutContentBinder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ public class HttpPutContentBinder : BodyContentBinder
1212

1313
public override void BindContent(ContentModelBindingContext bindingContext)
1414
{
15-
ResolvedContentResult result = bindingContext.GetResolvedContentResult();
15+
ModelDictionaryResult result = bindingContext.GetResolvedContentResult();
1616
List<string> keys = result.Dictionary.Keys.ToList();
1717
EnsureTemplate(bindingContext.MethodMarkerTemplate, bindingContext.Args, bindingContext.UriDefinition, result.Dictionary, keys);
1818
if (bindingContext.ArgsLength == 1)
Lines changed: 86 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System;
1+
using Microsoft.AspNetCore.Http;
2+
using System;
23
using System.Collections;
34
using System.Collections.Generic;
45
using System.Reflection;
@@ -14,6 +15,37 @@ public DefaultModelContentResolver(ProxyMetadataProvider metadataProvider)
1415
MetadataProvider = metadataProvider;
1516
}
1617

18+
private void TrySetFormFile(string prefix, ProxyModelMetadata modelMetadata, ModelDictionaryResult result, object value)
19+
{
20+
if (modelMetadata.IsNullableValueType)
21+
{
22+
// recall with prefix
23+
TrySetFormFile(prefix, modelMetadata.ElementType, result, value);
24+
return;
25+
}
26+
27+
if (modelMetadata.IsEnumerableType)
28+
{
29+
var enumerable = value as IEnumerable<IFormFile>;
30+
int index = 0;
31+
foreach (var item in enumerable)
32+
{
33+
if (item != null)
34+
{
35+
result.Files.Add($"{prefix}[{index}]", item);
36+
}
37+
index++;
38+
}
39+
40+
return;
41+
}
42+
43+
if (modelMetadata.IsFormFile)
44+
{
45+
result.Files.Add(prefix, (IFormFile)value);
46+
}
47+
}
48+
1749
private void SetSimpleEnumerable(string key, Dictionary<string, string> dictionary, object value)
1850
{
1951
var enumerable = value as IEnumerable;
@@ -31,8 +63,8 @@ private void SetSimpleEnumerable(string key, Dictionary<string, string> dictiona
3163
private void TrySetSystemObjectValue(string key,
3264
PropertyInfo propertyInfo,
3365
string propertyName,
34-
Type containerType,
35-
Dictionary<string, string> dictionary,
66+
Type containerType,
67+
ModelDictionaryResult result,
3668
object value)
3769
{
3870
var objModelMetadata = new ProxyModelMetadata(propertyInfo,
@@ -43,29 +75,37 @@ private void TrySetSystemObjectValue(string key,
4375

4476
if (objModelMetadata.IsSimpleType)
4577
{
46-
dictionary.Add(key, Convert.ToString(value));
78+
result.Dictionary.Add(key, Convert.ToString(value));
4779
return;
4880
}
4981

5082
if (objModelMetadata.IsEnumerableType)
5183
{
5284
if (objModelMetadata.ElementType.IsSimpleType)
5385
{
54-
SetSimpleEnumerable(key, dictionary, value);
86+
SetSimpleEnumerable(key, result.Dictionary, value);
5587
}
5688
else
5789
{
58-
TrySetValueInner(key, objModelMetadata, dictionary, value);
90+
TrySetValueInner(key, objModelMetadata, result, value);
5991
}
6092

6193
return;
6294
}
6395

6496
// Anonymous object resolver
65-
ResolveInternal(objModelMetadata, dictionary, value, key);
97+
for (int i = 0; i < objModelMetadata.Properties.Count; i++)
98+
{
99+
var modelMetadata = objModelMetadata.Properties[i];
100+
var v = modelMetadata.PropertyInfo.GetValue(value);
101+
if (v != null)
102+
{
103+
ResolveInternal(modelMetadata, result, v, isTopLevelObject: false, prefix: key);
104+
}
105+
}
66106
}
67107

68-
private void TrySetValueInner(string key, ProxyModelMetadata modelMetadata, Dictionary<string, string> dictionary, object value)
108+
private void TrySetValueInner(string key, ProxyModelMetadata modelMetadata, ModelDictionaryResult result, object value)
69109
{
70110
var count = modelMetadata.ElementType.PropertiesCount;
71111
var elementProperties = modelMetadata.ElementType.Properties;
@@ -80,72 +120,75 @@ private void TrySetValueInner(string key, ProxyModelMetadata modelMetadata, Dict
80120
{
81121
var propKey = $"{key}[{index}]";
82122
var propValue = propertyInfo?.GetValue(v);
83-
ResolveInternal(elementModelMetadata, dictionary, propValue, propKey);
123+
ResolveInternal(elementModelMetadata, result, propValue, isTopLevelObject:false, prefix: propKey);
84124
index++;
85125
}
86126
}
87127
}
88128
}
89129

90-
private void TrySetValue(string prefix, ProxyModelMetadata modelMetadata, Dictionary<string, string> dictionary, object value)
130+
private void TrySetValue(string prefix, ProxyModelMetadata modelMetadata, ModelDictionaryResult result, object value)
91131
{
92-
var key = modelMetadata.PropertyName;
93-
if (!string.IsNullOrEmpty(prefix))
94-
key = $"{prefix}.{key}";
132+
var key = prefix;
95133

96134
if (modelMetadata.IsNullableValueType)
97135
{
98136
// recall with prefix
99-
TrySetValue(prefix, modelMetadata.ElementType, dictionary, value);
137+
TrySetValue(prefix, modelMetadata.ElementType, result, value);
100138
return;
101139
}
102140

103141
if (modelMetadata.IsSimpleType)
104142
{
105-
dictionary.Add(key, Convert.ToString(value));
143+
result.Dictionary.Add(key, Convert.ToString(value));
106144
return;
107145
}
108146

109-
if (modelMetadata.IsFormFile)
110-
{
111-
// TODO Gencebay
112-
}
113-
114147
if (modelMetadata.IsEnumerableType)
115148
{
116149
if (modelMetadata.ElementType.IsSimpleType)
117150
{
118-
SetSimpleEnumerable(key, dictionary, value);
151+
SetSimpleEnumerable(key, result.Dictionary, value);
119152
}
120153
else if(modelMetadata.ElementType.IsSystemObject)
121154
{
122155
TrySetSystemObjectValue(key,
123156
modelMetadata.ElementType.PropertyInfo,
124157
modelMetadata.ElementType.PropertyName,
125158
modelMetadata.ContainerType,
126-
dictionary, value);
159+
result, value);
127160
}
128161
else
129162
{
130-
TrySetValueInner(key, modelMetadata, dictionary, value);
163+
TrySetValueInner(key, modelMetadata, result, value);
131164
}
132165

133166
return;
134167
}
135-
136-
// If typeof(object)
168+
137169
if (modelMetadata.IsSystemObject)
138170
{
139-
TrySetSystemObjectValue(key, modelMetadata.PropertyInfo, modelMetadata.PropertyName, modelMetadata.ContainerType, dictionary, value);
171+
TrySetSystemObjectValue(key, modelMetadata.PropertyInfo, modelMetadata.PropertyName, modelMetadata.ContainerType, result, value);
140172
}
141173
}
142174

143-
private void ResolveInternal(ProxyModelMetadata modelMetadata, Dictionary<string, string> dictionary, object value, string prefix = "")
175+
private void ResolveInternal(ProxyModelMetadata modelMetadata, ModelDictionaryResult result, object value, bool isTopLevelObject = false, string prefix = "")
144176
{
177+
var key = isTopLevelObject ? string.Empty : modelMetadata.PropertyName;
178+
if (!string.IsNullOrEmpty(prefix))
179+
key = $"{prefix}.{key}";
180+
181+
if (modelMetadata.IsFormFile || (modelMetadata.IsEnumerableType && modelMetadata.ElementType.IsFormFile))
182+
{
183+
TrySetFormFile(key, modelMetadata, result, value);
184+
return;
185+
}
186+
187+
var dictionary = result.Dictionary;
145188
var count = modelMetadata.PropertiesCount;
146189
if (count == 0)
147190
{
148-
TrySetValue(prefix, modelMetadata, dictionary, value);
191+
TrySetValue(key, modelMetadata, result, value);
149192
return;
150193
}
151194

@@ -154,44 +197,41 @@ private void ResolveInternal(ProxyModelMetadata modelMetadata, Dictionary<string
154197
var metadata = modelMetadata.Properties[i];
155198
if (metadata.ContainerType != null)
156199
{
157-
var parent = prefix;
158-
if (!metadata.IsSimpleType &&
159-
!metadata.IsEnumerableType &&
160-
!metadata.IsNullableValueType &&
161-
!metadata.IsSystemObject)
162-
{
163-
parent = !string.IsNullOrEmpty(prefix) ? $"{prefix}.{metadata.PropertyName}" : metadata.PropertyName;
164-
}
165-
166200
if (value != null)
167201
{
168202
var v = metadata.PropertyInfo.GetValue(value);
169203
if (v != null)
170204
{
171-
ResolveInternal(metadata, dictionary, v, parent);
205+
ResolveInternal(metadata, result, v, isTopLevelObject: false, prefix: key);
172206
}
173207
}
174208
}
175209
else
176210
{
177-
ResolveInternal(metadata, dictionary, value);
211+
ResolveInternal(metadata, result, value);
178212
}
179213
}
180214
}
181215

182216
// Per request parameter context resolver
183-
public ResolvedContentResult Resolve(List<ProxyModelMetadata> parameters, object[] args)
217+
public ModelDictionaryResult Resolve(List<ProxyModelMetadata> parameters, object[] args)
184218
{
185-
var dictionary = new Dictionary<string, string>(StringComparer.Ordinal);
186-
var count = parameters.Count;
219+
var result = new ModelDictionaryResult(new Dictionary<string, string>(StringComparer.Ordinal),
220+
new Dictionary<string, IFormFile>(StringComparer.Ordinal));
187221

188-
for (int i = 0; i < count; i++)
222+
for (int i = 0; i < parameters.Count; i++)
189223
{
190224
var modelMetadata = parameters[i];
191-
ResolveInternal(modelMetadata, dictionary, args[i]);
225+
string prefix = string.Empty;
226+
if (modelMetadata.ContainerType == null && !string.IsNullOrEmpty(modelMetadata.PropertyName))
227+
{
228+
prefix = modelMetadata.PropertyName;
229+
}
230+
231+
ResolveInternal(modelMetadata, result, args[i], isTopLevelObject: true, prefix: prefix);
192232
}
193233

194-
return new ResolvedContentResult(dictionary);
234+
return result;
195235
}
196236
}
197-
}
237+
}

src/NetCoreStack.Proxy/Extensions/ContentModelBindingContextExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ namespace NetCoreStack.Proxy.Extensions
66
{
77
public static class ContentModelBindingContextExtensions
88
{
9-
public static ResolvedContentResult GetResolvedContentResult(this ContentModelBindingContext bindingContext)
9+
public static ModelDictionaryResult GetResolvedContentResult(this ContentModelBindingContext bindingContext)
1010
{
1111
return bindingContext.ModelContentResolver.Resolve(bindingContext.Parameters, bindingContext.Args);
1212
}

src/NetCoreStack.Proxy/Extensions/ServiceCollectionExtensions.cs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,23 +50,28 @@ public static void AddNetCoreProxy(this IServiceCollection services,
5050

5151
services.TryAddSingleton<RoundRobinManager>();
5252

53-
var proxyBuilderOptions = new ProxyBuilderOptions();
54-
setup?.Invoke(proxyBuilderOptions);
55-
foreach (var item in proxyBuilderOptions.ProxyList)
53+
var options = new ProxyBuilderOptions();
54+
options.ModelResolvers.Add(new SimpleModelResolver());
55+
options.ModelResolvers.Add(new EnumerableModelResolver());
56+
options.ModelResolvers.Add(new ComplexModelResolver());
57+
options.ModelResolvers.Add(new SystemObjectModelResolver());
58+
options.ModelResolvers.Add(new FormFileModelResolver());
59+
setup?.Invoke(options);
60+
foreach (var item in options.ProxyList)
5661
{
5762
var type = item.GetTypeInfo().AsType();
5863
var genericRegistry = registryDelegate.MakeGenericMethod(type);
5964
genericRegistry.Invoke(null, new object[] { services });
6065
}
6166

62-
if (proxyBuilderOptions.ProxyContextFilter != null)
67+
if (options.ProxyContextFilter != null)
6368
{
64-
services.TryAdd(ServiceDescriptor.Scoped(typeof(IProxyContextFilter), proxyBuilderOptions.ProxyContextFilter));
69+
services.TryAdd(ServiceDescriptor.Scoped(typeof(IProxyContextFilter), options.ProxyContextFilter));
6570
}
6671

67-
var headerValues = new DefaultHeaderValues { Headers = proxyBuilderOptions.DefaultHeaders };
72+
var headerValues = new DefaultHeaderValues { Headers = options.DefaultHeaders };
6873
services.AddSingleton(Options.Create(headerValues));
69-
services.AddSingleton(proxyBuilderOptions);
74+
services.AddSingleton(options);
7075
}
7176

7277
internal static void RegisterProxy<TProxy>(IServiceCollection services) where TProxy : IApiContract

src/NetCoreStack.Proxy/Interfaces/IModelContentResolver.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ namespace NetCoreStack.Proxy
44
{
55
public interface IModelContentResolver
66
{
7-
ResolvedContentResult Resolve(List<ProxyModelMetadata> parameters, object[] args);
7+
ModelDictionaryResult Resolve(List<ProxyModelMetadata> parameters, object[] args);
88
}
99
}

0 commit comments

Comments
 (0)