diff --git a/src/SDK/Language/DotNet.php b/src/SDK/Language/DotNet.php
index f569225f2..4a3555b73 100644
--- a/src/SDK/Language/DotNet.php
+++ b/src/SDK/Language/DotNet.php
@@ -331,6 +331,11 @@ public function getFiles(): array
'destination' => '/src/{{ spec.title | caseUcfirst }}/{{ spec.title | caseUcfirst }}.csproj',
'template' => 'dotnet/src/Appwrite/Appwrite.csproj.twig',
],
+ [
+ 'scope' => 'default',
+ 'destination' => '/src/{{ spec.title | caseUcfirst }}.Tests/{{ spec.title | caseUcfirst }}.Tests.csproj',
+ 'template' => 'dotnet/src/Appwrite.Tests/Appwrite.Tests.csproj.twig',
+ ],
[
'scope' => 'default',
'destination' => '/src/{{ spec.title | caseUcfirst }}/Client.cs',
@@ -346,21 +351,41 @@ public function getFiles(): array
'destination' => '/src/{{ spec.title | caseUcfirst }}/ID.cs',
'template' => 'dotnet/src/Appwrite/ID.cs.twig',
],
+ [
+ 'scope' => 'default',
+ 'destination' => '/src/{{ spec.title | caseUcfirst }}.Tests/IDTest.cs',
+ 'template' => 'dotnet/src/Appwrite.Tests/IDTest.cs.twig',
+ ],
[
'scope' => 'default',
'destination' => '/src/{{ spec.title | caseUcfirst }}/Permission.cs',
'template' => 'dotnet/src/Appwrite/Permission.cs.twig',
],
+ [
+ 'scope' => 'default',
+ 'destination' => '/src/{{ spec.title | caseUcfirst }}.Tests/PermissionTest.cs',
+ 'template' => 'dotnet/src/Appwrite.Tests/PermissionTest.cs.twig',
+ ],
[
'scope' => 'default',
'destination' => '/src/{{ spec.title | caseUcfirst }}/Query.cs',
'template' => 'dotnet/src/Appwrite/Query.cs.twig',
],
+ [
+ 'scope' => 'default',
+ 'destination' => '/src/{{ spec.title | caseUcfirst }}.Tests/QueryTest.cs',
+ 'template' => 'dotnet/src/Appwrite.Tests/QueryTest.cs.twig',
+ ],
[
'scope' => 'default',
'destination' => '/src/{{ spec.title | caseUcfirst }}/Role.cs',
'template' => 'dotnet/src/Appwrite/Role.cs.twig',
],
+ [
+ 'scope' => 'default',
+ 'destination' => '/src/{{ spec.title | caseUcfirst }}.Tests/RoleTest.cs',
+ 'template' => 'dotnet/src/Appwrite.Tests/RoleTest.cs.twig',
+ ],
[
'scope' => 'default',
'destination' => '/src/{{ spec.title | caseUcfirst }}/Extensions/Extensions.cs',
@@ -391,10 +416,20 @@ public function getFiles(): array
'destination' => '/src/{{ spec.title | caseUcfirst }}/Services/{{service.name | caseUcfirst}}.cs',
'template' => 'dotnet/src/Appwrite/Services/ServiceTemplate.cs.twig',
],
+ [
+ 'scope' => 'service',
+ 'destination' => '/src/{{ spec.title | caseUcfirst }}.Tests/Services/{{service.name | caseUcfirst}}ServiceTest.cs',
+ 'template' => 'dotnet/src/Appwrite.Tests/Services/ServiceTest.cs.twig',
+ ],
[
'scope' => 'definition',
'destination' => '/src/{{ spec.title | caseUcfirst }}/Models/{{ definition.name | caseUcfirst | overrideIdentifier }}.cs',
'template' => 'dotnet/src/Appwrite/Models/Model.cs.twig',
+ ],
+ [
+ 'scope' => 'definition',
+ 'destination' => '/src/{{ spec.title | caseUcfirst }}.Tests/Models/{{ definition.name | caseUcfirst | overrideIdentifier }}Test.cs',
+ 'template' => 'dotnet/src/Appwrite.Tests/Models/ModelTest.cs.twig',
]
];
}
diff --git a/templates/dotnet/base/utils.twig b/templates/dotnet/base/utils.twig
index 35ec0a8b8..0d494168a 100644
--- a/templates/dotnet/base/utils.twig
+++ b/templates/dotnet/base/utils.twig
@@ -13,4 +13,7 @@
{% endmacro %}
{% macro resultType(namespace, method) %}
{% if method.type == "webAuth" %}bool{% elseif method.type == "location" %}byte[]{% elseif not method.responseModel or method.responseModel == 'any' %}object{% else %}Models.{{method.responseModel | caseUcfirst | overrideIdentifier }}{% endif %}
-{% endmacro %}
\ No newline at end of file
+{% endmacro %}
+{% macro sub_schema(property) %}
+{% if property.sub_schema %}{% if property.type == 'array' %}List<{{property.sub_schema | caseUcfirst | overrideIdentifier}}>{% else %}{{property.sub_schema | caseUcfirst | overrideIdentifier}}{% endif %}{% else %}{{property | typeName}}{% endif %}{% if not property.required %}?{% endif %}
+{% endmacro %}
diff --git a/templates/dotnet/src/Appwrite.Tests/Appwrite.Tests.csproj.twig b/templates/dotnet/src/Appwrite.Tests/Appwrite.Tests.csproj.twig
new file mode 100644
index 000000000..f95975cf0
--- /dev/null
+++ b/templates/dotnet/src/Appwrite.Tests/Appwrite.Tests.csproj.twig
@@ -0,0 +1,22 @@
+
+
+ net462
+ latest
+ enable
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/templates/dotnet/src/Appwrite.Tests/IDTest.cs.twig b/templates/dotnet/src/Appwrite.Tests/IDTest.cs.twig
new file mode 100644
index 000000000..3e14681ae
--- /dev/null
+++ b/templates/dotnet/src/Appwrite.Tests/IDTest.cs.twig
@@ -0,0 +1,18 @@
+using NUnit.Framework;
+
+namespace Appwrite.Tests;
+
+public class IDTest
+{
+ [Test]
+ public void TestUnique()
+ {
+ Assert.That(ID.Unique(), Is.EqualTo("unique()"));
+ }
+
+ [Test]
+ public void TestCustom()
+ {
+ Assert.That(ID.Custom("custom"), Is.EqualTo("custom"));
+ }
+}
diff --git a/templates/dotnet/src/Appwrite.Tests/Models/ModelTest.cs.twig b/templates/dotnet/src/Appwrite.Tests/Models/ModelTest.cs.twig
new file mode 100644
index 000000000..b20c446d9
--- /dev/null
+++ b/templates/dotnet/src/Appwrite.Tests/Models/ModelTest.cs.twig
@@ -0,0 +1,33 @@
+{% import 'dotnet/base/utils.twig' as utils -%}
+using NUnit.Framework;
+using System.Collections.Generic;
+
+using Appwrite.Models;
+
+namespace Appwrite.Tests.Models;
+
+public class {{ definition.name | caseUcfirst }}Test
+{
+ [Test]
+ public void TestSerialization()
+ {
+ var model = new {{ definition.name | caseUcfirst | overrideIdentifier }}(
+{% for property in definition.properties %}
+ {{ property.name | escapeKeyword | removeDollarSign }}: {% if property.type == 'array' %}new {{ utils.sub_schema(property) }}(){% elseif property.type == 'object' and (property.sub_schema == 'prefs' or property.sub_schema == 'preferences') %}new Preferences(new Dictionary()){% elseif property.type == 'object' %}new Dictionary(){% elseif property.type == 'string' %}"{{property['x-example']}}"{% elseif property.type == 'boolean' %}true{% elseif property.type == 'number' %}{{property['x-example'] | number_format(1)}}{% else %}{{property['x-example']}}{% endif %}{% if not loop.last or (loop.last and definition.additionalProperties) %},{% endif %}
+{% endfor %}
+{% if definition.additionalProperties %}
+ data: new Dictionary()
+{% endif %}
+ );
+
+ var map = model.ToMap();
+ var result = {{ definition.name | caseUcfirst | overrideIdentifier }}.From(map);
+
+{% for property in definition.properties %}
+ Assert.That(
+ result.{{ property.name | caseUcfirst | escapeKeyword | removeDollarSign }}{% if property.type == 'object' and (property.sub_schema == 'prefs' or property.sub_schema == 'preferences') %}.Data{% endif %},
+ Is.EqualTo({% if property.type == 'array' %}new {{ utils.sub_schema(property) }}(){% elseif property.type == 'object' and (property.sub_schema == 'prefs' or property.sub_schema == 'preferences') %}new Dictionary { {"data", new Dictionary()} }{% elseif property.type == 'object' %}new Dictionary(){% elseif property.type == 'string' %}"{{property['x-example']}}"{% elseif property.type == 'boolean' %}true{% elseif property.type == 'number' %}{{property['x-example'] | number_format(1)}}{% else %}{{property['x-example']}}{% endif %})
+ );
+{% endfor %}
+ }
+}
diff --git a/templates/dotnet/src/Appwrite.Tests/PermissionTest.cs.twig b/templates/dotnet/src/Appwrite.Tests/PermissionTest.cs.twig
new file mode 100644
index 000000000..13f6c4466
--- /dev/null
+++ b/templates/dotnet/src/Appwrite.Tests/PermissionTest.cs.twig
@@ -0,0 +1,36 @@
+using NUnit.Framework;
+
+namespace Appwrite.Tests;
+
+public class PermissionTest
+{
+ [Test]
+ public void TestRead()
+ {
+ Assert.That(Permission.Read(Role.Any()), Is.EqualTo("read(\"any\")"));
+ }
+
+ [Test]
+ public void TestWrite()
+ {
+ Assert.That(Permission.Write(Role.Any()), Is.EqualTo("write(\"any\")"));
+ }
+
+ [Test]
+ public void TestCreate()
+ {
+ Assert.That(Permission.Create(Role.Any()), Is.EqualTo("create(\"any\")"));
+ }
+
+ [Test]
+ public void TestUpdate()
+ {
+ Assert.That(Permission.Update(Role.Any()), Is.EqualTo("update(\"any\")"));
+ }
+
+ [Test]
+ public void TestDelete()
+ {
+ Assert.That(Permission.Delete(Role.Any()), Is.EqualTo("delete(\"any\")"));
+ }
+}
diff --git a/templates/dotnet/src/Appwrite.Tests/QueryTest.cs.twig b/templates/dotnet/src/Appwrite.Tests/QueryTest.cs.twig
new file mode 100644
index 000000000..e66be2578
--- /dev/null
+++ b/templates/dotnet/src/Appwrite.Tests/QueryTest.cs.twig
@@ -0,0 +1,193 @@
+using System.Collections.Generic;
+using System.Globalization;
+using NUnit.Framework;
+
+namespace Appwrite.Tests;
+
+class BasicFilterQueryTest
+{
+ public string Description { get; set; } = "";
+ public object Value { get; set; } = default!;
+ public string ExpectedValues { get; set; } = "";
+}
+
+public class QueryTest
+{
+ private readonly List _tests = new()
+ {
+ new BasicFilterQueryTest
+ {
+ Description = "with a string",
+ Value = "s",
+ ExpectedValues = "[\"s\"]"
+ },
+ new BasicFilterQueryTest
+ {
+ Description = "with a integer",
+ Value = 1,
+ ExpectedValues = "[1]"
+ },
+ new BasicFilterQueryTest
+ {
+ Description = "with a double",
+ Value = 1.2,
+ ExpectedValues = "[1.2]"
+ },
+ new BasicFilterQueryTest
+ {
+ Description = "with a whole number double",
+ Value = 1.0,
+ ExpectedValues = "[1]"
+ },
+ new BasicFilterQueryTest
+ {
+ Description = "with a bool",
+ Value = false,
+ ExpectedValues = "[false]"
+ },
+ new BasicFilterQueryTest
+ {
+ Description = "with a list",
+ Value = new [] {"a", "b", "c"},
+ ExpectedValues = "[\"a\",\"b\",\"c\"]"
+ }
+ };
+
+ [SetUp]
+ public void Setup()
+ {
+ CultureInfo.CurrentCulture = CultureInfo.InvariantCulture;
+ }
+
+ [Test]
+ public void TestEqual()
+ {
+ foreach (var test in _tests)
+ {
+ Assert.That(Query.Equal("attr", test.Value), Is.EqualTo($"equal(\"attr\", {test.ExpectedValues})"), test.Description);
+ }
+ }
+
+ [Test]
+ public void TestNotEqual()
+ {
+ foreach (var test in _tests)
+ {
+ Assert.That(Query.NotEqual("attr", test.Value), Is.EqualTo($"notEqual(\"attr\", {test.ExpectedValues})"), test.Description);
+ }
+ }
+
+ [Test]
+ public void TestLessThan()
+ {
+ foreach (var test in _tests)
+ {
+ Assert.That(Query.LessThan("attr", test.Value), Is.EqualTo($"lessThan(\"attr\", {test.ExpectedValues})"), test.Description);
+ }
+ }
+
+ [Test]
+ public void TestLessThanEqual()
+ {
+ foreach (var test in _tests)
+ {
+ Assert.That(Query.LessThanEqual("attr", test.Value), Is.EqualTo($"lessThanEqual(\"attr\", {test.ExpectedValues})"), test.Description);
+ }
+ }
+
+ [Test]
+ public void TestGreaterThan()
+ {
+ foreach (var test in _tests)
+ {
+ Assert.That(Query.GreaterThan("attr", test.Value), Is.EqualTo($"greaterThan(\"attr\", {test.ExpectedValues})"), test.Description);
+ }
+ }
+
+ [Test]
+ public void TestGreaterThanEqual()
+ {
+ foreach (var test in _tests)
+ {
+ Assert.That(Query.GreaterThanEqual("attr", test.Value), Is.EqualTo($"greaterThanEqual(\"attr\", {test.ExpectedValues})"), test.Description);
+ }
+ }
+
+ [Test]
+ public void TestSearch()
+ {
+ Assert.That(Query.Search("attr", "keyword1 keyword2"), Is.EqualTo("search(\"attr\", [\"keyword1 keyword2\"])"));
+ }
+
+ [Test]
+ public void TestIsNull()
+ {
+ Assert.That(Query.IsNull("attr"), Is.EqualTo("isNull(\"attr\")"));
+ }
+
+ [Test]
+ public void TestIsNotNull()
+ {
+ Assert.That(Query.IsNotNull("attr"), Is.EqualTo("isNotNull(\"attr\")"));
+ }
+
+ [Test]
+ public void TestBetweenWithIntegers()
+ {
+ Assert.That(Query.Between("attr", 1, 2), Is.EqualTo("between(\"attr\", 1, 2)"));
+ }
+
+ [Test]
+ public void TestBetweenWithDoubles()
+ {
+ Assert.That(Query.Between("attr", 1.2, 2.2), Is.EqualTo("between(\"attr\", 1.2, 2.2)"));
+ }
+
+ [Test]
+ public void TestBetweenWithStrings()
+ {
+ Assert.That(Query.Between("attr", "a", "z"), Is.EqualTo("between(\"attr\", \"a\", \"z\")"));
+ }
+
+ [Test]
+ public void TestSelect()
+ {
+ Assert.That(Query.Select(new List {"attr1", "attr2"}), Is.EqualTo("select([\"attr1\",\"attr2\"])"));
+ }
+
+ [Test]
+ public void TestOrderAsc()
+ {
+ Assert.That(Query.OrderAsc("attr"), Is.EqualTo("orderAsc(\"attr\")"));
+ }
+
+ [Test]
+ public void TestOrderDesc()
+ {
+ Assert.That(Query.OrderDesc("attr"), Is.EqualTo("orderDesc(\"attr\")"));
+ }
+
+ [Test]
+ public void TestCursorBefore()
+ {
+ Assert.That(Query.CursorBefore("attr"), Is.EqualTo("cursorBefore(\"attr\")"));
+ }
+
+ [Test]
+ public void TestCursorAfter()
+ {
+ Assert.That(Query.CursorAfter("attr"), Is.EqualTo("cursorAfter(\"attr\")"));
+ }
+
+ [Test]
+ public void TestLimit()
+ {
+ Assert.That(Query.Limit(1), Is.EqualTo("limit(1)"));
+ }
+
+ [Test]
+ public void TestOffset()
+ {
+ Assert.That(Query.Offset(1), Is.EqualTo("offset(1)"));
+ }
+}
diff --git a/templates/dotnet/src/Appwrite.Tests/RoleTest.cs.twig b/templates/dotnet/src/Appwrite.Tests/RoleTest.cs.twig
new file mode 100644
index 000000000..5dc316ad0
--- /dev/null
+++ b/templates/dotnet/src/Appwrite.Tests/RoleTest.cs.twig
@@ -0,0 +1,66 @@
+using NUnit.Framework;
+
+namespace Appwrite.Tests;
+
+public class RoleTest
+{
+ [Test]
+ public void TestAny()
+ {
+ Assert.That(Role.Any(), Is.EqualTo("any"));
+ }
+
+ [Test]
+ public void TestUserWithoutStatus()
+ {
+ Assert.That(Role.User("custom"), Is.EqualTo("user:custom"));
+ }
+
+ [Test]
+ public void TestUserWithStatus()
+ {
+ Assert.That(Role.User("custom", "verified"), Is.EqualTo("user:custom/verified"));
+ }
+
+ [Test]
+ public void TestUsersWithoutStatus()
+ {
+ Assert.That(Role.Users(), Is.EqualTo("users"));
+ }
+
+ [Test]
+ public void TestUsersWithStatus()
+ {
+ Assert.That(Role.Users("verified"), Is.EqualTo("users/verified"));
+ }
+
+ [Test]
+ public void TestGuests()
+ {
+ Assert.That(Role.Guests(), Is.EqualTo("guests"));
+ }
+
+ [Test]
+ public void TestTeamWithoutRole()
+ {
+ Assert.That(Role.Team("custom"), Is.EqualTo("team:custom"));
+ }
+
+ [Test]
+ public void TestTeamWithRole()
+ {
+ Assert.That(Role.Team("custom", "owner"), Is.EqualTo("team:custom/owner"));
+ }
+
+ [Test]
+ public void TestMember()
+ {
+ Assert.That(Role.Member("custom"), Is.EqualTo("member:custom"));
+ }
+
+ [Test]
+ public void TestLabel()
+ {
+ Assert.That(Role.Label("admin"), Is.EqualTo("label:admin"));
+ }
+}
diff --git a/templates/dotnet/src/Appwrite.Tests/Services/ServiceTest.cs.twig b/templates/dotnet/src/Appwrite.Tests/Services/ServiceTest.cs.twig
new file mode 100644
index 000000000..50b89aa64
--- /dev/null
+++ b/templates/dotnet/src/Appwrite.Tests/Services/ServiceTest.cs.twig
@@ -0,0 +1,80 @@
+{% import 'dotnet/base/utils.twig' as utils %}
+
+using Moq;
+using Moq.Protected;
+using Newtonsoft.Json;
+using NUnit.Framework;
+using System.Collections.Generic;
+using System.Net;
+using System.Net.Http;
+using System.IO;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+using Appwrite.Services;
+
+namespace Appwrite.Tests.Services;
+
+public class {{ service.name | caseUcfirst }}ServiceTest {
+ private readonly Mock _httpMessageHandlerMock;
+ private readonly {{ service.name | caseUcfirst }} _{{ service.name | caseCamel }};
+
+ public {{ service.name | caseUcfirst }}ServiceTest()
+ {
+ _httpMessageHandlerMock = new Mock();
+ var client = new HttpClient(_httpMessageHandlerMock.Object);
+ _{{ service.name | caseCamel }} = new {{ service.name | caseUcfirst }}(new Client(http: client));
+ }
+
+{% for method in service.methods %}
+ [Test]
+ public async Task Test{{ method.name | caseUcfirst }}() {
+ {%~ if method.type == 'webAuth' -%}
+ {%~ elseif method.type == 'location' -%}
+ var data = new byte[]{};
+ {%- else -%}
+ {%~ if method.responseModel and method.responseModel != 'any' ~%}
+ var data = new Dictionary {
+ {%- for definition in spec.definitions ~%}{%~ if definition.name == method.responseModel -%}{%~ for property in definition.properties | filter((param) => param.required) ~%}
+ {"{{property.name}}", {% if property.type == 'object' %}new Dictionary(){% elseif property.type == 'array' %}new List(){% elseif property.type == 'string' %}"{{property.example | escapeDollarSign}}"{% elseif property.type == 'boolean' %}true{% else %}{{property.example}}{% endif %}},{%~ endfor ~%}{% set break = true %}{%- else -%}{% set continue = true %}{%- endif -%}{%~ endfor -%}
+
+ };
+ {%~ else ~%}
+ var data = "";
+ {%- endif -%}
+ {% endif %}
+
+ _httpMessageHandlerMock
+ .Protected()
+ .Setup>("SendAsync", ItExpr.IsAny(), ItExpr.IsAny())
+ .Returns(() =>
+ {
+ var response = new HttpResponseMessage
+ {
+ {%~ if method.type == 'location' %}
+ Content = new StreamContent(new MemoryStream(data)) { Headers = { {"Content-Type", "application/octet-stream"} } },
+ {%~ elseif method.type == 'webAuth' %}
+ Content = new StringContent(""),
+ {%~ else %}
+ Content = new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json"),
+ {%~ endif %}
+ StatusCode = HttpStatusCode.OK,
+ };
+
+ return Task.FromResult(response);
+ });
+
+ {% if method.type != 'webAuth' %}var response = {% endif %}await _{{ service.name | caseCamel }}.{{ method.name | caseUcfirst }}({%~ for parameter in method.parameters.all | filter((param) => param.required) ~%}
+ {{parameter.name | escapeKeyword | caseCamel}}: {% if parameter.type == 'object' %}new Dictionary(){% elseif parameter.type == 'array' %}new List(){% elseif parameter.type == 'file' %}Appwrite.Models.InputFile.FromBytes(new byte[]{}, "input.png", "image/png"){% elseif parameter.type == 'boolean' %}true{% elseif parameter.type == 'string' %}"{% if parameter.example is not empty %}{{parameter.example | escapeDollarSign}}{% endif %}"{% elseif parameter.type == 'integer' and parameter['x-example'] is empty %}1{% elseif parameter.type == 'number' and parameter['x-example'] is empty %}1.0{% else %}{{parameter.example}}{%~ endif ~%}{% if not loop.last %},{% endif %}{%~ endfor ~%}
+ );
+
+ {%~ if method.type == 'location' ~%}
+ Assert.That(response, Is.InstanceOf());
+ {%~ elseif method.responseModel and method.responseModel != 'any' %}
+ Assert.That(response, Is.InstanceOf());
+ {%~ endif ~%}
+ }
+
+{% endfor %}
+}
diff --git a/templates/dotnet/src/Appwrite.sln b/templates/dotnet/src/Appwrite.sln
index a8e4b4e57..7562bcf91 100644
--- a/templates/dotnet/src/Appwrite.sln
+++ b/templates/dotnet/src/Appwrite.sln
@@ -5,6 +5,8 @@ VisualStudioVersion = 16.0.30114.128
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Appwrite", "Appwrite\Appwrite.csproj", "{ABD3EB63-B648-49D6-B7FD-C17A762A3EC3}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Appwrite.Tests", "Appwrite.Tests\Appwrite.Tests.csproj", "{2414D003-9709-4788-A33B-57B1A3874BAF}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -15,6 +17,10 @@ Global
{ABD3EB63-B648-49D6-B7FD-C17A762A3EC3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ABD3EB63-B648-49D6-B7FD-C17A762A3EC3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ABD3EB63-B648-49D6-B7FD-C17A762A3EC3}.Release|Any CPU.Build.0 = Release|Any CPU
+ {2414D003-9709-4788-A33B-57B1A3874BAF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2414D003-9709-4788-A33B-57B1A3874BAF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2414D003-9709-4788-A33B-57B1A3874BAF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2414D003-9709-4788-A33B-57B1A3874BAF}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/templates/dotnet/src/Appwrite/Client.cs.twig b/templates/dotnet/src/Appwrite/Client.cs.twig
index 0f11ee45f..615877341 100644
--- a/templates/dotnet/src/Appwrite/Client.cs.twig
+++ b/templates/dotnet/src/Appwrite/Client.cs.twig
@@ -165,7 +165,7 @@ namespace {{ spec.title | caseUcfirst }}
form.Add(new StringContent(list[index].ToString()!), $"{parameter.Key}[{index}]");
}
}
- else
+ else if (parameter.Value is not null)
{
form.Add(new StringContent(parameter.Value.ToString()!), parameter.Key);
}
diff --git a/templates/dotnet/src/Appwrite/Models/Model.cs.twig b/templates/dotnet/src/Appwrite/Models/Model.cs.twig
index 6e83a251a..d95beee1d 100644
--- a/templates/dotnet/src/Appwrite/Models/Model.cs.twig
+++ b/templates/dotnet/src/Appwrite/Models/Model.cs.twig
@@ -1,4 +1,4 @@
-{% macro sub_schema(property) %}{% if property.sub_schema %}{% if property.type == 'array' %}List<{{property.sub_schema | caseUcfirst | overrideIdentifier}}>{% else %}{{property.sub_schema | caseUcfirst | overrideIdentifier}}{% endif %}{% else %}{{property | typeName}}{% endif %}{% if not property.required %}?{% endif %}{% endmacro %}
+{% import 'dotnet/base/utils.twig' as utils %}
{% macro property_name(definition, property) %}{{ property.name | caseUcfirst | removeDollarSign | escapeKeyword}}{% endmacro %}
using System;
@@ -14,7 +14,7 @@ namespace {{ spec.title | caseUcfirst }}.Models
{
{%~ for property in definition.properties %}
[JsonProperty("{{ property.name }}")]
- public {{ _self.sub_schema(property) }} {{ _self.property_name(definition, property) }} { get; private set; }
+ public {{ utils.sub_schema(property) }} {{ _self.property_name(definition, property) }} { get; private set; }
{%~ endfor %}
{%~ if definition.additionalProperties %}
@@ -23,7 +23,7 @@ namespace {{ spec.title | caseUcfirst }}.Models
{%~ endif %}
public {{ definition.name | caseUcfirst | overrideIdentifier }}(
{%~ for property in definition.properties %}
- {{ _self.sub_schema(property) }} {{ property.name | caseCamel | escapeKeyword }}{% if not loop.last or (loop.last and definition.additionalProperties) %},{% endif %}
+ {{ utils.sub_schema(property) }} {{ property.name | caseCamel | escapeKeyword }}{% if not loop.last or (loop.last and definition.additionalProperties) %},{% endif %}
{%~ endfor %}
{%~ if definition.additionalProperties %}
@@ -40,7 +40,7 @@ namespace {{ spec.title | caseUcfirst }}.Models
public static {{ definition.name | caseUcfirst | overrideIdentifier}} From(Dictionary map) => new {{ definition.name | caseUcfirst | overrideIdentifier}}(
{%~ for property in definition.properties %}
- {{ property.name | caseCamel | escapeKeyword | removeDollarSign }}: {% if property.sub_schema %}{% if property.type == 'array' %}((JArray)map["{{ property.name }}"]).ToObject>>().Select(it => {{property.sub_schema | caseUcfirst | overrideIdentifier}}.From(map: it)).ToList(){% else %}{{property.sub_schema | caseUcfirst | overrideIdentifier}}.From(map: ((JObject)map["{{ property.name }}"]).ToObject>()!){% endif %}{% else %}{% if property.type == 'array' %}((JArray)map["{{ property.name }}"]).ToObject<{{ property | typeName }}>(){% else %}{% if property.type == "integer" or property.type == "number" %}{% if not property.required %}map["{{ property.name }}"] == null ? null : {% endif %}Convert.To{% if property.type == "integer" %}Int64{% else %}Double{% endif %}(map["{{ property.name }}"]){% else %}{% if property.type == "boolean" %}({{ property | typeName }}{% if not property.required %}?{% endif %})map["{{ property.name }}"]{% else %}map["{{ property.name }}"]{% if not property.required %}?{% endif %}.ToString(){% endif %}{% endif %}{% endif %}{% endif %}{% if not loop.last or (loop.last and definition.additionalProperties) %},{% endif %}
+ {{ property.name | caseCamel | escapeKeyword | removeDollarSign }}: {% if property.sub_schema %}{% if property.type == 'array' %}((JArray)map["{{ property.name }}"]).ToObject>>().Select(it => {{property.sub_schema | caseUcfirst | overrideIdentifier}}.From(map: it)).ToList(){% else %}{{property.sub_schema | caseUcfirst | overrideIdentifier}}.From(map: ((JObject)map["{{ property.name }}"]).ToObject>()!){% endif %}{% else %}{% if property.type == 'array' %}((JArray)map["{{ property.name }}"]).ToObject<{{ property | typeName }}>(){% else %}{% if property.type == "integer" or property.type == "number" %}{% if not property.required %}map["{{ property.name }}"] == null ? null : {% endif %}Convert.To{% if property.type == "integer" %}Int64{% else %}Double{% endif %}(map["{{ property.name }}"]){% else %}{% if property.type == "boolean" %}({{ property | typeName }}{% if not property.required %}?{% endif %})map["{{ property.name }}"]{% else %}{% if property.required %}map["{{ property.name }}"].ToString(){% else %}map.TryGetValue("{{ property.name }}", out var {{ property.name | removeDollarSign }}) ? {{ property.name | removeDollarSign }}.ToString() : null{% endif %}{% endif %}{% endif %}{% endif %}{% endif %}{% if not loop.last or (loop.last and definition.additionalProperties) %},{% endif %}
{%~ endfor %}
{%~ if definition.additionalProperties %}