MVC Compiled Views - asp.net-mvc

I want to take a look at my views with reflextor, I have set my project to compile views
<MvcBuildViews>true</MvcBuildViews>
But when opening the DLL for my application in reflextor I do not see the views...
I see the controllers and models but no views...
Have I not compiled the views correctly? or is there more to it?
Thanks,

If you want a fully compiled ASP.NET MVC project with your views compiled, you can either run aspnet_compiler.exe against your web app.
That's the hard way. The easy way is to install the Web Deployment Project add-in to Visual Studio. Then you can add a web deployment project and set it to fully compile your web application.
http://www.microsoft.com/downloads/details.aspx?FamilyId=0AA30AE8-C73B-4BDD-BB1B-FE697256C459&displaylang=en
It's really easy to use and gets you full compilation.

Is there any chance the views are just being compiled in order to provide you with compile time checking but not actually being included in the assembled output?
It seems like the main goal of this feature could be just to help catch compile time errors quicker not necessarily to speed up the processing of the page or anything.

Views are not compiled in DLL, they are copied as is to the output. Attribute that you use is only compile time check for them.

Related

Trying to understand the finer details application pool refresh and precompilation of Views in ASP.NET MVC

I am using ASP.NET MVC3, .NET4, Razor, C#, EF4.1, MS SQL2008(dev), SQL Azure(test,live).
I am deploying my web application to "Standard" Azure Websites. My process is:
1) Publish to local IIS folder, no precompilation options selected:
Project C# code is compiled as Project dll and put into "bin" folder.
Views stay as source *.cshtml files
2) FTP changed files to deployment server using Beyond Compare,so
Project DLL gets copied
Source *.cs files (Controllers, helpers, Models) get copied.
Changed source *.cshtml Views getting copied
With the initial call to the deployment server, the response is slow, due to JIT compilation. I suspect this is due to:
a) Views being compiled. Major factor as opposed to project dll??
b) Project DLL already precompiled so no issue here ??? Is this correct.
I try to keep the application pool in memory via pingback services either external monitor sites(Uptime Robot) or MS's "always on" service which is the same. But one can still get app pool refreshes and thus slow downs. It seems to me that everything should be precompiled for deployment so that if dropped from memory then rerunning will be quick.
My question(s)
1) Is my understanding correct about what is precompiled and what is not?
2) What should I do now to maximise precompilation and minimise these app pool refresh penalties, and thus keep performance at it peak ie no start of day warm ups etc. My initial impression is to precompile the Views. I did try editing the Project XML file, and this setting specifically:
<MvcBuildViews>true</MvcBuildViews>
However when I try to publish using the above setting I get an error:
obj\release\aspnetcompilemerge\source\web.config(45): error ASPCONFIG: It is an error to use a section registered as allowDefinition='MachineToApplication' beyond application level. This error can be caused by a virtual directory not being configured as an application in IIS.
EDIT
Having done a little more research it seems that I need to focus on precompiling the Views for wich 2 main tools exist:
a) RazorSingleFile
b) RazorGenerator
Apparently
<MvcBuildViews>true</MvcBuildViews>
just compiles rather than precompiles. Not sure of the difference. So it is recommended to use one of the tools above.
EDIT2
My main MVC project dll is 890k-ish in size. Is this large? Would the size cause more drop out from memory?
There is a serious rabbit hole when building views. There is some known bug that this particular error happens. The only known if is to use the <BaseIntermediateOutputPath>. This path needs to exist, and not be within the project path (I think). I usually use:
<MvcBuildViews>true</MvcBuildViews>
<BaseIntermediateOutputPath>..\..\tempMVC</BaseIntermediateOutputPath>
The Aspnet Compiler Build Task in Visual Studio 2010 ASP.Net MVC 2 Projects
I am 95% sure that: You can't pre-compile MVC views (cshtml, etc) for deployment (with any default version of Visual Studio, there may be add-ons). There are two separate issues here.
First, <MvcBuildViews> is only a buildtime strongly-typed checker when set to true. Meaning that if you build a view against a specific #model that the compiler will check the view during a build to make sure aren't using the model incorrectly (like trying to use a property on the model that doesn't exist).
Secondly, the notion of pre-compiling a view into an assembly is a process that exists for Webforms because there is a code in-front and code behind that can be combined. Views aren't tied to logic in this way so the compiler hasn't been designed to take MVC Views into account.
OK, my solution was to publish the application.
Then I selected:
Precompile during Publishing
I then clicked on "configure" and then unchecked:
Allow precompiled site to be updateable
I then selected:
Do not merge, create a seperate assembly for each page or control.
This enabled the precompilation of the views, and put them in the bin folder, in the form of:
_orders.cshtml.4deb95a2.compiled
I understand this to be p-code and so will still need a binary compilation on first load on the deployment server. The project dll is worse since it is bigger.
By the way I did encounter quite a few assembly references issues that were caused by old excluded code files. I thought if they were excluded that was good enough, but no..... In the end I just deleted them all and the precompilation completed successfully.
Doing this forced me to fixed quite a few hidden razor errors which would have come out at runtime as opposed to compile time.

ASP.Net MVC: How to dynamically load assemblies (controllers) without an AppPool restart/recycle

I'm trying to write a module/plugin system for a website I'm working on. The overall goals are:
That the main website does not have to be recompiled every time a new plugin is added.
To be able to dump DLL's and CSHTML files into a set of folders that would basically add a set of routes, controller(s), and any other assemblies that the module depends on (Entity Framework, etc).
To avoid marking plugin files as "embedded resources" -- especially views.
To be able to add and remove these modules/plugins WITHOUT having to restart/recycle the IIS app pool or unload the app domain.
I got #1-3 working by following the example of Umbraco. Basically, I marked a method with the PreApplicationStartMethod attribute, and in it I shadow copy DLLs around, and use a custom ViewEngine to locate the module's CSHTML files. When my website first starts up, my module's controllers and views are working, and assemblies are loaded: Hooray!
However, when it came time to try part #4, I am getting this error when calling BuildManager.AddReferencedAssembly():
This method can only be called during the application's pre-start
initialization phase. Use PreApplicationStartMethodAttribute to
declare a method that will be invoked in that phase
It's been a very frustrating process so far, and my gut tells me that this error signifies a dead end. Is this the case, or is there a clever workaround?
Editing the web.config file when you add the new modules should cause the site to recompile.
You could automate this in a script, forcing your new .dll's to be copied to the live ASP.NET temp files directory.
Check out portable areas. Essentially a regular MVC area (including views, controllers, etc.) gets compiled into a single dll. These dll's (one for each area) can be dropped into a hosting MVC website and can be called like any other MVC area.
Some references to get started:
Portable Areas three years later – Part 5
MvcContrib Portable Areas
"To be able to add and remove these modules/plugins WITHOUT having to restart/recycle the IIS app pool or unload the app domain."
It turns out that this you cannot unload an assembly from an app domain.
How to unload an assembly from the primary AppDomain?

Does MvcBuildViews actually do anything?

I've just discovered this property in MVC projects, but I'm having a hard time determining if it has any real effect. The following makes me believe this property has almost no real effect out of the box:
It does an in-place compilation of the site (AFAICT), and leaves the site "updateable" so that the markup files are not affected. This is important for in-place compilation so the sources aren't wiped out.
Because it's in a WAP project, all the code files will be compiled into the project's output assembly anyways (unless they're in App_Code, but that's just odd).
So the sources in the project were already compiled, and the markup files aren't affected. What is the actual impact of using MvcBuildViews?
When <MvcBuildViews> is set to true, building the web project results in errors if the views contain any server-side code issues. Note that this includes C# errors (compile-time / type-safety / etc.), but not JavaScript errors, as those are intrinsically non-compiled.
This feature works for Razor and WebForms views, but it seems to have no effect when the Spark view engine is being used.

Can Razor views be compiled?

I was wondering if Razor views could be compiled, like WebForm based views?
Does it even make sense to compile Razor views and why would somebody want to do that?
Edit:
Here is a blog post on this topic as well:
How to Detect Errors of Our ASP.NET MVC Views on Compile Time
To make your views to be compiled, do the following;
Unload your project by right
clicking the project on the solution
explorer in VS and clicking unload
project
right click the project which has
been converted to unavailable
project and click "Edit
your_project_name.csproj" (that
would be .vbproj if your
project is VB project)
see the following code;
<!--There some lines of code here and I deleted them to get to the point quickly-->
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<MvcBuildViews>false</MvcBuildViews>
change the MvcBuildViews tag value from false to true
after that save it and reload your
project.
after you build your solution to compile it, you will see that your view will be compiled too.
NOTE: to test it, break some code in one of your view on purpose and try to build. you will see that you'll get an error message.
The MvcBuildViews check is excellent but it adds a 5-10 second penalty for building your web app if it's complex enough. It doesn't cache the compilation output so it does a full compilation of all your views every time.
I found a nice compromise by following the above advice and adding a Condition attribute:
<MvcBuildViews Condition=" '$(Configuration)' == 'Release' ">true</MvcBuildViews>
We'd expect ReSharper to flag up any errors in the views anyway and the developer can always build in the release configuration as a test - we have a "preflight" script that developers run so they can easily make sure that package targets work and so on - and if all that fails, the build server will catch it.
Perhaps this trick is obvious but I've only really started learning about msbuild properly as opposed to writing Powershell scripts for these tasks. I hope this is helpful to someone.
Yes, you can. Take a look at the following post: Compile your asp.net mvc Razor views into a seperate dll
It's a "step-by-step" guide on how to compile your razor views into a separate dll. I don't know if that's what you aim to do but it'll definitely get you in the right direction.
Yes, it's possible. In fact, the best example I can think of would be email templating engines. If you compile and cache the template, then you can quickly rip off emails without having to go through the parsing all over again.
That's a good example of using Razor outside of MVC as well.

In an MVC web.config file what does the setting compilation debug='true' do?

For performance reasons an MVC app should have compilation debug='false' set in its web.config.
What benefits does having it set to 'true' during development give? I know that it 'inserts debugging symbols into the compiled page' but what is that for?
Check out this quite interesting link (very old, but still pertaining), which tries to explain in more detail the workings of either compilation mode, or, at least contrast between them well.
In an attempt to directly answer your question regarding what debugging symbols are used for - these give extra information about the compiled code and allow for interrogation of the executing code-base when a debugger is attached; allowing you to step through the source, for instance, as the binary can now be mapped back to it's location in the source file, variable names etc.
This is used for the code that is compiled on the fly (such as aspx and ascx pages) and will instruct the compiler how to compile the files.
Rest of the files such as models, global.asax, etc will be compiled to bin folder.

Resources