Skip to content

Commit 0ba1924

Browse files
committed
feat: ContentType & QueryService STJ Migration
1 parent 5673d9e commit 0ba1924

19 files changed

Lines changed: 183 additions & 141 deletions

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
11
# Changelog
22

3+
## [v1.0.0-beta.3](https://github.com/contentstack/contentstack-management-dotnet/tree/v1.0.0-beta.3)
4+
- **ContentType & QueryService STJ Migration**
5+
- **✅ ContentType Module**: Fully migrated ContentType model and dependencies to System.Text.Json
6+
- **✅ QueryService Migration**: Re-enabled and migrated QueryService for content type listing
7+
- **✅ Field System**: Converted core Field models (FieldMetadata, Field, FieldRules) to STJ
8+
- **✅ ContentModelling**: Updated ContentModelling and Option classes with STJ attributes
9+
- **✅ Service Layer**: Migrated CreateUpdateService, FetchDeleteService, and DeleteService
10+
- **✅ Web App Integration**: Complete ContentType CRUD interface with modern UI
11+
- **✅ Schema Validation**: Added default "Title" field to prevent 422 API errors
12+
- **✅ Error Handling**: Enhanced error reporting with detailed API validation messages
13+
- **✅ Navigation**: Integrated ContentType management into Stack workflow
14+
315
## [v1.0.0-beta.2](https://github.com/contentstack/contentstack-management-dotnet/tree/v1.0.0-beta.2)
416
- **System.Text.Json Migration Complete (Beta)**
517
- **✅ Core Modules STJ-Only**: Client, User, Organization, and Stack modules fully migrated

Contentstack.Management.Core/ContentstackClient.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ protected void Initialize(HttpClient? httpClient = null)
200200
SerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
201201
SerializerOptions.PropertyNameCaseInsensitive = true;
202202

203-
// SerializerOptions.Converters.Add(new FieldJsonConverter()); // Excluded for now
203+
SerializerOptions.Converters.Add(new FieldJsonConverter()); // Re-enabled for ContentType support
204204
SerializerOptions.Converters.Add(new NodeJsonConverter());
205205
SerializerOptions.Converters.Add(new TextNodeJsonConverter());
206206
}

Contentstack.Management.Core/Models/BaseModel.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public virtual ContentstackResponse Create(T model, ParameterCollection collecti
3131
{
3232
ThrowIfUidNotEmpty();
3333

34-
var service = new CreateUpdateService<T>(stack.client.serializer, stack, resourcePath, model, this.fieldName, collection: collection);
34+
var service = new CreateUpdateService<T>(stack, resourcePath, model, this.fieldName, collection: collection, stjOptions: stack.client.SerializerOptions);
3535
return stack.client.InvokeSync(service);
3636
}
3737

@@ -40,7 +40,7 @@ public virtual Task<ContentstackResponse> CreateAsync(T model, ParameterCollecti
4040
ThrowIfUidNotEmpty();
4141
stack.ThrowIfNotLoggedIn();
4242

43-
var service = new CreateUpdateService<T>(stack.client.serializer, stack, resourcePath, model, this.fieldName, collection: collection);
43+
var service = new CreateUpdateService<T>(stack, resourcePath, model, this.fieldName, collection: collection, stjOptions: stack.client.SerializerOptions);
4444

4545
return stack.client.InvokeAsync<CreateUpdateService<T>, ContentstackResponse>(service);
4646
}
@@ -49,7 +49,7 @@ public virtual ContentstackResponse Update(T model, ParameterCollection collecti
4949
{
5050
ThrowIfUidEmpty();
5151

52-
var service = new CreateUpdateService<T>(stack.client.serializer, stack, resourcePath, model, this.fieldName, "PUT", collection: collection);
52+
var service = new CreateUpdateService<T>(stack, resourcePath, model, this.fieldName, "PUT", collection: collection, stjOptions: stack.client.SerializerOptions);
5353
return stack.client.InvokeSync(service);
5454
}
5555

@@ -58,7 +58,7 @@ public virtual Task<ContentstackResponse> UpdateAsync(T model, ParameterCollecti
5858
stack.ThrowIfNotLoggedIn();
5959
ThrowIfUidEmpty();
6060

61-
var service = new CreateUpdateService<T>(stack.client.serializer, stack, resourcePath, model, this.fieldName, "PUT", collection: collection);
61+
var service = new CreateUpdateService<T>(stack, resourcePath, model, this.fieldName, "PUT", collection: collection, stjOptions: stack.client.SerializerOptions);
6262

6363
return stack.client.InvokeAsync<CreateUpdateService<T>, ContentstackResponse>(service);
6464
}
@@ -68,7 +68,7 @@ public virtual ContentstackResponse Fetch(ParameterCollection collection = null)
6868
stack.ThrowIfNotLoggedIn();
6969
ThrowIfUidEmpty();
7070

71-
var service = new FetchDeleteService(stack.client.serializer, stack, resourcePath, collection: collection);
71+
var service = new FetchDeleteService(stack, resourcePath, collection: collection, stjOptions: stack.client.SerializerOptions);
7272
return stack.client.InvokeSync(service);
7373
}
7474

@@ -77,7 +77,7 @@ public virtual Task<ContentstackResponse> FetchAsync(ParameterCollection collect
7777
stack.ThrowIfNotLoggedIn();
7878
ThrowIfUidEmpty();
7979

80-
var service = new FetchDeleteService(stack.client.serializer, stack, resourcePath, collection: collection);
80+
var service = new FetchDeleteService(stack, resourcePath, collection: collection, stjOptions: stack.client.SerializerOptions);
8181
return stack.client.InvokeAsync<FetchDeleteService, ContentstackResponse>(service);
8282
}
8383

@@ -86,7 +86,7 @@ public virtual ContentstackResponse Delete(ParameterCollection collection = null
8686
stack.ThrowIfNotLoggedIn();
8787
ThrowIfUidEmpty();
8888

89-
var service = new FetchDeleteService(stack.client.serializer, stack, resourcePath, "DELETE", collection: collection);
89+
var service = new FetchDeleteService(stack, resourcePath, "DELETE", collection: collection, stjOptions: stack.client.SerializerOptions);
9090
return stack.client.InvokeSync(service);
9191
}
9292

@@ -95,7 +95,7 @@ public virtual Task<ContentstackResponse> DeleteAsync(ParameterCollection collec
9595
stack.ThrowIfNotLoggedIn();
9696
ThrowIfUidEmpty();
9797

98-
var service = new FetchDeleteService(stack.client.serializer, stack, resourcePath, "DELETE", collection: collection);
98+
var service = new FetchDeleteService(stack, resourcePath, "DELETE", collection: collection, stjOptions: stack.client.SerializerOptions);
9999

100100
return stack.client.InvokeAsync<FetchDeleteService, ContentstackResponse>(service);
101101
}
Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,53 @@
11
using System.Collections.Generic;
22
using System.Linq;
3+
using System.Text.Json.Serialization;
34
using Contentstack.Management.Core.Models.Fields;
4-
using Newtonsoft.Json;
55

66
namespace Contentstack.Management.Core.Models
77
{
8-
[JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)]
98
public class ContentModelling
109
{
11-
[JsonProperty(propertyName: "title")]
12-
public string Title { get; set; }
10+
[JsonPropertyName("title")]
11+
public string? Title { get; set; }
1312

14-
[JsonProperty(propertyName: "uid")]
15-
public string Uid { get; set; }
13+
[JsonPropertyName("uid")]
14+
public string? Uid { get; set; }
1615

17-
[JsonProperty(propertyName: "description")]
18-
public string Description { get; set; }
16+
[JsonPropertyName("description")]
17+
public string? Description { get; set; }
1918

20-
[JsonProperty(propertyName: "field_rules")]
21-
public List<FieldRules> FieldRules { get; set; }
19+
[JsonPropertyName("field_rules")]
20+
public List<FieldRules>? FieldRules { get; set; }
2221

23-
[JsonProperty(propertyName: "schema")]
24-
public List<Field> Schema { get; set; }
22+
[JsonPropertyName("schema")]
23+
public List<Field>? Schema { get; set; }
2524

26-
[JsonProperty(propertyName: "global_field_refs")]
27-
public List<GlobalFieldRefs> GlobalFieldRefs { get; set; }
25+
[JsonPropertyName("global_field_refs")]
26+
public List<GlobalFieldRefs>? GlobalFieldRefs { get; set; }
2827

29-
[JsonProperty(propertyName: "options")]
30-
public Option Options { get; set; }
28+
[JsonPropertyName("options")]
29+
public Option? Options { get; set; }
3130
}
3231

33-
[JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)]
3432
public class Option
3533
{
36-
[JsonProperty(propertyName: "title")]
37-
public string Title { get; set; }
34+
[JsonPropertyName("title")]
35+
public string? Title { get; set; }
3836

39-
[JsonProperty(propertyName: "sub_title")]
40-
public List<string> SubTitle { get; set; }
37+
[JsonPropertyName("sub_title")]
38+
public List<string>? SubTitle { get; set; }
4139

42-
[JsonProperty(propertyName: "singleton")]
40+
[JsonPropertyName("singleton")]
4341
public bool Singleton { get; set; }
4442

45-
[JsonProperty(propertyName: "is_page")]
43+
[JsonPropertyName("is_page")]
4644
public bool IsPage { get; set; }
4745

48-
[JsonProperty(propertyName: "url_pattern")]
49-
public string UrlPattern { get; set; }
46+
[JsonPropertyName("url_pattern")]
47+
public string? UrlPattern { get; set; }
5048

51-
[JsonProperty(propertyName: "url_prefix")]
52-
public string UrlPrefix { get; set; }
49+
[JsonPropertyName("url_prefix")]
50+
public string? UrlPrefix { get; set; }
5351

5452
}
5553
}

Contentstack.Management.Core/Models/ContentType.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ public override Task<ContentstackResponse> DeleteAsync(ParameterCollection colle
155155
return base.DeleteAsync(collection);
156156
}
157157

158+
/*
158159
/// <summary>
159160
/// <see cref="Models.Entry" /> is the actual piece of content created using one of the defined content types.
160161
/// </summary>
@@ -176,5 +177,6 @@ public Entry Entry(string uid = null)
176177
ThrowIfUidEmpty();
177178
return new Entry(stack, Uid, uid);
178179
}
180+
*/
179181
}
180182
}
Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,44 @@
11
using System;
2-
using Newtonsoft.Json;
2+
using System.Text.Json.Serialization;
33

44
namespace Contentstack.Management.Core.Models.Fields
55
{
6-
[JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)]
76
public class Field
87
{
98
/// <summary>
109
/// Determines the display name of a field. It is a mandatory field.
1110
/// </summary>
12-
[JsonProperty(propertyName: "display_name")]
13-
public string DisplayName { get; set; }
11+
[JsonPropertyName("display_name")]
12+
public string? DisplayName { get; set; }
1413
/// <summary>
1514
/// Represents the unique ID of each field. It is a mandatory field.
1615
/// </summary>
17-
[JsonProperty(propertyName: "uid")]
18-
public string Uid { get; set; }
16+
[JsonPropertyName("uid")]
17+
public string? Uid { get; set; }
1918
/// <summary>
2019
/// Determines what value can be provided to the Title field.
2120
/// </summary>
22-
[JsonProperty(propertyName: "data_type")]
23-
public string DataType { get; set; }
21+
[JsonPropertyName("data_type")]
22+
public string? DataType { get; set; }
2423
/// <summary>
2524
/// Allows you to enter additional data about a field. Also, you can add additional values under 'field_metadata'.
2625
/// </summary>
27-
[JsonProperty(propertyName: "field_metadata")]
28-
public FieldMetadata FieldMetadata { get; set; }
26+
[JsonPropertyName("field_metadata")]
27+
public FieldMetadata? FieldMetadata { get; set; }
2928

30-
[JsonProperty(propertyName: "multiple")]
29+
[JsonPropertyName("multiple")]
3130
public bool Multiple { get; set; }
3231

33-
[JsonProperty(propertyName: "mandatory")]
32+
[JsonPropertyName("mandatory")]
3433
public bool Mandatory { get; set; }
3534

36-
[JsonProperty(propertyName: "unique")]
35+
[JsonPropertyName("unique")]
3736
public bool Unique { get; set; }
3837

3938
/// <summary>
4039
/// Presentation widget for text fields (e.g. dropdown, checkbox).
4140
/// </summary>
42-
[JsonProperty(propertyName: "display_type")]
43-
public string DisplayType { get; set; }
41+
[JsonPropertyName("display_type")]
42+
public string? DisplayType { get; set; }
4443
}
4544
}
Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,96 +1,98 @@
11
using System;
22
using System.Collections.Generic;
3-
using Newtonsoft.Json;
3+
using System.Text.Json;
4+
using System.Text.Json.Serialization;
45

56
namespace Contentstack.Management.Core.Models.Fields
67
{
78
public class FieldMetadata
89
{
910
/// <summary>
1011
/// Allows you to set default fields for content types.
12+
/// API can send both boolean and string values, so using JsonElement for flexibility.
1113
/// </summary>
12-
[JsonProperty(propertyName: "_default")]
13-
public string Default { get; set; }
14+
[JsonPropertyName("_default")]
15+
public JsonElement? Default { get; set; }
1416

1517
/// <summary>
1618
/// Allows you to set a default value for a field.
1719
/// </summary>
18-
[JsonProperty(propertyName: "default_value")]
19-
public object DefaultValue { get; set; }
20+
[JsonPropertyName("default_value")]
21+
public object? DefaultValue { get; set; }
2022

2123
/// <summary>
2224
/// Determines whether the editor will support rich text, and is set to ‘true’ by default for Rich Text Editors.
2325
/// </summary>
24-
[JsonProperty(propertyName: "allow_rich_text")]
26+
[JsonPropertyName("allow_rich_text")]
2527
public bool AllowRichText { get; set; }
2628

2729
/// <summary>
2830
/// Allows you to provide the content for the Rich text editor field.
2931
/// </summary>
30-
[JsonProperty(propertyName: "description")]
31-
public string Description { get; set; }
32+
[JsonPropertyName("description")]
33+
public string? Description { get; set; }
3234

3335
/// <summary>
3436
/// Provides multi-line capabilities to the Rich text editor.
3537
/// </summary>
36-
[JsonProperty(propertyName: "multiline")]
38+
[JsonPropertyName("multiline")]
3739
public bool Multiline { get; set; }
3840

3941
/// <summary>
4042
/// Lets you enable either the basic, custom, or advanced editor to enter your content.
4143
/// </summary>
42-
[JsonProperty(propertyName: "rich_text_type")]
43-
public string RichTextType { get; set; }
44+
[JsonPropertyName("rich_text_type")]
45+
public string? RichTextType { get; set; }
4446

4547
/// <summary>
4648
/// If you choose the Custom editor, then the options key lets you specify the formatting options you prefer for your RTE toolbar,
4749
/// e.g., "options": ["h3", "blockquote", "sup"]
4850
/// </summary>
49-
[JsonProperty(propertyName: "options")]
50-
public List<string> Options { get; set; }
51+
[JsonPropertyName("options")]
52+
public List<string>? Options { get; set; }
5153

5254
/// <summary>
5355
/// This key determines whether you are using the older version of the Rich Text Editor or the latest version.
5456
/// 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.
5557
/// </summary>
56-
[JsonProperty(propertyName: "version")]
58+
[JsonPropertyName("version")]
5759
public int Version { get; set; }
5860

5961
/// <summary>
6062
/// Lets you assign a field to be a markdown by setting its value to ‘true’.
6163
/// </summary>
62-
[JsonProperty(propertyName: "markdown")]
64+
[JsonPropertyName("markdown")]
6365
public bool Markdown { get; set; }
6466

6567
/// <summary>
6668
/// Allows you to provide a hint text about the values that need to be entered in an input field, e.g., Single Line Textbox.
6769
/// This text can be seen inside the field until you enter a value.
6870
/// </summary>
69-
[JsonProperty(propertyName: "placeholder")]
70-
public string Placeholder { get; set; }
71+
[JsonPropertyName("placeholder")]
72+
public string? Placeholder { get; set; }
7173

7274
/// <summary>
7375
/// Allows you to add instructions for the content managers while entering values for a field. The instructional text appears below the field.
7476
/// </summary>
75-
[JsonProperty(propertyName: "instruction")]
76-
public string Instruction { get; set; }
77+
[JsonPropertyName("instruction")]
78+
public string? Instruction { get; set; }
7779

7880
/// <summary>
7981
/// Allows you to set single or multiple reference to Reference field.
8082
/// </summary>
81-
[JsonProperty(propertyName: "ref_multiple")]
83+
[JsonPropertyName("ref_multiple")]
8284
public bool RefMultiple { get; set; }
8385

8486
/// <summary>
8587
/// When true, the field is a JSON Rich Text Editor (JRTE).
8688
/// </summary>
87-
[JsonProperty(propertyName: "allow_json_rte")]
89+
[JsonPropertyName("allow_json_rte")]
8890
public bool? AllowJsonRte { get; set; }
8991

9092
/// <summary>
9193
/// Allows embedding entries in the JSON RTE / rich text configuration.
9294
/// </summary>
93-
[JsonProperty(propertyName: "embed_entry")]
95+
[JsonPropertyName("embed_entry")]
9496
public bool? EmbedEntry { get; set; }
9597

9698
}
@@ -99,7 +101,7 @@ public class FileFieldMetadata: FieldMetadata
99101
/// <summary>
100102
/// Allows you to set single or multiple reference to Reference field.
101103
/// </summary>
102-
[JsonProperty(propertyName: "image")]
104+
[JsonPropertyName("image")]
103105
public bool AllowOnlyImage { get; set; }
104106
}
105107
}

0 commit comments

Comments
 (0)