I’m currently utilising .NET8 with its corresponding MongoDB driver. I have an array comprising mixed JSON objects that represent various actions to be executed based on rule evaluation, such as sending emails or setting timers.
To facilitate their storage an abstract BaseAction class has been implemented, which adheres to the IAction interface.
Derived from this base class are several action classes, each inheriting properties and functionalities from BaseAction. Serialisation to the database, specifically Cosmos DB for MongoDB, occurs smoothly without any issue when I implement the property of type BaseAction (as seen in the example of strategy class below) and I can deserialise the data. All seems well except that upon examination of the data returned using breakpoints there is the presence of all necessary properties having been fetched.
However inspecting the final returned strategies output via the associated swagger page, it becomes evident that the additional properties inherited from subclasses e.g. Hours, Minutes, Seconds or Recipients, EmailSubject, EmailMessage are discarded, leaving only those belonging to BaseAction.
I have tried replacing BaseAction with IAction but at this point the request to the database throws an exception leaving the solution to this issue rather uncertain.
Any help with this would be really helpful as I’m new to developing with MongoDb and would really appreciate any input.
Service:
{
private readonly MongoClient _client;
private IMongoDatabase? _database;
private IMongoCollection<Strategy>? _strategyCollection;
public StrategyService(IOptions<Settings> mongoDBSettings)
{
_client = new MongoClient(mongoDBSettings.Value.ConnectionURI);
}
private void SetDatabase(string networkId)
{
_database = _client.GetDatabase(networkId);
_strategyCollection = _database.GetCollection<Strategy>("Strategies");
}
public async Task<IEnumerable<Strategy>> GetStrategies(string networkId, Guid? strategyId)
{
try
{
SetDatabase(networkId);
var filter = Builders<Strategy>.Filter.Empty;
if (strategyId.HasValue)
{
filter = Builders<Strategy>.Filter.Eq("Id", strategyId);
}
var strategies = await _strategyCollection.Find<Strategy>(filter).ToListAsync();
return strategies;
}
catch (Exception ex)
{
Console.WriteLine($"Error in GetStrategies: {ex.Message}");
throw;
}
}
public async Task<IActionResult> AddStrategy(string networkId, StrategyRequest strategy)
{
try
{
SetDatabase(networkId);
var convertRequest = new Strategy(strategy);
if (_strategyCollection == null)
{
return new ObjectResult("Failed to add strategy. _strategyCollection is null.") { StatusCode = 500 };
}
await _strategyCollection.InsertOneAsync(convertRequest);
return new OkResult();
}
catch (Exception ex)
{
return new ObjectResult($"Failed to add strategy: {ex.Message}") { StatusCode = 500 };
}
}
}
Strategy Class which contains a list of actions
{
public List<BaseAction> Actions { get; set; } = [];
}
BaseAction Class:
[BsonKnownTypes(typeof(ActionChangeDataItem), typeof(ActionChangeStatus), typeof(ActionSendBatchCommand), typeof(ActionSendEmail), typeof(ActionSwitchPlan), typeof(ActionTimer))]
public abstract class BaseAction : IAction
{
public Guid Id { get; set; }
public string ActionOrigin { get; set; }
public string ActionType { get; set; }
public int Order { get; set; }
public BaseAction() { }
}
IAction Interface
{
Guid Id { get; set; }
string ActionOrigin { get; set; }
string ActionType { get; set; }
int Order { get; set; }
}
Example of actions inheriting from BaseAction / IAction
{
public List<string> Recipients { get; set; }
public string EmailSubject { get; set; }
public string EmailContent { get; set; }
}
public class ActionTimer : BaseAction
{
public int? Hours { get; set; }
public int? Minutes { get; set; }
public int? Seconds { get; set; }
public ActionTimer() { }
}