RazorJS - Write Razor inside your Javascript files

Update: Full Source code is available at BitBucket

Many times I have a Javascript file that contains a link and in order to be more generic I would prefer writing something like ~/image.png rather than /image.png or /myapp/image.png.

Also when one of my Views in an MVC project interacts with 3rd party components and services (like Google Maps, UserVoice etc.) contains a lot of Javascript code along with html/server-side code. The minute that this page reaches a stable version I tend to put the javascript code in a separate file to keep things cleaner. But if that code depends on my Model and is being rendered by Razor I can’t do that. That means this code must stay on that view and I may end up with duplicating it to other pages with similar functionality.

Struggling with the above I ran into a very good Nuget Package called RazorEngine and thought to create something using that to be able to have more flexibility in my Javascript Code.

And the name of this is RazorJS.

Let’s see a few examples:

Javascript Code in an external file

The JS File

image

The Razor Code

image

The Rendered HTML

image

Javascript Code with Model dependency

The JavaScript File

image

The Code

image

The HTML

image

What about performance?

The JS files are being cached just like Razor files with a CacheDependency so if a file changes the Razor template is being updated instantly. Every file is compiled just like Razor Pages and is being compiled the first time is requested or when a change is detected.

So the time to render each file the second time (and every time after) is really really small.

Known Issues

  • For now the Nuget package doesn’t have a dependency to RazorEngine because it needs a later version to perform better which isn’t yet available. Once RazorEngine 2.2 is released I will update the package.
  • For now the only method available to call is Href and the only property is only two properties are Model and Url. Please let me know other methods or properties that could be useful when writing Javascript.

That’s all for now! You can find it at the Nuget Feed!

Cheers!

54 Comments

  • 




Fatal

    How about passing the UrlHelper object through so that you could do @Url.Action(action, controller,....)

  • 




djsolid

    Yes, that's also supported!

  • Scott Wade on said

    Reply
    




Scott Wade

    This looks very promising and something I have been wishing for... I'm NuGet'ing right now and will try...
    $1
    $1Thx!

  • 




djsolid

    Thanks Scott! Please let me know if you have any feedback!

  • Thanigainathan Siranjeevi on said

    Reply
    




Thanigainathan Siranjeevi

    Hi,
    $1
    $1Can you please enable this for WebForm view engine too ?

  • 




djsolid

    I 'm afraid that it's not possible for the time being. It will be, when Razor Syntax is also included at WebForms.

  • 




Shukhrat

    Hi,
    $1
    $1is there a typo in package snippet on second screenshot? (RazorJSInlcude instead of RazorJSInclude) :)
    $1
    $1Thx!

  • 




Sham

    Awesome, just what I needed (yeah, there is a typo in the library :)).
    $1
    $1However, i found that if I use Glimpse an error is raised. Without glimpse it works perfectly.
    $1
    $1Excellent work.

  • 




djsolid

    Indeed there was a typo!
    $1Just update the package and fixed it.
    $1
    $1@Sham, Now it's also working with Glimpse!

  • 




Sham

    Thanks, amazing library. I am just getting into MVC and you have made my life easier. Not being a web developer by day, any chance of a write up on how you created the RazorJS? What did developers do before the RazorJS.
    $1
    $1Once again, excellent work.

  • 




sandeep

    Thanks for sharing that info, still i am new for that technology. Then please give me an idea from beginning level.
    $1

  • 




Chris

    One problem I see with this is that you lose the ability to cache these script files in the browser.
    $1
    $1Would a better solution not be to simply output a hidden DOM element with data-* attributes that contain the values you'd be injecting into the script in your example (e.g. the current date, the model values, etc...?
    $1
    $1Then you can still let the browser cache the JavaScript file and use jQuery to look up the data-* values you need from the hidden DOM element.
    $1
    $1Am I missing a scenario where that wouldn't work?

  • 




Zote

    Is it possible to add google clojure or another kind of compilation/minification of renerated js?
    $1
    $1Any way, it's a great project! My team and I will starting using it very soon.

  • 




Peter

    These Javascript files are not Javascript files anymore; you should follow Microsoft's example, name the files .cjs for example and add a entry to the web server config to not serve .cjs files.
    $1
    $1As it is now, the end user can directly request the .js file, and have access to it's source code, possibly creating security holes.
    $1
    $1Apart from security holes, the format used in the file is not JS format anymore, so continuing the .js extension can cause confusion.

  • 




<a href="http://www.noyasystem.com" rel="nofollow">ramin</a>

    Wonderful article. Thanks for sharing

  • 




Sam

    Hi djsolid,
    $1
    $1I got the error below, can you please tell me how to fix it?
    $1
    $1Thanks,
    $1
    $1----------------
    $1
    $1Configuration Error
    $1Description: An error occurred during the processing of a configuration file required to service this request. Please review the specific error details below and modify your configuration file appropriately.
    $1
    $1Parser Error Message: Could not load type 'RazorJS.RazorJSHandler'.
    $1
    $1Source Error:
    $1
    $1Line 59:
    $1Line 60: <httphandlers>
    $1Line 61: <add path="razorjs.axd" verb="GET" type="RazorJS.RazorJSHandler"></add>
    $1Line 62: </httphandlers>
    $1Line 63:

  • 




djsolid

    Hello Sam,
    $1
    $1I think that you haven't added as a reference the dlls of the package or you removed it by accident.
    $1
    $1Check that RazorJS.dll and RazorEngine.dll are added as a reference inside your web project.

  • 




Sam

    hi djsolid,
    $1
    $1the reference were there, anyway tried on another clean project worked fine.
    $1
    $1thanks for the cool package.
    $1
    $1cheers,

  • 




ahmed

    please can y help me in aproblem i want code c# for "work offline" button for browser
    $1y can send me in ahmed_essam_saad@hotmail.com
    $1
    $1please

  • MJ Richardson on said

    Reply
    




MJ Richardson

    Exposing the ViewBag property would also be useful.
    $1
    $1Have you considered open-sourcing this?

  • 




Roman

    Hi John. Thank you for your tool.
    $1What about Ajax support with AjaxOptions and InsertionMode.
    $1also I have an exception if use @Html.RazorJSInclude "Empty path name is not legal."
    $1Could you help please? Or if you like I'm ready to take part of your project.

  • 




djsolid

    Thank you all for your comments! Soon there will be an update and also I will upload the project to Codeplex!
    $1
    $1Cheers!

  • 




Swemail

    Great tool. Have one question, I use a separate assembly for my models, can I point to a model in a separate assembly in the 'from @Href(..) statement?

  • 




Swemail

    Great tool. Have one question, I use a separate assembly for my models, can I point to a model in a separate assembly in the 'from @Href(..) statement?

  • 




Alex

    Pretty nice !
    $1
    $1I just missed the ability to pass a model dedicated to javascript
    $1
    $1(because in my cases, it will not be the same as the view, i'll just need some parameters)
    $1
    $1So I added the following extension methods :
    $1
    $1public static IHtmlString RazorJSInline<tmodel>(this HtmlHelper html, string filename, TModel model)
    $1 {
    $1 return html.Raw(new RazorJSFileParser(filename).InlineScript(model));
    $1 }
    $1
    $1
    $1Actually, i still try to make it works with dynamic objects but am not so much familiar with it.
    $1
    $1I'll dig more soon :)
    $1
    $1Anyway, thanks for this tool :)</tmodel>

  • 




Denis

    Hi,
    $1
    $1First of all, thanks a lot for your great tool, I've been expecting something like this for a long time.
    $1
    $1However, I faced a problem: it seems that there is an issue with the scripts used via RazorJS when the solution is deployed to Azure.
    $1I made a small investigation and it seems that the problem appears in RazorEngine when running template service; in your code you check if template is compiled and then run with no compilation process, but looks like on Azure the compiled templates are not saved and for a second time the Engine throws an error. Sorry, didn't have enough time to find more, but I believe it's interesting.
    $1

  • 




Dominik

    Hey,
    $1
    $1I have just found this tool yesterday, and it helped me to reduce the number of inline scripts in my views. But as Denis said, I also get the error after deploying to azure. On the second load of the page I get an 500 error from server. The problem is as Denis described it.
    $1
    $1The problem doesn't occur with inline adding of scripts, but that's kind of a reason why I wanted to use it in the first place ^^

  • 




djsolid

    Hello, and thank you for reporting your issues.
    $1
    $1Since the full source is available here ( https://bitbucket.org/djsolid/razorjs/ ) can you please create an issue there? I will take a look as soon as possible.
    $1
    $1John

  • 




<a href="http://www.microsec.co.uk" rel="nofollow">AndyB</a>

    Works well. I use it, primarily, for localising javascript and for adding comments that I don't want the user to see (use Razor comments).
    $1
    $1There is problem. I can't see scripts delivered by razorjs in Firebug.
    $1
    $1It would be nice if the path could be something like /something/something/my.js instead of /razorjs.axd?fn=/something/my.js
    $1
    $1This should fix the Firebog issue and hide how the script was generated from the end user.
    $1
    $1Still a bit of a newbie at Razor, so not sure how to accomplish this (if at all)

  • 




Angelo

    I'm running into an issue... When the browser hits razorjs.axd sometimes it can't find the requested file and returns a 404. Other times it works just fine. I can't find a pattern. The code doesn't change but one time I run my MVC app and the browser doesn't get the JS file then if I rebuild it once or twice, it works.
    $1
    $1Any ideas? I've tried this in IE, FF and Chrome but it's not a browser issue.

  • 




Angelo

    Sorry, it's not coming back with a 404, it's coming back with a blank file. Again, this is intermittent. It won't work when I build 1-3 times, then I build again and it works fine for several more builds.
    $1
    $1I don't know if RazorJS is doing any internal caching but perhaps that's the issue?

  • Patrick Neborg on said

    Reply
    




Patrick Neborg

    I am experience the same issue as Angelo. Without this working consistently I will need to abandon using RazorJS.

  • EagleEye on said

    Reply
    




EagleEye

    I'm trying to use this in a MVC3 project and I've installed RazorJs and tried the first example above and the script file renders correctly into the html but the razor is still being interpreted as strings. Am I doing something wrong? We are looking to use this throughout our companies medical websites.

  • EagleEye on said

    Reply
    




EagleEye

    Scatch my last comment I got it working now for some reason. And now that I re-read what I wrote it's to vague to decipher any problem anyways. But thank you for this... it really cleaned up my views A LOT.

  • 




Pavel

    I installed the package today and tried use it. But I failed to use @Html.RazorJSInlcude("") and @Html.RazorJSInclude("")
    $1
    $1I searched for them both in the RazorEngine.dll and System.Web.Razor.dll assemblies via Reflector but failed to find mentioned methods. What I do wrong?

  • 




Joel

    Nice plugin! I noticed that if you have custom routes.MapRoutes, the Url mapping is messed up. Is this a known issue or something new? If you want some example code, email me and I'll post it.

  • wizmagister on said

    Reply
    




wizmagister

    I've done a simple thing: renamed the external JS file to "cshtml" and put my code into a <script></script>

  • 




yurivan

    hi, I was testing with visual studio mvc 4 in 11 and gave me the following error Could not load type 'System.Web.Razor.Parser.MarkupParser' from assembly 'System.Web.Razor, Version = 2.0.0.0, Culture = neutral, PublicKeyToken = 31bf3856ad364e35 'and not to be exactly should I update the source code version 4 also mvc?

  • 




Shimon

    Very good Extenstion...
    $1
    $1Thanks...
    $1
    $1I try to move my js code to files and get error about the follow components:
    $1ViewBag, Json, Html.Raw, etc...
    $1
    $1It will be very usefull if all this classes, intaces will be support..
    $1
    $1thanks again
    $1
    $1

  • 




Brij

    Excellent plugin !!!
    $1
    $1Hope, It'll support Viewbag and Session soon. Right now I'm using Session or Viewbag by passing in place of model in js file. See following for more details:
    $1http://goo.gl/hKQxK

  • 




marlin

    Thanks!!!
    $1I was testing with MVC 4,I found the source code is dependend on mvc's System.Web.Mvc and System.Web.WebPages. The library is differ from mvc3.
    $1So need to modify the source code's reference then rebuild. But i think it's not a good idea to change the source.

  • Gian Carlo on said

    Reply
    




Gian Carlo

    Plugin is fine but i have a problem with a my application hosted on arvixe.com. Infact loading the page the first time doesn't give me any error, but when I refresh the page pressing F5 i can see in firebug an error loading javascript file. The error I receive is a 500 internal server error stating an Object reference not set to an instance of an object.
    $1Googling around the world and investigating the problem i found that may depend on a Microsoft IIS Component by name URL rewrite. This component I think is installed by arvixe and i can't do nothing to uninstall because is on a Arvixe Server. So please can you help me to solve this problem?

  • 




Alireza

    Thanks, great job !
    $1
    $1but please warn about the "allowedPaths" setting in this post or project's nuget page. I spent more than an hour and went through downloading the source code to find out why I can't use my scripts which were placed in "~/JS/" directory ! the error message could be a little bit more helpful too :)

  • 




Muthu

    Hi i installed nuget using Library Package Manager. installed correctly and i can see reference.but i am unable to code Html.RazorIsInclude . how to update htmlhelper to use this. Thanks

  • muthucsm on said

    Reply
    




muthucsm

    hi its my mistake.i didn't install razorjs package. but now i can see RazorJsInclude but its not call the Js file. Here is my code looks
    $1@Html.RazorJSInclude("~/Js/test.js");
    $1and in Js file just put
    $1alert("hi");
    $1any help?

  • LordToro on said

    Reply
    




LordToro

    Hi, I has some question. Normally I rendered .js file by using "BundleConfig.cs" like bundles.Add(new ScriptBundle("~/bundles/user").Include(
    $1 "~/Scripts/User/User.js"));
    $1
    $1Is it possible to use this plugin together with Bundle? Thanks in advance.

  • Alejandro Mosquera on said

    Reply
    




Alejandro Mosquera

    Thanks! This is Great!

  • Guilherme Cardoso on said

    Reply
    




Guilherme Cardoso

    I ask the same as @LordToro

  • 




Rodrigo

    I'm having the following error Could not load type System.Web.Razor.Parser.MarkupParser System.Web.Razor assembly, Version = 2.0.0.0, Culture = neutral, PublicKeyToken = 31bf3856ad364e35.

  • 




Proxy

    i'm interested on the same as @LordToro

  • 




Chai

    Hi,
    $1My JS file contains the following statement:
    $1@foreach(var routedata in Html.ViewContext.RouteData.Values) {
    $1
    $1 . . .
    $1
    $1}
    $1
    $1I'm getting the following errors:
    $1"The name 'Html' does not exist ion the current context"
    $1"The name 'routedata' does not exist ion the current context"
    $1
    $1how can i use the HtmlHelper (with the viewcontext) insode the JS file ?
    $1
    $1Thanks for the help,
    $1
    $1Chai

  • Dinesh Jain on said

    Reply
    




Dinesh Jain

    Any solution for the issues revolving the MarkupProcessor and the RazorEngine incompatibilities? Also, I get the above issues only when I use the RazorJSInline method and not using RazorJsInclude. However if I use RazorJsInclude my .js files is rendered empty :(.
    $1
    $1Really looking forward to use this library as it will help me a great deal.
    $1
    $1Thanks in advance.

  • 




Andreas

    Is it posible to run Razorjs with mvc 5 and razor 3 ?
    $1
    $1I'm receiving following error when trying:
    $1
    $1
    $1Could not read System.Web.Razor.Parser.MarkupParser from599 System.Web.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
    $1

  • 




sai

    Hello ,
    $1Getting the fillowing exception:
    $1Unable to load referenced library '*\packages\Microsoft.AspNet.Razor.2.0.20715.0\lib\net40\System.Web.Razor.dll': The system cannot find the file specified.
    $1

Add a Comment (gravatar-enabled)