diff --git a/Templates/CSharp/Base/SharedCSharp.template.tt b/Templates/CSharp/Base/SharedCSharp.template.tt
index 32bd671e3..95031f75c 100644
--- a/Templates/CSharp/Base/SharedCSharp.template.tt
+++ b/Templates/CSharp/Base/SharedCSharp.template.tt
@@ -314,4 +314,34 @@ public string GetRequestMethodWithOptionsHeader()
/// The built request.";
}
+// -------------------------------------------------------------
+// Methods used in MethodRequest.cs.tt and IMethodRequest.cs.tt for OData actions and functions.
+// -------------------------------------------------------------
+
+///
+/// Used in MethodRequest.cs.tt and IMethodRequest.cs.tt to get the ODataMethod*Response type
+/// defined in Microsoft.Graph.Core. Updates to supported OData primitives for OData methods
+/// needs to occur in MethodRequest.cs.tt, IMethodRequest.cs.tt, Microsoft.Graph.Core, and here.
+///
+///
+///
+public string GetMethodRequestPrimitiveReturnTypeString(string type)
+{
+ switch (type.ToLowerInvariant())
+ {
+ case "string":
+ return "ODataMethodStringResponse";
+ case "int32":
+ return "ODataMethodIntResponse";
+ case "boolean":
+ case "bool":
+ return "ODataMethodBooleanResponse";
+ case "int64":
+ return "ODataMethodLongResponse";
+ default:
+ return type;
+ }
+}
+
+
#>
diff --git a/Templates/CSharp/Requests/IMethodRequest.cs.tt b/Templates/CSharp/Requests/IMethodRequest.cs.tt
index 8756ac348..abd559cc8 100644
--- a/Templates/CSharp/Requests/IMethodRequest.cs.tt
+++ b/Templates/CSharp/Requests/IMethodRequest.cs.tt
@@ -18,19 +18,42 @@ var requestType = entityName + methodName + "Request";
var returnEntityType = method.ReturnType == null ? null : method.ReturnType.GetTypeString(@namespace);
var returnEntityParameter = string.Empty;
-if (returnEntityType != null) {returnEntityParameter = returnEntityType.ToLower();}
+if (returnEntityType != null)
+{
+ returnEntityParameter = returnEntityType.ToLower();
+
+ // Updates to supported OData primitives need to occur here,
+ // IMethodRequest.cs.tt, Microsoft.Graph.Core, and in
+ // GetMethodRequestPrimitiveReturnTypeString() in SharedCSharp.
+ var tempReturnType = GetMethodRequestPrimitiveReturnTypeString(returnEntityType);
+
+ // These magic strings represent types in Microsoft.Graph.Core.
+ // If the return type is a primitive, then make it nullable.
+ if (tempReturnType == "ODataMethodIntResponse" ||
+ tempReturnType == "ODataMethodBooleanResponse" ||
+ tempReturnType == "ODataMethodLongResponse")
+ {
+ returnEntityType = returnEntityType + "?";
+ }
+}
var returnTypeObject = method.ReturnType == null ? null : method.ReturnType.AsOdcmClass();
+
+
var isCollection = method.IsCollection;
var sendAsyncReturnType = isCollection
? "I" + entityName + methodName + "CollectionPage"
: returnEntityType;
+
+
var methodReturnType = sendAsyncReturnType == null
? "System.Threading.Tasks.Task"
: "System.Threading.Tasks.Task<" + sendAsyncReturnType + ">";
+
+
bool hasParameters = method.Parameters != null && method.Parameters.Any();
bool includeRequestBody = hasParameters && isAction;
bool returnsStream = string.Equals(sendAsyncReturnType, "Stream");
diff --git a/Templates/CSharp/Requests/MethodRequest.cs.tt b/Templates/CSharp/Requests/MethodRequest.cs.tt
index e1ecce8a4..31b4db233 100644
--- a/Templates/CSharp/Requests/MethodRequest.cs.tt
+++ b/Templates/CSharp/Requests/MethodRequest.cs.tt
@@ -16,28 +16,79 @@ var entityName = method.Class.Name.ToCheckedCase();
var isFunction = method.IsFunction;
var isAction = !isFunction;
var isComposable = method.IsComposable;
+var isCollection = method.IsCollection;
var methodName = method.Name.Substring(method.Name.IndexOf('.') + 1).ToCheckedCase();
var requestType = entityName + methodName + "Request";
-var returnEntityType = method.ReturnType == null ? null : method.ReturnType.GetTypeString(@namespace);
-
var returnEntityParameter = string.Empty;
-if (returnEntityType != null) {returnEntityParameter = returnEntityType.ToLower();}
-var isCollection = method.IsCollection;
+// Represents the return of the SendAsync call within a public GetSync() or PostAsync() call.
+var sendAsyncReturnType = string.Empty;
-var sendAsyncReturnType = isCollection
- ? "I" + entityName + methodName + "CollectionPage"
- : returnEntityType;
+// Indicates whether the OData method returns an OData primitive (non-collection).
+// Collections of OData primitives is already supported.
+var isPrimitiveReturnType = false;
-var methodReturnType = sendAsyncReturnType == null
- ? "System.Threading.Tasks.Task"
- : "System.Threading.Tasks.Task<" + sendAsyncReturnType + ">";
+// Represents the return type of a GetAsync() or PostAsync() call.
+var returnEntityType = method.ReturnType == null ? null : method.ReturnType.GetTypeString(@namespace);
+
+// Set the SendAsync return type and determine whether we are working with an OData primitive.
+if (returnEntityType != null)
+{
+ returnEntityParameter = returnEntityType.ToLower();
+ if (isCollection)
+ {
+ sendAsyncReturnType = "I" + entityName + methodName + "CollectionPage";
+ }
+ else
+ {
+ // Updates to supported OData primitives need to occur here,
+ // IMethodRequest.cs.tt, Microsoft.Graph.Core, and in
+ // GetMethodRequestPrimitiveReturnTypeString() in SharedCSharp.
+ sendAsyncReturnType = GetMethodRequestPrimitiveReturnTypeString(returnEntityType);
+
+ // These magic strings represent types in M.G.C.
+ if (sendAsyncReturnType == "ODataMethodStringResponse" ||
+ sendAsyncReturnType == "ODataMethodIntResponse" ||
+ sendAsyncReturnType == "ODataMethodBooleanResponse" ||
+ sendAsyncReturnType == "ODataMethodLongResponse")
+ {
+ isPrimitiveReturnType = true;
+ }
+ }
+}
+else
+{
+ sendAsyncReturnType = returnEntityType;
+}
+
+// Set the return type of the public GetSync() or PostAsync() call.
+var methodReturnType = string.Empty;
+if (sendAsyncReturnType == null)
+{
+ methodReturnType = "System.Threading.Tasks.Task";
+}
+else
+{
+ if (isCollection)
+ {
+ var collectionPage = "I" + entityName + methodName + "CollectionPage";
+ methodReturnType = "System.Threading.Tasks.Task<" + collectionPage + ">";
+ }
+ else
+ {
+ var returnParameter = sendAsyncReturnType == "ODataMethodIntResponse" ||
+ sendAsyncReturnType == "ODataMethodBooleanResponse" ||
+ sendAsyncReturnType == "ODataMethodLongResponse" ? returnEntityType + "?"
+ : returnEntityType;
+ methodReturnType = "System.Threading.Tasks.Task<" + returnParameter + ">";
+ }
+}
string methodOverloadReturnType = methodReturnType;
-if (isCollection)
+if (isCollection || isPrimitiveReturnType)
{
methodReturnType = string.Concat("async ", methodReturnType);
}
@@ -178,9 +229,19 @@ namespace <#=@namespace#>
}
else if (!string.IsNullOrEmpty(sendAsyncReturnType))
{
+ if (isPrimitiveReturnType)
+ {
+#>
+ var response = await this.SendAsync<<#=sendAsyncReturnType#>>(<#=methodParameter#>, cancellationToken);
+ return response.Value;
+<#
+ }
+ else
+ {
#>
return this.SendAsync<<#=sendAsyncReturnType#>>(<#=methodParameter#>, cancellationToken);
<#
+ }
}
else
{
@@ -278,9 +339,19 @@ namespace <#=@namespace#>
}
else if (!string.IsNullOrEmpty(sendAsyncReturnType))
{
+ if (isPrimitiveReturnType)
+ {
+#>
+ var response = await this.SendAsync<<#=sendAsyncReturnType#>>(null, cancellationToken);
+ return response.Value;
+<#
+ }
+ else
+ {
#>
return this.SendAsync<<#=sendAsyncReturnType#>>(null, cancellationToken);
<#
+ }
}
else
{
diff --git a/test/Typewriter.Test/Given_a_valid_metadata_file_to_Typewriter.cs b/test/Typewriter.Test/Given_a_valid_metadata_file_to_Typewriter.cs
index fe808712f..ba2ebc103 100644
--- a/test/Typewriter.Test/Given_a_valid_metadata_file_to_Typewriter.cs
+++ b/test/Typewriter.Test/Given_a_valid_metadata_file_to_Typewriter.cs
@@ -555,5 +555,42 @@ public void It_transforms_metadata()
Assert.IsTrue(hasContainsTargetBeenSet, $"The expected ContainsTarget attribute wasn't set in the transformed cleaned metadata.");
Assert.IsFalse(hasCapabilityAnnotations, $"The expected capability annotations weren't removed in the transformed cleaned metadata.");
}
+
+ [Test, RunInApplicationDomain]
+ [TestCase("TestType2FunctionMethodWithStringRequest.cs", "var response = await this.SendAsync(null, cancellationToken);")]
+ [TestCase("TestType2FunctionMethodWithBooleanRequest.cs", "var response = await this.SendAsync(null, cancellationToken);")]
+ [TestCase("TestType2FunctionMethodWithInt32Request.cs", "var response = await this.SendAsync(null, cancellationToken);")]
+ [TestCase("TestType3ActionMethodWithInt64Request.cs", "var response = await this.SendAsync(null, cancellationToken);")]
+ public void It_creates_method_request_with_OData_return_type(string outputFileName, string testParameter)
+ {
+ const string outputDirectory = "output";
+
+ Options optionsCSharp = new Options()
+ {
+ Output = outputDirectory,
+ Language = "CSharp",
+ GenerationMode = GenerationMode.Files
+ };
+
+ Generator.GenerateFiles(testMetadata, optionsCSharp);
+
+ FileInfo fileInfo = new FileInfo(outputDirectory + generatedOutputUrl + @"\Requests\" + outputFileName);
+ Assert.IsTrue(fileInfo.Exists, $"Expected: {fileInfo.FullName}. File was not found.");
+
+ IEnumerable lines = File.ReadLines(fileInfo.FullName);
+ bool hasTestParameter = false;
+
+ foreach (var line in lines)
+ {
+ // We only need to check once.
+ if (line.Contains(testParameter))
+ {
+ hasTestParameter = true;
+ break;
+ }
+ }
+
+ Assert.IsTrue(hasTestParameter, $"The expected test token string, '{testParameter}', was not set in the generated test file. We didn't properly generate the SendAsync method.");
+ }
}
}
diff --git a/test/Typewriter.Test/Resources/dirtyMetadata.xml b/test/Typewriter.Test/Resources/dirtyMetadata.xml
index f3a52404c..7ba1deed7 100644
--- a/test/Typewriter.Test/Resources/dirtyMetadata.xml
+++ b/test/Typewriter.Test/Resources/dirtyMetadata.xml
@@ -92,6 +92,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+