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!

40 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...

    Thx!

  • 



djsolid

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

  • Thanigainathan Siranjeevi on said

    Reply
    



Thanigainathan Siranjeevi

    Hi,

    Can 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 on said

    Reply
    



Shukhrat

    Hi,

    is there a typo in package snippet on second screenshot? (RazorJSInlcude instead of RazorJSInclude) :)

    Thx!

  • 



Sham

    Awesome, just what I needed (yeah, there is a typo in the library :)).

    However, i found that if I use Glimpse an error is raised. Without glimpse it works perfectly.

    Excellent work.

  • 



djsolid

    Indeed there was a typo!
    Just update the package and fixed it.

    @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.

    Once 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.

  • 



Chris

    One problem I see with this is that you lose the ability to cache these script files in the browser.

    Would 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...?

    Then 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.

    Am 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?

    Any 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.

    As it is now, the end user can directly request the .js file, and have access to it's source code, possibly creating security holes.

    Apart 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,

    I got the error below, can you please tell me how to fix it?

    Thanks,

    ----------------

    Configuration Error
    Description: 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.

    Parser Error Message: Could not load type 'RazorJS.RazorJSHandler'.

    Source Error:

    Line 59: </pages>
    Line 60: <httpHandlers>
    Line 61: <add path="razorjs.axd" verb="GET" type="RazorJS.RazorJSHandler" />
    Line 62: </httpHandlers>
    Line 63: </system.web>

  • 



djsolid

    Hello Sam,

    I think that you haven't added as a reference the dlls of the package or you removed it by accident.

    Check that RazorJS.dll and RazorEngine.dll are added as a reference inside your web project.

  • 



Sam

    hi djsolid,

    the reference were there, anyway tried on another clean project worked fine.

    thanks for the cool package.

    cheers,

  • 



ahmed

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

    please

  • MJ Richardson on said

    Reply
    



MJ Richardson

    Exposing the ViewBag property would also be useful.

    Have you considered open-sourcing this?

  • 



Roman

    Hi John. Thank you for your tool.
    What about Ajax support with AjaxOptions and InsertionMode.
    also I have an exception if use @Html.RazorJSInclude "Empty path name is not legal."
    Could 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!

    Cheers!

  • 



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 !

    I just missed the ability to pass a model dedicated to javascript

    (because in my cases, it will not be the same as the view, i'll just need some parameters)

    So I added the following extension methods :

    public static IHtmlString RazorJSInline<TModel>(this HtmlHelper html, string filename, TModel model)
    {
    return html.Raw(new RazorJSFileParser(filename).InlineScript(model));
    }


    Actually, i still try to make it works with dynamic objects but am not so much familiar with it.

    I'll dig more soon :)

    Anyway, thanks for this tool :)

  • 



Denis

    Hi,

    First of all, thanks a lot for your great tool, I've been expecting something like this for a long time.

    However, I faced a problem: it seems that there is an issue with the scripts used via RazorJS when the solution is deployed to Azure.
    I 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.

  • 



Dominik

    Hey,

    I 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.

    The 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.

    Since 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.

    John

  • 



<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).

    There is problem. I can't see scripts delivered by razorjs in Firebug.

    It would be nice if the path could be something like /something/something/my.js instead of /razorjs.axd?fn=/something/my.js

    This should fix the Firebog issue and hide how the script was generated from the end user.

    Still 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.

    Any 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.

    I 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

    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

    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("")

    I 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> block. I can then use @Razor syntax.

    Instead of referencing a JS, simply add "Html.Partial()" ...

  • 



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...

    Thanks...

    I try to move my js code to files and get error about the follow components:
    ViewBag, Json, Html.Raw, etc...

    It will be very usefull if all this classes, intaces will be support..

    thanks again

  • Brij on said

    Reply
    



Brij

    Excellent plugin !!!

    Hope, 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:
    http://goo.gl/hKQxK

Add a Comment (gravatar-enabled)