ASP.NET MVC: No parameterless constructor defined for this object

烈酒焚心 提交于 2019-11-25 19:14:03

I just had a similar problem. The same exception occurs when a Model has no parameterless constructor.

The call stack was figuring a method responsible for creating a new instance of a model.

System.Web.Mvc.DefaultModelBinder.CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)


Here is a sample:

public class MyController : Controller
{
    public ActionResult Action(MyModel model)
    {

    }
}

public class MyModel
{
    public MyModel(IHelper helper) // MVC cannot call that
    {
        // ...
    }

    public MyModel() // MVC can call that
    {
    }
}
Chris S

This can also be caused if your Model is using a SelectList, as this has no parameterless constructor:

public class MyViewModel
{
    public SelectList Contacts { get;set; }
}

You'll need to refactor your model to do it a different way if this is the cause. So using an IEnumerable<Contact> and writing an extension method that creates the drop down list with the different property definitions:

public class MyViewModel
{
    public Contact SelectedContact { get;set; }
    public IEnumerable<Contact> Contacts { get;set; }
}

public static MvcHtmlString DropDownListForContacts(this HtmlHelper helper, IEnumerable<Contact> contacts, string name, Contact selectedContact)
{
    // Create a List<SelectListItem>, populate it, return DropDownList(..)
}

Or you can use the @Mark and @krilovich approach, just need replace SelectList to IEnumerable, it's works with MultiSelectList too.

 public class MyViewModel
    {
        public Contact SelectedContact { get;set; }
        public IEnumerable<SelectListItem> Contacts { get;set; }
    }

You need the action that corresponds to the controller to not have a parameter.

Looks like for the controller / action combination you have:

public ActionResult Action(int parameter)
{

}

but you need

public ActionResult Action()
{

}

Also, check out Phil Haack's Route Debugger to troubleshoot routes.

By default, MVC Controllers require a default constructor with no parameters. The simplest would be to make a default constructor that calls the one with parameters:

public MyController() : this(new Helper()) {
}

public MyController(IHelper helper) {
  this.helper = helper;
}

However, you can override this functionality by rolling your own ControllerFactory. This way you can tell MVC that when you are creating a MyController give it an instance of Helper.

This allows you to use Dependency Injection frameworks with MVC, and really decouple everything. A good example of this is over at the StructureMap website. The whole quickstart is good, and he gets specific to MVC towards the bottom at "Auto Wiring".

This error also occurs when using an IDependencyResolver, such as when using an IoC container, and the dependency resolver returns null. In this case ASP.NET MVC 3 defaults to using the DefaultControllerActivator to create the object. If the object being created does not have a public no-args constructor an exception will then be thrown any time the provided dependency resolver has returned null.

Here's one such stack trace:

[MissingMethodException: No parameterless constructor defined for this object.]
   System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) +0
   System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache) +98
   System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean skipCheckThis, Boolean fillCache) +241
   System.Activator.CreateInstance(Type type, Boolean nonPublic) +69
   System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType) +67

[InvalidOperationException: An error occurred when trying to create a controller of type 'My.Namespace.MyController'. Make sure that the controller has a parameterless public constructor.]
   System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType) +182
   System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType) +80
   System.Web.Mvc.DefaultControllerFactory.CreateController(RequestContext requestContext, String controllerName) +74
   System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory) +232
   System.Web.Mvc.<>c__DisplayClass6.<BeginProcessRequest>b__2() +49
   System.Web.Mvc.<>c__DisplayClassb`1.<ProcessInApplicationTrust>b__a() +13
   System.Web.Mvc.SecurityUtil.<GetCallInAppTrustThunk>b__0(Action f) +7
   System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Action action) +22
   System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Func`1 func) +124
   System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +98
   System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state) +50
   System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +16
   System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +8963444
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +184

You can get this exception at many different places in the MVC framework (e.g. it can't create the controller, or it can't create a model to give that controller).

The only easy way I've found to diagnose this problem is to override MVC as close to the exception as possible with your own code. Then your code will break inside Visual Studio when this exception occurs, and you can read the Type causing the problem from the stack trace.

This seems like a horrible way to approach this problem, but it's very fast, and very consistent.

For example, if this error is occurring inside the MVC DefaultModelBinder (which you will know by checking the stack trace), then replace the DefaultModelBinder with this code:

public class MyDefaultModelBinder : System.Web.Mvc.DefaultModelBinder
{
    protected override object CreateModel(System.Web.Mvc.ControllerContext controllerContext, System.Web.Mvc.ModelBindingContext bindingContext, Type modelType)
    {
        return base.CreateModel(controllerContext, bindingContext, modelType);
    }
}

And update your Global.asax.cs:

public class MvcApplication : System.Web.HttpApplication
{
...
    protected void Application_Start(object sender, EventArgs e)
    {
        ModelBinders.Binders.DefaultBinder = new MyDefaultModelBinder();
    }
}

Now the next time you get that exception, Visual Studio will stop inside your MyDefaultModelBinder class, and you can check the "modelType" property to see what type caused the problem.

The example above works for when you get the "No parameterless constructor defined for this object" exception during model binding, only. But similar code can be written for other extension points in MVC (e.g. controller construction).

I got the same error, the culprit in my case was the constructor which was neither public nor private.

No parameterless constructor defined for this object.

Exception Details: System.MissingMethodException: No parameterless constructor defined for this object.

Repro code: Make sure the constructor has public before it.

public class Chuchi()
{
     Chuchi()    // The problem is this line. Public is missing
     {
         // initialization
         name="Tom Hanks";
     }

    public string name
    {
        get;
        set;
    }
}

First video on http://tekpub.com/conferences/mvcconf

47:10 minutes in show the error and shows how to override the default ControllerFactory. I.e. to create structure map controller factory.

Basically, you are probably trying to implement dependency injection??

The problem is that is the interface dependency.

I got the same error when:

Using a custom ModelView, both Actions (GET and POST) were passing the ModelView that contained two objects:

public ActionResult Add(int? categoryID)
{
    ...
    ProductViewModel productViewModel = new ProductViewModel(
            product,
            rootCategories
            );
    return View(productViewModel); 
}

And the POST also accepting the same model view:

[HttpPost]
[ValidateInput(false)]
public ActionResult Add(ProductModelView productModelView)
{...}

Problem was the View received the ModelView (needed both product and list of categories info), but after submitted was returning only the Product object, but as the POST Add expected a ProductModelView it passed a NULL but then the ProductModelView only constructor needed two parameters(Product, RootCategories), then it tried to find another constructor with no parameters for this NULL case then fails with "no parameterles..."

So, fixing the POST Add as follows correct the problem:

[HttpPost]
[ValidateInput(false)]
public ActionResult Add(Product product)
{...}

Hope this can help somebody (I spent almost half day to find this out!).

The same for me. My problem appeared because i forgot that my base model class already has property with the name which was defined in the view.

public class CTX : DbContext {  // context with domain models
    public DbSet<Products> Products { get; set; }  // "Products" is the source property
    public CTX() : base("Entities") {}
}

public class BaseModel : CTX { ... }
public class ProductModel : BaseModel { ... }
public class OrderIndexModel : OrderModel  { ... }

... and controller processing model :

[HttpPost]
[ValidateInput(false)]
public ActionResult Index(OrderIndexModel order) { ... }

Nothing special, right? But then i define the view ...

<div class="dataItem">
    <%=Html.Label("Products")%>
    <%=Html.Hidden("Products", Model.index)%>   // I FORGOT THAT I ALREADY HAVE PROPERTY CALLED "Products"
    <%=Html.DropDownList("ProductList", Model.products)%>
    <%=Html.ActionLink("Delete", "D")%>
</div>

... which causes "Parameterless constructor" error on POST request.

Hope that helps.

I had a similar problem, and basically the point is that there are some arguments in the action method that were not supplied by the Model Binding process, (and in other words these fields were not submitted by the submitting page).

This problem will come up even if all arguments but one are supplied, and even if the one missing is a nullable type.

The problem might also be a result of a typo, in which the name of the argument and name of the form field will not be identical.

The solution is to 1) verify that the names match up 2) provide a default value for the argument 3) or provide another action method without this argument.

I had this problem as well and thought I'd share since I can't find my problem above.

This was my code

return RedirectToAction("Overview", model.Id);

Calling this ActionResult:

public ActionResult Overview(int id)

I assumed it would be smart enough to figure out that the value I pass it is the id paramter for Overview, but it's not. This fixed it:

return RedirectToAction("Overview", new {id = model.Id});

I got same exception due to there was no parameterless public contructor

Code was like this:

public class HomeController : Controller
{        
    private HomeController()
    {
        _repo = new Repository();
    }

changed to

 public class HomeController : Controller
{        
    public HomeController()
    {
        _repo = new Repository();
    }

problem resolved to me.

I had the same problem...

If your using a interface to decouple your connection against your DbContext (like me) you can use structuremap.mvc (3 or 4 - nudget package) to be able to use a constructure in your controller class. This will give you a DependencyResolution folder. Just change the commented line with your For< InterfaceClass >() and to Use< DbContextClass >().

While this may be obvious to some, the culprit of this error for me was my MVC method was binding to a model that contained a property of type Tuple<>. Tuple<> has no parameterless constructor.

All of the answers say to create a parameters less constructor which isn't ideal if you don't want any other devs using it and only the model binder.

The attribute [Obsolete("For model binding only", true)] above a public constructor will throw a compiler error if another dev tries to use this. Took me ages to find this, hope it helps someone.

I got this error. I was using interfaces in my constructor and my dependency resolver wasn't able to resolve, when i registered it then the error went away.

This error started for me when I added a new way to instantiate a class.

Example:

    public class myClass
    {
         public string id{ get; set; }
         public List<string> myList{get; set;}

         // error happened after I added this
         public myClass(string id, List<string> lst)
         {
             this.id= id;
             this.myList= lst;
         }
     }

The error was resolved when I added when I made this change, adding a parameterless constructor. I believe the compiler creates a parameterless constuctor by default but if you add your own then you must explicitly create it.

    public class myClass
    {
         public string id{ get; set; }
         public List<string> myList{get; set;}

         // error doesn't happen when I add this
         public myClass() { }

         // error happened after I added this, but no longer happens after adding above
         public myClass(string id, List<string> lst)
         {
             this.id= id;
             this.myList= lst;
         }
     }

I'd added a DropDownList to my form, however in my case it wasn't (and wasn't intended to be) submitted with the form as it was outside of the <form></form> tags:

@Html.DropDownList("myField", Model.MyField)

As the Model contained the field for display only, this also caused the No parameterless constructor defined for this object error because the field wasn't submitted at all.

In this case I fixed it by adding an exclude binding:

public ActionResult Foo(int id, int? page, [Bind(Exclude = "MyField")]MyModel model)

This happened to me, and the results on this page were a good resource that led me in many directions, but I would like to add another possibility:

As stated in other replies, creating a constructor with parameters removes the implicit parameterless constructor, so you have to explicitly type it.

What was my problem was that a constructor with default parameters also triggered this exception.

Gives errors:

public CustomerWrapper(CustomerDto customer = null){...}

Works:

public CustomerWrapper(CustomerDto customer){...}
public CustomerWrapper():this(null){}

Most probably you might have parameterized constructor in your controller and whatever dependency resolver you are using is not able to resolve the dependency properly. You need to put break-point where the dependency resolver method is written and you will get the exact error in inner exception.

I had same problem but later found adding any new interface and corresponding class requires it to be registered under Initializable Module for dependency injection. In my case it was inside code as follows:

[InitializableModule]
[ModuleDependency(typeof(EPiServer.Web.InitializationModule))]
public class DependencyResolverInitialization : IConfigurableModule
{

    public void ConfigureContainer(ServiceConfigurationContext context)
    {
        context.Container.Configure(ConfigureContainer);
        var structureMapDependencyResolver = new StructureMapDependencyResolver(context.Container);
        DependencyResolver.SetResolver(structureMapDependencyResolver);
        GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerActivator), structureMapDependencyResolver);
    }

    private void ConfigureContainer(ConfigurationExpression container)
    {
        container.For<IAppSettingService>().Use<AppSettingService>();
        container.For<ISiteSettingService>().Use<SiteSettingService>();
        container.For<IBreadcrumbBuilder>().Use<BreadcrumbBuilder>();
        container.For<IFilterContentService>().Use<FilterContentService>().Singleton();
        container.For<IDependecyFactoryResolver>().Use<DependecyFactoryResolver>();
        container.For<IUserService>().Use<UserService>();
        container.For<IGalleryVmFactory>().Use<GalleryVmFactory>();
        container.For<ILanguageService>().Use<LanguageService>();
        container.For<ILanguageBranchRepository>().Use<LanguageBranchRepository>();
        container.For<ICacheService>().Use<CacheService>(); 
        container.For<ISearchService>().Use<SearchService>();
        container.For<IReflectionService>().Use<ReflectionService>();
        container.For<ILocalizationService>().Use<LocalizationService>();
        container.For<IBookingFormService>().Use<BookingFormService>();
        container.For<IGeoService>().Use<GeoService>();
        container.For<ILocationService>().Use<LocationService>();
        RegisterEnterpriseAPIClient(container);
    }

   public void Initialize(InitializationEngine context)
    {
    }

    public void Uninitialize(InitializationEngine context)
    {
    }

    public void Preload(string[] parameters)
    {
    }
}

}

I had the same problem.

Just Removed HttpFileCollectionBase files from Post Action method argument and added like HttpFileCollectionBase files = Request.Files; in method body.

In my case, my class had the [Serializable] attribute.

You are required to have a constructor that takes no parameters if your class is [Serializable]

So I have gotten that message before as well, when doing an ajax call. So what it's basically asking for is a constructor in that model class that is being called by the contoller, doesn't have any parameter.

Here is an example

public class MyClass{

     public MyClass(){} // so here would be your parameterless constructor

 }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!