November
22

NOTE: THE GENERATOR HAS EVOLVED SINCE THIS POST.Although the post is still worth reading, please go to http://razorgenerator.codeplex.com/ for the most up to date version.

Inspired by David Ebbo’s blog post ‘Turn your Razor helpers into reusable libraries’ I wanted to be able to embed compiled Razor views in a dll. This would allow for easy distribution of asp.net mvc ‘modules’ that have their default views embedded, but allowing you to place files in your ‘views’ folder to override those default views.

To generate the c# code for the views, I just started out with David Ebbo’s single file generator and modified it to generate views instead of helpers only. To do this, there had to be a WebRazorHostFactory that knew about all the mvc stuff (what dll’s to reference, what namespaces to use, etc) .I could either choose to include all that information statically in the code, or I could look for a web.config in the same project and let the WebRazorHostFactory use that config. I chose the latter option, so that everyone can easily change the WebRazorHostFactory behavior  by adding a web.config file to their project.

Next, I started figuring out how the PageVirtualPathAttribute inside System.Web.Webpages.dll is used by Microsoft. I found out that it is used when you call ApplicationPart.Register and after that call, there’s not much you can use of this functionality without some heavy reflection. I know it’s the wrong path to choose, but did it anyway. I ended up creating a ViewEngine calling into ApplicationPart’s internal methods to output compiled views. It worked, but I didn’t like it much: there had to be a better way.

I then tried if I could hook into the BuildManager stuff that asp.net mvc uses to generate the views. It was actually much easier then expected, now why didn’t I go on that path the first time!

I ended up creating

  • a CompiledRazorBuildProvider, which inherits from the default RazorBuildProvider,
  • a CompiledVirtualPathProvider which returns a CompiledVirtualFile if it decides that a compiled view should be used
  • and a ApplicationPartRegistry, which registers which compiled views are available.

To view the source, head over to

To just get started without viewing the source, read on, I will explain step by step how to use this library with some screenshots.

If you have improvements, fork the project on GitHub and let me know! If you have suggestions for improvement, just drop it in the comments.

Step 1: Install the FileGenerator

Download and install the Visual Studio extension: http://visualstudiogallery.msdn.microsoft.com/en-us/f28290ce-d987-4f91-b034-707031e10ce6/file/39295/0/RazorSingleFileGenerator.vsix

Step 2: Create new mvc project

image

image

Step 3: Add a class library to hold the views

image

image

Step 4: Cut your Models & Views folders

image

Step 5: Paste them into the just created Class Library

image

Step 6: Copy the website’s web.config file

image

Step 7: Paste that web.config file into the class library

image

Step 8: Select all your .cshtml files in the class library and set the Custom Tool to ‘MvcRazorClassGenerator’

Does anyone have a suggestion on improving this step??

image

Step 9: Build your class library

Step 10: Add your class library to the references of the web application

image

image

Step 11: Add ‘Commons.web.mvc.precompiledviews.dll’ as a reference to your website

this dll is copied to the class library’s output folder (in this case ../EmbeddedViews/bin/debug’)

image

Step 12: Register your views by adding a line to the application_start in global.asax.cs

image

Step 13: Run your website!

Now, you will see the normal default website, even though there aren’t any views in your website path!

If you wish to override some views, just create the normal folders (eg /Views/Home) and add your views there, but don’t forget to copy back the deleted /Views/web.config back into your project then!

106 Comments

@csteeg

This is really awesome Chris!

Thanks,
Bart Plasmeijer

Very cool, Chris! I ran through all the steps and it worked perfectly.

Ideally, we’d merge both projects into one that has both generators (helpers and views).

@David Ebbo: due to the fact that I use the same builder as mvc does, cshtml files in App_Code in your project will be compiled to HelperPages. What would your prefered method be?

Placing your helpers in App_Code like in webprojects or setting a different CustomTool if you want a helper to be generated?

I haven’t yet decided what I like more….

Well, the helpers are meant to be used by views. So if the views get precompiled at build time, you can’t have the helpers they rely on be compiled at runtime from App_Code.

Or am I misunderstanding you your question?

Yes, I think you misunderstood me :)

If you create an App_Code folder in the assembly containing the precompiled views (the EmbeddedPreviews project in my screenshots), put your .cshtml helper files in there and set the CustomTool of those cshtml files to ‘MvcRazorClassGenerator’, the generated c# code will inherit from HelperPage. So, it works the same as in webprojects, plus you can precompile your Helpers that way.

This is due to the fact that WebRazorHostFactory checks if the path starts with “App_Code” and if it does, it returns a WebCodeRazorHost instead of the default WebPagRazorHost

[...] Compile your asp.net MVC Razor views into a separate dll – Chris van de Steeg walks through the process of building C# code for Razor view files allowing them to be compiled into a DLL making it possible to ship views as you would compiled code. [...]

Sorry, didn’t see this comment (not sure how to get notifications).

Ok, I understand what you mean now. So it’s the choice between a single generator that does the right thing based on the path, and two different generators that ignore that path.

Maybe one down side of relying on the folder to get Helper behavior is that you lose control over the namespace that your helpers end up in (or do you?). Also, some people might find it strange to have an App_Code in a library project.

On the positive side, one generator might reduce confusion.

If we had some nice item templates to create precompiled views & helpers, that might remove some pain.

@David seemed my blog had some problem sending out its email, hope it works now…

I feel exactly the same, App_Code seems a little awkward in a library, but it’s handy that it’s only one custom tool you have to know about.

I was thinking I could also check myself, if the folder-name contains Helpers/ to switch to your version of the code

Could item templates have the CustomTool property set automatically… indeed that would be a nice option then

Is het possible to add the controllers for the embedded views as well to the library, to create a self contained package, so it would be possible to use it as some sort of component library ? I’m thinking about creating libraries that would encapsulate functionality that can be reused in different projects…

@rekna Yes you can embed everything into one library, in fact, that’s exactly what it’s good for :)

Wonderful tool, Chris! But I cannot get the Commons.web.mvc.precompiledviews.dll
What could I be missing?

@Ted, could you please check the output window if there are any errors being displayed?

And did it generate the .cs file underneath your .cshtml file?

Hi, Chris, it’s me again

1) There are no errors while building the library.
2) Step 8: Setting the “CustomTool” property to “MvcRazorClassGenerator” did not work. I.e. it did not generate the *.cs code parts. So I set it to “RazorClassGenerator” as it was originally advised by David Ebbo and it worked immediately.
However, Commons.web.mvc.precompiledviews.dll did not appears anywhere.
3) I searched the web and found this:
https://github.com/csteeg/BoC/tree/master/Src/Commons.Web.PrecompiledViews
so I downloaded, built it and got the DLL in the references of my web app. OK so far.
4) I am somewhat confused about moving (!) the entire “Model” folder to the separate library, moreover I have localized resources referenced in the models (data annotation messages etc). So I tried to:
4.1) build without moving
4.2) build with just copying the “Models”
None of these worked, the result is error:

The view ‘Index’ or its master was not found. The following locations were searched:
~/Views/Home/Index.aspx
~/Views/Home/Index.ascx

5. In the Application_Start() I suspected I needed to register the embedded views library, so another thing I tried was to place this:
BoC.Web.Mvc.PrecompiledViews.ApplicationPartRegistry.Register(typeof(PartialViewsDummyClass).Assembly);
where “PartialViewsDummyClass” was an empty class in the classlibrary… (but without the views)

I am definitly missing something.

Just to paste the entire web error (after running the application):

Server Error in ‘/’ Application.
————————————-
The view ‘Index’ or its master was not found. The following locations were searched:
~/Views/Home/Index.aspx
~/Views/Home/Index.ascx
~/Views/Shared/Index.aspx
~/Views/Shared/Index.ascx
~/Views/Home/Index.cshtml
~/Views/Home/Index.vbhtml
~/Views/Shared/Index.cshtml
~/Views/Shared/Index.vbhtml

@Ted could you
1) try to manually trigger the customtool by right-clicking the file and select ‘Run custom tool’? If there are any errors, it should now give you a popup message.
2) try the step-by-step example in this starting with a clean solution

Sorry for the delay…

Well, there were two problems:
1) Stupid me – I had messed up both tools – (yours: http://visualstudiogallery.msdn.microsoft.com/en-us/f28290ce-d987-4f91-b034-707031e10ce6 ) and (David Ebbo’s: http://visualstudiogallery.msdn.microsoft.com/en-us/1f6ec6ff-e89b-4c47-8e79-d2d68df894ec )
This solved the puzzle around “RazorClassGenerator”/”MvcRazorClassGenerator” and the generated DLL Commons.web.mvc.precompiledviews.dll

2) Second – I had to move the resources into another separate library project, plus some enumerations and custom data annotation attributes, used for decoration of models. And, yes, models have to be moved to the embedded views project as well.

Finally everything works like a magic!
Thanks Chris, nice tool :)

The question is not connected with subject. Which theme for VS2010 are You using ?

Hi,

Great work :) works like a charm….

Minor question: Is it possible to load all the embedded views in single line of code at the application_start event?

Thanks

@yh: see step 12… that’s only one line of code (?)

ApplicationPartRegistry.Register(this.GetType().Assembly);

Hi,

I thought I needed to register each view separately, I will move my models there and try it as you did.

My bad

Thanks

How about performance benchmark ?

Is there any advantage for precompiled views ?

[...] a starting point I used Chris van de Steegs code (Compile your asp.net mvc Razor views into a seperate dll), though what I ended up with was quite different. The current implementation of BuildManager is [...]

Emm. I just updated this tool today and now it don’t make .cs files of my .cshtml views anymore… So basically it’s stopped working for me which kinda sucks, cause I’m stuck in developement…

Actually, I get this error: http://i.imgur.com/OU5lC.png.

After restarting vs, uninstalling and reinstalling the extension (several times) it works again :-)

@Alxandr: You should always restart visualstudio after updating the extension (does anyone know how to force this from the extension’s manifest file?)

Hi Chris,

Congrats for your work. Works like a charm and is just what we needed.

We are about to release the 2.0 version of our framework (Signum Framework) and we are planning to use you solution to embedd views on libraries. Could this be a problem? Of course we will give you authorship in the documentation.

We are also trying to enable debuging in the cshtml and/or generated cs files but we feel a little bit lost.

We have been taking a look to base RazorBuildProvider and somehow we would like to include the debug information in the pdb together with the CompiledVirtualFile.

Can you give us some orientation on this?

Kind regards

@Olmo, sure it’s fine to include the code in your framework! No problem.

I just checked in a new version that doesn’t use the custom buildprovider. Instead, the virtualfile returns a cshtml-string @inheriting from the compiled razorview.
Should solve some issues I had with the buildprovider and simplifies things.

I still can’t debug the compiled types though… I’ll look into that. I don’t actually understand yet why that doesn’t work

Hi again Chris.

Clever hack! https://github.com/csteeg/BoC/blob/master/Src/Commons.Web.PrecompiledViews/CompiledVirtualFile.cs

I will use Utf8 instead of ascii thought, it’s the default encoding that razor views uses.

Hey! I just realized that maybe is cos of the #line hidden directive in the generated code. http://www.chrisvandesteeg.nl/wp-content/themes/01_green/images/submit-button.jpg

If this works will enable debugging the generated code, this is ok for us so far.

I try some hacks and i tell you.

@Olmo – the #line hidden probably is the issue – in normal usage you don’t want to see the generated code. I’ll probably try a fix myself with a simple string replace when I get to a better connected pc.

Being able to debug the cshtml rather than cshtml.cs would be nice though – #line filename should help at least as far as opening the right file to fix errors, but I’m not sure how it would be possible to get the right line numbers.

DevWonder 07/02/11 @ 1:42 am

Hi man,
awesome thing what you made, but i am facing one problem which is i cant use the one line to register all Embedded Views like you mentioned.

i tried this in Global.ascx in host application
ApplicationPartRegistry.Register(this.GetType().Assembly);

but i get this error
The view ‘Custom’ or its master was not found or no view engine supports the searched locations. The following locations were searched:
~/Views/Test/EmbeddedTest.aspx
~/Views/Test/EmbeddedTest.ascx
~/Views/Shared/EmbeddedTest.aspx
~/Views/Shared/EmbeddedTest.ascx
~/Views/Test/EmbeddedTest.cshtml
~/Views/Test/EmbeddedTest.vbhtml
~/Views/Shared/EmbeddedTest.cshtml
~/Views/Shared/EmbeddedTest.vbhtml

@DevWonder could you send the solution to me or does it contain code that you can’t expose?

Totally Appreciate the help Chris :) , here is Yousend it link for the project

https://www.yousendit.com/download/ MzZGSlJ3NDRIcWRjR0E9PQ

@DevWonder: you need to register the Assembly containing the views. In your case, you could register your views by changing

ApplicationPartRegistry.Register(this.GetType().Assembly)

to

ApplicationPartRegistry.Register(typeof(TestController).Assembly)

Man You are amazing, it works perfectly now :)
but if you don’t mind me asking, what if i have multiple Modules inside this Plugins Project, Like Blog, NewsLetter, in Folder Structure like Areas
Plugins Project
|–Blog
|-BlogController
|-BlogEditController
|–NewsLetter
|-NewsLetterController
|-NewsLetterEditController

is there a way to register them all?

another thing is, now i cant reference Declarative Helpers like i used to with David Version, am i missing something ?

totally appreciate your time and response.

@DevWonder, every view in your assembly will be registered. If you have multiple assemblies, you can just call ApplicationPartRegistry.Register for each of those assemblies.

You can only access Declarative Helpers if they are compiled as well. So if you add a App_Code folder to your plugins project, and set the helpers in there to be compiled just like your other views, you can use them.

DevWonder 08/02/11 @ 6:21 pm

Chris thanks a lot again, you are right i just have to register one Controllers and the rest will work.

but now i have got a new problem, if i create an Areas like structure like
Plugins Project
|–BlogModule
|-Controllers
|-BlogController
|-BlogEditController
|-Views
|-Index
|-BlogEdit
|–-NewsLetterModule
|-Controllers
|-NewsLetterController
|-NewsLetterEditController
|-Views
|-Index
|-NewsLetterEdit

i get 404 error.

now i have create arearegisteration class in hte blog Blog folder with following route
context.MapRoute(“Blog_Default”, “One”, new { controller = “Blog”, action = “Index” });

so i assume this is not supported, or i am still doing something stupid :)

regarding the HTML Helpers, please correct me if i am wrong,what you meant is that your extension only support helpers if they are in App_Code Folder and set Build Action to Compile, unlike David one where you can put them anywhere and set build Action to none?

if this is the case, can i use yours for embedded views and David Extension for declarative helpers or installing them both will create a conflict ?

again my Extreme appreciation for your quick response and patience.

@DevWonder working with area’s should be supported. Let me look into that.

You’re right about the HTML Helpers : I’m using exact the same technique to compile cshtml files as the aspnet_compiler does. So however you create your helpers in a normal mvc project, you can do the same here. As long as you set them to compile

DevWonder 13/02/11 @ 3:43 pm

thanks alot man for your input, i hope your tests prove that Areas Work, specially if i have created custom view Engine to locate Views in none standard MVC folder structure.

Hi Chris,
The custom tool is awesome.
I wanted to access all the MVC3 Templates within the new View Class Library Project.
Is there any way of porting the T4 templates to this class library.
Sorry if this is not within the context of this biog post.

@Veera, sorry, I’m afraid I don’t understand your question

Hi Chris,
I am not able to add a new cshtml files to the project. I lost the options that the Visual studio provides to add views(from existing templates) to the class library. I just want to check if the problem is because the mvc3 templates are available only on a mvc web project.
Is there a way of creating new razor files from visual studio on the class library project?
Sorry if iam not clear.

@veera, indeed, cshtml files can only be added to a mvc webproject.
You can however use the Custom BuildTool in an mvc webproject also if you’d like.

Otherwise, you just have to place a .cshtml ‘by hand’ in your class library (but you can’t use the t4 templates then indeed)

Hi Chris,

This is great. There’re a couple of projects where we will start to use this. Just a few questions.
-How far did you get with the PDB request?
-What’s the license?
-Could we just take the code of PrecompiledViews and merge it with our own Views dll? I was thinking of ILMerge, but it might be better for us to just hack this and make this the default behavior (making all those classes internal). I want to avoid the dependency on a second assembly.
- Did you agree on something with Dave? We’re thinking of using both approaches and I agree with the initial comments that it would be nice to have only one generator.

Cheers. Great job.

Miguel

Hi Chris,

I don’t see my previous posts. I’m not sure if there was an error when posting. Anyway, amongst other things I was suggesting to merge both tools and add support for Debug Symbols. I sent you a pull request with both changes.
https://github.com/csteeg/BoC/pull/1

Please let me know if you have any questions.

Regards,
Miguel

Hi Miguel,

sorry, I went skiing last week, so that’s why there were on updates :)

Thanks for your pull-request, I’ve pulled it into the master branch.

[...] in the view. Fortunately, thanks to the wonders of Visual Studio extensions, it’s possible to compile Razor helpers into a class library that could be used [...]

Excellent. Thanks. I hope you enjoyed the skiing :)

Would you agree on merging the PrecompiledViews dll? What do you think? I’ll have a go at it later today.

BTW, I noticed the one in the VS Gallery is still not updated… Not in a rush since we’re using the one from my fork ATM, but just wanted to let you know.

Do you know if this works in non “Full Trust” cases? I know VirtualPathProviders don’t always play nice with hosted server solutions.

Hi,
Excellent work, very useful for making modular mvc apps.
But i got something wrong when i try to use your tool…
I got namespaces problems :
“The type or namespace name ‘Views’ could not be found (are you missing a using directive or an assembly reference?)”

at this point :
public class _Page_Areas_Blog_Views_Blog_Index_cshtml : Views.Blog._Page_Blog_Views_Blog_Index_cshtml {

It seems the compiled file is under namespace ASP, instead of being under my library’s one.

Maybe I do something wrong, but what ?

I have followed your steps and everything works until I try to build the web application project. I am getting: “Assembly generation failed — Referenced assembly ‘Commons.Web.Mvc.PrecompiledViews’ does not have a strong name.” My projects have a strong name key. Any suggestions?

thx,
gabe

Very nice, thanks for sharing.
Just have to issues:
1) When moved the views to another project (as suggested), the debugging of views stopped going through the razor code.
2) Because I am using the Resharper utility, the controller stopped identifying the views, although its not complaining, its only marking the view name in red.

Thanks again.

[...] when experimenting with MVC routing seems rather constrained, and getting MVC to compile and use Razor views seemed rather like a hack than a natural, supported [...]

This works great!!! Just one questions though, how can I get intellisense to work for the Views in my Class Library?
For instance, it’s complaining ViewBag is not in the current context. Is there any way to fix that?

Hi Chris,

Is the debugging supported now? And does this mean that you can debug in the original helper file rather than the compiled version?

Cheers
Dewy

I ran through your steps, and I ran into a couple of tricky issues. Here is a quick FAQ from my experience with the initial setup:

Q: What does the Custom Tool, “MvcRazorClassGenerator”, do?
A: When it is applied to the “Custom Tool” property for all the views (*.cshtml), it adds a *.cs file to the view. Basically, it converts the view into code-behind, so it can be generated into a DLL.

Q: I keep getting an error like this:
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.aspx
~/Views/Home/Index.ascx
~/Views/Shared/Index.aspx
~/Views/Shared/Index.ascx
~/Views/Home/Index.cshtml
~/Views/Home/Index.vbhtml
~/Views/Shared/Index.cshtml
~/Views/Shared/Index.vbhtml

What do I do?
A: The compiler is telling you that it doesn’t know where to look for the view(s). You probably aren’t referencing the correct Project (Assembly).

To fix this issue:
1. Add a placeholder CS file in the embedded view project, e.g. “Class1.cs”.
2. In your Global.asax file in your general project, add:
BoC.Web.Mvc.PrecompiledViews.ApplicationPartRegistry.Register(typeof([YOUR_FULL_EMBEDDED_VIEW_PATH].Class1).Assembly);

where [YOUR_FULL_EMBEDDED_VIEW_PATH] is the complete path to access your Class1.cs file (you could just type in Class1.cs, and press Control + “.”).

3. Run your application, and it should work!

Thanks Sam, that’s great!

I’ll put that up on GitHub if that’s ok with you

Hi Chris

How about use embedded resource to store the views in assembly. just like MVCContrib PortableArea functionality.

That sounds good to me. Glad I could help other programmers for a change. :-)

Hi Chris,

I’m having an issue when I use @Html.RenderAction or Html.RenderPartial.
The tool generates “Write(Html.RenderAction(actionName, object routeValue));”.
And of course this doesn’t compile as Html.RenderAction returns void.

Really cool stuff otherwise thanks!
JP

Samuel Béliveau 13/06/11 @ 8:21 pm

First, thanks for providing this useful library ! :)

On my side, instead of directly referencing the class library, I would like to load assemblies at runtime (for a plugin system). I use BuildManager.AddReferencedAssembly(assembly) in PreApplicationStartMethod and it seems to resolve correctly the controller. However, your library no longer seems to resolve the View.

Interestingly, the first query of “locahost:12345/Query”, DictionaryBasedApplicationPartRegistry.GetCompiledType will correctly ask for “~/Views/Plugin/Index.cshtml” and return the instance. The following queries however won’t look for this one, but instead paths like “~/Plugin/Index.cshtml” or “~/Views/Plugin/Index.vbhtml”.

Got any idea ? :)

Thanks !

Samuel Béliveau 13/06/11 @ 8:23 pm

Oops, I made a typo in my last comment, it should read:

Interestingly, when the first query “locahost:12345/Plugin” triggers, [...]

Samuel Béliveau 14/06/11 @ 4:36 pm

I followed recommandations from http://shazwazza.com/post/Developing-a-plugin-framework-in-ASPNET-with-medium-trust.aspx and I solved my issue by registering to AppDomain.AssemblyResolve event.

Is there any vbhtml support? I have tried and can’t get it to work for vbhtml and I have to use VB at my workplace so can’t use c#.

Thank you to Sam (May 11, 2011) for the suggestion of ApplicationPartRegistry.Register(typeof(ClassLibrary1.Class1).Assembly);

TIP: Want that right-click, Add View menu item in your class library?
Edit csproj file for the web app. Copy the ProjectTypeGuids line. Paste this into your classlib csproj file.

I just wanted to add. Recommend trying the second project as another MVC project instead of a class library. I will refer to these as MvcMain and MvcClasslib for reference.

I was finding that when a view had an error, that the error line was line 0 in MvcMain. Now given the ability to run the second MvcClassLib project directly gives a specific error. It is the best of both worlds because the compiling of MvcClassLib views prevents syntax errors.

You just have to make sure you have Web.Config in both places. I made my MvcMain global.asax inherit from MvcClassLib global.asax.

(This means my previous tip of having your class library act like an MvcProject template is no longer needed).

~Good luck

Raja Kolli 14/07/11 @ 9:36 pm

@Chris, First of all thank you very much for this excellent utility. I am not sure why something as basic like this does not come out of the box.

Hey Veera/Chris, what approach did you guys finally decide on…
the question being
“…
veera says:
Feb 16, 2011
Hi Chris,
I am not able to add a new cshtml files to the project. I lost the options that the Visual studio provides to add views(from existing templates) to the class library. I just want to check if the problem is because the mvc3 templates are available only on a mvc web project.
Is there a way of creating new razor files from visual studio on the class library project?
Sorry if iam not clear.

Chris van de Steeg says:
Feb 16, 2011
@veera, indeed, cshtml files can only be added to a mvc webproject.
You can however use the Custom BuildTool in an mvc webproject also if you’d like.
Otherwise, you just have to place a .cshtml ‘by hand’ in your class library (but you can’t use the t4 templates then indeed)

I want to know what/how the developer community is using the seperate class library approach.
How are people using scaffolding templates?
How do people define a view as a partial view?
How are you doing “Add View” and “Add Controller” functionality that are some of the core MVC 3 core concepts.

I am sorry is some of my questions are lame or redundant. Please feel free to answer few or all questions.
Thank you once again.

Tom Schreck 15/07/11 @ 3:44 am

Hi Chris. Thank you very much for this tool. It looks very promising. I have some common tables that are used in multiple projects. I think I can use this approach to provide customization to the common tables as needed (I hope). I’m still feeling my way through this.

How does this compare to MVC3′s Areas and MvcContrib’s Portable Areas? With Areas you have to register the area for routing purposes. Are there any routing concerns with your approach? I tried creating the same Controller in the embeded project and the web app and got an error saying the same controller name exists in 2 locations and it suggested using Are registration.

I created a controller in the embeded project and was able to navigate to it. The parent web app had no knowledge of the controller. Pretty cool.

Thanks

Tom

Tom Schreck 15/07/11 @ 5:00 am

How do you access JavaScript and CSS files from the embeded dll? Thanks.

@Chris:

Would you kindly inform us whether this tool is still needed, given the latest version of T4MVC?

It seems that they now overlap quite significantly. Which is currently (July 2011) the preferred tool for use? I don’t quite understand what the difference is between them anymore.

Otherwise, great tool! Helped me alot for older projects! :-)

Meant to say in my last post, not really T4MVC, but Ebbo’s “Razor Single File Generator”.

Why did you delete my posts?

Hi Chris,

Really nice work. Have a look here http://fzysqr.com/2010/09/10/asp-net-mvc2-plugin-architecture-tutorial-part-3/
I liked that approach because that doesnt require to generate any cs file. but that works good with WebViewengine and not with cshtml files, specially if you are passing a model to the view. Can we achieve same result without generating cs file.

Also, I wana do some serious work with your library. Should I do it or its just for learning purpose. Is there any other solution if you can suggest.

Regards
Parminder

Playing, Playing, Playing.

Hi Chris,

One more issue here. I created two plugins (Home and Users) and have HomeController and Index method in both. I managed to register route using namespace like this.
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute(“{resource}.axd/{*pathInfo}”);

routes.MapRoute(
“Default”, // Route name
“Home”, // URL with parameters
new { controller = “Home”, action = “Index”, id = UrlParameter.Optional }, new[] { “Dha.Plugin.Home.Controllers” }
);

routes.MapRoute(
“Users”, // Route name
“users”, // URL with parameters
new { controller = “Home”, action = “Index”, id = UrlParameter.Optional }, new[] { “Plugin.Users.Controllers” }
);

routes.MapRoute(
“Users-justatest”, // Route name
“users/justatest”, // URL with parameters
new { controller = “Home”, action = “justatest”, id = UrlParameter.Optional }, new[] { “Plugin.Users.Controllers” }
);

}

It works well, but returns me index view from Users moudule even when I am accessing the home url (http://site/home). I think it should look for the view the same assembly where the controller is being called.

Help will be appreciated.

Regards
Parminder

I have set up a working demo where I have 3 external class libraries. 1 has the top level views as you describe here, and the other 2 are where I put the area code in its entirety.

Everything works great.

However, I did not copy over the main web.config from my main project to these libraries and things are still good. Why exactly do I need that Web.config to be copied over to my class library?

I did not do your step 6 and step 7.

Hi, great work on this btw, i’m loving it. So, i have my solution running and building however i need to install the RazorGenerator onto a build server, so ideally into the GAC. For some reason it’s not copying to the GAC though (no errors). What is the best way to reference the Generator for build servers (obviously i don’t want to version my bin folder or create a dependencies folder just for one assembly). Any help will be greatly appreciated. Cheers, Dom

Hi Chris,

Excellent article!
I’ve just implemented this into a new MVC3 framework I’m using for all custom web applications. It’s just what I was looking for!

Many thanks!

Regards
Marijn

@chris – well done! allows for some splendid possibilities. reminds me a bit of the XNA Custom Pipeline processors

[...] resource as described here.   Initially I wanted to “pre-compile” them as described here but in my experience I could not get that to work (something about compiling in some ASP [...]

May I inquire as to where you are with getting this ready for Visual Studio 11?

[...] is a detailed blog from Chris van de Steeg here. With the help of the information in this blog we were able to reuse the MVC views. In this blog I [...]

António Albuquerque 17/11/11 @ 6:37 pm

Hi.

I’m trying to use the precompiled views in a project similar with a CMS.

Instead of adding the Assembly to the main mvc web project, I load the assembly with reflection in the Application_Start() method and then register using BoC.Web.Mvc.PrecompiledViews.ApplicationPartRegistry.Register().

All works fine until I try to open a page and I get an error like: An unexpected exception occurred while binding a dynamic operation and it points to the generated .cs of the page I’m trying to open.

Any ideas?

Thanks

[...] I guess I have to compile that view and I’ve followed these instructions. [...]

What about using filters to secure controllers?

This is awesome. Thanks.

I’m looking at using it for Partial Views, however, which I am thinking is not going to work as I get an error when compiling within the Execute() override method: “THe name ‘model’ does not exist in the current context”

[System.CodeDom.Compiler.GeneratedCodeAttribute("MvcRazorClassGenerator", "1.0")]
[System.Web.WebPages.PageVirtualPathAttribute("~/Views/CurrentLivePolicyCountParams.cshtml")]
public class _Page_Views_CurrentLivePolicyCountParams_cshtml : System.Web.Mvc.WebViewPage
{
#line hidden

public _Page_Views_CurrentLivePolicyCountParams_cshtml()
{
}
protected System.Web.HttpApplication ApplicationInstance
{
get
{
return ((System.Web.HttpApplication)(Context.ApplicationInstance));
}
}
public override void Execute()
{

Write(model); // <– ERROR position

WriteLiteral(" Mis.Reports.Models.CurrentLivePolicyCountReportModel\r\n\r\nHell” +
“o”);

}
}
}

I have experienced the problem from Sam’s FAQ, however, I was not able to resolve that problem with the provided information. What is the “Full Path” of the class? Is it the full namespace of the class with the class name at the end, or is it the physical path of the DLL of the embeded project output or what should it be? Any help would be very much appreciated. Thanks.

What about routing? I mean each module might have its own routes. Also route definitions might collide.

I am trying to implement in ASP.NET MVC4.

I am getting this 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.aspx
~/Views/Home/Index.ascx
~/Views/Shared/Index.aspx
~/Views/Shared/Index.ascx
~/Views/Home/Index.cshtml
~/Views/Home/Index.vbhtml
~/Views/Shared/Index.cshtml
~/Views/Shared/Index.vbhtml

Could any one explain me what i am doing wrong. I have complete all the step what is shown above.

-Thanks

I am also not able to generate .cs code behind file for all the view in asp.net mvc4

I installed the correct extension but when trying to set the CustomTool to MvcRazorClassGenerator, my system says it can not find the extension. I am working with a VB class library and vbhtml views. I noticed in the source that the vsContextGuids.vsContextGuidVBProject line was commented out. Do I need to switch the comment on the CS line and build the extension? I tried that and it seemed to work but I’m not sure how to generate the vsix file. Any help would be great.

I split views in more than 1 project, but i can’t include references with the same name into the main project, so, how can i include views? Is there any way to change Commons.Web.Mvc.PrecompiledViews.dll to a custom .dll?

Can you please answer to @Parminder or @Giovanni question above. I have same issue when you have same controller/view name in EmbeddedViews DLL and user DLL. It always looks at the User DLL first. I know it will work if I create a different view folder structure and write viewEngine to look at those location first, but I prefer to keep the same view folder structure.

Please help.

I can’t seem to get this to work. The controller is unable to find the View. Only difference is I didn’t create a LogOnModel and I don’t have any models created and so I didn’t add the extra code in the Global.asax.cs file. If this is what is required, then I would need to create an empty Model and add that to Global.asax.cs for this to work?

BTW, I’m using C# v4.0 with VS2010 SP1Rel and MVC3 on Windows 7 64bit.

Nevermind, I found my answer. I had to add this line in the Application_Start method in the Global.asax.cs file…

ApplicationPartRegistry.Register(typeof(RazorViews.Views.FileClaim._Page_Views_FileClaim_Index_cshtml).Assembly);

I hope that helps someone!

How can we get Intellisense to work for the Razor Views? Any ideas from anyone are welcomed!

Hi all,

there is now an official supported version of the generator at http://razorgenerator.codeplex.com/

I advice to use the version on codeplex, as this version is an outdated one

Regards,
Chris

Chris,

I am using RazorSingleFileGenerator.vsix extension with MVC4 VS2010.

Setting the custom tool to MvcRazorClassGenerator and compiling the class libary (step 8 & 9 above) doesn’t create the generated view files.

Ran the ‘Run Custom tool’ option on one of the views to spot the issue. It errors out with:

“The custom tool ‘MvcRazorClassGenerator’ failed. Could not load file or assembly ‘System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral,PublicKeyToken=31bf3856ad364e35′ or one of its dependencies. The system cannot find the file specified.

Looks like the tool expects 1.0.0.0 of the version but I am using the latest. Probably the tool source is compiled with Specific Version set to true for this binary.

Any solution would be greatly appreciated.

Thanks,
elvy

Chris,

I earlier posted a question on the workings of this tool – RazorSingleFileGenerator.vsix (v1.05 or v1.07) with MVC4, but it looks like it has been deleted. Any issues?

Regards.

Something to say?

Please note: Comment moderation is enabled and may delay your comment. There is no need to resubmit your comment.