diff --git a/CHANGELOG.md b/CHANGELOG.md index b4baaa2..09165f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## [v1.0.0-beta.3](https://github.com/contentstack/contentstack-management-dotnet/tree/v1.0.0-beta.3) + - **ContentType & QueryService STJ Migration** + - **✅ ContentType Module**: Fully migrated ContentType model and dependencies to System.Text.Json + - **✅ QueryService Migration**: Re-enabled and migrated QueryService for content type listing + - **✅ Field System**: Converted core Field models (FieldMetadata, Field, FieldRules) to STJ + - **✅ ContentModelling**: Updated ContentModelling and Option classes with STJ attributes + - **✅ Service Layer**: Migrated CreateUpdateService, FetchDeleteService, and DeleteService + - **✅ Web App Integration**: Complete ContentType CRUD interface with modern UI + - **✅ Schema Validation**: Added default "Title" field to prevent 422 API errors + - **✅ Error Handling**: Enhanced error reporting with detailed API validation messages + - **✅ Navigation**: Integrated ContentType management into Stack workflow + ## [v1.0.0-beta.2](https://github.com/contentstack/contentstack-management-dotnet/tree/v1.0.0-beta.2) - **System.Text.Json Migration Complete (Beta)** - **✅ Core Modules STJ-Only**: Client, User, Organization, and Stack modules fully migrated diff --git a/Contentstack.Management.Core/ContentstackClient.cs b/Contentstack.Management.Core/ContentstackClient.cs index 3c5f94c..0cbf678 100644 --- a/Contentstack.Management.Core/ContentstackClient.cs +++ b/Contentstack.Management.Core/ContentstackClient.cs @@ -200,7 +200,7 @@ protected void Initialize(HttpClient? httpClient = null) SerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull; SerializerOptions.PropertyNameCaseInsensitive = true; - // SerializerOptions.Converters.Add(new FieldJsonConverter()); // Excluded for now + SerializerOptions.Converters.Add(new FieldJsonConverter()); // Re-enabled for ContentType support SerializerOptions.Converters.Add(new NodeJsonConverter()); SerializerOptions.Converters.Add(new TextNodeJsonConverter()); } diff --git a/Contentstack.Management.Core/Models/BaseModel.cs b/Contentstack.Management.Core/Models/BaseModel.cs index b8b996c..7be25d7 100644 --- a/Contentstack.Management.Core/Models/BaseModel.cs +++ b/Contentstack.Management.Core/Models/BaseModel.cs @@ -15,7 +15,7 @@ public class BaseModel public string Uid { get; set; } - public BaseModel(Stack stack, string fieldName, string uid = null) + public BaseModel(Stack stack, string fieldName, string? uid = null) { stack.ThrowIfAPIKeyEmpty(); if (fieldName == null) @@ -27,75 +27,75 @@ public BaseModel(Stack stack, string fieldName, string uid = null) Uid = uid; } - public virtual ContentstackResponse Create(T model, ParameterCollection collection = null) + public virtual ContentstackResponse Create(T model, ParameterCollection? collection = null) { ThrowIfUidNotEmpty(); - var service = new CreateUpdateService(stack.client.serializer, stack, resourcePath, model, this.fieldName, collection: collection); + var service = new CreateUpdateService(stack, resourcePath, model, this.fieldName, collection: collection, stjOptions: stack.client.SerializerOptions); return stack.client.InvokeSync(service); } - public virtual Task CreateAsync(T model, ParameterCollection collection = null) + public virtual Task CreateAsync(T model, ParameterCollection? collection = null) { ThrowIfUidNotEmpty(); stack.ThrowIfNotLoggedIn(); - var service = new CreateUpdateService(stack.client.serializer, stack, resourcePath, model, this.fieldName, collection: collection); + var service = new CreateUpdateService(stack, resourcePath, model, this.fieldName, collection: collection, stjOptions: stack.client.SerializerOptions); return stack.client.InvokeAsync, ContentstackResponse>(service); } - public virtual ContentstackResponse Update(T model, ParameterCollection collection = null) + public virtual ContentstackResponse Update(T model, ParameterCollection? collection = null) { ThrowIfUidEmpty(); - var service = new CreateUpdateService(stack.client.serializer, stack, resourcePath, model, this.fieldName, "PUT", collection: collection); + var service = new CreateUpdateService(stack, resourcePath, model, this.fieldName, "PUT", collection: collection, stjOptions: stack.client.SerializerOptions); return stack.client.InvokeSync(service); } - public virtual Task UpdateAsync(T model, ParameterCollection collection = null) + public virtual Task UpdateAsync(T model, ParameterCollection? collection = null) { stack.ThrowIfNotLoggedIn(); ThrowIfUidEmpty(); - var service = new CreateUpdateService(stack.client.serializer, stack, resourcePath, model, this.fieldName, "PUT", collection: collection); + var service = new CreateUpdateService(stack, resourcePath, model, this.fieldName, "PUT", collection: collection, stjOptions: stack.client.SerializerOptions); return stack.client.InvokeAsync, ContentstackResponse>(service); } - public virtual ContentstackResponse Fetch(ParameterCollection collection = null) + public virtual ContentstackResponse Fetch(ParameterCollection? collection = null) { stack.ThrowIfNotLoggedIn(); ThrowIfUidEmpty(); - var service = new FetchDeleteService(stack.client.serializer, stack, resourcePath, collection: collection); + var service = new FetchDeleteService(stack, resourcePath, collection: collection, stjOptions: stack.client.SerializerOptions); return stack.client.InvokeSync(service); } - public virtual Task FetchAsync(ParameterCollection collection = null) + public virtual Task FetchAsync(ParameterCollection? collection = null) { stack.ThrowIfNotLoggedIn(); ThrowIfUidEmpty(); - var service = new FetchDeleteService(stack.client.serializer, stack, resourcePath, collection: collection); + var service = new FetchDeleteService(stack, resourcePath, collection: collection, stjOptions: stack.client.SerializerOptions); return stack.client.InvokeAsync(service); } - public virtual ContentstackResponse Delete(ParameterCollection collection = null) + public virtual ContentstackResponse Delete(ParameterCollection? collection = null) { stack.ThrowIfNotLoggedIn(); ThrowIfUidEmpty(); - var service = new FetchDeleteService(stack.client.serializer, stack, resourcePath, "DELETE", collection: collection); + var service = new FetchDeleteService(stack, resourcePath, "DELETE", collection: collection, stjOptions: stack.client.SerializerOptions); return stack.client.InvokeSync(service); } - public virtual Task DeleteAsync(ParameterCollection collection = null) + public virtual Task DeleteAsync(ParameterCollection? collection = null) { stack.ThrowIfNotLoggedIn(); ThrowIfUidEmpty(); - var service = new FetchDeleteService(stack.client.serializer, stack, resourcePath, "DELETE", collection: collection); + var service = new FetchDeleteService(stack, resourcePath, "DELETE", collection: collection, stjOptions: stack.client.SerializerOptions); return stack.client.InvokeAsync(service); } diff --git a/Contentstack.Management.Core/Models/ContentModelling.cs b/Contentstack.Management.Core/Models/ContentModelling.cs index a43eac7..21f58a3 100644 --- a/Contentstack.Management.Core/Models/ContentModelling.cs +++ b/Contentstack.Management.Core/Models/ContentModelling.cs @@ -1,55 +1,53 @@ using System.Collections.Generic; using System.Linq; +using System.Text.Json.Serialization; using Contentstack.Management.Core.Models.Fields; -using Newtonsoft.Json; namespace Contentstack.Management.Core.Models { - [JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)] public class ContentModelling { - [JsonProperty(propertyName: "title")] - public string Title { get; set; } + [JsonPropertyName("title")] + public string? Title { get; set; } - [JsonProperty(propertyName: "uid")] - public string Uid { get; set; } + [JsonPropertyName("uid")] + public string? Uid { get; set; } - [JsonProperty(propertyName: "description")] - public string Description { get; set; } + [JsonPropertyName("description")] + public string? Description { get; set; } - [JsonProperty(propertyName: "field_rules")] - public List FieldRules { get; set; } + [JsonPropertyName("field_rules")] + public List? FieldRules { get; set; } - [JsonProperty(propertyName: "schema")] - public List Schema { get; set; } + [JsonPropertyName("schema")] + public List? Schema { get; set; } - [JsonProperty(propertyName: "global_field_refs")] - public List GlobalFieldRefs { get; set; } + [JsonPropertyName("global_field_refs")] + public List? GlobalFieldRefs { get; set; } - [JsonProperty(propertyName: "options")] - public Option Options { get; set; } + [JsonPropertyName("options")] + public Option? Options { get; set; } } - [JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)] public class Option { - [JsonProperty(propertyName: "title")] - public string Title { get; set; } + [JsonPropertyName("title")] + public string? Title { get; set; } - [JsonProperty(propertyName: "sub_title")] - public List SubTitle { get; set; } + [JsonPropertyName("sub_title")] + public List? SubTitle { get; set; } - [JsonProperty(propertyName: "singleton")] + [JsonPropertyName("singleton")] public bool Singleton { get; set; } - [JsonProperty(propertyName: "is_page")] + [JsonPropertyName("is_page")] public bool IsPage { get; set; } - [JsonProperty(propertyName: "url_pattern")] - public string UrlPattern { get; set; } + [JsonPropertyName("url_pattern")] + public string? UrlPattern { get; set; } - [JsonProperty(propertyName: "url_prefix")] - public string UrlPrefix { get; set; } + [JsonPropertyName("url_prefix")] + public string? UrlPrefix { get; set; } } } diff --git a/Contentstack.Management.Core/Models/ContentType.cs b/Contentstack.Management.Core/Models/ContentType.cs index 793fc16..8bd6c50 100644 --- a/Contentstack.Management.Core/Models/ContentType.cs +++ b/Contentstack.Management.Core/Models/ContentType.cs @@ -39,7 +39,7 @@ public Query Query() /// /// IContentType for updating Content Type. /// - public override ContentstackResponse Create(ContentModelling model, ParameterCollection collection = null) + public override ContentstackResponse Create(ContentModelling model, ParameterCollection? collection = null) { return base.Create(model, collection); } @@ -56,7 +56,7 @@ public override ContentstackResponse Create(ContentModelling model, ParameterCol /// /// IContentType for updating Content Type. /// - public override Task CreateAsync(ContentModelling model, ParameterCollection collection = null) + public override Task CreateAsync(ContentModelling model, ParameterCollection? collection = null) { return base.CreateAsync(model, collection); } @@ -73,7 +73,7 @@ public override Task CreateAsync(ContentModelling model, P /// /// IContentType for updating Content Type. /// - public override ContentstackResponse Update(ContentModelling model, ParameterCollection collection = null) + public override ContentstackResponse Update(ContentModelling model, ParameterCollection? collection = null) { return base.Update(model, collection); } @@ -90,7 +90,7 @@ public override ContentstackResponse Update(ContentModelling model, ParameterCol /// /// IContentType for updating Content Type. /// - public override Task UpdateAsync(ContentModelling model, ParameterCollection collection = null) + public override Task UpdateAsync(ContentModelling model, ParameterCollection? collection = null) { return base.UpdateAsync(model, collection); } @@ -105,7 +105,7 @@ public override Task UpdateAsync(ContentModelling model, P /// /// /// The . - public override ContentstackResponse Fetch(ParameterCollection collection = null) + public override ContentstackResponse Fetch(ParameterCollection? collection = null) { return base.Fetch(collection); } @@ -120,7 +120,7 @@ public override ContentstackResponse Fetch(ParameterCollection collection = null /// /// /// The Task. - public override Task FetchAsync(ParameterCollection collection = null) + public override Task FetchAsync(ParameterCollection? collection = null) { return base.FetchAsync(collection); } @@ -135,7 +135,7 @@ public override Task FetchAsync(ParameterCollection collec /// /// /// The . - public override ContentstackResponse Delete(ParameterCollection collection = null) + public override ContentstackResponse Delete(ParameterCollection? collection = null) { return base.Delete(collection); } @@ -150,11 +150,12 @@ public override ContentstackResponse Delete(ParameterCollection collection = nul /// /// /// The Task. - public override Task DeleteAsync(ParameterCollection collection = null) + public override Task DeleteAsync(ParameterCollection? collection = null) { return base.DeleteAsync(collection); } + /* /// /// is the actual piece of content created using one of the defined content types. /// @@ -176,5 +177,6 @@ public Entry Entry(string uid = null) ThrowIfUidEmpty(); return new Entry(stack, Uid, uid); } + */ } } diff --git a/Contentstack.Management.Core/Models/Fields/DateField.cs b/Contentstack.Management.Core/Models/Fields/DateField.cs index 84f3d4e..1712ed1 100644 --- a/Contentstack.Management.Core/Models/Fields/DateField.cs +++ b/Contentstack.Management.Core/Models/Fields/DateField.cs @@ -1,13 +1,13 @@ using System; -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Contentstack.Management.Core.Models.Fields { public class DateField : Field { - [JsonProperty(propertyName: "startDate")] + [JsonPropertyName("startDate")] public string StartDate { get; set; } - [JsonProperty(propertyName: "endDate")] + [JsonPropertyName("endDate")] public string EndDate { get; set; } } } diff --git a/Contentstack.Management.Core/Models/Fields/ExtensionField.cs b/Contentstack.Management.Core/Models/Fields/ExtensionField.cs index 1c2b144..abc4996 100644 --- a/Contentstack.Management.Core/Models/Fields/ExtensionField.cs +++ b/Contentstack.Management.Core/Models/Fields/ExtensionField.cs @@ -1,14 +1,15 @@ using System; using System.Collections.Generic; -using Newtonsoft.Json; +using System.Text.Json; +using System.Text.Json.Serialization; namespace Contentstack.Management.Core.Models.Fields { public class ExtensionField : Field { - [JsonProperty(propertyName: "extension_uid")] + [JsonPropertyName("extension_uid")] public string extension_uid { get; set; } - [JsonProperty(propertyName: "config")] - public Dictionary config { get; set; } + [JsonPropertyName("config")] + public Dictionary config { get; set; } } } diff --git a/Contentstack.Management.Core/Models/Fields/Field.cs b/Contentstack.Management.Core/Models/Fields/Field.cs index cc86ebd..25676d6 100644 --- a/Contentstack.Management.Core/Models/Fields/Field.cs +++ b/Contentstack.Management.Core/Models/Fields/Field.cs @@ -1,45 +1,44 @@ using System; -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Contentstack.Management.Core.Models.Fields { - [JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)] public class Field { /// /// Determines the display name of a field. It is a mandatory field. /// - [JsonProperty(propertyName: "display_name")] - public string DisplayName { get; set; } + [JsonPropertyName("display_name")] + public string? DisplayName { get; set; } /// /// Represents the unique ID of each field. It is a mandatory field. /// - [JsonProperty(propertyName: "uid")] - public string Uid { get; set; } + [JsonPropertyName("uid")] + public string? Uid { get; set; } /// /// Determines what value can be provided to the Title field. /// - [JsonProperty(propertyName: "data_type")] - public string DataType { get; set; } + [JsonPropertyName("data_type")] + public string? DataType { get; set; } /// /// Allows you to enter additional data about a field. Also, you can add additional values under 'field_metadata'. /// - [JsonProperty(propertyName: "field_metadata")] - public FieldMetadata FieldMetadata { get; set; } + [JsonPropertyName("field_metadata")] + public FieldMetadata? FieldMetadata { get; set; } - [JsonProperty(propertyName: "multiple")] + [JsonPropertyName("multiple")] public bool Multiple { get; set; } - [JsonProperty(propertyName: "mandatory")] + [JsonPropertyName("mandatory")] public bool Mandatory { get; set; } - [JsonProperty(propertyName: "unique")] + [JsonPropertyName("unique")] public bool Unique { get; set; } /// /// Presentation widget for text fields (e.g. dropdown, checkbox). /// - [JsonProperty(propertyName: "display_type")] - public string DisplayType { get; set; } + [JsonPropertyName("display_type")] + public string? DisplayType { get; set; } } } diff --git a/Contentstack.Management.Core/Models/Fields/FieldMetadata.cs b/Contentstack.Management.Core/Models/Fields/FieldMetadata.cs index b384edf..ab269ff 100644 --- a/Contentstack.Management.Core/Models/Fields/FieldMetadata.cs +++ b/Contentstack.Management.Core/Models/Fields/FieldMetadata.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; -using Newtonsoft.Json; +using System.Text.Json; +using System.Text.Json.Serialization; namespace Contentstack.Management.Core.Models.Fields { @@ -8,89 +9,90 @@ public class FieldMetadata { /// /// Allows you to set default fields for content types. + /// API can send both boolean and string values, so using JsonElement for flexibility. /// - [JsonProperty(propertyName: "_default")] - public string Default { get; set; } + [JsonPropertyName("_default")] + public JsonElement? Default { get; set; } /// /// Allows you to set a default value for a field. /// - [JsonProperty(propertyName: "default_value")] - public object DefaultValue { get; set; } + [JsonPropertyName("default_value")] + public object? DefaultValue { get; set; } /// /// Determines whether the editor will support rich text, and is set to ‘true’ by default for Rich Text Editors. /// - [JsonProperty(propertyName: "allow_rich_text")] + [JsonPropertyName("allow_rich_text")] public bool AllowRichText { get; set; } /// /// Allows you to provide the content for the Rich text editor field. /// - [JsonProperty(propertyName: "description")] - public string Description { get; set; } + [JsonPropertyName("description")] + public string? Description { get; set; } /// /// Provides multi-line capabilities to the Rich text editor. /// - [JsonProperty(propertyName: "multiline")] + [JsonPropertyName("multiline")] public bool Multiline { get; set; } /// /// Lets you enable either the basic, custom, or advanced editor to enter your content. /// - [JsonProperty(propertyName: "rich_text_type")] - public string RichTextType { get; set; } + [JsonPropertyName("rich_text_type")] + public string? RichTextType { get; set; } /// /// If you choose the Custom editor, then the options key lets you specify the formatting options you prefer for your RTE toolbar, /// e.g., "options": ["h3", "blockquote", "sup"] /// - [JsonProperty(propertyName: "options")] - public List Options { get; set; } + [JsonPropertyName("options")] + public List? Options { get; set; } /// /// This key determines whether you are using the older version of the Rich Text Editor or the latest version. /// The value of 1 denotes that it is an older version of the editor, while 3 denotes that it is the latest version of the editor. /// - [JsonProperty(propertyName: "version")] + [JsonPropertyName("version")] public int Version { get; set; } /// /// Lets you assign a field to be a markdown by setting its value to ‘true’. /// - [JsonProperty(propertyName: "markdown")] + [JsonPropertyName("markdown")] public bool Markdown { get; set; } /// /// Allows you to provide a hint text about the values that need to be entered in an input field, e.g., Single Line Textbox. /// This text can be seen inside the field until you enter a value. /// - [JsonProperty(propertyName: "placeholder")] - public string Placeholder { get; set; } + [JsonPropertyName("placeholder")] + public string? Placeholder { get; set; } /// /// Allows you to add instructions for the content managers while entering values for a field. The instructional text appears below the field. /// - [JsonProperty(propertyName: "instruction")] - public string Instruction { get; set; } + [JsonPropertyName("instruction")] + public string? Instruction { get; set; } /// /// Allows you to set single or multiple reference to Reference field. /// - [JsonProperty(propertyName: "ref_multiple")] + [JsonPropertyName("ref_multiple")] public bool RefMultiple { get; set; } /// /// When true, the field is a JSON Rich Text Editor (JRTE). /// - [JsonProperty(propertyName: "allow_json_rte")] + [JsonPropertyName("allow_json_rte")] public bool? AllowJsonRte { get; set; } /// /// Allows embedding entries in the JSON RTE / rich text configuration. /// - [JsonProperty(propertyName: "embed_entry")] + [JsonPropertyName("embed_entry")] public bool? EmbedEntry { get; set; } } @@ -99,7 +101,7 @@ public class FileFieldMetadata: FieldMetadata /// /// Allows you to set single or multiple reference to Reference field. /// - [JsonProperty(propertyName: "image")] + [JsonPropertyName("image")] public bool AllowOnlyImage { get; set; } } } diff --git a/Contentstack.Management.Core/Models/Fields/FieldRules.cs b/Contentstack.Management.Core/Models/Fields/FieldRules.cs index 0b0318e..1c55464 100644 --- a/Contentstack.Management.Core/Models/Fields/FieldRules.cs +++ b/Contentstack.Management.Core/Models/Fields/FieldRules.cs @@ -1,36 +1,36 @@ using System; using System.Collections.Generic; -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Contentstack.Management.Core.Models.Fields { public class FieldRules { - [JsonProperty(propertyName: "match_type")] - public string MatchType { get; set; } - [JsonProperty(propertyName: "actions")] - public List Actions { get; set; } - [JsonProperty(propertyName: "conditions")] - public List conditions { get; set; } + [JsonPropertyName("match_type")] + public string? MatchType { get; set; } + [JsonPropertyName("actions")] + public List? Actions { get; set; } + [JsonPropertyName("conditions")] + public List? conditions { get; set; } } public class Action { - [JsonProperty(propertyName: "action")] - public string state { get; set; } - [JsonProperty(propertyName: "target_field")] - public string TargetField { get; set; } + [JsonPropertyName("action")] + public string? state { get; set; } + [JsonPropertyName("target_field")] + public string? TargetField { get; set; } } public class Condition { - [JsonProperty(propertyName: "dataType")] - public string DataType { get; set; } - [JsonProperty(propertyName: "operand_field")] - public string OperandField { get; set; } - [JsonProperty(propertyName: "operator")] - public string Operator { get; set; } - [JsonProperty(propertyName: "value")] - public string Value { get; set; } + [JsonPropertyName("dataType")] + public string? DataType { get; set; } + [JsonPropertyName("operand_field")] + public string? OperandField { get; set; } + [JsonPropertyName("operator")] + public string? Operator { get; set; } + [JsonPropertyName("value")] + public string? Value { get; set; } } } diff --git a/Contentstack.Management.Core/Models/Fields/FileField.cs b/Contentstack.Management.Core/Models/Fields/FileField.cs index cedb73b..6b24cb1 100644 --- a/Contentstack.Management.Core/Models/Fields/FileField.cs +++ b/Contentstack.Management.Core/Models/Fields/FileField.cs @@ -1,34 +1,34 @@ using System; using System.Collections.Generic; -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Contentstack.Management.Core.Models.Fields { public class FileField : Field { - [JsonProperty(propertyName: "extensions")] + [JsonPropertyName("extensions")] public List Extensions { get; set; } - [JsonProperty(propertyName: "max")] + [JsonPropertyName("max")] public int? Maxsize { get; set; } - [JsonProperty(propertyName: "min")] + [JsonPropertyName("min")] public int? MinSize { get; set; } } public class ImageField : FileField { - [JsonProperty(propertyName: "dimension")] + [JsonPropertyName("dimension")] public Dimension Dimensions { get; set; } /// /// Allows you to enter additional data about a field. Also, you can add additional values under ‘field_metadata’. /// - [JsonProperty(propertyName: "field_metadata")] + [JsonPropertyName("field_metadata")] public new FileFieldMetadata FieldMetadata { get; set; } } public class Dimension { - [JsonProperty(propertyName: "height")] + [JsonPropertyName("height")] public Dictionary Height { get; set; } - [JsonProperty(propertyName: "width")] + [JsonPropertyName("width")] public Dictionary Width { get; set; } } } diff --git a/Contentstack.Management.Core/Models/Fields/GlobalFieldReference.cs b/Contentstack.Management.Core/Models/Fields/GlobalFieldReference.cs index 05e7e49..b5181a2 100644 --- a/Contentstack.Management.Core/Models/Fields/GlobalFieldReference.cs +++ b/Contentstack.Management.Core/Models/Fields/GlobalFieldReference.cs @@ -1,5 +1,5 @@ using System; -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Contentstack.Management.Core.Models.Fields { @@ -12,30 +12,30 @@ public class GlobalFieldReference : Field /// /// The UID of the global field being referenced. /// - [JsonProperty(propertyName: "reference_to")] + [JsonPropertyName("reference_to")] public string ReferenceTo { get; set; } /// /// Determines if this field can accept multiple values. /// - [JsonProperty(propertyName: "multiple")] + [JsonPropertyName("multiple")] public new bool Multiple { get; set; } /// /// Determines if this field is mandatory. /// - [JsonProperty(propertyName: "mandatory")] + [JsonPropertyName("mandatory")] public new bool Mandatory { get; set; } /// /// Determines if this field value must be unique. /// - [JsonProperty(propertyName: "unique")] + [JsonPropertyName("unique")] public new bool Unique { get; set; } /// /// Determines if this field is non-localizable. /// - [JsonProperty(propertyName: "non_localizable")] + [JsonPropertyName("non_localizable")] public bool NonLocalizable { get; set; } } } diff --git a/Contentstack.Management.Core/Models/Fields/GroupField.cs b/Contentstack.Management.Core/Models/Fields/GroupField.cs index f556696..0458972 100644 --- a/Contentstack.Management.Core/Models/Fields/GroupField.cs +++ b/Contentstack.Management.Core/Models/Fields/GroupField.cs @@ -1,16 +1,16 @@ using System; using System.Collections.Generic; -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Contentstack.Management.Core.Models.Fields { public class GroupField : Field { - [JsonProperty(propertyName: "format")] + [JsonPropertyName("format")] public string Format { get; set; } - [JsonProperty(propertyName: "schema")] + [JsonPropertyName("schema")] public List Schema { get; set; } - [JsonProperty(propertyName: "max_instance")] + [JsonPropertyName("max_instance")] public int? MaxInstance { get; set; } } } diff --git a/Contentstack.Management.Core/Models/Fields/JsonField.cs b/Contentstack.Management.Core/Models/Fields/JsonField.cs index fefd923..2188f8a 100644 --- a/Contentstack.Management.Core/Models/Fields/JsonField.cs +++ b/Contentstack.Management.Core/Models/Fields/JsonField.cs @@ -1,4 +1,5 @@ -using Newtonsoft.Json; +using System.Text.Json; +using System.Text.Json.Serialization; namespace Contentstack.Management.Core.Models.Fields { @@ -7,7 +8,7 @@ namespace Contentstack.Management.Core.Models.Fields /// public class JsonField : TextboxField { - [JsonProperty(propertyName: "reference_to")] - public object ReferenceTo { get; set; } + [JsonPropertyName("reference_to")] + public JsonElement? ReferenceTo { get; set; } } } diff --git a/Contentstack.Management.Core/Models/Fields/ModularBlockField.cs b/Contentstack.Management.Core/Models/Fields/ModularBlockField.cs index b177607..871d091 100644 --- a/Contentstack.Management.Core/Models/Fields/ModularBlockField.cs +++ b/Contentstack.Management.Core/Models/Fields/ModularBlockField.cs @@ -1,26 +1,26 @@ using System; using System.Collections.Generic; -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Contentstack.Management.Core.Models.Fields { public class ModularBlockField : Field { - [JsonProperty(propertyName: "blocks")] + [JsonPropertyName("blocks")] public List blocks { get; set; } } public class Block { - [JsonProperty(propertyName: "title")] + [JsonPropertyName("title")] public string Title { get; set; } - [JsonProperty(propertyName: "uid")] + [JsonPropertyName("uid")] public string Uid { get; set; } - [JsonProperty(propertyName: "autoEdit")] + [JsonPropertyName("autoEdit")] public bool AutoEdit { get; set; } - [JsonProperty(propertyName: "blockType")] + [JsonPropertyName("blockType")] public bool BlockType { get; set; } - [JsonProperty(propertyName: "schema")] + [JsonPropertyName("schema")] public List Schema { get; set; } } } diff --git a/Contentstack.Management.Core/Models/Fields/NumberField.cs b/Contentstack.Management.Core/Models/Fields/NumberField.cs index f67e92f..69b325a 100644 --- a/Contentstack.Management.Core/Models/Fields/NumberField.cs +++ b/Contentstack.Management.Core/Models/Fields/NumberField.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Contentstack.Management.Core.Models.Fields { @@ -7,10 +7,10 @@ namespace Contentstack.Management.Core.Models.Fields /// public class NumberField : Field { - [JsonProperty(propertyName: "min")] + [JsonPropertyName("min")] public int? Min { get; set; } - [JsonProperty(propertyName: "max")] + [JsonPropertyName("max")] public int? Max { get; set; } } } diff --git a/Contentstack.Management.Core/Models/Fields/ReferenceField.cs b/Contentstack.Management.Core/Models/Fields/ReferenceField.cs index 135dc0b..569de5f 100644 --- a/Contentstack.Management.Core/Models/Fields/ReferenceField.cs +++ b/Contentstack.Management.Core/Models/Fields/ReferenceField.cs @@ -1,14 +1,15 @@ using System; using System.Collections.Generic; -using Newtonsoft.Json; +using System.Text.Json; +using System.Text.Json.Serialization; namespace Contentstack.Management.Core.Models.Fields { public class ReferenceField : Field { - [JsonProperty(propertyName: "reference_to")] - public object ReferenceTo { get; set; } - [JsonProperty(propertyName: "plugins")] + [JsonPropertyName("reference_to")] + public JsonElement? ReferenceTo { get; set; } + [JsonPropertyName("plugins")] public List Plugins { get; set; } } } diff --git a/Contentstack.Management.Core/Models/Fields/SelectField.cs b/Contentstack.Management.Core/Models/Fields/SelectField.cs index cfbdf14..ca03fe7 100644 --- a/Contentstack.Management.Core/Models/Fields/SelectField.cs +++ b/Contentstack.Management.Core/Models/Fields/SelectField.cs @@ -1,23 +1,24 @@ using System; using System.Collections.Generic; -using Newtonsoft.Json; +using System.Text.Json; +using System.Text.Json.Serialization; namespace Contentstack.Management.Core.Models.Fields { public class SelectField : Field { - [JsonProperty(propertyName: "enum")] + [JsonPropertyName("enum")] public SelectEnum Enum { get; set; } } public class SelectEnum { - [JsonProperty(propertyName: "advanced")] + [JsonPropertyName("advanced")] public bool Advanced { get; set; } - [JsonProperty(propertyName: "choices")] - public List> Choices { get; set; } + [JsonPropertyName("choices")] + public List> Choices { get; set; } } } diff --git a/Contentstack.Management.Core/Models/Fields/TaxonomyField.cs b/Contentstack.Management.Core/Models/Fields/TaxonomyField.cs index c9698ef..f700e2b 100644 --- a/Contentstack.Management.Core/Models/Fields/TaxonomyField.cs +++ b/Contentstack.Management.Core/Models/Fields/TaxonomyField.cs @@ -1,5 +1,5 @@ using System.Collections.Generic; -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Contentstack.Management.Core.Models.Fields { @@ -8,7 +8,7 @@ namespace Contentstack.Management.Core.Models.Fields /// public class TaxonomyField : Field { - [JsonProperty(propertyName: "taxonomies")] + [JsonPropertyName("taxonomies")] public List Taxonomies { get; set; } } @@ -17,19 +17,19 @@ public class TaxonomyField : Field /// public class TaxonomyFieldBinding { - [JsonProperty(propertyName: "taxonomy_uid")] + [JsonPropertyName("taxonomy_uid")] public string TaxonomyUid { get; set; } - [JsonProperty(propertyName: "max_terms")] + [JsonPropertyName("max_terms")] public int? MaxTerms { get; set; } - [JsonProperty(propertyName: "mandatory")] + [JsonPropertyName("mandatory")] public bool Mandatory { get; set; } - [JsonProperty(propertyName: "multiple")] + [JsonPropertyName("multiple")] public bool Multiple { get; set; } - [JsonProperty(propertyName: "non_localizable")] + [JsonPropertyName("non_localizable")] public bool NonLocalizable { get; set; } } } diff --git a/Contentstack.Management.Core/Models/Fields/TextboxField.cs b/Contentstack.Management.Core/Models/Fields/TextboxField.cs index 7ad201b..cdd2fdc 100644 --- a/Contentstack.Management.Core/Models/Fields/TextboxField.cs +++ b/Contentstack.Management.Core/Models/Fields/TextboxField.cs @@ -1,16 +1,15 @@ using System; using System.Collections.Generic; -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Contentstack.Management.Core.Models.Fields { public class TextboxField : Field { - - [JsonProperty(propertyName: "format")] + [JsonPropertyName("format")] public string Format { get; set; } - [JsonProperty(propertyName: "error_messages")] + [JsonPropertyName("error_messages")] public Dictionary ErrorMessages { get; set; } } } diff --git a/Contentstack.Management.Core/Models/GlobalFieldRefs.cs b/Contentstack.Management.Core/Models/GlobalFieldRefs.cs index ea9de95..dfe0088 100644 --- a/Contentstack.Management.Core/Models/GlobalFieldRefs.cs +++ b/Contentstack.Management.Core/Models/GlobalFieldRefs.cs @@ -1,5 +1,5 @@ using System.Collections.Generic; -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Contentstack.Management.Core.Models { @@ -12,25 +12,25 @@ public class GlobalFieldRefs /// /// The UID of the referenced global field. /// - [JsonProperty(propertyName: "uid")] - public string Uid { get; set; } + [JsonPropertyName("uid")] + public string? Uid { get; set; } /// /// The number of times this global field is referenced in the schema. /// - [JsonProperty(propertyName: "occurrence_count")] + [JsonPropertyName("occurrence_count")] public int OccurrenceCount { get; set; } /// /// Indicates whether this is a child reference. /// - [JsonProperty(propertyName: "isChild")] + [JsonPropertyName("isChild")] public bool IsChild { get; set; } /// /// Array of paths where this global field reference occurs in the schema. /// - [JsonProperty(propertyName: "paths")] - public List Paths { get; set; } + [JsonPropertyName("paths")] + public List? Paths { get; set; } } } \ No newline at end of file diff --git a/Contentstack.Management.Core/Models/Stack.cs b/Contentstack.Management.Core/Models/Stack.cs index e400c80..636b1b8 100644 --- a/Contentstack.Management.Core/Models/Stack.cs +++ b/Contentstack.Management.Core/Models/Stack.cs @@ -604,8 +604,6 @@ public Locale Locale(string code = null) } */ - /* - // The following resource methods are temporarily commented out as they reference excluded model types /// /// defines the structure or schema of a page or a section of your web or mobile property. /// To create content for your application, you are required to first create a content type, and then create entries using the content type. @@ -619,13 +617,15 @@ public Locale Locale(string code = null) /// /// /// The - public ContentType ContentType(string uid = null) + public ContentType ContentType(string? uid = null) { ThrowIfNotLoggedIn(); ThrowIfAPIKeyEmpty(); return new ContentType(this, uid); } + + /* /// /// efer to all the media files (images, videos, PDFs, audio files, and so on) uploaded in your Contentstack repository for future use. /// diff --git a/Contentstack.Management.Core/Queryable/Query.cs b/Contentstack.Management.Core/Queryable/Query.cs index e071188..32cc3ed 100644 --- a/Contentstack.Management.Core/Queryable/Query.cs +++ b/Contentstack.Management.Core/Queryable/Query.cs @@ -79,7 +79,6 @@ public Query IncludeCount() return this; } - /* /// /// The Find all object call fetches the list of all objects owned by a particular user account. /// @@ -119,7 +118,6 @@ public Task FindAsync(ParameterCollection collection = nul return _stack.client.InvokeAsync(service, false, _apiVersion); } - */ #endregion #region Throw Error diff --git a/Contentstack.Management.Core/Services/ContentstackService.cs b/Contentstack.Management.Core/Services/ContentstackService.cs index 60a994c..f9b5d0b 100644 --- a/Contentstack.Management.Core/Services/ContentstackService.cs +++ b/Contentstack.Management.Core/Services/ContentstackService.cs @@ -29,7 +29,7 @@ internal class ContentstackService : IContentstackService #endregion #region Constructor - internal ContentstackService(JsonSerializerOptions serializerOptions, Models.Stack stack = null, ParameterCollection collection = null) + internal ContentstackService(JsonSerializerOptions serializerOptions, Contentstack.Management.Core.Models.Stack stack = null, ParameterCollection collection = null) { if (serializerOptions == null) { diff --git a/Contentstack.Management.Core/Services/Models/CreateUpdateService.cs b/Contentstack.Management.Core/Services/Models/CreateUpdateService.cs index b4530e6..ac1a7ac 100644 --- a/Contentstack.Management.Core/Services/Models/CreateUpdateService.cs +++ b/Contentstack.Management.Core/Services/Models/CreateUpdateService.cs @@ -1,8 +1,7 @@ using System; -using System.Globalization; -using System.IO; +using System.Collections.Generic; +using System.Text.Json; using Contentstack.Management.Core.Queryable; -using Newtonsoft.Json; using Contentstack.Management.Core.Utils; namespace Contentstack.Management.Core.Services.Models @@ -13,8 +12,8 @@ internal class CreateUpdateService : ContentstackService private readonly string fieldName; #region Internal - internal CreateUpdateService(JsonSerializer serializer, Core.Models.Stack stack, string resourcePath, T dataModel, string fieldName, string httpMethod = "POST", ParameterCollection collection = null) - : base(serializer, stack: stack, collection) + internal CreateUpdateService(Core.Models.Stack stack, string resourcePath, T dataModel, string fieldName, string httpMethod = "POST", ParameterCollection collection = null, JsonSerializerOptions stjOptions = null) + : base(stjOptions ?? stack?.client?.SerializerOptions ?? new JsonSerializerOptions(), stack: stack, collection: collection) { if (stack.APIKey == null) { @@ -45,14 +44,13 @@ internal CreateUpdateService(JsonSerializer serializer, Core.Models.Stack stack, public override void ContentBody() { - using (StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture)) + var requestData = new Dictionary { - JsonWriter writer = new JsonTextWriter(stringWriter); + { fieldName, _typedModel } + }; - Serializer.Serialize(writer, _typedModel); - string snippet = $"{{\"{fieldName}\": {stringWriter.ToString()}}}"; - this.ByteContent = System.Text.Encoding.UTF8.GetBytes(snippet); - } + string jsonString = JsonSerializer.Serialize(requestData, SerializerOptions); + this.ByteContent = System.Text.Encoding.UTF8.GetBytes(jsonString); } } } diff --git a/Contentstack.Management.Core/Services/Models/DeleteService.cs b/Contentstack.Management.Core/Services/Models/DeleteService.cs index c0c4bec..715139b 100644 --- a/Contentstack.Management.Core/Services/Models/DeleteService.cs +++ b/Contentstack.Management.Core/Services/Models/DeleteService.cs @@ -1,8 +1,7 @@ using System; -using System.Globalization; -using System.IO; +using System.Collections.Generic; +using System.Text.Json; using Contentstack.Management.Core.Queryable; -using Newtonsoft.Json; using Contentstack.Management.Core.Utils; namespace Contentstack.Management.Core.Services.Models @@ -12,8 +11,8 @@ internal class DeleteService: ContentstackService internal string fieldName; internal T model; - internal DeleteService(JsonSerializer serializer, Core.Models.Stack stack, string resourcePath, string fieldName, T model, ParameterCollection collection = null) - : base(serializer, stack: stack, collection: collection) + internal DeleteService(Core.Models.Stack stack, string resourcePath, string fieldName, T model, ParameterCollection collection = null, JsonSerializerOptions stjOptions = null) + : base(stjOptions ?? stack?.client?.SerializerOptions ?? new JsonSerializerOptions(), stack: stack, collection: collection) { if (stack.APIKey == null) { @@ -40,14 +39,13 @@ internal DeleteService(JsonSerializer serializer, Core.Models.Stack stack, strin public override void ContentBody() { - using (StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture)) + var requestData = new Dictionary { - JsonWriter writer = new JsonTextWriter(stringWriter); + { fieldName, model } + }; - Serializer.Serialize(writer, model); - string snippet = $"{{\"{fieldName}\": {stringWriter.ToString()}}}"; - this.ByteContent = System.Text.Encoding.UTF8.GetBytes(snippet); - } + string jsonString = JsonSerializer.Serialize(requestData, SerializerOptions); + this.ByteContent = System.Text.Encoding.UTF8.GetBytes(jsonString); } } } diff --git a/Contentstack.Management.Core/Services/Models/FetchDeleteService.cs b/Contentstack.Management.Core/Services/Models/FetchDeleteService.cs index 8bd26bb..6ed5953 100644 --- a/Contentstack.Management.Core/Services/Models/FetchDeleteService.cs +++ b/Contentstack.Management.Core/Services/Models/FetchDeleteService.cs @@ -1,6 +1,6 @@ using System; +using System.Text.Json; using Contentstack.Management.Core.Queryable; -using Newtonsoft.Json; using Contentstack.Management.Core.Utils; namespace Contentstack.Management.Core.Services.Models @@ -9,8 +9,8 @@ internal class FetchDeleteService: ContentstackService { #region Internal - internal FetchDeleteService(JsonSerializer serializer, Core.Models.Stack stack, string resourcePath, string httpMethod = "GET", ParameterCollection collection = null) - : base(serializer, stack: stack, collection) + internal FetchDeleteService(Core.Models.Stack stack, string resourcePath, string httpMethod = "GET", ParameterCollection collection = null, JsonSerializerOptions stjOptions = null) + : base(stjOptions ?? stack?.client?.SerializerOptions ?? new JsonSerializerOptions(), stack: stack, collection: collection) { if (stack.APIKey == null) { diff --git a/Contentstack.Management.Core/Services/QueryService.cs b/Contentstack.Management.Core/Services/QueryService.cs index 751e7c4..fc60dcd 100644 --- a/Contentstack.Management.Core/Services/QueryService.cs +++ b/Contentstack.Management.Core/Services/QueryService.cs @@ -1,5 +1,5 @@ using System; -using Newtonsoft.Json; +using System.Text.Json; using Contentstack.Management.Core.Queryable; using Contentstack.Management.Core.Utils; @@ -10,7 +10,7 @@ internal class QueryService: ContentstackService #region Internal internal QueryService(Core.Models.Stack stack, ParameterCollection collection, string resourcePath) - : base(stack.client.serializer, stack, collection) + : base(stack.client.SerializerOptions, stack, collection) { if (string.IsNullOrEmpty(resourcePath)) { diff --git a/Contentstack.Management.Core/Utils/FieldJsonConverter.cs b/Contentstack.Management.Core/Utils/FieldJsonConverter.cs index 6d70e6a..f92c15f 100644 --- a/Contentstack.Management.Core/Utils/FieldJsonConverter.cs +++ b/Contentstack.Management.Core/Utils/FieldJsonConverter.cs @@ -36,6 +36,7 @@ public override void Write(Utf8JsonWriter writer, Field value, JsonSerializerOpt private static Type ResolveConcreteType(JsonElement jo) { + // Check for extension fields first var extensionUid = jo.TryGetProperty("extension_uid", out var ext) ? ext.GetString() : null; if (!string.IsNullOrEmpty(extensionUid)) return typeof(ExtensionField); diff --git a/Contentstack.Management.Core/contentstack.management.core.csproj b/Contentstack.Management.Core/contentstack.management.core.csproj index ebd9fef..c1efd89 100644 --- a/Contentstack.Management.Core/contentstack.management.core.csproj +++ b/Contentstack.Management.Core/contentstack.management.core.csproj @@ -84,10 +84,10 @@ - + - - + + @@ -110,13 +110,35 @@ - + + + + + + + + + + - - + + + + + + + + + + + + + + + @@ -127,8 +149,7 @@ - - + diff --git a/Directory.Build.props b/Directory.Build.props index 2ad39e3..1945233 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,5 +1,5 @@ - 1.0.0-beta.2 + 1.0.0-beta.3