single page applications on javascript and asp.net mvc4
DESCRIPTION
Single page applications on JavaScript and asp.net mvc4 from Minsk SEC 2013 conference (Jan 2013)TRANSCRIPT
![Page 2: Single Page Applications on JavaScript and ASP.NET MVC4](https://reader035.vdocuments.net/reader035/viewer/2022062513/5558bdb9d8b42aa52a8b505e/html5/thumbnails/2.jpg)
TOPICS
Definition
SPA Architecture
Server Stack
Client Stack
JavaScript Patterns
Web Optimization
Examples of components
![Page 3: Single Page Applications on JavaScript and ASP.NET MVC4](https://reader035.vdocuments.net/reader035/viewer/2022062513/5558bdb9d8b42aa52a8b505e/html5/thumbnails/3.jpg)
WHAT’S A SPA?
• is a web application that fits on a single web page, providing a fluid UX akin to a desktop application.
• Maintain navigation, history, page linking.
• Whole applications fits on a single web page.
• Persisting important state on the client
• Fully (or mostly) loaded in the initial page load
• Progressively downloads data as required
![Page 4: Single Page Applications on JavaScript and ASP.NET MVC4](https://reader035.vdocuments.net/reader035/viewer/2022062513/5558bdb9d8b42aa52a8b505e/html5/thumbnails/4.jpg)
SPA HIGH LEVEL ARCHITECTURE
Server Client
Database
Data Services
ASP.NET + (JavaScript /
HTML / CSS)
Application(JavaScript)
Views (HTML / CSS)
Data Access(JavaScript)
Navigation
![Page 5: Single Page Applications on JavaScript and ASP.NET MVC4](https://reader035.vdocuments.net/reader035/viewer/2022062513/5558bdb9d8b42aa52a8b505e/html5/thumbnails/5.jpg)
SERVER SIDE DESIGN
Database
Repository Pattern
Unit of Work Pattern
Entity Framework
Web API JSON
EF Code First
ASP.NET Web API
![Page 6: Single Page Applications on JavaScript and ASP.NET MVC4](https://reader035.vdocuments.net/reader035/viewer/2022062513/5558bdb9d8b42aa52a8b505e/html5/thumbnails/6.jpg)
ASP.NET WEB API
• Simplifies web services
•Good for serving JSON
SQL Server Data LayerASP.NET Web
API
Models
JSON
![Page 7: Single Page Applications on JavaScript and ASP.NET MVC4](https://reader035.vdocuments.net/reader035/viewer/2022062513/5558bdb9d8b42aa52a8b505e/html5/thumbnails/7.jpg)
CONTROLLERSpublic IEnumerable<Activity> GetAll() { return Uow.Activities.GetAll().OrderBy(p => p.Name);}
public Activity Get(int id) { var activity = Uow.Activities.GetById(id); if(activity != null) return activity;}
public HttpResponseMessage Put(Activity activity) { Uow.Activities.Update(activity); Uow.Commit(); return new HttpResponseMessage(HttpStatusCode.NoContent);}}
![Page 8: Single Page Applications on JavaScript and ASP.NET MVC4](https://reader035.vdocuments.net/reader035/viewer/2022062513/5558bdb9d8b42aa52a8b505e/html5/thumbnails/8.jpg)
INDEX.HTML
•Using HTML5 Boilerplate• (http://html5boilerplate.com/)• Modernizr.js – checks supported features in client browser.
•@using System.Web.Optimization
• Configuring App_Start• BundleConfig
![Page 9: Single Page Applications on JavaScript and ASP.NET MVC4](https://reader035.vdocuments.net/reader035/viewer/2022062513/5558bdb9d8b42aa52a8b505e/html5/thumbnails/9.jpg)
BUNDLING AND MINIFICATION
• To reduce size of resources which we transfer to client in initial page load, we are using bundling and minification.
• Bundling reduce server calls for resources.
• Minification reduce the size of file.
![Page 10: Single Page Applications on JavaScript and ASP.NET MVC4](https://reader035.vdocuments.net/reader035/viewer/2022062513/5558bdb9d8b42aa52a8b505e/html5/thumbnails/10.jpg)
BUNDLING
• Instead of this:
<script type="text/javascript" src="jquery.easing.js"></script>
<script type="text/javascript" src="jquery-ui.js"></script>
<script type="text/javascript" src="inputlabel.js"></script>
<script type="text/javascript" src="jquery.treeview.js"></script>
<script type="text/javascript “src="quickpager.jquery.js"></script>
<script type="text/javascript" src="jquery.modalboxmin.js"></script>
<script type="text/javascript" src="jquery.activity-indi.js"></script>
<script type="text/javascript" src="/lib/js/tabs.js"></script>
<script type="text/javascript" src="/lib/js/socializ.js"></script>
<script type="text/javascript" src="/lib/js/muScript.js"></script>
<!-- ... -->
![Page 11: Single Page Applications on JavaScript and ASP.NET MVC4](https://reader035.vdocuments.net/reader035/viewer/2022062513/5558bdb9d8b42aa52a8b505e/html5/thumbnails/11.jpg)
BUNDLING
… doing this for scripts:
public static void RegisterBundles(BundleCollection bundles)
{
bundles.Add(new ScriptBundle("~/bundles/jsextlibs").Include(
"~/Scripts/lib/jquery.activity-indicator-{version}.js",
"~/Scripts/lib/knockout-{version}.js",
"~/Scripts/lib/underscore.js",
"~/Scripts/lib/moment.js",
"~/Scripts/lib/sammy.js",
"~/Scripts/lib/amplify.js"
// ...
));
![Page 12: Single Page Applications on JavaScript and ASP.NET MVC4](https://reader035.vdocuments.net/reader035/viewer/2022062513/5558bdb9d8b42aa52a8b505e/html5/thumbnails/12.jpg)
BUNDLING
… and for other resources:bundles.Add(new ScriptBundle("~/bundles/jsapplibs").
IncludeDirectory("~/Scripts/app/", "*.js",
searchSubdirectories: false));
bundles.Add(new StyleBundle("~/Content/css").
Include(
"~/Content/normalize.css",
"~/Content/main.css", ));
bundles.Add(new Bundle("~/Content/Less",
new LessTransform(), new CssMinify())
.Include("~/Content/styles.less"));
![Page 13: Single Page Applications on JavaScript and ASP.NET MVC4](https://reader035.vdocuments.net/reader035/viewer/2022062513/5558bdb9d8b42aa52a8b505e/html5/thumbnails/13.jpg)
BUNDLING
Add bundles on [email protected]("~/Content/css", "~/Content/less")
@Scripts.Render("~/bundles/modernizr")
@Scripts.Render(
"~/bundles/jquery",
"~/bundles/jsextlibs",
"~/Scripts/lib/require.js",
"~/bundles/jsapplibs",
"~/bundles/jsmocks",
"~/Scripts/main.js"
)
![Page 14: Single Page Applications on JavaScript and ASP.NET MVC4](https://reader035.vdocuments.net/reader035/viewer/2022062513/5558bdb9d8b42aa52a8b505e/html5/thumbnails/14.jpg)
BUNDLING AND MINIFICATION
Using B/M Without B/MChange
File Requests
9 34 256%
KB Sent 3.26 11.92 266%
KB Received
388.51 530 36%
Load Time
510 MS 780 MS 53%
![Page 15: Single Page Applications on JavaScript and ASP.NET MVC4](https://reader035.vdocuments.net/reader035/viewer/2022062513/5558bdb9d8b42aa52a8b505e/html5/thumbnails/15.jpg)
CSS AND LESS
Less – Dynamic Stylesheet language
.accent-top (@sizeMultiplier: 1, @lineHeightMultiplier: 1) {
.accent;
width: @base-accent-top-width * @sizeMultiplier;
height: @base-accent-top-height * @sizeMultiplier;
div {
text-transform: uppercase;
}}
![Page 16: Single Page Applications on JavaScript and ASP.NET MVC4](https://reader035.vdocuments.net/reader035/viewer/2022062513/5558bdb9d8b42aa52a8b505e/html5/thumbnails/16.jpg)
LESS TO CSS
Creating custom BundleTransform using library dotLett.
public class LessTransform : IBundleTransform
{
public void Process(BundleContext c, BundleResponse resp)
{
resp.Content = dotless.Core.Less.Parse(resp.Content);
response.ContentType = "text/css";
}}
![Page 17: Single Page Applications on JavaScript and ASP.NET MVC4](https://reader035.vdocuments.net/reader035/viewer/2022062513/5558bdb9d8b42aa52a8b505e/html5/thumbnails/17.jpg)
RENDER VIEWS
• Render all pages in main section.• All pages are stored in Views folder• General components like header, navigation and footer we are defining above or below of main section.
<section class="main">
@RenderPage("Views/workspace.cshtml")
@RenderPage("Views/statistics.cshtml")
@RenderPage("Views/settings.cshtml")
@* ... *@
</section>
![Page 18: Single Page Applications on JavaScript and ASP.NET MVC4](https://reader035.vdocuments.net/reader035/viewer/2022062513/5558bdb9d8b42aa52a8b505e/html5/thumbnails/18.jpg)
VIEWS
• View is a simple html with data-bind.• Views might contain Knockout templates
<section id="workspace-view" class="view">
<h2 data-bind="text: context.date"></h2>
<ul data-bind="template: { name: 'activity-template',
foreach: activities }" class="activity"></ul>
<button data-bind="click: addActivity" class="add- activity">+</button>
<table data-bind="template: { name: timelogTemplate }">
</table>
</section>
![Page 19: Single Page Applications on JavaScript and ASP.NET MVC4](https://reader035.vdocuments.net/reader035/viewer/2022062513/5558bdb9d8b42aa52a8b505e/html5/thumbnails/19.jpg)
CLIENT SIDE DESIGN
BootstrapperHTML ViewsHTML ViewsHTML Views
HTML / ViewsMVVM Binder Data Primer
Data Context
Data Services
Model MappersModel MappersModel MappersModel Mappers
SortingHTML / ViewsHTML / ViewsHTML / Views
ViewModels
HTML / ViewsHTML / ViewsHTML / ViewsModelsFiltering
![Page 20: Single Page Applications on JavaScript and ASP.NET MVC4](https://reader035.vdocuments.net/reader035/viewer/2022062513/5558bdb9d8b42aa52a8b505e/html5/thumbnails/20.jpg)
JAVASCRIPT LIBRARIES
jQuery Working with DOM,
Knockout.js Data Binding and MVVM
Amplify.js Data Push/Pull, Caching, Client Storage
Breeze.js Querying with filters, ordering and paging
Sammy.js Navigation and History
require.js Dependency Resolution
underscore.js JavaScript helper
toastr.js UI Alerts
qunit Unit Testing
![Page 21: Single Page Applications on JavaScript and ASP.NET MVC4](https://reader035.vdocuments.net/reader035/viewer/2022062513/5558bdb9d8b42aa52a8b505e/html5/thumbnails/21.jpg)
JAVASCRIPT PATTERNS
• AMD (Asynchronous Module Definition)• is a JavaScript API for defining modules and their dependencies in such a way that modules may be asynchronously loaded
• Revealing Module Pattern• we define all of our functions and variables in the private scope and return an anonymous object with pointers to the private functionality we wished to reveal as public.
• MVVM
![Page 22: Single Page Applications on JavaScript and ASP.NET MVC4](https://reader035.vdocuments.net/reader035/viewer/2022062513/5558bdb9d8b42aa52a8b505e/html5/thumbnails/22.jpg)
AMD PATTERN
Application
Data Context
Controller
Data Services Model
Navigation
• Sequence of loading component might cause an issue.
![Page 23: Single Page Applications on JavaScript and ASP.NET MVC4](https://reader035.vdocuments.net/reader035/viewer/2022062513/5558bdb9d8b42aa52a8b505e/html5/thumbnails/23.jpg)
DEFINING A MODULE IN REQUIRE.JS
define('model',
[‘settings', 'model.workspace'],
function (settings, workspace) {
var
model = {
Workspace: workspace
}; // ...
return model;
});
Module ID
Dependencies
Module Factory
![Page 24: Single Page Applications on JavaScript and ASP.NET MVC4](https://reader035.vdocuments.net/reader035/viewer/2022062513/5558bdb9d8b42aa52a8b505e/html5/thumbnails/24.jpg)
STARTING THE SPA
Prime the Data
Models
Data Services
Data Context
Setup the presentation
Navigation Router
HTML Views
View Models
Bootstrapper
![Page 25: Single Page Applications on JavaScript and ASP.NET MVC4](https://reader035.vdocuments.net/reader035/viewer/2022062513/5558bdb9d8b42aa52a8b505e/html5/thumbnails/25.jpg)
BOOTSTRAPPER
Bootstrapper responsible for initial application run.define('bootstrapper',['jquery', 'route-config', 'presenter', 'dataprimer', 'binder'], function ($, routeConfig, presenter, dataprimer, binder) { var run = function () { presenter.toggleActivity(true); $.when(dataprimer.fetch()) .done(binder.bind) .done(routeConfig.register) .always(function () { presenter.toggleActivity(false); }); } return { run : run }});
var run = function () {
presenter.toggleActivity(true);
$.when(dataprimer.fetch())
.done(binder.bind)
.done(routeConfig.register)
.always(function () {
presenter.toggleActivity(false);
}}
![Page 26: Single Page Applications on JavaScript and ASP.NET MVC4](https://reader035.vdocuments.net/reader035/viewer/2022062513/5558bdb9d8b42aa52a8b505e/html5/thumbnails/26.jpg)
DATASERVICE var init = function () { amplify.request.define('activities', 'ajax', { url: '/api/activities', dataType: 'json', type: 'GET' }); },
getActivities = function (callbacks) { return amplify.request({ resourceId: 'activities', data: '', success: callbacks.success, error: callbacks.error });}; init();
return { getActivities: getActivities };
![Page 27: Single Page Applications on JavaScript and ASP.NET MVC4](https://reader035.vdocuments.net/reader035/viewer/2022062513/5558bdb9d8b42aa52a8b505e/html5/thumbnails/27.jpg)
VIEWMODEL activityItemTemplate = 'common.activityitem', timelogTemplate = 'common.timelogtable'; activities = ko.observableArray();
activate = function (routerData, callback) { refresh(callback); } getWorkspace = function (callback) { datacontext.activities.getActivities(id); } return {
activate: activate activityItemTemplate: activityItemTemplate, timelogTemplate: timelogTemplate }});
![Page 28: Single Page Applications on JavaScript and ASP.NET MVC4](https://reader035.vdocuments.net/reader035/viewer/2022062513/5558bdb9d8b42aa52a8b505e/html5/thumbnails/28.jpg)
AS RESULT WE HAVE
• Async services• Client side application & business logic• Long-lived client-side state• 2 way data binding• Tombstoning / dropped connection
![Page 29: Single Page Applications on JavaScript and ASP.NET MVC4](https://reader035.vdocuments.net/reader035/viewer/2022062513/5558bdb9d8b42aa52a8b505e/html5/thumbnails/29.jpg)
PROS AND CONS
• Faster UI• More Interactive• Can work offline• UI is just another
Client• UI can have BI• Perfect for
HTML5 and Mobile apps
• Bad for SEO
• More complex to build
• Need to expose application logic to client
• Require strong JavaScript skills