Apresentação do Marco Silva sobre a utilização de KnockoutJS com ASP .NET MVC 3 na 28a Reunião Presencial da Comunidade NetPonto em Lisboa (http://netponto.org).
3. Marco André Silva
• Consultor Sénior na |create|it|, uma empresa
especializada na área de soluções colaborativas e
integração de sistemas.
• Actualmente é responsável pela área de soluções
da|create|it|, desenvolvendo também aplicações
baseadas em SharePoint, ASP.NET, WCF e outras
tecnologias Microsoft.
• Os seus principais interesses são o desenvolvimento de
arquitecturas de serviços e interfaces ricas
4. Agenda
• ASP.NET MVC 3
• Knockout JS
• Demo – Knockout O Essencial
• Integração Knockout JS com ASP.NET MVC 3
• Demo – Knockout JS com ASP.NET MVC 3
• Experiência de utilização
• O futuro
• Conclusões
5. Contexto
• Projecto com 6 pessoas
• + 1 ano
• Aplicação Web
• Volume elevado de informação a apresentar
• Experiência de utilização similar a aplicação nativa
• Desafios de usabilidade e interacção com a aplicação
• Facilidade de manutenção e evolução da aplicação
Reflecte a nossa experiência e melhores práticas e não uma verdade universal
6. Model
ASP.NET MVC 3 - Introdução
• Browser faz pedido (GET) a URL View Controller
• Rota é determinada
• Controlador é instanciado
• Acção de controlador é invocada
• Controlador processa pedido e retorna modelo para a vista
• Vista (HTML) é elaborada com base no modelo
7. Knockout JS (KO JS) - Introdução
• Biblioteca JavaScript Open source
• Funciona do lado do cliente (browser), e promover interactividade
• Padrão MVVM – Separar lógica de negócio de interface
• Suporte para vários browsers
• Não existem event handlers de JavaScript/Jquery. Existe sim, JavaScript object-oriented e bindings declarativos
• Binding automático em dois sentidos:
– Da interface para o modelo
– Do modelo para a interface
• Calculo automático de dependências
• Suporte para templating
• Diversos tipos de bindings out-of-box com possibilidade de implementar custom bindings
• Desenvolvido e mantido por Steve Sanderson, colaborador da Microsoft, mas o KO é um projecto pessoal e open-source
• Versão actual 2.0. Versão 2.1 a caminho.
8. Model
Knockout JS - MVVM
• Informação importada do Modelo para o View
View
Model
ViewModel
• Quando a informação do ViewModel é actualizada é
exportada de volta para o Modelo
• Quando a informação do ViewModel é actualizada, a
Vista é automaticamente actualizada
• Quando a informação da Vista é alterada, o ViewModel é
automaticamente alterado
9. Knockout JS – Data Binding - Conceito
View Model
Data Binding
View Model
10. Knockout JS – Data Binding - Exemplo
// ViewModel
var cartLineViewModel = {
category: ‘Ships’,
product: ‘The Titanic’,
quantity: 123
};
// View -> Data Binding
The category is <span data-bind=‚text: category‛ />
// Activar KO
ko.applyBindings(cartLineViewModel);
11. Knockout JS – Observables
Actualização automática da UI
// ViewModel
var cartLineViewModel = {
category: ko.observable(‘Ships’),
product: ko.observable(‘The Titanic’),
quantity: ko.observable(123)
};
// View -> Data Binding
The category is <span data-bind=‚text: category‛ />
The category is <input data-bind=‚value: category‛ />
// Activar KO
ko.applyBindings(cartLineViewModel);
12. Knockout JS – Computed Observables
Calculo Automático de Dependências
// ViewModel
var cartLineViewModel = {
…
subtotal: ko.computed(function() {
return this.product().price * this.quantity();
}, this);
};
// View -> Data Binding
The sub total is <span data-bind=‚text: subtotal‛ />
// Activar KO
ko.applyBindings(cartLineViewModel);
19. KO JS - Integração com ASP.NET MVC 3
• Paradigma diferente do desenvolvimento
MVC normal:
– Geração da página no cliente em vez de no
servidor
– View Models desenhados de forma diferente
a pensar no cliente
– Lógica de negócio no cliente
20. KO JS - Integração com ASP.NET MVC 3
• Inclusão referência:
– <script type='text/javascript' src='knockout.js'></script>
• Estruturação de Views e inclusão de JavaScripts
• Models MVC Models Knockout JS
– Geração de modelos JavaScript Leitura
– Resultados de acções em formato JSON Leitura
• Models Knockout JS Models MVC
– Model Binding MVC 3 a partir de JSON Gravação
• Elaboração de Views
– Model Validation & Data Annotations
• Alternativa: Utilização de HTML Helpers
21. KO JS – MVC 3
Estruturação de Views e JavaScript
MVC View
// View model (se necessário)
@model CartViewModel
// KO JS references
<script src="@Url.Content("~/Scripts/Knockoutjs/knockout-latest.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/Knockoutjs/knockout.mapping-latest.js")" type="text/javascript"></script>
…
// View scripts
@section Scripts
{
// Passagem de parâmetros para JavaScript
<script language="javascript" type="text/javascript">
var settings = {
urlSave: '@Url.Action(‚Save", ‚Cart")’,
urlGet: '@Url.Action(‚Get", ‚Cart")’,
id: @Model.Id // Se existir View Model
};
</script>
// KO JS ViewModel
<script src="@Url.Content("~/Scripts/App/Cart.js")‛ type="text/javascript"></script>
}
JavaScript
// KO JS ViewModel
var cartViewModel = {
serverModel: {}
}
22. KO JS – MVC 3
Models MVC Models KO – Geração inline na vista MVC
MVC View
// View model (necessário!!!)
@model CartViewModel
…
// View scripts
@section Scripts
{
// Passagem de parâmetros para JavaScript
<script language="javascript" type="text/javascript">
var settings = {
…
// Geração de modelo JavaScript a partir de classe de modelo MVC
clientModel: @(Html.InterpretJson(Model))
};
</script>
// KO JS ViewModel
<script src="@Url.Content("~/Scripts/App/Cart.js")‛ type="text/javascript"> </script>
}
JavaScript
// Gerar Client Model a partir do model contido na página
cartViewModel.serverModel = ko.mapping.fromJSON(serverModel);
23. KO JS – MVC 3
Models MVC Models KO – Resultado de acção em formato JSON
MVC View
…
MVC Controller
// View scripts public ActionResult Edit(int id)
@section Scripts
{ {
// Passagem de parâmetros para JavaScript
<script language="javascript" type="text/javascript">
// Retornar vista Pode ter modelo
var settings = { (tipicamente simples), ou ser apenas HTML
… markup
};
</script> return View();
// KO JS ViewModel }
<script src="@Url.Content("~/Scripts/App/Cart.js")‛
type="text/javascript"></script>
} public ActionResult Get(int id)
JavaScript {
// Dialogo de aguarde
ToggleLoadingDialog(); // Criar modelo
CartViewModel viewModel = BuildViewModel(
// Obter model do servidor Acção Get do controlador
var serverModel = GetServerModel(); id);
// Gerar Client Model a partir de model do servidor
cartViewModel.serverModel = ko.mapping.fromJSON( // Retornar modelo em JSON
serverModel);
return Json(viewModel);
}
24. KO JS – MVC 3
Models KO Models MVC – Model Binding MVC 3 a partir de JSON
JavaScript Model Class
var cartViewModel = {
public class Cart
save: function() {
// Validar página / modelo {
… // Cart lines
// Dialogo de aguarde public List<CartLine> Lines { get; set; }
ToggleLoadingDialog(); }
// Submeter pedido de gravação ao servidor
$.ajax(ko.mapping.toJSON( public class CartLine
cartViewModel.serverModel); {
public string Category { get; set; }
MVC Controller
[HttpPost] public string Product { get; set; }
public ActionResult Save(Cart cart) public int Quantity { get; set; }
{ public int SubTotal { get; set; }
// Gravar
Repository.Save(cart); }
// Retornar resultado relevante da acção
return Json(result);
}
25. KO JS – MVC 3
Elaboração de Views
MVC View
@model CartViewModel
…
// Percorrer cada linha
<tbody data-bind='foreach: cartViewModel.serverModel.Lines'>
…
// Com o produto da linha
<td class='price' data-bind='with: Product'>
// Produto tem preço
<span data-bind='text: formatCurrency(price)'> </span>
</td>
// Se a linha tiver um produto, mostrar quantidade. Incluir validações
<td class='quantity'>
<input
name="@Html.NameFor(m => m.Product.Quantity)"
data-bind='visible: product, value: quantity, valueUpdate: "afterkeydown"'
@Html.ValidationAttributesFor(m => m.Product.Quantity) />
@Html.ValidationMessageFor(m => m.Product.Quantity)
</td>
// Se a linha tiver um produto, mostrar subtotal
<td class='price'>
<span data-bind='visible: product, text: formatCurrency(subtotal())' > </span>
</td>
// Link para remover linha de produto. Chama função do view model
<td>
<a href='#' data-bind='click: $parent.removeLine'>Remove</a>
</td>
…
</tbody>
…
// Botões de acção. Chamam funções do view Model
<button data-bind='click: addLine'>Add product</button>
<button data-bind='click: save'>Submit order</button>
27. Experiência de utilização
O menos bom
• Bugs de Model Binding de MVC
• Mapping Plugin de KO e modelos grandes (Script running
too long)
• Execução de pedidos AJAX manualmente (GET / POST)
• Performance do serializer JSON usado no MVC
• Articulação com MVC Data Annotation Validations
28. Experiência de Utilização
O bom
• Model Binding de JSON
• Geração de modelos cliente a partir de modelos servidor
• Mapping Plugin de KO
• Data Binding e Facilidade de criação da UI no cliente
• Trabalhar no cliente com objectos em vez de eventos
• Facilidade de construção da aplicação
• Fluidez da aplicação no cliente
• Essencial para desenvolver Single Page Applications!!!!
29. O futuro – MVC 4
Servidor Cliente
Visible UI
HTML/CSS
Web UI
HTML/CSS/JS
Knockout.js
Data Services Application Layer Navigation APIs
JSON/XML JavaScript
WebAPI History.js
Data Access Layer UpShot.js
JavaScript
Local Storage HTML 5
MVC
30. Conclusões
• As duas tecnologias resultam bem em conjunto
• Desenvolvimento mais facilitado
• Aplicações mais fluidas e rápidas
• Grande foco na interacção com o utilizador
• Conceitos aplicam-se também fora de aplicações Web (ex:
Apps para Windows 8)
34. Próximas reuniões presenciais
• 21-04-2012 – Abril
• 26-05-2012 – Maio
• 02-06-2012 – Junho (Coimbra)
• 16-06-2012 – Junho
• 21-07-2012 – Julho
Reserva estes dias na agenda! :)