1

This question is related to another question I asked on this site but I think I have to post a new question to get an answer. That question is: How do I get the values of the properties of a model object in ASP.NET MVC when passed in as an object?

I would like to add a method to each of the model classes that were generated by MVC for the database tables. I want to be able to write information to a log about any object from the model by just calling some method on each object. It could be .LogInfo and would return a string. Currently I am using JSON serialization in my logging method and I pass in whatever object I want to log about. I have to knock out certain fields with the [JsonIgnore] attribute to prevent sensitive information being written to the log. It would be better to have to affirmatively add each field I want to log to some method.

I feel like I should be extending a class that contains an abstract .LogInfo method that each class from my model should extend. But I don't think I can do that, even with partial classes.

Is there some way this can be done with some facility I don't know about? If I add the .LogInfo method to each model class, then it would be wiped out if I have to regenerate the model. Maybe this is acceptable, but I am wondering if there is a more proper way.

This is how I cam declaring my LogEvent method, so I can pass in any object from the model:

public void LogEvent(string userName, int? userID, int? townID, string httpVerb, string description, bool isError, Object obj)
{
    JsonSerializerSettings settings = new JsonSerializerSettings();
    settings.MaxDepth = 1;
    settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
    settings.NullValueHandling = NullValueHandling.Ignore;
    string bigText = JsonConvert.SerializeObject(obj, settings);
    LogEvent(userName, userID, townID, httpVerb, description, isError, bigText);
}

because I have another overloaded method that takes the last parameter as a string and writes it to the log.

but I would rather be doing this:

public void LogEvent(string userName, int? userID, int? townID, string httpVerb, string description, bool isError, Object obj)
{
    LogEvent(userName, userID, townID, httpVerb, description, isError, obj.LogInfo());
}
jkurant
  • 45
  • 7

3 Answers3

2

Each class generated by EF is actually a partial class.

public partial class SomeObject

This means you can add to them in another file. Create another file of your own, and add your method there:

public partial class SomeObject
{
    public string LogInfo(object objToLog)
    {
        // do log stuff here
    }
}

This way, your new method will not be overwritten if you regenerate the model.

Nathan Miller
  • 785
  • 4
  • 11
1

First, define a base class that gets the LogInfo for you.

class EntityBase
{
    public string LogInfo()
    {
        return JsonConvert.Serialize(this);  //Just an example
    }
}

Now define partial classes for your models. These partial classes will be merged with the ones that EF generates. When you define them, add the base class inheritance; this will propogate to the EF classes when you compile, even though the inheritance is only declared in one place (see If a partial class inherits from a class then all other partials classes should also inherit the base class).

partial class MyEntity : EntityBase
{
    //You don't actually have to put anything here unless you want to override LogInfo
}          

Now change your logging method and specify the base class instead of object:

public void LogEvent(string userName, int? userID, int? townID, string httpVerb, string description, bool isError, EntityBase obj)
{
    LogEvent(userName, userID, townID, httpVerb, description, isError, obj.LogInfo());
}
John Wu
  • 50,556
  • 8
  • 44
  • 80
  • 1
    That's it! Thank you so much! What I didn't know is this: If a partial class inherits from a class then all other partial classes should also inherit the base class. – jkurant Jan 04 '20 at 04:31
0

You can create an extension method:

public static class LogExtensions
{
    public static void LogInfo(this YourModelType model)
    {
        //do your logging
    }
}

that can be used like that:

var model = new YourModelType();
model.LogInfo();
Roman.Pavelko
  • 1,555
  • 2
  • 15
  • 18