TL;DR
What are the best practices when using .NET Razor views and AngularJS?
Context
We are developing a public website (not an intranet application) using mvc4 with razor, and we weren't very familiar with client script, so we started with what we knew: jQuery.
But now things are getting more complicated and we'd like to switch to AngularJS.
On the .NET part, we use Razor templates and UIHintAttribute
(plus some custom ones) to render the right html "control". We also add custom html attributes to give extra information to the jQuery part (like title
for a tooltip....)
So we already use a declarative way of setting the user interface behavior, that's why AngularJS seems a good option.
Questions
Since we already have models defined server side, and since AngularJS also uses models, wouldn't it force us to duplicate code?
How do we deal with data binding feature, since we already do some binding server side (in the views). Should we make a completely asynchronous application, making AJAX calls from AngularJS to load data, or can we mix both?
Anything else we should be aware of when trying to use both of these technologies?
I did some research on Google, but I can't find detailed ways of mixing Razor views and templates with AngularJS... Perhaps that's just not a good thing to do?
We dealt with this issue for months when working with MVC plus another JavaScript framework (Knockout). Ultimately, if you're going to be using a client-side MV* framework for rendering your user interface, you will find that mostly ditching Razor is going to be your best bet.
Most of the major MV* JavaScript frameworks, including AngularJS, assume you will be maintaining UI state and rendering your user interface based on JavaScript models or view models. Trying to mix in server-side rendering is just not going to work very well.
That's not to say there is no use for MVC when it comes to developing an Angular application. You can still take advantage of some great features like ASP.NET Bundling and Minification. And sometimes it works really well to embed JSON directly into the page using a Razor view or partial as opposed to making an additional AJAX call.
As for models, you may want to take a look at Breeze.js. It's a JavaScript library for data access that goes great with ASP.NET on the server side to share model metadata.
We wrote our own data binding mechanism that synchronizes the angular.js model with a view model on the server side. The javascript model is generated from a JSON serialization of the server-side view model to avoid the duplicate code that you were talking about.
We are using SignalR to update the client's view model from the server.
Server-side changes of the C# view model properties are sent to the client as a packet containing the path to the property, e.g. Persons[42].Address.City, and the value itself, e.g. New York. The view model inherits a base class that takes care of generating the property path, so the actual view model looks quite clean and we can concentrate on business logic.
Client-side changes of the javascript view model properties are sent to the server in the same way. To catch the change events, we encapsulate all fields of the original javascript model in get/set properties where the setter sends the update packet to the server.
Server-side methods of the view model can be invoked in a similar way. All objects in the view model have an invokeMethod function that can be used like this: Products[42].Manufacturer.invokeMethod('SendEmail', 'mailsubject', 'mailbody'). This will send a packet to the server containing the method path Products[42].Manufacturer.SendEmail and the arguments as an array of ['mailsubject','mailbody'].
In conclusion, the html view (kind of) binds to the view model on the server side where other systems, such as regular Razor views can work on the same objects.
The source code can be found here: SharpAngie.