0

Class:

public class ClassNameA :ISomeInterface { } public class ClassNameB :ISomeInterface { }

From javascript:

var reqP = { 'Id': id, 'Name':name };
var ReqParams = { 'ReqParams': reqP };
var obj = { 'ClassNameA': ReqParams };

makeAjaxCall("POST",
        JSON.stringify(obj), '/ControllerName/someMethod/', 'html',

Action method looks like:

public ActionResult someMethod(object obj){
    // call comes to this method but obj is not populated. 
}

public ActionResult someMethod(ISomeInterface obj){
    // call comes to this method but throws exception. 
    // Exception : Cannot instantiate interface. but i am passing class object.
}

from JavaScript I will pass object of a concrete class type which implements ISomeInterface so that I can have multiple implementations. Concrete Class can of any one of the two types.

Any Suggestions?

Nikolay Kostov
  • 14,580
  • 20
  • 75
  • 115
Aman
  • 224
  • 2
  • 4
  • 13
  • You need a defined model as the parameter. – tymeJV Mar 26 '14 at 18:21
  • then it becomes tightly coupled with that defined model type. i do not want that. so if I use generic type then I can use that to go to particular implementation based on object type after casting. – Aman Mar 26 '14 at 18:28

2 Answers2

0

That won't work. The model binder needs a concrete type to be able to create an instance and bind the values.

object is a concrete type and can be created using Activator.CreateInstance, but it doesn't have any properties that will match the data you receive.

The interface (or abstract types) cannot be created, since they're not concrete types. It's a simple as that.

If the JSON contained some hint about the type, it migth be possible to implement a custom model binder to create the instances for you. You can read more about the model binding process here.

khellang
  • 15,622
  • 5
  • 56
  • 81
  • yes the json object has information of class type. when i look in firbug then it shows me object with concrete class name and populated properties.. so i was thinking to use reflection to get the type(object.getType()) and then create its instance and perform rest of functionality. – Aman Mar 26 '14 at 20:14
0

The default model binder is not going to be able to figure out what to do. Let's just go through the exercise with some sample interfaces to show why. Say you have this:

public ActionResult SomeMethod(ISomeInterface obj)
{
    // ...
}

...and say you have these two implemenetations:

class ClassA : ISomeInterface
{
    public string Name { get; set; }
    public string Phone { get; set; }
}

class ClassB : ISomeInterface
{
    public string Name { get; set; }
    public string Email { get; set; }
}

...and say this JSON is posted:

{ "Name": "Some Value" }

How would the model binder know which class to use? Would it search all defined classes in all assemblies to find all implementations of the interface? And if so, even if it had smart selection logic based on properties, how would it select between ClassA or ClassB, both of which are compatible?

What you may want to do is either use a type like Dictionary<string, object> that you know will be compatible, dynamic, or go with a concrete class that is a union of everything you need. Alternately, you can create a custom model binder with its own logic for selecting the class you want to instantiate. See this question for more details.

Community
  • 1
  • 1
Jacob
  • 72,750
  • 22
  • 137
  • 214