6

Hi I'm trying to use interfaces in my MVC 5 project with the code below:

public ActionResult Index(IAccountController AccountInterface) 
{
    var DynamicID_DDL = AccountInterface.IDMethod(); 
    var model = new loggedinViewModel
    {
        bIDlistItems = new SelectList(DynamicID_DDL)
    };
    ViewBag.DynamicID_DDL = new List<ID>(DynamicID_DDL);            
    return View(model);
}

&

interface

public interface IAccountController
{
    languageSetting[] languageSettingMethod();
    ID[] IDMethod();
}

However I get the error:

Cannot create an instance of an interface.

Why is this happening and how can I fix it ?

Chris Schiffhauer
  • 17,102
  • 15
  • 79
  • 88
  • 2
    You can't just pass interface types as action parameters, the default model binder expects concrete types that it can instantiate if and when required. You would need to implement your own [interface model binder](http://stackoverflow.com/questions/2970672/asp-net-mvc-custom-model-binder-on-interface-type#3172925). – James Oct 24 '14 at 09:01
  • hi @James im trying to follow your other post on the link you gave me, '' InterfaceModelBinder.Models.InterfaceModelBinder()'' seems to be missing in MVC 5 any thoughts? –  Oct 24 '14 at 09:11
  • `InterfaceModelBinder` is the new model binder type you need to create (you can see the source for this in the answer) - It's not something that ships with MVC 5. I get the feeling you are relatively new to MVC (or even C# in general) my suggestion would be go read some tutortials and get yourself up to speed with the language before trying to do complicated things like this. – James Oct 24 '14 at 12:06
  • only new to MVC not c# been programming years now :) –  Oct 24 '14 at 12:46

2 Answers2

3

When MVC controllers are called via some route, the model binder attempts to find the null CTOR of that parameter and initialize that object prior to entering the controller action method. Interfaces cannot be instantiated, as they don't have a null CTOR... You could change the parameter type to a concrete class that implements that interface if you are not concerned with tight coupling.

OR here's example on custom model binding

     public class HomeCustomBinder : IModelBinder
    {
        public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            HttpRequestBase request = controllerContext.HttpContext.Request;

            string title = request.Form.Get("Title");
            string day = request.Form.Get("Day");
            string month = request.Form.Get("Month");
            string year = request.Form.Get("Year");

            return new HomePageModels
            {
                Title = title,
                Date = day + "/" + month + "/" + year
            };
        }
        public class HomePageModels {
            public string Title { get; set; }
            public string Date { get; set; }

        }
    }
JWP
  • 6,672
  • 3
  • 50
  • 74
  • 2
    Have you considered that the OP may *deliberately* want to use an interface here to avoid tight coupling? – James Oct 24 '14 at 09:06
  • I was trying a void tight coupling, along with less code –  Oct 24 '14 at 09:26
0

Create a class which implements the Interface

Public class AccountController: IAccountController
{

    //Interface Methods
}

Use the class as parameter in your action Method

 public ActionResult Index(AccountController Account) 
  {
        //Your Code
  }
Hemant B
  • 140
  • 1
  • 9