Monday, February 18, 2013

ASP.NET MVC Error No Parameterless Constructor Defined For This Object

If you see following error when developing ASP.NET MVC application, that means one of the model class or any type of a complex model's properties does not have public default constructor.

No parameterless constructor defined for this object.
[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, StackCrawlMark& stackMark) +113
   System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +232
   System.Activator.CreateInstance(Type type, Boolean nonPublic) +83
   System.Activator.CreateInstance(Type type) +6
   System.Web.Mvc.DefaultModelBinder.CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)

Solution to this problem, is to identify which type does not have the public default constructor or default constructor is NOT marked as public. 

You can either look at the source code to find out.  Or if you have ASP.NET MVC source code available to debug through, put a break point at first line of DefaultModelBinder.cs, it will tell you which type.
        protected virtual object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
        {
            Type typeToCreate = modelType;
 
For how to debug ASP.NET MVC source code, please look at my blog at http://luchen1021.blogspot.com/2013/02/debug-aspnet-mvc-4-source-code.html

Debug ASP.NET MVC 4 Source Code


Download SkipStrongNames http://aka.ms/skipsn, and unzip it. From an elevated command prompt, run “skipstrongnames -e” to allow you to run unit tests against the delay-signed binaries.

 


 

Copy following from ASP.NET MVC 4 Source Code to new folder AspNetMvc4

"ASP.NET MVC 4 SourceCode\src\System.Web.WebPages"

"ASP.NET MVC 4 SourceCode\src\Common"

"ASP.NET MVC 4 SourceCode\src\System.Web.Mvc"

"ASP.NET MVC 4 SourceCode\src\VirtualPathUtilityWrapper.cs"

"ASP.NET MVC 4 SourceCode\src\CodeAnalysisDictionary.xml"

"ASP.NET MVC 4 SourceCode\src\CommonAssemblyInfo.cs"

"ASP.NET MVC 4 SourceCode\src\CommonResources.Designer.cs"

"ASP.NET MVC 4 SourceCode\src\CommonResources.resx"

"ASP.NET MVC 4 SourceCode\src\ExceptionHelper.cs"

"ASP.NET MVC 4 SourceCode\src\GlobalSuppressions.cs"

"ASP.NET MVC 4 SourceCode\src\HashCodeCombiner.cs"

"ASP.NET MVC 4 SourceCode\src\IVirtualPathUtility.cs"

"ASP.NET MVC 4 SourceCode\src\MimeMapping.cs"

"ASP.NET MVC 4 SourceCode\src\TransparentCommonAssemblyInfo.cs"

 

Create new solution AspNetMvc4, add following 2 projects

System.Web.Mvc.csproj

System.Web.WebPages.csproj

 

Modify following 2 project files in text editor, or right click "Edit Project File" in VS2012 IDE.

System.Web.Mvc.csproj

System.Web.WebPages.csproj

Remove

<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory),Runtime.sln))\tools\WebStack.settings.targets" />

Change

<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">

      <HintPath>..\..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>

    </Reference>

To

<Reference Include="Microsoft.Web.Infrastructure" />

Change

<OutputPath>..\..\bin\Debug\</OutputPath>

To

<OutputPath>bin\Debug\</OutputPath>

Change

<OutputPath>..\..\bin\Release\</OutputPath>

To

<OutputPath>bin\Release\</OutputPath>

Remove

<DocumentationFile>$(OutputPath)\$(AssemblyName).xml</DocumentationFile>

Remove

<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'CodeCoverage|AnyCPU'">

  <DebugSymbols>true</DebugSymbols>

  <OutputPath>..\..\bin\CodeCoverage\</OutputPath>

  <DefineConstants>TRACE;DEBUG;CODE_COVERAGE;ASPNETMVC</DefineConstants>

  <DebugType>full</DebugType>

  <CodeAnalysisRuleSet>..\Strict.ruleset</CodeAnalysisRuleSet>

</PropertyGroup>

Change

    <ProjectReference Include="..\System.Web.Razor\System.Web.Razor.csproj">

      <Project>{8F18041B-9410-4C36-A9C5-067813DF5F31}</Project>

      <Name>System.Web.Razor</Name>

    </ProjectReference>

    <ProjectReference Include="..\System.Web.WebPages.Razor\System.Web.WebPages.Razor.csproj">

      <Project>{0939B11A-FE4E-4BA1-8AD6-D97741EE314F}</Project>

      <Name>System.Web.WebPages.Razor</Name>

    </ProjectReference>

To

    <Reference Include="System.Web.Razor" />

    <Reference Include="System.Web.WebPages.Razor" />

 

Modify "Properties\AssemblyInfo.cs" in System.Web.WebPages.csproj

Change

[assembly: InternalsVisibleTo("System.Web.Mvc, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")]

To

[assembly: InternalsVisibleTo("System.Web.Mvc")]

 

Compile new solution AspNetMvc4, ready to debug through ASP.NET MVC 4 source code!