Problem when trying to use precompiled views in a separate library

Dec 13, 2011 at 7:05 AM

I created a test MVC3 app to test the concept of putting precompiled views in a separate library as discussed in David's post here.  I tried to follow the instructions carefully.  However, when I execute the app the following error occurs:

Attempted to access an element as a type incompatible with the array.

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.ArrayTypeMismatchException: Attempted to access an element as a type incompatible with the array.

Source Error: 

Line 13:             };
Line 14: 
Line 15:             ViewEngines.Engines.Insert(0, engine);
Line 16: 
Line 17:             // StartPage lookups are done by WebPages. 


Source File: H:\VS Projects\RazorGeneratorTest1\MyPrecompiledViews\App_Start\RazorGeneratorMvcStart.cs    Line: 15 

Stack Trace: 

[ArrayTypeMismatchException: Attempted to access an element as a type incompatible with the array.]
   System.Collections.Generic.List`1.Insert(Int32 index, T item) +49
   System.Web.Mvc.ViewEngineCollection.InsertItem(Int32 index, IViewEngine item) +27
   System.Collections.ObjectModel.Collection`1.Insert(Int32 index, T item) +116
   MyPrecompiledViews.App_Start.RazorGeneratorMvcStart.Start() in H:\VS Projects\RazorGeneratorTest1\MyPrecompiledViews\App_Start\RazorGeneratorMvcStart.cs:15

[TargetInvocationException: Exception has been thrown by the target of an invocation.]
   System.RuntimeMethodHandle._InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeType typeOwner) +0
   System.RuntimeMethodHandle.InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeType typeOwner) +72
   System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks) +335
   System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) +28
   System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters) +19
   WebActivator.BaseActivationMethodAttribute.InvokeMethod() +221
   WebActivator.ActivationManager.RunActivationMethods() +342
   WebActivator.ActivationManager.RunPostStartMethods() +27
   WebActivator.StartMethodCallingModule.Init(HttpApplication context) +131
   System.Web.HttpApplication.InitModulesCommon() +172
   System.Web.HttpApplication.InitModules() +43
   System.Web.HttpApplication.InitInternal(HttpContext context, HttpApplicationState state, MethodInfo[] handlers) +828
   System.Web.HttpApplicationFactory.GetNormalApplicationInstance(HttpContext context) +304
   System.Web.HttpApplicationFactory.GetApplicationInstance(HttpContext context) +107
   System.Web.HttpRuntime.ProcessRequestInternal(HttpWorkerRequest wr) +327

Any suggestions as to how to resolve?

Coordinator
Dec 13, 2011 at 7:12 AM

That's quite puzzling. Maybe you have an unusual situation with multiple versions of the MVC runtime getting loaded? All the code is doing is add a view engine to a collection of view engines, so if that blows up there is an issue that goes beyond razorgenerator I think.

Dec 13, 2011 at 7:19 AM

I don't know how I could have multiple versions o the MVC runtime loaded.  When I store the precomplied views in the same assembly as the MVC app everything works fine.  The problem only occurs when there is a separate project included for the precompiled views.

Any suggestions as to how to try to debug?

Coordinator
Dec 13, 2011 at 7:30 AM

Try setting a BP at that line 15 location, and evaluate these two expressions:

  • engine.GetType().BaseType.Assembly.Location
  • typeof(IViewEngine).Assembly.Location

In theory, they should be the same.

Dec 13, 2011 at 7:30 AM

David, I have uploaded the sample app here.  I would appreciate it if you could run it on your system and see if you get the error.

 

Thanks.

Dec 13, 2011 at 7:35 AM

I set the BP at line 15 the results of evaluating the expressions are as follows:

engine.GetType().BaseType.Assembly.Location

"C:\\Windows\\Microsoft.Net\\assembly\\GAC_MSIL\\System.Web.Mvc\\v4.0_3.0.0.0__31bf3856ad364e35\\System.Web.Mvc.dll"

typeof(IViewEngine).Assembly.Location

The type 'System.Web.Mvc.IViewEngine' exists in both 'System.Web.Mvc.dll' and 'System.Web.Mvc.dll'

Coordinator
Dec 13, 2011 at 7:37 AM

Yes, as suspected, the problem is that you're using two different versions of MVC at once. You view project references 4.0, while your web project has 3.0 in its _bin_deployableAssemblies.

Dec 13, 2011 at 7:45 AM

Ok, I changed it so now both projects reference MVC 3.0 and now get the following error:

The view 'Index' or its master was not found or no view engine supports the searched locations. The following locations were searched:
~/Views/Home/Index.cshtml
~/Views/Shared/Index.cshtml
~/Views/Home/Index.aspx
~/Views/Home/Index.ascx
~/Views/Shared/Index.aspx
~/Views/Shared/Index.ascx
~/Views/Home/Index.vbhtml
~/Views/Shared/Index.vbhtml

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 view 'Index' or its master was not found or no view engine supports the searched locations. The following locations were searched:
~/Views/Home/Index.cshtml
~/Views/Shared/Index.cshtml
~/Views/Home/Index.aspx
~/Views/Home/Index.ascx
~/Views/Shared/Index.aspx
~/Views/Shared/Index.ascx
~/Views/Home/Index.vbhtml
~/Views/Shared/Index.vbhtml

Coordinator
Dec 13, 2011 at 8:02 AM

I just created a new app and it worked fine. You can get it from here. Not sure what's different about yours, though it would be interesting to know if you spot the difference.

Dec 13, 2011 at 8:24 AM

I got your app and it does work fine.  The biggest difference between your app and mine is that yours uses MVC 4 and mine uses MVC 3.

I then created a new app doing everything the same as when I built the first app, except this time using MVC 4.0 and it works.  The problem appears to be somehow related to MVC 3 and Razor Generator.

I notice that in this discussion a similar issue has occurred.

Feb 11, 2012 at 3:47 PM

@mmoore99 - I am interested to know if you ever got to the bottom of this issue.

I am also trying to add views to a separate library and have the same ArrayTypeMismatchException issue.  Again, it seems to be related to the System.Web.MVC references added in the projects (in the MVC application a reference to version 3 is automatically added where in the library, the precompiled view engine automatically adds a reference to version 4), however changing the references used does not work.  Additionally, I have tried to create an MVC4 project with a separate library and found that (like in your situation) it does work.  Very frustrating.

I would be interested to know if you managed to resolve this issue or found a work around to this?

Many thanks.

Coordinator
Feb 12, 2012 at 1:16 AM

Would be nice to get to the bottom of it indeed. If you share out a minimal repro the demonstrates the issue, I can try to investigate further.

Feb 12, 2012 at 1:23 AM

@dangerous81 - Sorry, but I never resolved the issue.

Coordinator
Feb 12, 2012 at 1:30 AM

I just did a quick test, and it all seemed to work for me:

  • Created new MVC 3 app
  • Created second MVC 3 app to act as the view library project
  • In first app, delete all the views
  • In the second app, install RazorGenerator.Mvc and run Enable-RazorGenerator
  • In first app, add reference to second app

And it all ran fine. Note that I'm not using MVC 4 anywhere.

You can get my code from https://github.com/davidebbo/MvcApplicationRazorGeneratorSeparateLibrary.

Are you doing something much different from those steps?

Feb 13, 2012 at 5:26 PM

Thank you for the response.  It turns out that I was setting it up incorrectly after all.  For some reason I was under the impression that you could just use a class library for your separate view library.  I set it up using an MVC3 project acting as a view library and then all worked correctly.  Thank you for your time with this.

Coordinator
Feb 13, 2012 at 5:37 PM

Great! I have updated the wiki on http://razorgenerator.codeplex.com/ with that info. Hopefully, this will help others later. :)

Aug 23, 2012 at 11:59 AM

Just had the same problem in the process of upgrading to MVC 4 from MVC 3. My set up is 2 projects, an MVC view library using RazorGenerator and a Hybrid Webforms/MVC web app.

Followed the steps in the release docs (http://www.asp.net/whitepapers/mvc4-release-notes#_Toc303253806) but ended up with the exception above, and when setting a breakpoint as described by david above I got message "The type 'System.Web.Mvc.IViewEngine' exists in both 'System.Web.Mvc.dll' and 'System.Web.Mvc.dll'". Clearly was running MVC3 and 4 at the same time, even though I had changed every reference to MVC4 and the binding redirects were installed in the web.config.

Turns out the binding redirects were not being applied because I had used an existing AssemblyBinding section in my config that was .net 2 only, and something somewhere had a dependency on MVC3. So my config was:

<assemblyBinding appliesTo="v2.0.50727" xmlns="urn:schemas-microsoft-com:asm.v1">

And changing to this made it go away.

<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
Hope this helps someone else.

May 20, 2013 at 10:54 PM
When I create two fresh MVC4 apps and follow this procedure for them they work perfectly.

However, when I attempt to create a reference to the library from my existing app (the one I want to move a view from) it gives me the above error.

I have checked both the framework and MVC versions and they match.

When I examine "ViewEngines" in the debugger I get the message "The type 'System.Web.Mvc.ViewEngines' exists in both 'System.Web.Mvc.dll' and 'System.Web.Mvc.dll'"

I am not sure what else to do. I guess I can recreate everything, but that would be a lot of work.

Jacob
Coordinator
May 20, 2013 at 11:01 PM
And are you sure that you're not missing the MVC4 binding redirect in web.config? With a binding redirect, it's should be impossible for both to be loaded.
May 20, 2013 at 11:09 PM
I am not sure what you mean by missing the redirect. I do know that my assemblyBinding tag matches what is recommended three posts above this.

Since my last post I actually copied my app, changed the name, added it to my sln, and set the copy up as a view library. As soon as I added a reference to it I got the error. I am certain that all of the references and config files are identical except the reference to RazorGenerator.Mvc.

Jacob

P.S. thank you for responding so quickly.
Coordinator
May 21, 2013 at 2:35 AM
Looking through this thread, it has evolved through various different issues, so I'm not actually sure which one you're referring to here. :)

Are you able to get at that issue starting from a new Mvc app to which you add RG.Mvc? It would be good to isolate what may be different about your app. If you have a repro you can share (e.g. in github), that would be ideal.
May 21, 2013 at 3:48 PM
It worked when I originally tested this concept, before I tried to incorporate it into my real site.

However, I went back to the basics at http://blog.davidebbo.com/2011/06/precompile-your-mvc-views-using.html and created two projects as described. I used the Internet Application template for the "main" project and the Empty template for the library, both under MVC4.

I got the error described in the original post in this thread.

---- instant update

As I was typing the above, for no reason I ran it again and IT WORKED. I made no changes. The debugger was stopped on Line 15 as described and I hit stop, then I ran it again and it worked.

I don't understand, I am going to delete the projects and start again, to see if this happens again. I will post my results here.

Jacob
May 21, 2013 at 4:16 PM
ok, this has got to be some kind of race condition having to do with the server starting up.

I recreated both apps from scratch just as I described in my last post. I discovered several things:
  • If I simply stop and run it again, the code runs correctly, as in my last post
  • If I stop the site in the ASP.Net development server, from the system tray; then the error reoccurs, but only the first time
  • If I force it to recompile MyPrecompiledViews but leave the server running, the error does not reoccur
  • If I stop the site but place a breakpoint at the beginning of RazorGeneratorMvcStart.Start then continue after the breakpoint is hit; then the error does NOT reoccur
  • If I switch to using IIS Express instead of the ASP.NET Development Server, the error does not occur and cannot be reproduced
  • If I switch back to ASP.NET Development Server (without recreating the project), the problem does not occur and cannot be reproduced
Armed with this odd set of facts I will see if I can get it working in my real site.

Jacob
May 24, 2013 at 9:40 PM
I just realized that my final post somehow didn't make it here somehow.

I discovered that the above did NOT solve my problem with the real project.

I began to look for differences between the project I created to test and the one with the actual site in it. And I found it; somehow the library requires WebGrease on the main (i.e Host) application.

Steps to reproduce (in VS 2010):
  1. Create an app and a view library as described in http://blog.davidebbo.com/2011/06/precompile-your-mvc-views-using.html with one exception, make both of them using the MVC4 "Empty" template (the blog post recommends using the "Internet Application" template)
  2. Create a HomeController and a simple ~/Views/Home/Index.cshtml in the main application
  3. Continue as described in the blog post
You will get the ArrayTypeMismatchException described at the beginning of this discussion.

To fix:
  1. Open the NuGet manager for the main application (not the library)
  2. Add the latest version of WebGrease
The app should now run without additional changes.

This requirement was invisible using the "Internet Application" template because it includes WebGrease out of the box, as do all of the MVC4 standard templates except "empty". It turns out that my app (created long before I contemplated a view library) was made from "empty"

Thanks for your help.
Jacob
Coordinator
May 24, 2013 at 9:52 PM
Great, thanks for following up with the workaround!
Jun 3, 2013 at 8:51 AM
Hi,

I'm also having an error like this "attempted to access an element as a type incompatible with the array". As Mr Davidebbo said I evaluate these two expressions:
  • engine.GetType().BaseType.Assembly.Location
  • typeof(IViewEngine).Assembly.Location
and get the result as this :

engine.GetType().BaseType.Assembly.Location
"C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Web.Mvc\v4.0_3.0.0.0__31bf3856ad364e35\System.Web.Mvc.dll"
typeof(IViewEngine).Assembly.Location
The type 'System.Web.Mvc.IViewEngine' exists in both 'System.Web.Mvc.dll' and 'System.Web.Mvc.dll'

I dont know how to change the versions. I checked the version of System.Web.MVC. they are same. Here i'm doing the mef also.

Thanks

Chinnu
Jun 3, 2013 at 9:32 AM
Hi,

How to change the refernce of view and web project. I'm using MVC 4
Coordinator
Jun 3, 2013 at 4:44 PM
Do you have two separate projects for your views and your controller? If so, could you also verify if the both have the same binding redirects?
Coordinator
Jun 3, 2013 at 5:21 PM
Could be this issue? Check if the configuration tag in your web.config has a schema (e.g. xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0"), and try removing it.
Jun 4, 2013 at 7:15 AM
@davidebbo- in my web.config i have - xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform".
Jun 4, 2013 at 3:50 PM
@Chinnu

The "XML-DocumentTransform" is likely in one of your configuration specific config files, these will have a name like Web.Debug.config or Web.Release.config or possibly Web.{Something Else}.config .

Try to look in the file that is just called Web.config .

If that doesn't work do a project wide search for the text ".NetConfiguration" . If that search finds no results then you don't have the tag that @davidebbo is talking about or anything similar to it.

Jacob
Jul 2, 2013 at 10:35 PM
I have been resolved this trouble comparing the web.config application from the library source project and the web.config from the project destiny.
If you can not find the solution, copy all the content of the web.config from the library to the project destiny.
Sep 2, 2013 at 2:49 AM
Edited Sep 2, 2013 at 2:49 AM
I have the same problem, but only with MVC 4 Project.
When I use MVC 3 works perfectly.

I edited the *.csproj in both projects to reference the same DLL.
Before the Nuget had referenced another DLL:
<Reference Include="System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
  <Private>True</Private>
  <HintPath>..\packages\Microsoft.AspNet.Mvc.4.0.20710.0\lib\net40\System.Web.Mvc.dll</HintPath>
</Reference>
Now both are referencing the same DLL (GAC)
<Reference Include="System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
ie, there is no conflict.
...but not what happens when I run the web application.
When I run the web application the "Attempted to access an element as a type incompatible with the array" error occurs:
Attempted to access an element as a type incompatible with the array.
// Source File: ...\App_Start\RazorGeneratorMvcStart.cs    Line: 15 
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.ArrayTypeMismatchException: Attempted to access an element as a type incompatible with the array.

Line 15: ViewEngines.Engines.Insert(0, engine);

//Output: The type 'System.Web.Mvc.ViewEngines' exists in both 'System.Web.Mvc.dll' and 'System.Web.Mvc.dll'
So, what can I do?
I tried using RazorGenerator with "Class Library" and "Web Application", but doesn't work.

ps: Works when I try to use RazorGenerator in a "Class Library" or "Web Application" with the main project being "MVC 3", but doesn't work when the main project is "MVC 4."

Could you help me?
Oct 2, 2013 at 1:11 PM
Edited Oct 2, 2013 at 1:14 PM
I had exactly the same problem as others on this thread.

I created a brand new solution. I then created two MVC apps (using the Empty template). MvcApplication1 (the "main" app), and Docs (the "satellite"). This is with VS 2012, I have verified that both projects are built against .NET 4.5.

MvcApplication1 has a reference to Docs.

On running it I get the same issue raised above.

I've added debug code into the RazorGeneratorMvcStart class and can see that two different version of MVC are loaded...
engine.GetType().BaseType.Assembly.Location => C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Web.Mvc\v4.0_3.0.0.0__31bf3856ad364e35\System.Web.Mvc.dll
typeof(IViewEngine).Assembly.Location => C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Web.Mvc\v4.0_4.0.0.0__31bf3856ad364e35\System.Web.Mvc.dll
I have verified this with fuslogvw too.

Now, as another posted suggested I've installed the latest version of WebGrease, That had no affect.

What worked for me however was adding the assembly binding redirect. The following sorted it for me...
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35"/>
        <bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
This is in the main projects web.config, not the satellite project. I can see from fuslogvw that the appropriate assembly is now being loaded, and naturally the code no longer crashes.

That treats the symptom - the cause is that the current version of RazorGenerator.Mvc has a reference to System.Web.Mvc 3. If you look in Reflector (or ILDasm) it'll show you the culprit...
// Assembly Reference System.Web.Mvc

Version: 3.0.0.0 
Name: System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
David - could you update the references in the project (and do System.Web.WebPages at the same time too)? That should solve the issue for most folks - I realise that this might break backwards compatibility, but in all fairness most people should upgrade to v4 anyway as if not they're missing out on a lot of great stuff.

Cheers,

Morgan
Coordinator
Oct 2, 2013 at 10:11 PM
It's a bug in the Empty template that it doesn't have the redirects. All the others have it.

But maybe just updating the reference to v4 is the way to go anyway as you suggest.
Coordinator
Oct 9, 2013 at 10:22 PM
Note that this is also affected by a NuGet bug. Normally, NuGet adds all the relevant binding redirects, but they have a regression in 2.7 that causes this not to work.
Dec 4, 2013 at 2:27 PM
Hi!
Well,well, I came here again because the new version still not working with MVC4 (at least to me), but I found a solution:

Just add the following section in the 'main' web.config (not Views web.config):
<runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
Dec 7, 2013 at 8:54 AM
Hi.

I have faced same issue while working with Spark view engine.
Problem was System.Web.Mvc assembly reference try to refere assembly runtime version :v4.0.30319,version : 3.0.0.0.