I'm using StructureMap 2.6.4.1 with a new MVC 5 project. Previously, in MVC 4 projects, our setup works fine.
We have a SM controller factory, such as this:
public class StructureMapControllerFactory : DefaultControllerFactory
{
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
var instance = ObjectFactory.GetInstance(controllerType) as IController;
if (instance == null)
{
return base.GetControllerInstance(requestContext, controllerType);
}
return instance;
}
}
And in the Global.asax.cs, in app start, we set it like this:
ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory());
The issue is, if this last line is enabled in app start, we get this:
**[EntryPointNotFoundException: Entry point was not found.]**
System.Web.Mvc.IControllerFactory.GetControllerSessionBehavior(RequestContext requestContext, String controllerName) +0
System.Web.Mvc.MvcRouteHandler.GetSessionStateBehavior(RequestContext requestContext) +131
System.Web.Mvc.MvcRouteHandler.GetHttpHandler(RequestContext requestContext) +33
System.Web.Mvc.MvcRouteHandler.System.Web.Routing.IRouteHandler.GetHttpHandler(RequestContext requestContext) +10
System.Web.Routing.UrlRoutingModule.PostResolveRequestCache(HttpContextBase context) +9767524
System.Web.Routing.UrlRoutingModule.OnApplicationPostResolveRequestCache(Object sender, EventArgs e) +82
System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +136
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +69
Again, this works just fine in our MVC 4 projects, but I cannot find enough information that relates to MVC 5. I'd hate to revert back to MVC 4, but will if I have to. Thanks.
It's may a version of assembly problem
You need to change the assembly to latest version
see this Entry point was not found exception
Fixed my own issue. For some reason, while I created a new MVC5 project, it was still referencing the old WebPages 2.0 and MVC 4 assemblies. No idea why. I ran an update via nuget and it fixed the issues (it also updated other existing MVC4 apps to 5 without issue).
Ramesh, technically your answer is correct.
Related
I used article "Use Dependency Injection In WebForms Application" https://devblogs.microsoft.com/aspnet/use-dependency-injection-in-webforms-application/
The project retargeted to .NET Framework 4.7.2 in project properties and in web.config:
<system.web>
<httpRuntime targetFramework="4.72" ...
AspNet.WebFormsDependencyInjection.Unity NuGet package is installed.
Type is registered in Global:
public class Global : System.Web.HttpApplication
{
void Application_Start(object sender, EventArgs e)
{
var container = this.AddUnity();
container.RegisterType<IVCRole, eVCRole>();
}
...
I checked container and it is working and registering interface IVCRole mapping to class eVCRole.
Default.aspx.cs is refactored:
public partial class Default : System.Web.UI.Page
{
private IVCRole vcr;
public Default(IVCRole avcr)
{
vcr = avcr;
}
protected void Page_Load(object sender, EventArgs e)
{
...
But when I run web application there is an error
"Constructor on type 'ASP.default_aspx' not found."
If I add this constructor:
public partial class Default : System.Web.UI.Page
{
private IVCRole vcr;
public Default() {}
public Default(IVCRole avcr)
{
vcr = avcr;
}
protected void Page_Load(object sender, EventArgs e)
{
...
the constructor for DI
public Default(IVCRole avcr)
{
vcr = avcr;
}
is never called and "vcr" is always null in Page_Load.
There is an article: "Dependency Injection in ASP.NET Web Forms":
https://makingloops.com/dependency-injection-in-web-forms/
where this error is mentioned:
"On occasion you may see a build error complaining about the lack of a zero-argument constructor on the page. I notice that this error will magically go away depending on the context. Someone else suggested using property injection with the Dependency attribute on pages to get around this, but i didn’t find that was necessary."
But in my case there is no "magic".
There is similar question in Stackoverflow:
.NET 4.7.2 Dependency Injection in ASP.NET WebForms Website - Constructor injection not working
But in my case property injection is not working:
public partial class Default : System.Web.UI.Page
{
[Dependency]
public IVCRole vcr { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
...
"vcr" in Page_Load is still null.
There is solution to get it working with custom implementation of DI provider but I already using .NET 4.7.2 an Unity. Author mentioned that for web application should not be any problem as the problem is with website compiler.
How to get DI constructor or property injection to working in Default page using .NET 4.7.2 and Unity?
This is Stack:
[MissingMethodException: Constructor on type 'ASP.default_aspx' not found.]
System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, StackCrawlMark& stackMark) +1173
System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes) +130
System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture) +21
Microsoft.AspNet.WebFormsDependencyInjection.Unity.ContainerServiceProvider.DefaultCreateInstance(Type type) +17
Microsoft.AspNet.WebFormsDependencyInjection.Unity.ContainerServiceProvider.GetService(Type serviceType) +161
__ASP.FastObjectFactory_app_web_mmaneivx.Create_ASP_default_aspx() in c:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files\vs\19e4d468\8c7800a0\App_Web_mmaneivx.2.cs:0
System.Web.Compilation.BuildResultCompiledType.CreateInstance() +31
System.Web.Compilation.BuildManager.CreateInstanceFromVirtualPath(VirtualPath virtualPath, Type requiredBaseType, HttpContext context, Boolean allowCrossApp) +104
System.Web.UI.PageHandlerFactory.GetHandlerHelper(HttpContext context, String requestType, VirtualPath virtualPath, String physicalPath) +33
System.Web.UI.PageHandlerFactory.GetHandler(HttpContext context, String requestType, String virtualPath, String path) +39
System.Web.MaterializeHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +386
System.Web.HttpApplication.ExecuteStepImpl(IExecutionStep step) +50
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +163
Disclaimer: I maintain this NuGet package and project that use Microsoft.Extensions.DependencyInjection for ASP.NET WebForms (and MVC, SignalR and WCF) in the .NET Framework 4.7.2 - however the content of this post isn't specific to my implementation of DI for ASP.NET.
Check your .csproj:
Ensure you're targeting .NET Framework 4.7.2 or later (note that many shared web-hosts - including Azure App Services - may be running older versions of the .NET Framework):
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
Check your web.config
Ensure you have <system.web><compilation targetFramework="4.7.2">
Ensure you have <system.web><httpRuntime targetFramework="4.7.2"/>
If you have <assemblies><clear /> ensure you have <add assembly="*"/> after the <clear /> or otherwise ensure you're explicitly listing all required assemblies in <add /> elements.
Your ConfigureServices method (or anything that configures DI) must run before Global.asax's Application_Start!
Currently your code is instantiating the Unity container as a local inside Application_Start - this is a bad idea (as you aren't preserving a strong-reference in a field - a bug elsewhere could cause the GC to collect your DI container, which would be a bad thing.
You also need to add a IHttpModule to support scoped DI containers (my package does this for you already).
This is done by using the PreApplicationStartMethod attribute (from WebActivatorEx.
Note that PreApplicationStartMethod is not the same as OWIN's [assembly: Microsoft.Owin.OwinStartup() attribute! Your project may need to use both if you're using DI with SignalR.
Your Startup class code should look like this:
[assembly: PreApplicationStartMethod ( typeof( global::MyProject.RssStartup ), methodName: nameof( global::MyProject.MyStartup.OnPreStart ) )]
namespace MyProject
{
internal static class MyStartup
{
internal static void OnPreStart()
{
// Set-up your DI system here and then call your `ConfigureServices` method before this method returns.
}
}
}
I had exactly the same problem (exception MissingMethodException: Constructor on type 'ASP.*my_page*_aspx' not found.) and it turned out that there was error in creating inner dependency.
I mean, I had:
public class Global : System.Web.HttpApplication
{
private IUnityContainer container;
protected void Application_Start(object sender, EventArgs e)
{
container = this.AddUnity();
container.RegisterType<IDataStorage>(
new InjectionFactory(c => DataStorageBuilder.GetDefaultStorage()));
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
and Page:
public partial class Contact : System.Web.UI.Page
{
private IDataStorage storage { get; set; }
public Contact(IDataStorage storage)
{
this.storage = storage;
}
protected void Page_Load(object sender, EventArgs e)
{
storage.DoRequest();
}
}
And DataStorageBuilder.GetDefaultStorage() actually threw exception, which Unity wrapped in Constructor on type 'ASP.contact_aspx' not found.
So maybe, you need to check that container can correctly create all inner dependencies of page (in your example it is eVCRole).
For me the solution was to remove optimizeCompilations="true" from:
<system.web>
<compilation debug="true" targetFramework="4.8" optimizeCompilations="true">
</compilation>
</system.web>
in Web.Config
I had a very similar issue as the above answer by Света Нестерова https://stackoverflow.com/a/65205408/6901318
One of the dependencies I was trying to register was from an internally maintained Nuget package.
For whatever reason, it is not able to register the type when it is defined in a dll like that. I have done this with .Net Core and it works fine. I am assuming that those references have not been resolved at this point in the application startup. I could be wrong though. It is just a guess, if anyone knows please comment on it.
I ended up making an empty class that inherited from the class I wanted to inject. And, that also implemented the interface that was defined in the NuGet package.
public interface IADAuthenticationManager: IADManager
{
}
IADAuthenticationManager is the wrapper interface and IADManager is the interface defined in the package.
public class ADAuthenticationManager: ADManager, IADAuthenticationManager
{
public ADAuthenticationManager(IADProvider aDProvider, IErrorLogger logger) :
base(aDProvider, logger)
{
}
}
ADAuthenticationManager is the wrapper class. ADManager is the class that implements IADManager and is also defined in the NuGet package. IADAuthenticationManager is the wrapper interface from above.
In my Global.asax.cs
protected void Application_Start(object sender, EventArgs e)
{
...
var container = this.AddUnity();
...
container.RegisterType<IADManager, ADAuthenticationManager>();
container.RegisterType<IADAuthenticationManager, ADAuthenticationManager>();
}
The classes in the NuGet package also had some dependencies that needed wrapper classes created as well. It was a process. But, everything is working now.
I'm experiencing a weird issue when attempting to use Postal within an MVC application that also uses Mvc.Unity4.
I believe the issue is thrown due to lacking access to the HttpContext.
I attempt to send the email from inside one of my Controllers using Postal:
dynamic e = new Email("AccountActivation");
e.To = "name#email.com"
e.Send();
Attempting to send an email results in the following exception within Unity.Mvc4.UnityDependencyResolver:
[NullReferenceException: Object reference not set to an instance of an object.]
Unity.Mvc4.UnityDependencyResolver.get_ChildContainer() +57
Unity.Mvc4.UnityDependencyResolver.GetService(Type serviceType) +241
System.Web.Mvc.DefaultViewPageActivator.Create(ControllerContext controllerContext, Type type) +87
System.Web.Mvc.BuildManagerCompiledView.Render(ViewContext viewContext, TextWriter writer) +216
Postal.EmailViewRenderer.RenderView(IView view, ViewDataDictionary viewData, ControllerContext controllerContext, ImageEmbedder imageEmbedder) +182
Postal.EmailViewRenderer.Render(Email email, String viewName) +204
Postal.EmailService.CreateMailMessage(Email email) +72
Postal.EmailService.Send(Email email) +65
I'm not too familiar with Mvc.Unity4, as this was added by a different developer.
Grasping at straws, I did try to register the correct Postal types within the Application_Start. The initialization of the Unity container is occurring in Bootstrapper.cs:
container.RegisterType<UsersController>(new InjectionConstructor());
container.RegisterInstance<IEmailService>(new EmailService());
Within my controller, I have:
private IEmailService _emailService;
public UsersController()
{
_emailService = new Postal.EmailService();
}
public UsersController(Postal.EmailService emailService)
{
_emailService = emailService;
}
[HttpPost]
public async Task<ActionResult> SendEmail(EmailViewModel viewModel)
{
dynamic e = new Email("AccountActivation");
e.ViewData.Add("To", "name#email.com");
e.ViewData.Add("From", "no-reply#email.com");
_emailService.Send(e);
More code...
}
I think your suspicion is right. HttpContext is not available during application initialization. Therefore Postal will not work (because it relies on ControllerContext and ViewContext) in the Application_Start event.
Since you are using DI, this also extends to the constructor of every class that is configured using Unity - you cannot use Postal in the constructor, but can in methods that are called after Application_Start is complete.
You need to move the call to Postal outside of Application_Start or else use the native .NET mail libraries in this one case (because they rely on System.Net and have no dependencies on HttpContext).
Sorry to answer my own question, but I was finally able to get this working.
Once I removed the async from the method, everything began working as expected.
So by changing...
public async Task<ActionResult> SendEmail(EmailViewModel viewModel)
To this...
public ActionResult SendEmail(EmailViewModel viewModel)
I was then able to send the emails without triggering the exception inside Unity.Mvc4.UnityDependencyResolver.get_ChildContainer().
I'm not sure why I wasn't able to call Postal's .Send() from within an async method (side note, I tried to call .SendAsync() with the same Unity issue resulting). If anyone can shed some light on why this would work within an async method, it would be much appreciated.
Thanks.
This is what i use to implement an Dependency Injection in my MVC3 project,
public class NinjectControllerFactory : DefaultControllerFactory
{
private readonly IKernel _ninjectKernel;
public NinjectControllerFactory()
{
_ninjectKernel = new StandardKernel();
AddBindings();
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
return controllerType == null ? null : (IController)_ninjectKernel.Get(controllerType);
}
private void AddBindings()
{
_ninjectKernel.Bind<IUserRepository>().To<UserRepository>().InSingletonScope();
}
}
but i have a huge problem i want to use an Generic Handler an ".ashx" to implement my logic.
But i get an exception because the httphandler is not a Controller.
here is the exception:
Server Error in '/' Application.
The IControllerFactory 'Infrastructure.NinjectFactory.NinjectControllerFactory' did not return a controller for the name 'registercustomer.ashx'.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.InvalidOperationException: The IControllerFactory 'Infrastructure.NinjectFactory.NinjectControllerFactory' did not return a controller for the name 'registercustomer.ashx'.
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
Stack Trace:
[InvalidOperationException: The IControllerFactory 'Infrastructure.NinjectFactory.NinjectControllerFactory' did not return a controller for the name 'registercustomer.ashx'.]
System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory) +422803
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() +8971636
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +184
Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.547
Now is the question: How do i implement the work around this bug, to me to be able to an HttpHandler and still remain using the Ninject in my project?
Thanks in advance.
Due to the HttpHandler being created by the framework and there is no hook or factory method to intercept the creation of the ashx file, ninject is not able to create this object.
However you can use service locator calls or property injection from the ashx to request dependancies from the ashx code. But as far as I know, the ashx must have a default constructor, and you can then either resolve the dependancies from inside the constructor (or anywhere really) via service locator (less preferred method) or via property injection simply like this:
public class Handler
{
[Inject]
public IService Service { get; set; }
}
EDIT: also, to tell mvc to not process the ashx file you need to add this to ignore the route:
routes.IgnoreRoute("{resource}.ashx/{*pathInfo}");
Looking at my Elmah error logs, I am seeing a few InvalidOperationExceptions from Entity Framework that deal with:
The context cannot be used while the model is being created.
This is with the latest EF CodeFirst library from Nuget. The only information I have been able to find on the net is that it is being caused by having data contexts as singletons, which is most certainly not my case. In my Windsor installer, my EF unit of work structure is being registered with:
container.Register(Component.For<IUnitOfWork>()
.ImplementedBy<EFUnitOfWork>()
.LifeStyle
.PerWebRequest);
I am able to recreate the error by hitting F5 in VS to start a debugging sessions, and while IIS is spinning up load up a second webpage to the debug session.
I suspect it is because the user is trying to access the system while Asp.net has unloaded due to the lack of activity, which makes sense as my product is currently in a very very small beta test. However, since real people are using the website with live data, I need as little errors occurring as possible.
Does anyone have any idea how to prevent this from occurring?
Edit: I updated my windsor controller to now contain the following code:
container.Register(Component.For<IUnitOfWork>().ImplementedBy<EFUnitOfWork>().LifeStyle.PerWebRequest);
using (var context = new MyJobLeadsDbContext())
{
context.Set<UnitTestEntity>().Any();
}
However, when I attempt to perform a 2nd web request while IIS is loading the application, the previous error still occurs
Edit 2: As requested, here is the stack
at System.Data.Entity.Internal.LazyInternalContext.InitializeContext()
at System.Data.Entity.Internal.InternalContext.Initialize()
at System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType)
at System.Data.Entity.Internal.Linq.InternalSet`1.Initialize()
at System.Data.Entity.Internal.Linq.InternalSet`1.get_InternalContext()
at System.Data.Entity.Infrastructure.DbQuery`1.System.Linq.IQueryable.get_Provider()
at System.Linq.Queryable.Where[TSource](IQueryable`1 source, Expression`1 predicate)
at MyApp.DomainModel.Queries.Users.UserByEmailQuery.Execute() in C:\Users\KallDrexx\Documents\Projects\MyApp\MyApp.DomainModel\Queries\Users\UserByEmailQuery.cs:line 44
at MyApp.Infrastructure.MyAppMembershipProvider.GetUser(String email, Boolean userIsOnline) in C:\Users\KallDrexx\Documents\Projects\MyApp\MyApp\Infrastructure\MyAppMembershipProvider.cs:line 102
at System.Web.Security.Membership.GetUser(String username, Boolean userIsOnline)
at System.Web.Security.Membership.GetUser()
at MyApp.MyAppBaseController.Initialize(RequestContext requestContext) in C:\Users\KallDrexx\Documents\Projects\MyApp\MyApp\MyAppBaseController.cs:line 23
at System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext)
at System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext)
at System.Web.Mvc.MvcHandler.<>c__DisplayClass6.<>c__DisplayClassb.<BeginProcessRequest>b__5()
at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass1.<MakeVoidDelegate>b__0()
at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass8`1.<BeginSynchronous>b__7(IAsyncResult _)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.End()
at System.Web.Mvc.MvcHandler.<>c__DisplayClasse.<EndProcessRequest>b__d()
at System.Web.Mvc.SecurityUtil.<GetCallInAppTrustThunk>b__0(Action f)
at System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Action action)
at System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult)
at System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
I finally figured out the true cause of this, at least for me.
The issue was that I was retrieving a DbContext from Windsor in my custom Asp.Net Membership provider. This caused an issue because the membership provider has a lifespan of the whole application, while all other retrieval calls for the db context were new db contexts for the specific web requests. This meant that two database contexts were "spinning up" at the same time and thus this error was thrown.
This also caused a lot of hard to debug entity caching issues as well, so anyone who uses EF in their membership provider needs to be real careful about their context lifetime.
Edit: In response to DotNetWise, I solved this by forcing my custom membership provider to always use an EF connection from Windsor by storing the Windsor connection factory in my constructor, then always retrieving my EF data context from the factory at that point.
For example:
public class CustomMembershipProvider : MembershipProvider
{
private IServiceFactory _serviceFactory;
public CustomMembershipProvider() : this(null) { }
public CustomMembershipProvider(IServiceFactory factory)
{
// IF no factory was provided, we need to get one from the bootstrapper
if (factory == null)
_serviceFactory = new WindsorServiceFactory(Bootstrapper.WindsorContainer);
else
_serviceFactory = factory;
}
public override string ResetPassword(string email, string answer)
{
var unitOfWork = GetUnitOfWork();
return new ResetUserPasswordCommand(unitOfWork).WithUserEmail(email).Execute();
}
private IUnitOfWork GetUnitOfWork()
{
return _serviceFactory.GetService<IUnitOfWork>();
}
}
The idea being that any action the membership provider performs gets the UnitOfWork class from Windsor, and uses that to perform the action (in this case my UnitOfWork class is a repository holder to wrap up my EF data context)
I ran into the same issue in a multithreaded WPF app.
My workaround was to force DbContext initialization from the Windsor installer:
container.Register(Component.For(TheDbContext.Blah.Blah));
using (var context = new TheDbContext())
context.Set<SomeRandomEntity>().Any();
I might add in my opinion this qualifies as a bug in EF: they should have used thread-safe (with locks, or whatever) code for DbContext initialization.
Of course, a better solution is what NHibernate does: the SessionFactory is an explicitly created, separate object from the Session.
When i encountered this issue, i found it was a dbconnection gone wrong.
I corrected my EntityFramework dbconnection string and all was fine
The callstack shows the following:
[MissingMethodException: No parameterless constructor defined for this object.]
System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandle& ctor, Boolean& bNeedSecurityCheck) +0
System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean fillCache) +86
System.RuntimeType.CreateInstanceImpl(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean fillCache) +230
System.Activator.CreateInstance(Type type, Boolean nonPublic) +67
System.Activator.CreateInstance(Type type) +6
System.Web.Mvc.DefaultModelBinder.CreateModel(ModelBindingContext bindingContext, Type modelType) +277
System.Web.Mvc.<>c__DisplayClass1.<BindModel>b__0() +98
System.Web.Mvc.ModelBindingContext.get_Model() +51
System.Web.Mvc.DefaultModelBinder.BindModelCore(ModelBindingContext bindingContext) +2600
System.Web.Mvc.DefaultModelBinder.BindModel(ModelBindingContext bindingContext) +1067
System.Web.Mvc.DefaultModelBinder.BindProperty(ModelBindingContext parentContext, Type propertyType, Func`1 propertyValueProvider, String propertyName) +208
System.Web.Mvc.DefaultModelBinder.BindModelCore(ModelBindingContext bindingContext) +1787
System.Web.Mvc.DefaultModelBinder.BindModel(ModelBindingContext bindingContext) +1067
System.Web.Mvc.ControllerActionInvoker.GetParameterValue(ParameterInfo parameterInfo) +355
System.Web.Mvc.ControllerActionInvoker.GetParameterValues(MethodInfo methodInfo) +439
System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +288
System.Web.Mvc.Controller.ExecuteCore() +180
System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) +96
System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext) +36
System.Web.Mvc.MvcHandler.ProcessRequest(HttpContextBase httpContext) +377
System.Web.Mvc.MvcHandler.ProcessRequest(HttpContext httpContext) +71
System.Web.Mvc.MvcHandler.System.Web.IHttpHandler.ProcessRequest(HttpContext httpContext) +36
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +181
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +75
I have a tiny form with a bunch of hidden fields and one submit button.
When I press it, I never even hit the requested method.
How do I go on and debug this?
It would be a great start if I knew WHAT object didn't have a parameterless constructor.
Where is this object? How can I solve this?
I know the question is rather vague, but currently it's all I've got..
--EDIT--
In my form I added Html.Hidden() inputs. Depending on previous actions, these can have a value of "". The action makes use of ModelBinding. Whenever the value is "" and the datatype is a SelectList, the modelbinder goes berzerk on me.
I feel more and more uncomfortable with how the SelectList is doing it's thing...
The idea is good, but there are some issues with it.
I solved the issue which is caused of SelectList object because it does not provide the default constructor so we cant have in out ViewModel.
For those Googling this exception, here is a more general way to diagnose it:
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).
Your custom classes in the action args must have a parameterless constructor in order to use the default model binder. Otherwise, either (1) create a custom model binder or (2) pass primitive types instead of custom classes to the Action.
I also have properties on my view model class that return SelectList instances. I decorated my class with the Bind attribute to exclude these properties like this:
[Bind(Exclude = "Countries")]
public class MyViewModel
{
...
public SelectList Countries { get; set; }
}
Hope that helps,
Roger
Did you remove Default.aspx? That needs to be in place to render the root properly. This can also happen if you're trying to use Dependency Injection and your container isn't setup properly - meaning there is no ControllerFactory that asks the DI Container for the instance.
The root of my problem was also SelectList.
I had this:
<%: Html.DropDownListFor(m => Model.Destinations, Model.Destinations)%>
When I should have had this:
<%: Html.DropDownListFor(m => Model.Destination, Model.Destinations)%>
Destination is the user's selection, Destinations is the list of possible values. Using the plural SelectList twice caused the problem.