9

I'm buliding an application in ASP.NET MVC and considering backbone.js for the client side interaction etc..

Ideally when the pages are loaded i'd like to have all the existing content pre-rendered on the server side and then any new content rendered by backbone.js on the fly.

Naturally i dont really want to write my templates twice.

I'm considering having most of the application templated using the razor view engine and then using mustache templates for the small areas that need to be shared between server and front end.

My question is, what does the actual technical implementation of this look like?

Can you provide code samples of how you would achieve this?

For example which library would you use to render the template on the server and then would you manually extract the text from the template file and inject it into the javascript?

Daniel Upton
  • 5,561
  • 8
  • 41
  • 64
  • 1
    You can use `RenderPartial` or `@Html.Partial` to refresh your new content using Ajax. That way you only need to have your Razor template. Double bonus: Return the partial view after updating the new content for avoiding another trip to the server. – Eduardo Molteni Dec 30 '11 at 18:29
  • +1 Good question. I've not found a good way of sharing the views between client server. I wish I could, it introduces risk and work having to maintain both – reach4thelasers Apr 17 '12 at 14:45

5 Answers5

1

I am evaluating Razor Client Templates (GitHub) at the moment. It is in version 0.7.0 and seems a bit brittle currently.

It allows you to reference individual partial razor views as JavaScript templates.

As part of a commercial product we will be taking this further to output Handlebars.js compatible templates from our Razor partials.

Andy Hoyle
  • 668
  • 6
  • 8
1

If you want a RESTy MVC application I recommend ServiceStack. There's a backbone w servicestack todo-app you could view-source on.

I did something similar (not using mustache) where the controller outputs the model as json for backbone to work with.

Toft
  • 167
  • 2
  • 8
1

Not so much a technical as a functional answer see my answer here for a functional flow incorporating server- and clientside rendering (using Mustache)

Accessibility and all these JavaScript frameworks

hth,

Community
  • 1
  • 1
Geert-Jan
  • 18,623
  • 16
  • 75
  • 137
0

Have you considered jQuery templates, on our project we used them and i found them quite useful. We actually used this one http://github.com/BorisMoore/jsviews, that is a bit optimized version of jquery template for render to string. You have a lot of demos there. On server side we placed all templates in one partial view and render it.

Vladimir Bozic
  • 434
  • 6
  • 18
0

First we made the choice to embed v8 in MVC.net and WebApi and implement the templates with underscore or mustache to keep exactly the same templates.

Even if you have the same templates, the rendering logic can be different and you need constantly to refactor the templates, the frontend views and the backend views. Specially if you are doing a restfull api.

We finally choose an other solution to provide non javascript alternative for accessibility and seo requirements using a headless browser (PhantomJs) to render the pages.

It's quite easy to implement, you need to install PhantomJs on your server, add a javascript to render completely the page with all the javascript interactions and serve the html output.

You can found an example of use here : http://backbonetutorials.com/seo-for-single-page-apps/

The example is for node.js but it's easy to implement it with ASP

The phantom script we use is similar :

//phantom-server.js

var page = require('webpage').create();
var system = require('system');

var lastReceived = new Date().getTime();
var requestCount = 0;
var responseCount = 0;
var requestIds = [];
var startTime = new Date().getTime();

page.onResourceReceived = function (response) {
    if(requestIds.indexOf(response.id) !== -1) {
        lastReceived = new Date().getTime();
        responseCount++;
        requestIds[requestIds.indexOf(response.id)] = null;
    }
};
page.onResourceRequested = function (request) {
    if(requestIds.indexOf(request.id) === -1) {
        requestIds.push(request.id);
        requestCount++;
    }
};

// Open the page
page.open(system.args[1], function () {});

var checkComplete = function () {
  // We don't allow it to take longer than 5 seconds but
  // don't return until all requests are finished
  if((new Date().getTime() - lastReceived > 300 && requestCount === responseCount) || new Date().getTime() - startTime > 5000)  {
    clearInterval(checkCompleteInterval);
    console.log(page.content);
    phantom.exit();
  }
}
// Let us check to see if the page is finished rendering
var checkCompleteInterval = setInterval(checkComplete, 1);

There is also services that provide you the same result : http://prerender.io/

Val Entin
  • 953
  • 10
  • 18