[#ASP.NET/MVC] Arrays dinámicos con datos del Modelo

Desde mi poca experiencia y conocimiento en programación web os dejo un tip cortito para obtener un array con datos dinámicos (en tiempo de ejecución) en una aplicación web usando ASP.NET MVC 4, ya que es con lo que llevo pegándome media mañana. 

En este caso, la idea es implementar un ranking en el Home de una aplicación web y queremos que obtenga los datos de forma dinámica de nuestra base de datos. Para ello, preparamos dos listas en el controlador: una con el nombre del equipo y otra con los puntos que tiene, y se la pasamos a la vista utilizando el ViewBag:

 C# |  copy code |? 
  1. public class HomeController : Controller
  2.     {
  3.         UsuariosRepository usuariosRepository = new UsuariosRepository(new AppContext());
  4.         public ActionResult Index()
  5.         {
  6.             IEnumerable<Usuario> usuarios = usuariosRepository.GetAll();
  7.             usuarios = usuarios.OrderByDescending(usuario => usuario.Puntos());
  8.             List<string> nombres = new List<string>();
  9.             List<int> puntos = new List<int>();
  10.             foreach (var user in usuarios)
  11.             {
  12.                 nombres.Add(user.Nombre);
  13.                 puntos.Add(user.Puntos());
  14.             }
  15.             ViewBag.Nombres = nombres;
  16.             ViewBag.Puntos = puntos;
  17.             return View(usuarios);
  18.         }
  19.     }

Para utilizarlo en nuestra vista debería bastarnos con referenciar al elemento del ViewBag, transformarlo en un array y presentarlo…pero no es así.

La transformación a array viene por necesidad del script utilizado para mostrar el ranking, en este caso un gráfico de barras horizontales usando Highcharts. que nos pide un array de strings para las categorías (en este caso, los nombres de los equipos) y otro array de int para los valores de cada serie (en este caso, los puntos de cada equipo en una fase). Por lo tanto, declaramos nuestros arrays (uno para los nombres y otro para los puntos), recorremos todos nuestros elementos para obtener el nombre y los puntos de cada equipo, y almacenamos estos valores de forma dinámica en nuestros arrays:

 Javascript |  copy code |? 
  1.     var arrayNombres = new Array();
  2.     var arrayPuntos = new Array();
  3.     @{  
  4.         string messageNombres = "";
  5.         string messagePuntos = "";
  6.      }
  7.     @for (int i = 0; i < ViewBag.Nombres.Count; i++)
  8.     {
  9.         messageNombres += "arrayNombres[" + i + "]=\"" + ViewBag.Nombres[i] + "\";";
  10.         messagePuntos += "arrayPuntos[" + i + "]=\"" + ViewBag.Puntos[i] + "\";";
  11.     }
  12.     @MvcHtmlString.Create(messageNombres);
  13.     @MvcHtmlString.Create(messagePuntos);

Para las categorías con esto es suficiente, ya que son cadenas de texto directamente, pero para presentar los valores de los puntos de cada equipo necesitamos hacer un ajuste más y parsear estas cadenas a números enteros. En mi caso he utilizado una función muy sencillita:

 Javascript |  copy code |? 
  1. $(function parsearPuntos() {
  2.         for (var i in arrayPuntos)
  3.             arrayPuntos[i] = parseInt(arrayPuntos[i]);
  4. })

Con esto podemos obtener de forma sencilla un ranking  para nuestras aplicaciones web, os dejo el script completo del gráfico por si queréis usarlo:

 HTML |  copy code |? 
  1. <head>
  2.     <title>Ranking fase 2 (gráfico)</title>
  3.     <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
  4.     <script type="text/javascript">
  5.         $(function () {
  6.             var chart;
  7.             var arrayNombres = new Array();
  8.             var arrayPuntos = new Array();
  9.     @{  
  10.         string messageNombres = "";
  11.         string messagePuntos = "";
  12.      }
  13.     @for (int i = 0; i < ViewBag.Nombres.Count; i++)
  14.     {
  15.         messageNombres += "arrayNombres[" + i + "]=\"" + ViewBag.Nombres[i] + "\";";
  16.         messagePuntos += "arrayPuntos[" + i + "]=\"" + ViewBag.Puntos[i] + "\";";
  17.     }
  18.     @MvcHtmlString.Create(messageNombres);
  19.     @MvcHtmlString.Create(messagePuntos);
  20.     $(function parsearPuntos() {
  21.         for (var i in arrayPuntos)
  22.             arrayPuntos[i] = parseInt(arrayPuntos[i]);
  23.     })
  24.     $(document).ready(function () {
  25.         chart = new Highcharts.Chart({
  26.             chart: {
  27.                 renderTo: 'container',
  28.                 type: 'bar'
  29.             },
  30.             title: {
  31.                 text: ''
  32.             },
  33.             xAxis: {
  34.                 categories: arrayNombres,
  35.                 title: {
  36.                     text: null
  37.                 }
  38.             },
  39.             yAxis: {
  40.                 min: 0,
  41.                 title: {
  42.                     text: 'Puntos',
  43.                     align: 'high'
  44.                 },
  45.                 labels: {
  46.                     overflow: 'justify'
  47.                 }
  48.             },
  49.             tooltip: {
  50.                 formatter: function () {
  51.                     return '' +
  52.                         this.series.name + ': ' + this.y + ' puntos';
  53.                 }
  54.             },
  55.             plotOptions: {
  56.                 bar: {
  57.                     dataLabels: {
  58.                         enabled: true
  59.                     }
  60.                 }
  61.             },
  62.             legend: {
  63.                 layout: 'vertical',
  64.                 align: 'right',
  65.                 verticalAlign: 'top',
  66.                 x: -100,
  67.                 y: 100,
  68.                 floating: true,
  69.                 borderWidth: 1,
  70.                 backgroundColor: '#FFFFFF',
  71.                 shadow: true
  72.             },
  73.             credits: {
  74.                 enabled: false
  75.             },
  76.             series: [
  77.                 {
  78.                     name: 'Fase 1',
  79.                     data: arrayPuntos
  80.                 },
  81.             {
  82.                 name: 'Fase 2',
  83.                 data: arrayPuntos
  84.             }
  85.             ]
  86.         });
  87.     });
  88. });
  89.     </script>
  90. </head>
  91. <body>
  92.     <script src="../../scripts/highcharts.js"></script>
  93.     <script src="../../scripts/exporting.js"></script>
  94.     <div id="container" style="min-width: 400px; height: 400px; margin: 0 auto"></div>
  95. </body>

Y el resultado…

Como siempre, espero que haya sido útil :)

 PD: Agradecimiento grande a mi compañero @tracker086 por currarse la lógica de la base de datos, comunicación con esta, etc.

Gk out

About Gorka Madariaga

Media Apps Dev en Plain Concepts, ex-Microsoft en el equipo de DPE/DX y parte del equipo de @TrackSeriesTv. Basketball coach-player-lover. Hay quien dice que soy de acero.