Skip to content

Commit a3a28fa

Browse files
committed
Builds, but there are issues in ODataUnitTests.tpl and three unit tests fail.
1 parent b0c2122 commit a3a28fa

File tree

95 files changed

+11847
-1106
lines changed

Some content is hidden

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

95 files changed

+11847
-1106
lines changed

Harmony.OData/Harmony.OData.synproj

+4
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@
4747
<PackageReference Include="Microsoft.OData.Core">
4848
<Version>7.10.0</Version>
4949
</PackageReference>
50+
<PackageReference Include="Swashbuckle.AspNetCore">
51+
<Version>6.4.0</Version>
52+
</PackageReference>
5053
<PackageReference Include="Synergex.SynergyDE.Build">
5154
<Version>22.8.1287</Version>
5255
</PackageReference>
@@ -74,6 +77,7 @@
7477
<Compile Include="MethodSecurityAttribute.dbl" />
7578
<Compile Include="ODataConventionModelBuilderExtensions.dbl" />
7679
<Compile Include="CallableMethodConfigurationAttribute.dbl" />
80+
<Compile Include="ODataParametersSwaggerDefinition.dbl" />
7781
<Compile Include="PathTemplateHandler.dbl" />
7882
<Compile Include="RefEdmModel.dbl" />
7983
<Compile Include="UnqualifiedAltKeyUriResolver.dbl" />
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
2+
import Microsoft.AspNetCore.OData.Query
3+
import Microsoft.AspNetCore.OData.Results
4+
import Microsoft.AspNetCore.Mvc.ApiExplorer
5+
import Microsoft.OpenApi.Models
6+
import Swashbuckle.AspNetCore.SwaggerGen
7+
import System
8+
import System.Collections.Generic
9+
import System.Linq
10+
11+
namespace Harmony.OData
12+
13+
;;; <summary>
14+
;;; This filter adds OData query capabilities such as $select, $filter
15+
;;; $orderby, $top and $skip to the "try it out" panes of the swagger docs.
16+
;;; </summary>
17+
public class ODataParametersSwaggerDefinition implements IOperationFilter
18+
19+
public method Apply, void
20+
operation, @OpenApiOperation
21+
context, @OperationFilterContext
22+
proc
23+
;Does the method (endpoint) have the {EnableQuery} atttribuite ?
24+
data isQueryable = Attribute.IsDefined(context.MethodInfo, ^typeof(EnableQueryAttribute))
25+
26+
;Does the method (endpoint) return @SingleResult<type> ?
27+
data isSingleResult = context.MethodInfo.ReturnType.IsGenericType && context.MethodInfo.ReturnType.GetGenericTypeDefinition() == ^typeof(SingleResult<>)
28+
29+
;If the method (endpoint) is not docorated with {EnableQuery} we don't add anything
30+
if (isQueryable)
31+
begin
32+
;If there are no existing parameters then we need to create a new parameters collection to add to
33+
if (operation.Parameters == ^null)
34+
operation.Parameters = new List<OpenApiParameter>()
35+
36+
data oap, @OpenApiParameter
37+
38+
;Add $select to all queryable endpoints
39+
oap = new OpenApiParameter()
40+
oap.Name = "$select"
41+
oap.Description = "Trim the fields returned using OData syntax"
42+
oap.Required = false
43+
oap.In = ParameterLocation.Query
44+
oap.Schema = new OpenApiSchema()
45+
oap.Schema.Type = "string"
46+
operation.Parameters.Add(oap)
47+
;Breaking change OpenApiFactory.CreateFor => OpenApiFactory.CreateFromJson
48+
;& Example = OpenApiAnyFactory.CreateFor(stringSchema, "Id,ProductName"),
49+
50+
if (!isSingleResult)
51+
begin
52+
;Add $filter, $orderby, $top and $skip to endpoints that can produce multiple results
53+
oap = new OpenApiParameter()
54+
oap.Name = "$filter"
55+
oap.Description = "Filter the results using OData syntax."
56+
oap.Required = false
57+
oap.In = ParameterLocation.Query
58+
oap.Schema = new OpenApiSchema()
59+
oap.Schema.Type = "string"
60+
operation.Parameters.Add(oap)
61+
62+
oap = new OpenApiParameter()
63+
oap.Name = "$orderby"
64+
oap.Description = "Order the results using OData syntax."
65+
oap.Required = false
66+
oap.In = ParameterLocation.Query
67+
oap.Schema = new OpenApiSchema()
68+
oap.Schema.Type = "string"
69+
operation.Parameters.Add(oap)
70+
71+
oap = new OpenApiParameter()
72+
oap.Name = "$top"
73+
oap.Description = "The number of results to return."
74+
oap.Required = false
75+
oap.In = ParameterLocation.Query
76+
oap.Schema = new OpenApiSchema()
77+
oap.Schema.Type = "integer"
78+
operation.Parameters.Add(oap)
79+
80+
oap = new OpenApiParameter()
81+
oap.Name = "$skip"
82+
oap.Description = "The number of results to skip."
83+
oap.Required = false
84+
oap.In = ParameterLocation.Query
85+
oap.Schema = new OpenApiSchema()
86+
oap.Schema.Type = "integer"
87+
operation.Parameters.Add(oap)
88+
end
89+
90+
end
91+
92+
endmethod
93+
94+
endclass
95+
96+
endnamespace

HarmonyCore.sln

+8-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ EndProject
1818
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Templates", "Templates", "{3A316055-4B0B-442C-9FDB-846494C58E8D}"
1919
ProjectSection(SolutionItems) = preProject
2020
Templates\GenerateTestValues.tpl = Templates\GenerateTestValues.tpl
21-
Templates\HarmonyCoreCustomization.json = Templates\HarmonyCoreCustomization.json
2221
Templates\ODataClientModel.tpl = Templates\ODataClientModel.tpl
2322
Templates\ODataController.tpl = Templates\ODataController.tpl
2423
Templates\ODataControllerPropertyEndpoints.tpl = Templates\ODataControllerPropertyEndpoints.tpl
@@ -49,6 +48,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
4948
cli-tool-versions.json = cli-tool-versions.json
5049
Example Queries.odata = Example Queries.odata
5150
ExampleJsonResponse.txt = ExampleJsonResponse.txt
51+
HarmonyCoreCustomization.json = HarmonyCoreCustomization.json
5252
MakeLinuxDistro.bat = MakeLinuxDistro.bat
5353
MakeWindowsDistro.bat = MakeWindowsDistro.bat
5454
Generators\Enabled\ODataGenerator.csx = Generators\Enabled\ODataGenerator.csx
@@ -200,6 +200,13 @@ Project("{BBD0F5D1-1CC4-42FD-BA4C-A96779C64378}") = "HarmonyCoreCodeGen.Core", "
200200
EndProject
201201
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Terminal.Gui", "Terminal.Gui\Terminal.Gui\Terminal.Gui.csproj", "{29E1385D-D456-4341-B426-5D68C83216A5}"
202202
EndProject
203+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "XmlDoc", "XmlDoc", "{DCE82EE4-9552-4C8B-B1E8-97E27DF65488}"
204+
ProjectSection(SolutionItems) = preProject
205+
XmlDoc\Services.Controllers.xml = XmlDoc\Services.Controllers.xml
206+
XmlDoc\Services.Models.xml = XmlDoc\Services.Models.xml
207+
XmlDoc\Services.xml = XmlDoc\Services.xml
208+
EndProjectSection
209+
EndProject
203210
Global
204211
GlobalSection(SolutionConfigurationPlatforms) = preSolution
205212
Debug|Any CPU = Debug|Any CPU
File renamed without changes.

HarmonyCoreEF/Extensions/ModelBuilderExtensions.cs

+44-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,20 @@
1-
using Microsoft.EntityFrameworkCore;
1+
using Harmony.Core.FileIO.Queryable.Expressions;
2+
using Microsoft.EntityFrameworkCore;
23
using System;
34
using System.Collections.Generic;
45
using System.Linq.Expressions;
6+
using System.Reflection.Metadata;
57
using System.Text;
68

79
namespace Harmony.Core.EF.Extensions
810
{
11+
public enum TagConnector
12+
{
13+
None,
14+
AndExpression,
15+
OrExpression
16+
}
17+
918
public static class ModelBuilderExtensions
1019
{
1120
public static void AddOneToOneToOneRelation<D, J>(this ModelBuilder builder, string drivingProperty, string drivingKey, string joinedProperty, string joinedKey)
@@ -88,5 +97,39 @@ public static void AddGlobalTagFilter<T>(this ModelBuilder builder, ParameterExp
8897
Expression.Block(resultExpression), paramExpr));
8998

9099
}
100+
101+
public static void AddGlobalTagFilterAndOr<T>(this ModelBuilder builder, ParameterExpression paramExpr, List<Tuple<Expression, TagConnector>> tagExpressions)
102+
{
103+
Expression resultExpression = null;
104+
105+
foreach (Tuple<Expression, TagConnector> exprTuple in tagExpressions)
106+
{
107+
Expression newExpressionPart = exprTuple.Item1;
108+
TagConnector connector = exprTuple.Item2;
109+
110+
if (resultExpression == null)
111+
{
112+
resultExpression = newExpressionPart;
113+
}
114+
else
115+
{
116+
switch (connector)
117+
{
118+
case TagConnector.None:
119+
case TagConnector.AndExpression:
120+
resultExpression = Expression.AndAlso(resultExpression, newExpressionPart);
121+
break;
122+
case TagConnector.OrExpression:
123+
resultExpression = Expression.OrElse(resultExpression, newExpressionPart);
124+
break;
125+
}
126+
}
127+
}
128+
129+
builder.Entity(typeof(T))
130+
.HasQueryFilter(
131+
Expression.Lambda(
132+
Expression.Block(resultExpression), paramExpr));
133+
}
91134
}
92135
}

0 commit comments

Comments
 (0)