186 votes

ASP.NET MVC: Aucun constructeur sans paramètre défini pour cet objet

Erreur de serveur dans l'application '/'
--------------------------------------------------------------------------------

Aucun constructeur sans paramètre défini pour cet objet.
Description : Une exception non gérée s'est produite lors de l'exécution de la requête Web actuelle. Veuillez consulter la trace de la pile pour plus d'informations sur l'erreur et son origine dans le code.

Détails de l'exception : System.MissingMethodException : Aucun constructeur sans paramètre défini pour cet objet.

Erreur source :

Ligne 16 :             HttpContext.Current.RewritePath(Request.ApplicationPath, false);
Ligne 17 :             IHttpHandler httpHandler = new MvcHttpHandler();
Ligne 18 :             httpHandler.ProcessRequest(HttpContext.Current);
Ligne 19 :             HttpContext.Current.RewritePath(originalPath, false);
Ligne 20 :         }

Je suivais le livre de Steven Sanderson 'Pro ASP.NET MVC Framework'. À la page 132, conformément à la recommandation de l'auteur, j'ai téléchargé l'ensemble des ASP.NET MVC Futures et l'ai ajouté à mon projet MVC. [Note : cela pourrait être une fausse piste.]

Après cela, je n'ai plus pu charger mon projet. L'erreur ci-dessus m'a complètement bloqué.

Ma question n'est pas : "Pouvez-vous m'aider à corriger mon code ?"

Je voudrais plutôt savoir de manière plus générale :

  • Comment devrais-je résoudre ce problème ?
  • Que devrais-je rechercher ?
  • Quelle pourrait être la cause profonde ?

Il semble que je devrais comprendre le routage et les contrôleurs à un niveau plus approfondi que maintenant.

238voto

SandRock Points 1990

J'ai eu un problème similaire. La même exception se produit lorsqu'un Model n'a pas de constructeur sans paramètres.

La pile d'appels indiquait une méthode responsable de la création d'une nouvelle instance d'un modèle.

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


Voici un exemple:

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

    }
}

public class MyModel
{
    public MyModel(IHelper helper) // MVC ne peut pas appeler cela
    {
        // ...
    }

    public MyModel() // MVC peut appeler cela
    {
    }
}

17 votes

Lorsque je POSTais des données JSON vers mon action, je recevais une erreur similaire. Il s'avère que mon modèle vers lequel il tente de lier n'a pas de constructeur sans paramètre!

1 votes

NB: J'ai ce problème (aucun paramètre bla bla...) lors de la sérialisation si je définis un constructeur et non un constructeur sans paramètre. Autrement dit, dans cet exemple, si vous supprimez le constructeur que vous avez défini (public MyModel(IHelper helper) {}), le problème disparaît... donc chaque fois que vous créez un constructeur, vous devez en créer un sans paramètre... Je peux comprendre cela comme : une fois que vous commencez à définir un constructeur, le système ne prend pas de risques pour créer des 'objets par défaut' car il ne sait pas si cela a du sens... quelque chose comme ça.

1 votes

Tuples ... peut-être pour d'autres personnes qui viennent ici: si vous avez juste des Tuples (comme Tuple data;) dans votre classe, la sérialisation se passera bien (car j'ai rencontré ce problème lors de la sérialisation JSON)... mais si vous utilisez quelque chose comme List> data; vous commencerez à avoir l'erreur 'pas de constructeur sans paramètre'. Parce que .Net ne peut pas / ne crée pas de Tuples (je n'ai pas de référence pour cela mais Tuple data = new Tuple(); ne compilera pas... tandis que Tuple data = new Tuple("", ""); fonctionne.

93voto

Chris S Points 32376

Cela peut également être causé si votre modèle utilise un SelectList, car celui-ci n'a pas de constructeur sans paramètre :

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

Vous devrez refactoriser votre modèle pour le faire d'une manière différente si c'est la cause. Utilisez donc un IEnumerable et écrivez une méthode d'extension qui crée la liste déroulante avec les différentes définitions de propriété :

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

public static MvcHtmlString DropDownListForContacts(this HtmlHelper helper, IEnumerable contacts, string name, Contact selectedContact)
{
    // Créez une List, peuplez-la, retournez DropDownList(..)
}

Ou vous pouvez utiliser l'approche de @Mark et @krilovich, il suffit de remplacer SelectList par IEnumerable, cela fonctionne également avec MultiSelectList.

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

1 votes

J'ai tellement perdu de temps sur ça... et j'ai dû transformer ma fonction d'aide qui renvoyait un SelectList en une qui renverrait une List....blarg

0 votes

Vous pouvez utiliser IEnumerable et les instancier dans votre constructeur en tant que nouvelle Liste()

0 votes

Merci, cela a été extrêmement utile!

25voto

Martin Points 7782

Vous avez besoin que l'action qui correspond au contrôleur n'ait pas de paramètre.

On dirait que pour la combinaison contrôleur / action que vous avez:

public ActionResult Action(int parameter)
{

}

mais vous avez besoin de

public ActionResult Action()
{

}

Aussi, consultez le Route Debugger de Phil Haack pour dépanner les routes.

6 votes

L'exception est liée au constructeur, pas à la méthode d'action.

4 votes

@Logrythmik. L'exception rapportée concerne le constructeur, mais le problème se trouve dans la méthode d'action. J'avais une classe et une méthode d'action qui fonctionnaient, puis j'ai ajouté un paramètre à la méthode d'action, et j'ai obtenu cette erreur. Une solution alternative est de fournir une valeur pour le paramètre. Ou rendre le paramètre facultatif - cela devrait fonctionner lorsque le contrôleur est en C#, mais cela n'a pas fonctionné pour moi avec F#

0 votes

Aussi, si vous faites quelque chose comme @Html.Action("SomeAction", new { myParameter = "42" }), assurez-vous que le nom du paramètre dans votre appel Html.Action correspond au nom du paramètre défini dans votre méthode d'action !

22voto

swilliams Points 19415

Par défaut, les contrôleurs MVC nécessitent un constructeur par défaut sans paramètres. Le plus simple serait de créer un constructeur par défaut qui appelle celui avec des paramètres :

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

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

Cependant, vous pouvez remplacer cette fonctionnalité en créant votre propre ControllerFactory. De cette façon, vous pouvez dire à MVC que lorsque vous créez un MyController, donnez-lui une instance de Helper.

Cela vous permet d'utiliser des frameworks d'injection de dépendances avec MVC, et vraiment de tout découpler. Un bon exemple de cela se trouve sur le site web de StructureMap. Le tutoriel complet est bon, et il est spécifique à MVC vers le bas dans la section "Auto Wiring".

8 votes

Je ne pense pas que ce soit la bonne réponse, @swilliams. La clé ici est la partie : défini pour cet objet. C'est un message d'erreur bidon qui laisse entendre que le(s) INPUT MODEL(s) passé(s) ne peuvent être créé(s). Donc si vous avez un modèle d'entrée qui n'a pas de constructeur sans paramètre, vous obtenez cette erreur. Très facile de penser que cela était lié au constructeur du CONTRÔLEUR. Mais ce n'est pas le cas.

2 votes

C'est un message bidon, qui vous fera partir à la chasse aux oies sauvages si ce n'était pas pour des réponses comme celles-ci. Grâce à cette réponse et à la réponse précédente, j'ai pu régler les choses. Je suppose que c'est une question de ne pas comprendre pleinement ce que le binder fait en arrière-plan. Je pensais qu'il définirait simplement chaque propriété mais pour une raison quelconque, il appelle le get avant de définir lors de la publication également. Donc, parce que j'ai surchargé mon constructeur et j'ai dû compenser avec un constructeur sans paramètre, j'ai dû tenir compte des nulls pour certaines de mes propriétés, ce qui était également inattendu.

14voto

Josh Points 1001

Vous pouvez obtenir cette exception à de nombreux endroits différents dans le framework MVC (par exemple, il ne peut pas créer le contrôleur, ou il ne peut pas créer un modèle à donner à ce contrôleur).

La seule façon facile que j'ai trouvée pour diagnostiquer ce problème est de remplacer le MVC aussi près que possible de l'exception avec votre propre code. Ensuite, votre code se cassera à l'intérieur de Visual Studio lorsque cette exception se produira, et vous pourrez lire le Type causant le problème depuis la trace de la pile.

Cela semble être une façon horrible d'aborder ce problème, mais c'est très rapide et très cohérent.

Par exemple, si cette erreur se produit à l'intérieur du DefaultModelBinder MVC (ce que vous saurez en vérifiant la trace de la pile), remplacez le DefaultModelBinder par ce 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);
    }
}

Et mettez à jour votre Global.asax.cs :

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

Maintenant, la prochaine fois que vous obtiendrez cette exception, Visual Studio s'arrêtera à l'intérieur de votre classe MyDefaultModelBinder, et vous pourrez vérifier la propriété "modelType" pour voir quel type a causé le problème.

L'exemple ci-dessus fonctionne pour lorsque vous obtenez l'exception "Aucun constructeur sans paramètre défini pour cet objet" lors de la liaison de modèle uniquement. Mais un code similaire peut être écrit pour d'autres points d'extension dans MVC (par exemple, la construction de contrôleur).

0 votes

C'est ce à quoi je pensais faire pour mon problème.

0 votes

J'aimerais pouvoir voter pour ça encore plus. Ça m'a épargné plus que quelques minutes de mon temps.

0 votes

+10 ! cela m'a beaucoup aidé !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X