Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion Contentstack.Management.Core/ContentstackClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
Expand Down
34 changes: 17 additions & 17 deletions Contentstack.Management.Core/Models/BaseModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class BaseModel<T>
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)
Expand All @@ -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<T>(stack.client.serializer, stack, resourcePath, model, this.fieldName, collection: collection);
var service = new CreateUpdateService<T>(stack, resourcePath, model, this.fieldName, collection: collection, stjOptions: stack.client.SerializerOptions);
return stack.client.InvokeSync(service);
}

public virtual Task<ContentstackResponse> CreateAsync(T model, ParameterCollection collection = null)
public virtual Task<ContentstackResponse> CreateAsync(T model, ParameterCollection? collection = null)
{
ThrowIfUidNotEmpty();
stack.ThrowIfNotLoggedIn();

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

return stack.client.InvokeAsync<CreateUpdateService<T>, 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<T>(stack.client.serializer, stack, resourcePath, model, this.fieldName, "PUT", collection: collection);
var service = new CreateUpdateService<T>(stack, resourcePath, model, this.fieldName, "PUT", collection: collection, stjOptions: stack.client.SerializerOptions);
return stack.client.InvokeSync(service);
}

public virtual Task<ContentstackResponse> UpdateAsync(T model, ParameterCollection collection = null)
public virtual Task<ContentstackResponse> UpdateAsync(T model, ParameterCollection? collection = null)
{
stack.ThrowIfNotLoggedIn();
ThrowIfUidEmpty();

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

return stack.client.InvokeAsync<CreateUpdateService<T>, 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<ContentstackResponse> FetchAsync(ParameterCollection collection = null)
public virtual Task<ContentstackResponse> 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<FetchDeleteService, ContentstackResponse>(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<ContentstackResponse> DeleteAsync(ParameterCollection collection = null)
public virtual Task<ContentstackResponse> 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<FetchDeleteService, ContentstackResponse>(service);
}
Expand Down
52 changes: 25 additions & 27 deletions Contentstack.Management.Core/Models/ContentModelling.cs
Original file line number Diff line number Diff line change
@@ -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> FieldRules { get; set; }
[JsonPropertyName("field_rules")]
public List<FieldRules>? FieldRules { get; set; }

[JsonProperty(propertyName: "schema")]
public List<Field> Schema { get; set; }
[JsonPropertyName("schema")]
public List<Field>? Schema { get; set; }

[JsonProperty(propertyName: "global_field_refs")]
public List<GlobalFieldRefs> GlobalFieldRefs { get; set; }
[JsonPropertyName("global_field_refs")]
public List<GlobalFieldRefs>? 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<string> SubTitle { get; set; }
[JsonPropertyName("sub_title")]
public List<string>? 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; }

}
}
18 changes: 10 additions & 8 deletions Contentstack.Management.Core/Models/ContentType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public Query Query()
/// </example>
/// <param name="model">IContentType for updating Content Type.</param>
/// <returns></returns>
public override ContentstackResponse Create(ContentModelling model, ParameterCollection collection = null)
public override ContentstackResponse Create(ContentModelling model, ParameterCollection? collection = null)
{
return base.Create(model, collection);
}
Expand All @@ -56,7 +56,7 @@ public override ContentstackResponse Create(ContentModelling model, ParameterCol
/// </example>
/// <param name="model">IContentType for updating Content Type.</param>
/// <returns></returns>
public override Task<ContentstackResponse> CreateAsync(ContentModelling model, ParameterCollection collection = null)
public override Task<ContentstackResponse> CreateAsync(ContentModelling model, ParameterCollection? collection = null)
{
return base.CreateAsync(model, collection);
}
Expand All @@ -73,7 +73,7 @@ public override Task<ContentstackResponse> CreateAsync(ContentModelling model, P
/// </example>
/// <param name="model">IContentType for updating Content Type.</param>
/// <returns></returns>
public override ContentstackResponse Update(ContentModelling model, ParameterCollection collection = null)
public override ContentstackResponse Update(ContentModelling model, ParameterCollection? collection = null)
{
return base.Update(model, collection);
}
Expand All @@ -90,7 +90,7 @@ public override ContentstackResponse Update(ContentModelling model, ParameterCol
/// </example>
/// <param name="model">IContentType for updating Content Type.</param>
/// <returns></returns>
public override Task<ContentstackResponse> UpdateAsync(ContentModelling model, ParameterCollection collection = null)
public override Task<ContentstackResponse> UpdateAsync(ContentModelling model, ParameterCollection? collection = null)
{
return base.UpdateAsync(model, collection);
}
Expand All @@ -105,7 +105,7 @@ public override Task<ContentstackResponse> UpdateAsync(ContentModelling model, P
/// </code></pre>
/// </example>
/// <returns>The <see cref="ContentstackResponse"/>.</returns>
public override ContentstackResponse Fetch(ParameterCollection collection = null)
public override ContentstackResponse Fetch(ParameterCollection? collection = null)
{
return base.Fetch(collection);
}
Expand All @@ -120,7 +120,7 @@ public override ContentstackResponse Fetch(ParameterCollection collection = null
/// </code></pre>
/// </example>
/// <returns>The Task.</returns>
public override Task<ContentstackResponse> FetchAsync(ParameterCollection collection = null)
public override Task<ContentstackResponse> FetchAsync(ParameterCollection? collection = null)
{
return base.FetchAsync(collection);
}
Expand All @@ -135,7 +135,7 @@ public override Task<ContentstackResponse> FetchAsync(ParameterCollection collec
/// </code></pre>
/// </example>
/// <returns>The <see cref="ContentstackResponse"/>.</returns>
public override ContentstackResponse Delete(ParameterCollection collection = null)
public override ContentstackResponse Delete(ParameterCollection? collection = null)
{
return base.Delete(collection);
}
Expand All @@ -150,11 +150,12 @@ public override ContentstackResponse Delete(ParameterCollection collection = nul
/// </code></pre>
/// </example>
/// <returns>The Task.</returns>
public override Task<ContentstackResponse> DeleteAsync(ParameterCollection collection = null)
public override Task<ContentstackResponse> DeleteAsync(ParameterCollection? collection = null)
{
return base.DeleteAsync(collection);
}

/*
/// <summary>
/// <see cref="Models.Entry" /> is the actual piece of content created using one of the defined content types.
/// </summary>
Expand All @@ -176,5 +177,6 @@ public Entry Entry(string uid = null)
ThrowIfUidEmpty();
return new Entry(stack, Uid, uid);
}
*/
}
}
6 changes: 3 additions & 3 deletions Contentstack.Management.Core/Models/Fields/DateField.cs
Original file line number Diff line number Diff line change
@@ -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; }
}
}
Original file line number Diff line number Diff line change
@@ -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<string, object> config { get; set; }
[JsonPropertyName("config")]
public Dictionary<string, JsonElement> config { get; set; }
}
}
29 changes: 14 additions & 15 deletions Contentstack.Management.Core/Models/Fields/Field.cs
Original file line number Diff line number Diff line change
@@ -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
{
/// <summary>
/// Determines the display name of a field. It is a mandatory field.
/// </summary>
[JsonProperty(propertyName: "display_name")]
public string DisplayName { get; set; }
[JsonPropertyName("display_name")]
public string? DisplayName { get; set; }
/// <summary>
/// Represents the unique ID of each field. It is a mandatory field.
/// </summary>
[JsonProperty(propertyName: "uid")]
public string Uid { get; set; }
[JsonPropertyName("uid")]
public string? Uid { get; set; }
/// <summary>
/// Determines what value can be provided to the Title field.
/// </summary>
[JsonProperty(propertyName: "data_type")]
public string DataType { get; set; }
[JsonPropertyName("data_type")]
public string? DataType { get; set; }
/// <summary>
/// Allows you to enter additional data about a field. Also, you can add additional values under 'field_metadata'.
/// </summary>
[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; }

/// <summary>
/// Presentation widget for text fields (e.g. dropdown, checkbox).
/// </summary>
[JsonProperty(propertyName: "display_type")]
public string DisplayType { get; set; }
[JsonPropertyName("display_type")]
public string? DisplayType { get; set; }
}
}
Loading
Loading