Dentro de Visual Studio, seleccionamos la opcion de «Create New Project» y seleccionamos la opción de ASP.NET Core Web App (Model-View-Controller) y le damos el nombre de proyecto que queramos

Dentro del proyecto, en la carpeta de wwwroot, guardamos el archivo JS de la librería de HighCharts que encontraremos en el siguiente enlace:

https://code.highcharts.com/highcharts.js

Llamamos en el _Layout, al JS de la libreria que acabamos de descargar

Una vez con esto realizado, ya podremos realizar gráficas. Para hacer la prueba, realizaremos una app para ver la gráfica de los valores alimenticios de un artículo.

Recogeremos estos datos de un XML, creamos una carpeta llamada documents dentro de wwwroot y pegamos el siguiente contenido. Llamamos al archivo «articulos.xml»

<?xml version="1.0" encoding="utf-8"?>
<articulos>
  <articulo idarticulo="1">
    <nombre>Curry</nombre>
    <descripcion>Plato tipico de la India donde blablabla</descripcion>
    <calorias>150</calorias>
    <proteinas>100</proteinas>
    <hidratos>200</hidratos>
    <glucosa>25</glucosa>
    <cantidad>0</cantidad>
  </articulo>
  <articulo idarticulo="2">
    <nombre>Patatas Bravas</nombre>
    <descripcion>Plato tipico de España donde blablabla</descripcion>
    <calorias>150</calorias>
    <proteinas>20</proteinas>
    <hidratos>100</hidratos>
    <glucosa>55</glucosa>
    <cantidad>0</cantidad>
  </articulo>
  <articulo idarticulo="3">
    <nombre>Baguettes</nombre>
    <descripcion>Plato tipico de Francia donde blablabla</descripcion>
    <calorias>20</calorias>
    <proteinas>10</proteinas>
    <hidratos>40</hidratos>
    <glucosa>10</glucosa>
    <cantidad>0</cantidad>
  </articulo>
  <articulo idarticulo="4">
    <nombre>Spaghettis</nombre>
    <descripcion>Plato tipico de Italia donde blablabla</descripcion>
    <calorias>50</calorias>
    <proteinas>60</proteinas>
    <hidratos>80</hidratos>
    <glucosa>100</glucosa>
    <cantidad>0</cantidad>
  </articulo>
  <articulo idarticulo="5">
    <nombre>Salchichas Frankfurt</nombre>
    <descripcion>Plato tipico de Alemania donde blablabla</descripcion>
    <calorias>70</calorias>
    <proteinas>10</proteinas>
    <hidratos>150</hidratos>
    <glucosa>85</glucosa>
    <cantidad>0</cantidad>
  </articulo>
  <articulo idarticulo="6">
    <nombre>Cocido Madrileño</nombre>
    <descripcion>Plato tipico de Madrid donde blablabla</descripcion>
    <calorias>100</calorias>
    <proteinas>50</proteinas>
    <hidratos>200</hidratos>
    <glucosa>75</glucosa>
    <cantidad>0</cantidad>
  </articulo>
  <articulo idarticulo="7">
    <nombre>Asado macerado</nombre>
    <descripcion>Tipico plato de Argentina donde blablabla</descripcion>
    <calorias>70</calorias>
    <proteinas>30</proteinas>
    <hidratos>100</hidratos>
    <glucosa>20</glucosa>
  </articulo>
</articulos>

Hacemos click derecho en el proyecto (Subrayado en amarillo en la imagen) y le damos a la opción de «Manage NuGet Packages». Instalaremos la versión 6.0.x del NuGet que se muestra en la imagen

Esto permitirá que podamos leer ficheros XML. Una vez terminado, crearemos una carpeta Helpers dentro del proyecto y una clase llamada «HelperPathProvider», para conseguir la ruta de acceso al XML.

Simplemente, tendremos un método que nos devolverá la ruta donde se encuentra situado el XML

public enum Folders { images = 0, documents = 1 }

    public class HelperPathProvider
    {
        private IWebHostEnvironment environment;

        public HelperPathProvider(IWebHostEnvironment environment)
        {
            this.environment = environment;
        }

        public string MapPath(string fileName, Folders folder)
        {
            string carpeta = "";
            if (folder == Folders.images)
            {
                carpeta = "images";
            }
            else if (folder == Folders.documents)
            {
                carpeta = "documents";
            }
            string path = Path.Combine(this.environment.WebRootPath
                , carpeta, fileName);
            return path;
        }
    }

Cuando hayamos finalizado de realizar el Helper, crearemos dentro de la carpeta models, una clase llamada ArticuloXML y pegaremos el siguiente contenido

public class ArticuloXML
{
    public int IdArticulo { get; set; }
    public string Nombre { get; set; }
    public string Descripcion { get; set; }
    public int Calorias { get; set; }
    public int Proteinas { get; set; }
    public int Hidratos { get; set; }
    public int Glucosa { get; set; }

}

Una vez creado el modelo, creamos a la altura del proyecto una carpeta llamada «Repositories» y una clase llamada «RepositoryArticulos», donde tendremos todos los métodos para actualizar / mostrar la información del XML

public class RepositoryArticulos
{
    private HelperPathProvider helper;
    private XDocument documentArticulos;
    private string pathArticulos;

    public RepositoryArticulos(HelperPathProvider helper)
    {
        this.helper = helper;
        this.pathArticulos = this.helper.MapPath("articulos.xml", Folders.documents);
        documentArticulos = XDocument.Load(this.pathArticulos);
    }

    public ArticuloXML GetArticuloXPosicion(int posicion, ref int numeroarticulos)
    {
        List<ArticuloXML> listaarticulos = this.GetAllArticulos();
        numeroarticulos = listaarticulos.Count;
        ArticuloXML articulo = listaarticulos.Skip(posicion).Take(1).FirstOrDefault();
        return articulo;
    }


    public List<ArticuloXML> GetAllArticulos()
    {

        var consulta = from datos in documentArticulos.Descendants("articulo")
                       select datos;

        List<ArticuloXML> listaarticulos = new List<ArticuloXML>();
        foreach (XElement tag in consulta)
        {
            ArticuloXML articulo = new ArticuloXML();
            articulo.IdArticulo = int.Parse(tag.Attribute("idarticulo").Value);
            articulo.Nombre = tag.Element("nombre").Value;
            articulo.Descripcion = tag.Element("descripcion").Value;
            articulo.Calorias = int.Parse(tag.Element("calorias").Value);
            articulo.Proteinas = int.Parse(tag.Element("proteinas").Value);
            articulo.Hidratos = int.Parse(tag.Element("hidratos").Value);
            articulo.Glucosa = int.Parse(tag.Element("glucosa").Value);

            listaarticulos.Add(articulo);
        }

        return listaarticulos;
    }

    public ArticuloXML GetArticuloById(int idarticulo)
    {
        return this.GetAllArticulos().Where(x => x.IdArticulo == idarticulo).AsEnumerable().FirstOrDefault();
    }

    public async Task InsertArticulos(string nombre, string descripcion, int calorias, int proteinas, int hidratos, int glucosa)
    {
        XElement rootArticulo = new XElement("articulo");

        rootArticulo.Add(new XAttribute("idarticulo", this.GetAllArticulos().Max(x => x.IdArticulo) + 1));
        rootArticulo.Add(new XElement("nombre", nombre));
        rootArticulo.Add(new XElement("descripcion", descripcion));
        rootArticulo.Add(new XElement("calorias", calorias));
        rootArticulo.Add(new XElement("proteinas", proteinas));
        rootArticulo.Add(new XElement("hidratos", hidratos));
        rootArticulo.Add(new XElement("glucosa", glucosa));

        this.documentArticulos.Element("articulos").Add(rootArticulo);
        this.documentArticulos.Save(this.pathArticulos);
    }

    public async Task DeleteArticulo(int idarticulo)
    {
        var consulta = from datos in
                       this.documentArticulos.Descendants("articulo")
                       where int.Parse(datos.Attribute("idarticulo").Value) == idarticulo
                       select datos;

        XElement articuloXML = consulta.FirstOrDefault();

        articuloXML.Remove();
        this.documentArticulos.Save(this.pathArticulos);
    }

    public async Task UpdateArticulo(ArticuloXML articulo)
    {
        var consulta = from datos in
                       this.documentArticulos.Descendants("articulo")
                       where int.Parse(datos.Attribute("idarticulo").Value) == articulo.IdArticulo
                       select datos;

         XElement articuloXML = consulta.FirstOrDefault();

        articuloXML.Element("nombre").Value = articulo.Nombre;
        articuloXML.Element("descripcion").Value = articulo.Descripcion;
        articuloXML.Element("calorias").Value = articulo.Calorias.ToString();
        articuloXML.Element("proteinas").Value = articulo.Proteinas.ToString();
        articuloXML.Element("hidratos").Value = articulo.Hidratos.ToString();
        articuloXML.Element("glucosa").Value = articulo.Glucosa.ToString();

        this.documentArticulos.Save(this.pathArticulos);
    }
}

Una vez terminado, dentro de Controllers, creamos un nuevo controlador llamado ArticuloController, importamos el repositorio que hemos creado, dentro del controller, y creamos los métodos.

public class ArticuloController : Controller
{
    private RepositoryArticulos repo;

    public ArticuloController(RepositoryArticulos repo)
    {
        this.repo = repo;
    }
    public IActionResult InfoArticulos()
    {
        return View();
    }

    public IActionResult EditArticulo(int idarticulo)
    {
        return View(this.repo.GetArticuloById(idarticulo));
    }

    public async Task<IActionResult> DeleteArticulo(int idarticulo)
    {
        await this.repo.DeleteArticulo(idarticulo);
        return RedirectToAction("ListaArticulos", "Articulo");
    }

    [HttpPost]
    public async Task<IActionResult> EditArticulo(ArticuloXML articulo)
    {
        await this.repo.UpdateArticulo(articulo);
        return RedirectToAction("ListaArticulos", "Articulo");
    }

    public IActionResult InsertArticulo()
    {
        return View();
    }

    [HttpPost]
    public async Task<IActionResult> InsertArticulo(string nombre, string descripcion, int calorias, int proteinas, int hidratos, int glucosa)
    {
        await this.repo.InsertArticulos(nombre,descripcion,calorias,proteinas,hidratos,glucosa);
        return RedirectToAction("ListaArticulos", "Articulo");
    }

    public IActionResult ListaArticulos()
    {
        return View(this.repo.GetAllArticulos());
    }

    public IActionResult _PaginacionAjax(int? posicion)
    {
        int numarticulos = 0;
        ArticuloXML articulo = this.repo.GetArticuloXPosicion
            (posicion.Value, ref numarticulos);

        ViewData["DATOS"] = "Articulo " + (posicion + 1) + " de " + numarticulos;

        int siguiente = posicion.Value + 1;
        if (siguiente >= numarticulos)
        {
            siguiente = 0;
        }
        int anterior = posicion.Value - 1;
        if (anterior < 0)
        {
            anterior = numarticulos - 1;
        }
        ViewData["SIGUIENTE"] = siguiente;
        ViewData["ANTERIOR"] = anterior;

        return PartialView("_PaginacionAjax", articulo);
    }
}

Generamos todas las vistas del controller con Scaffolding, y el modelo del ArticuloXML, a excepción de _PaginacionAjax y InfoArticulos

Además de ello, deberemos realizar un pequeños cambios en nuestras vistas generadas por Scaffolding
– En ListaArticulos, añadir el idarticulo de los enlaces de borrar y editar, y eliminar el enlace de detalles

– En EditArticulo, cambiar el div donde se encuentra el idarticulo y cambiarlo por input type hidden con el name «idarticulo» y el value del IdArticulo del modelo

Una vez realizado estos cambios, creamos la vista de InfoArticulos, que será la base donde mostraremos la gráfica

<h1 align="center" style="background-color: black; width: 80%; margin-left: 10%; padding: 20px;border: 1px solid black;color:white">INFORME DE ALIMENTOS</h1>

<div id="contenidoajax" style="margin:0px 10% 50px 10%; width: 80%; text-align:center; height: 750px;background: linear-gradient(0deg, rgba(47,42,36,1) 0%, rgba(224,201,139,1) 100%);color:white; border: 1px solid black">
    
</div>

@section Scripts{
    <script>
        $(document).ready(function () {
            llamaAjaxAfter(0);
        });

        function llamaAjaxAfter(posicion){
            $("#contenidoajax").load("/Articulo/_PaginacionAjax?posicion=" + posicion);
        }
    </script>
}

Una vez creada, debemos crear la vista parcial de _PaginacionAjax, en la carpeta de Articulo, dentro de views, donde tendremos el script para crear la gráfica

@model ArticuloXML

@{
    int anterior = 0;
    int siguiente = 0;

    if (ViewData["ANTERIOR"] != null)
    {
        anterior = (int)ViewData["ANTERIOR"];
    }

    if (ViewData["SIGUIENTE"] != null)
    {
        siguiente = (int)ViewData["SIGUIENTE"];
    }
}

<div id="graficaajax" style="height:500px">
</div>
<h1 style="margin: 20px 0px 20px 0px">@Model.Nombre</h1>
<p>@Model.Descripcion</p>
<div id="botonera" style="display:flex">
    <button onclick="llamaAjaxAfter(@anterior)" style="height: 45px;width: 40%; margin: 40px 5% 10px 5%; padding: 10px 0px 10px 0px; background-color: black; border: 1px solid white;color: white">Anterior</button>
    <button onclick="llamaAjaxAfter(@siguiente)" style="height: 45px;width: 40%; margin: 40px 5% 10px 5%; padding: 10px 0px 10px 0px; background-color: black; border: 1px solid white;color: white">Siguiente</button>
</div>

<script>
    var datos = @Json.Serialize(Model);
    var labeldata = []

    console.log(datos);

    if (datos.glucosa != 0){
        labeldata.push(["Glucosa", datos.glucosa]);
    }

    if (datos.hidratos != 0) {
        labeldata.push(["Hidratos", datos.hidratos]);
    }

    if (datos.proteinas != 0){
        labeldata.push(["Proteinas", datos.proteinas]);
    }

    if (datos.calorias != 0) {
        labeldata.push(["Calorias", datos.calorias]);
    }

    Highcharts.chart("graficaajax", {
        chart: {
            backgroundColor: "transparent",
            plotBorderWidth: 0,
            plotShadow: false,
        },
        title: {
            useHTML: true,
            text: "",
            y: 60,
            style: {
                fontWeight: 'bold',
                color: 'white',
                fontSize: '17px',
                'background-color': '#000000',
                'text-align': "center"
            }
        },
        plotOptions: {
            pie: {
                dataLabels: {
                    enabled: true,
                    distance: -50,
                    style: {
                        fontWeight: 'bold',
                        color: 'white',
                        fontSize: '16px'
                    }
                },
                startAngle: -90,
                endAngle: 90,
                center: ['50%', '80%'],
                size: '110%'
            }
        },
        series: [{
            type: 'pie',
            name: 'Total',
            innerSize: '40%',
            data: labeldata
        }],
    });

    $("text.highcharts-credits").hide();
</script>

Una vez finiquitado, añadiremos un enlace dentro del Layout a la vista de InfoArticulos para poder comprobar su funcionamiento, y a ListaArticulos, para editar la información que incluiremos en las gráficas

Por último, debemos incluir las dependencias del Helper, y del repositorio dentro de nuestro archivo Program.cs

Y listo! Ya deberíamos poder probar la aplicación visualizando nuestras gráficas.

Autor: Fernando García Garrido
Curso: Desarrollo Web Full Stack + MultiCloud con Azure y AWS
Centro: Tajamar
Año académico: 2022 – 2023
GitHub:
https://github.com/fgarcia211/NetCoreHighCharts

Leave a Comment

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.