I have the following Log classes in my application that can be logged into MongoDB:
public abstract class Log
{
public Guid Id { get; set; }
public DateTime DateCreated { get; set; }
}
public class ActivityLog : Log
{
public string RouteParameters { get; set; }
public string RequestType { get; set; }
}
public class ErrorLog : Log
{
public string StackTrace { get; set; }
}
public class WebErrorLog : ErrorLog
{
public string RouteParameters { get; set; }
public string RequestType { get; set; }
}
As you can see, the Log class is the base class for all of my logging types. The WebErrorLog inherits the properties of the ErrorLog class and also extends to include the RouteParameters and RequestType properties (which are also included in the ActivityLog class). On my application I create a new WebErrorLog and save it into the MongoDB. Although it is being saved to the correct database (WebErrorLog db) the properties inherited from the ErrorLog class are being ignored. I think it might have to do in how my classes are registered in the BsonClassMapper as follows:
public static void RegisterLogClasses()
{
if (!BsonClassMap.IsClassMapRegistered(typeof(Log)))
{
BsonClassMap.RegisterClassMap<Log>(
cm =>
{
cm.AutoMap();
cm.MapIdProperty(c => c.Id);
cm.GetMemberMap(c => c.Id).SetRepresentation(BsonType.String);
cm.SetIgnoreExtraElements(true);
});
}
if (!BsonClassMap.IsClassMapRegistered(typeof(ErrorLog)))
{
BsonClassMap.RegisterClassMap<ErrorLog>(
cm =>
{
cm.SetIgnoreExtraElements(true);
});
}
if (!BsonClassMap.IsClassMapRegistered(typeof(WebErrorLog)))
{
BsonClassMap.RegisterClassMap<WebErrorLog>();
}
if (!BsonClassMap.IsClassMapRegistered(typeof(ActivityLog)))
{
BsonClassMap.RegisterClassMap<ActivityLog>();
}
if (!BsonClassMap.IsClassMapRegistered(typeof(DebugLog)))
{
BsonClassMap.RegisterClassMap<DebugLog>();
}
BsonSerializer.UseNullIdChecker = true;
}
}
I have solved the issue. It turns out that I was not correctly mapping the classes in the BsonClassMapper. So I removed the code in the RegisterLogClasses method and replaced with the following:
public static void RegisterLogClasses()
{
if (!BsonClassMap.IsClassMapRegistered(typeof(Log)))
{
BsonClassMap.RegisterClassMap<Log>();
}
if (!BsonClassMap.IsClassMapRegistered(typeof(ErrorLog)))
{
BsonClassMap.RegisterClassMap<ErrorLog>();
}
if (!BsonClassMap.IsClassMapRegistered(typeof(WebErrorLog)))
{
BsonClassMap.RegisterClassMap<WebErrorLog>();
}
if (!BsonClassMap.IsClassMapRegistered(typeof(ActivityLog)))
{
BsonClassMap.RegisterClassMap<ActivityLog>();
}
BsonSerializer.UseNullIdChecker = true;
}
}
And I had to change the class definition to add the constraints as data annotations. I had to add a BsonDiscriminator to the root class and define the possible class implementations on the root classes.
[BsonIgnoreExtraElements]
[BsonDiscriminator(RootClass = true)]
[BsonKnownTypes(typeof(ActivityLog), typeof(ErrorLog))]
public abstract class Log
{
[BsonId]
public Guid Id { get; set; }
public DateTime DateCreated { get; set; }
}
[BsonIgnoreExtraElements]
public class ActivityLog : Log
{
public string RouteParameters { get; set; }
public string RequestType { get; set; }
}
[BsonIgnoreExtraElements]
[BsonKnownTypes(typeof(WebErrorLog))]
public class ErrorLog : Log
{
public string StackTrace { get; set; }
}
[BsonIgnoreExtraElements]
[BsonDiscriminator("WebErrorLog")]
public class WebErrorLog : ErrorLog
{
public string RouteParameters { get; set; }
public string RequestType { get; set; }
}