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!

Wednesday, January 18, 2012

CSLA Message Size Is HUGH ???

The project I am working on experiencing some performance issue, slow communication between server and client, system out of memory exception.

The project is a Silverlight Rich Internet Application.  Silverlight + Prism on the client, CSLA an application framework for middle tier, SQL Server at backend.  The hardware specification of the hosting environment is good enough for our current few pilot users, less than a hundred of users.

Since, hardware is good enough to support our current user load.  We decided to benchmark our middle tier CSLA, which we cannot get any existing benchmark from anywhere.  Nobody is using CSLA? :) We compared with WCF Service and WCF RIA Service as well.

The benchmark result is a little surprising and explain some of the issue we have.

Display a list object which contains 20 item objects, each item object has 11 properties, int, bool, datetime or string values.

Without IIS compression enabled.




With IIS compression enabled.





































IIS compression is one way only, for downloading data from server to client.  Sending data from client to server is NOT compressed.  It is getting worse when sending data from client to server using CSLA.  We use a single object which has 23 properties, int, bool, datetime and string values.


















Given a typical business unit who have 10 users and share a regular DSL line for internet connection which has a average of 100KB upstream speed,
10 x 6KB = 60KB / 100KB = 60%.
So, CSLA itself will use at least 60% of the bandwidth!!!

The big message size of CSLA is not only affecting the communication but also the memory usage on the Silverlight Client.  Why?






































Even if the message is IIS compressed in a smaller size for faster downloading, it will be uncompressed on the client, and Silverlight .NET runtime have to allocate enough memory to handle the uncompressed message which is much bigger than WCF Service or WCF RIA Service message.  This will cause extra CPU and memory usage, plus Silverlight .NET runtime is not as effecient as desktop .NET runtime, which will end with System.OutOfMemory issue sometime.

Are you also using CSLA or planning to use CSLA for your Silverlight Rich Internet Application?  Let me know your performance experience.

Deep Zoom Service Is NOT Free

The project I am working on is using Deep Zoom Service to display images uploaded by the user.  Based on the network traffic monitored by Fiddler and Silverlight client memory debugging by WinDbg, we found out Deep Zoom Service is free for development, but in order to support it, the deployment environment must have extra internet bandwidth, and Silvelight client must have enough free memory.  See below test results using a 1MB size of jpeg file, after image displayed in System.Windows.Controls.MultiScaleImage control, doing only a few zoom in, zoom out and move directions.

Network traffic monitored by Fidder, total 43 network round trip for just displaying one image.




































Memory usage debugging by WinDbg, total 12MB is used for one image.

0:048> !dumpheap -mt 7ac18ea8
 Address       MT     Size
287509e8 7ac18ea8       72    

total 0 objects
Statistics:

      MT    Count    TotalSize Class Name
7ac18ea8        1           72 System.Windows.Controls.MultiScaleImage
Total 1 objects

0:048> !objsize 287509e8
sizeof(287509e8) =     12690624 (    0xc1a4c0) bytes (System.Windows.Controls.MultiScaleImage)

Monday, January 2, 2012

Monitor AppFabric Cache Status Using PowerShell

While working on the AppFabric Cache feature for the current project, I create the following PowerShell script to monitor the AppFabric Cache status.

First, using following DOS command to start AppFabric Cache PowerShell environment in one of the cache host server:

%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -NoExit -Command "Set-ExecutionPolicy RemoteSigned;Import-Module DistributedCacheAdministration;Import-Module DistributedCacheConfiguration;Use-CacheCluster;Cd C:\\;Cls"

Second, assume the script MonitorAppFabricCache.ps1 is under C:\ folder, run following in PowerShell environment. It will generate the output at c:\AppFabricCacheStatus.txt and open the output:

.\MonitorAppFabricCache.ps1

Following is the content of MonitorAppFabricCache.ps1.

$AppFabricCacheStatusFile = "c:\AppFabricCacheStatus.txt"
Get-Date -format g | Out-File $AppFabricCacheStatusFile -Force
Out-File $AppFabricCacheStatusFile -InputObject "" -Append
Out-File $AppFabricCacheStatusFile -InputObject "" -Append
Out-File $AppFabricCacheStatusFile -InputObject "" -Append
Out-File $AppFabricCacheStatusFile -InputObject "Cache hosts status" -Append
Out-File $AppFabricCacheStatusFile -InputObject "=========================" -Append
Get-CacheHost | Out-File $AppFabricCacheStatusFile -Append
Get-CacheClusterHealth | Out-File $AppFabricCacheStatusFile -Append
$CacheHosts = Get-CacheHost
foreach ($CacheHost in $CacheHosts)
{
    Out-File $AppFabricCacheStatusFile -InputObject "Cache host config - $($CacheHost.HostName)" -Append
    Out-File $AppFabricCacheStatusFile -InputObject "=========================" -Append
    Get-CacheHostConfig -HostName $CacheHost.HostName -CachePort $CacheHost.PortNo | Out-File $AppFabricCacheStatusFile -Append
}
$Caches = Get-Cache
foreach ($Cache in $Caches)
{
    Out-File $AppFabricCacheStatusFile -InputObject "Cache statistics - $($Cache.CacheName)" -Append
    Out-File $AppFabricCacheStatusFile -InputObject "=========================" -Append
    Get-CacheStatistics -CacheName $Cache.CacheName | Out-File $AppFabricCacheStatusFile -Append
}
foreach ($Cache in $Caches)
{
    Out-File $AppFabricCacheStatusFile -InputObject "Cache config - $($Cache.CacheName)" -Append
    Out-File $AppFabricCacheStatusFile -InputObject "=========================" -Append
    Get-CacheConfig -CacheName $Cache.CacheName | Out-File $AppFabricCacheStatusFile -Append
}
Out-File $AppFabricCacheStatusFile -InputObject "Regions by cache" -Append
Out-File $AppFabricCacheStatusFile -InputObject "=========================" -Append
Get-Cache | Out-File $AppFabricCacheStatusFile -Append
Out-File $AppFabricCacheStatusFile -InputObject "Regions by cache host" -Append
Out-File $AppFabricCacheStatusFile -InputObject "=========================" -Append
Get-CacheRegion | Out-File $AppFabricCacheStatusFile -Append
Invoke-Expression -Command $AppFabricCacheStatusFile

Wednesday, December 21, 2011

Reset Password Fail in AD, ADLDS or ADAM

When reset password using System.DirectoryServices.Protocols APIs, it failed with exception type DirectoryOperationException.  DirectoryOperationException.Response.ErrorMessage contains following string "problem 5012 (DIR_ERROR)".

If the AD, ADLDS or ADAM connection is not SSL enabled, by default the password string must be encrypted.  That's why above exception is thrown when reset password on non-SSL connection.

In order to work around this issue while not have to enable SSL connection, abbribute "dSHeuristics" needs to be set to 0000000001001 to allow clear text password being sent.





Create Load Balance and Https Enabled Web Farm using Microsoft Web Farm Framework 2.2 and Application Request Routing 2.5

 


1. Run following command on ARR server and all Web/Application servers to register and enable ASP.NET and WCF.

"%WINDIR%\Microsoft.Net\Framework\v4.0.30319\aspnet_regiis" -i  -enable

"%WINDIR%\Microsoft.Net\Framework\v4.0.30319\ServiceModelReg.exe" -r

2. Create Self-Signed certificate on ARR server, specify friendly name as *.ARR_Host_Name, where  ARR_Host_Name is the host name of the ARR server. "*." prefix is a must for https binding with specific host name which will be explained later.



3. Export created Self-Signed certificate


  
4. Import created Self-Signed certificate on ARR server and all Web/Application servers to Trusted Root Certification Authorities -> Local Computer



5. Verify certificate imported successfully by checking the IE Internet Options -> Content -> Certificate -> Trusted Root Certification Authorities.


6. Import Self-Signed certificate on all Web/Application servers to IIS Server Certificate store




7. Add https binding to default website in ARR server with Self-Signed certificate.




8. Run following Dos command to get Self-Signed certificate hash, e.g., 3fd08f1b81befae5007a7a02e535d17dfd0943a3
NetSH Http Show SSLCert IPPort=0.0.0.0:443


 

9. Install Microsoft Web Farm Framework 2.2 on ARR server
http://go.microsoft.com/?linkid=9739157



10. Install Application Request Routing 2.5 on ARR server



11. Verify the above installation by opening IIS Manager on ARR server.  Server Farms empty node is shown on the left side Connection panel, and URL Rewrite is shown on the center Feature View panel.



12. Create a "No Managed Code" and "Classic" application pool.  The website to be created is only used for routing purpose, so no need to run any managed code.


13. Create a website with above application pool, http binding with host name specified as ARR server host name.



14. Add https binding with host name and Self-Signed certificate.



15. Create a ".NET Framework v4.0.30319" and "Integrated" application pool on all Web/Application Servers.



16. Optionally, change the Application Pool Identity to custom credential that have access to all resources including SQL Server.


17. Create a website with above application pool, http binding with host name specified as ARR server host name, NOT the Web/Application server host name, it is required for WCF service routing.



18. Add https binding with ARR server host name, NOT the Web/Application server host name, and Self-Signed certificate.



19. Create Firewall rule for http and https port on ARR server and all Web/Application servers.  Do the following for both http and https ports.







20. Create a web farm. Click Yes at the end of the wizard to create a default URL Rewrite rule







21. Change web farm application and platform provision schedules to turn off automatic application and platform provision.



22. Change URL Rewrite rule to use https routing and binding.








23. Configure health check monitoring. Create a html page HealthCheck.html with following content.  Put HealthCheck.html in root folder of all Web/Application servers.

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Health Check</title>
</head>
<body>
<h1>Healthy</h1>
</body>
</html>
 


24. Configure machine key for primary Web/Application servers at Website level NOT Webserver level.  Synchronize all Web/Application server with application provision. Use following Dos command to validate machine key
C:\Windows\System32\InetSrv\AppCmd List Config "WebsiteName" /Section:machinekey


25. Use following Dos command to review the web farm and URL Rewrite rule:
C:\Windows\System32\inetsrv\AppCmd List Config  /Section:webFarms
C:\Windows\System32\inetsrv\AppCmd List Config /Section:system.webServer/rewrite/globalRules

26. Recommend to change the WCF binding to Basic HTTP Binding, according to the following MSDN documentation.
WCF Guidelines and Best Practices - Load Balancinghttp://msdn.microsoft.com/en-us/library/ms730128.aspx

27. Optionally change load balance algorithm.



28. Optionally, enable SQL Server TCP/IP connection, if website hosted by web farm needs to connect to the SQL Server.



29. Optionally, enable Firewall port for SQL Server TCP Protocol 1433, if website hosted by web farm needs to connect to the SQL Server.