0

I would like to add the httpcontext name property in a generic way to my objects before I save it to the database and I thought I could use the OnActionExecuting method to do that.

I'm using one of web api life cycle hooks OnActionExecuting. And I'm trying to cast the incoming parameter to List<object> but it keeps failing with the error saying it cannot complete the task:

    public override void OnActionExecuting(ActionExecutingContext context)
    {


        if (context.ModelState.IsValid)
        {

            try
            {
                var result = context;
                var actionParameter = context.ActionArguments["dtoItem"];
                List<object> collection = (List<object>)actionParameter;


                    context.ActionArguments["dtoItem"] = actionParameter;
                }
            }
            catch
            {

            }

        }
    }

The error that I get for this is:

Unable to cast object of type
'System.Collections.Generic.List1[Ctrac.WebApi.Core.Models.TestModel]' to type 'System.Collections.Generic.List1[System.Object]'.

itminus
  • 23,772
  • 2
  • 53
  • 88
Tom Kurian
  • 113
  • 13

1 Answers1

0

You just can't cast a type of List<T1> to List<T> even if T1 extends T.

This is by design.

Suppose that the compiler allows us to do that, think about the following code :

List<objects> models = new  List<TestModel>();  // suppose we can do this
var o = new {a = 1 };
var index = models.IndexOf(o);                  // now we can invoke IndexOf(o)

Actually, the models here "points to" an instance of List<TestModel>, which means the invocation of models.IndexOf(o) will eventually call the method of List<TestModel>.IndexOf(TestModel o) instead of the List<object>.IndexOf(object o) . ( Similar to polymorphism ).

List<object>    .IndexOf(object o)
                           |
                           |
                           V
List<TestModel>.IndexOf(TestModel o)

In other words, you're assuming the instance o ( whose type is object) can be converted to TestModel. Obviously, that is unsafe.

See Covariance and Contravariance in Generics.

How to fix

Simply use LINQ to cast :

List<object> collection = actionParameter
         .Select( m => (object) m)
         .ToList();
itminus
  • 23,772
  • 2
  • 53
  • 88