0

I am trying to create a web service to handle all logging for application asynchronous, where I can send two of the same object and compare each property. Then create of log of property that changed.

The issue i am having, i don't know how can the apicontroller accept any object:

This is i have so far:

public class PropertyLogApiCall
{
    public string Id { get; set; }
    public string Username { get; set; }
    public string Task { get; set; }
    public object OldEntity { get; set; }
    public object NewEntity { get; set; }
    public string OldEntityType { get; set; }
    public string NewEntityType { get; set; }
}

POST - ApiController

public void Post(PropertyLogApiCall paramList)
{
    try
    {
        var id = paramList.Id;
        var username = paramList.Username;
        var task = paramList.Task;

        var newType = Type.GetType(paramList.NewEntityType);
        var oldType = Type.GetType(paramList.OldEntityType); 

        var newEntity = Convert.ChangeType(paramList.NewEntity, newType);
        var oldEntity = Convert.ChangeType(paramList.OldEntity, oldType);


        var properties = oldEntity.GetType().GetProperties();
        var logsToSave = new List<PropertyLog>();
        var dateTimeStamp = DateTime.Now;

        foreach (var property in properties)
        {
            var oldValue = property.GetValue(oldEntity, null);
            var newValue = newEntity.GetType().GetProperty(property.Name).GetValue(newEntity, null);
            var propertyType = property.PropertyType;
            var name = oldEntity.GetType().Name;
            var propName = property.Name;
            PropertyLog log = null;

            if (propertyType == typeof(string))
            {
                log = CreateLogString(oldValue, newValue);
            }
            else if (propertyType == typeof(int))
            {
                log = CreateLogInt(oldValue, newValue); 
            }

            if (log != null)
            {

                log.Created = dateTimeStamp;
                log.EntityId = id;
                log.Username = username;
                log.EntityName = name;
                log.Property = propName;
                log.Task = task;
                logsToSave.Add(log);
            }

        }
         //Save Logs
         .....
    }
    catch (Exception e)
    {    
        //send email                    
    }

This doesn't work because most of the time newType/oldType is null. And some entity don't implement the IConvertible interface.

Is this even possible to do?

John Saunders
  • 160,644
  • 26
  • 247
  • 397
Valter
  • 2,859
  • 5
  • 30
  • 51
  • I have edited your title. Please see, "[Should questions include “tags” in their titles?](http://meta.stackexchange.com/questions/19190/)", where the consensus is "no, they should not". – John Saunders May 28 '15 at 15:10

1 Answers1

0

As you say that in many occassions you don't have the object type, you need to do it dynamically. It's impossible to recreate an object if you don't know its type.

Change the parameter of your action to dynamic, and the object will be dynamically created including all the properties coming in the request. Then you need to step through all the properties of the OldEntity and compare them with those on the NewEntity. If a property can be a complex object with additional properties you'll have to do it recursively. However in SO you have this information: How do I enumerate through a JObject?

You can get ideas from this SO Q&A: Comparing dynamic objects in C#.

Alternatively, if you're posting it as JSON, you can receive the parameter as a JObject, and make the same opeartions on it. At this moment http://www.newtonsoft.com/ is down, so I cannot give you an exact pointer to JObject docs.

Community
  • 1
  • 1
JotaBe
  • 38,030
  • 8
  • 98
  • 117