none
Como se puede actualizar una vista parcial automaticamente cada determinado tiempo ?. RRS feed

  • Pregunta

  • Saludos!

    Amigos, he logrado a traves de razor obtener la información del campo que necesito soy novato, trabajo con MVC5 / SQL / VS /C#, mi solicitud de ayuda es para lograr que se actualice la vista parcial que incluye los turnos a mostrar esto mediante algún control timer cada 3 minutos por decir un tiempo.

    Les muestro mi codigo hasta el momento:

    Como podrán apreciar es relativamente pequeña la sección que intento hacer, solo mostrar los turnos de los modulos A y B, ahora bien utilice vista parcial para depositar los numeros de turnos, mi vista padre Inicio llama a vista parcial MuestraTurnos la cual es la que quiero se llame cada cierto tiempo consultado a la Base de datos si algún turno ha sido llamado para mostrarlo en pantalla actualizandoce solo la vista parcial.

    He leido algunos ejemplos en el foro, intente un codigo que podrán apreciar en el controlador PartialViewResult para desde el controlador cargar la vista parcial, pero como hacer para que se ejecute a traves de un timer ?.

    Agradezco de su apoyo en orientarme como puedo hacer la actualización de la vista parcial automaticamente cada cierto tiempo.

    miércoles, 24 de enero de 2018 5:40

Respuestas

  • Es difícil determinar así a ojo qué es lo que falta en el equipo cliente. Usa la F12 en el navegador de ese equipo, a ver si el javascript está arrojando algún error que nos ilustre el problema. Si no hay errores, usa también la F12 para capturar el tráfico de red, a ver si está enviando las peticiones ajax al servidor, y a ver si el servidor responde correctamente. Si fuese necesario, también puedes depurar el javascript localmente con las propias F12, aunque en ese equipo no tengas Visual Studio con el debugger.
    • Marcado como respuesta Marco Bueno viernes, 2 de marzo de 2018 2:42
    viernes, 26 de enero de 2018 21:36

Todas las respuestas

  • Lo que quieres hacer no se puede conseguir con C# desde el lado servidor. Es necesario programarlo con javascript dentro de la vista. El motivo es que no existe ninguna forma de que el servidor pueda "inyectar" la vista cambiada dentro del navegador; es necesario que sea el navegador el que tome la iniciativa y le pida al servidor los nuevos datos.

    Esto puedes conseguirlo con un timer de javascript, y cada vez que se dispare el timer usas la librería jQuery para hacer un ".load" poniendo en la url la dirección del método de acción que devuelve la vista parcial, y usando como destino del "load" el contenedor (tal como un <div> dentro del cual quieres mostrar la vista actualizada.

    miércoles, 24 de enero de 2018 7:56
  • Saludos amigo Alberto.

    Muchas gracias por tu respuesta, entiendo el punto, gracias por la orientación al respecto, de hecho te comento que el codigo agregado al controlador que tengo:

            public PartialViewResult VerTurnos()
            {
                TurnosContext db = new TurnosContext();
                List<GeneraTurnos> Lista = db.GeneraTurnos.Where(a => a.cestado_turno == "Llamado").ToList();

                return PartialView("MuestraTurnos",Lista);
            }

    ... surge de una pregunta en el foro de vistas parciales donde precisamente se lleva a cabo la actualización y presisamente das tu bendición al codigo del usuario como bueno, donde señalas verifique otros factores, y bien retomando la idea este segmento de codigo, no se donde implementarlo:

    function ListarLoad() {
         $('#contenedorNoticia').load('/Inicio/ListarNoticias');
    }

    O el codigo incluido en PartialViewResult es suficiente y ya solo debo enfocarme en el timer para llamar la accion del controlador ?

    Me dare a la tarea de indagar lo del timer, para aplicarlo.

    Muchas gracias, por la orientación, espero no ser tan mas evidente del nivel inicial que tengo.... por lo que definitivamente me pondré las pilas al respecto.

    miércoles, 24 de enero de 2018 14:59
  • Saludos amigo Alberto.

    Muchas gracias por tu respuesta, entiendo el punto, gracias por la orientación al respecto, de hecho te comento que el codigo agregado al controlador que tengo:

            public PartialViewResult VerTurnos()
            {
                TurnosContext db = new TurnosContext();
                List<GeneraTurnos> Lista = db.GeneraTurnos.Where(a => a.cestado_turno == "Llamado").ToList();

                return PartialView("MuestraTurnos",Lista);
            }

    ... surge de una pregunta en el foro de vistas parciales donde precisamente se lleva a cabo la actualización y presisamente das tu bendición al codigo del usuario como bueno, donde señalas verifique otros factores, y bien retomando la idea este segmento de codigo, no se donde implementarlo:

    function ListarLoad() {
         $('#contenedorNoticia').load('/Inicio/ListarNoticias');
    }

    O el codigo incluido en PartialViewResult es suficiente y ya solo debo enfocarme en el timer para llamar la accion del controlador ?

    Me dare a la tarea de indagar lo del timer, para aplicarlo.

    Muchas gracias, por la orientación, espero no ser tan mas evidente del nivel inicial que tengo.... por lo que definitivamente me pondré las pilas al respecto.

    Intenta de esta forma

    setInterval(function () {ListarLoad() }, 5000);
    
    Esto se ejecutaria cada 5 segundos


    Att. Franklin Andino

    miércoles, 24 de enero de 2018 15:12
  • no se donde implementarlo

    Eso tienes que escribirlo dentro de la vista (la vista principal, no la parcial). Dentro de un bloque <script>, como es lógico. Vale cualquiera de las modalidades del <script>, puede ser una llamada a un .js o puede estar directamente en la página, y si usas la plantilla MVC estándar puedes usar la región de Scripts que ya viene prevista "de fábrica". Eso sí, una precaución: tiene que estar DESPUÉS de la carga del jQuery, si lo pones antes no funciona y da un error diciendo que "$" no está definido.

    Para lo del "timer" se usa la función setInterval:

    setInterval ( "ListarLoad()", 5000 );

    Esto tienes que llamrlo en donde quieras disparar el inicio de los "refrescos" de la vista parcial, por ejemplo, en el click de un botón. Si quieres que inicie desde el principio, ponlo la inicialización de jQuery: $(function(){setInterval ( "ListarLoad()", 5000 );}); Esto como es obvio va tambi'en en un bloque de script igual que dijimos antes (puede ser el mismo bloque que contiene la funcion ListarLoad).

    miércoles, 24 de enero de 2018 15:14
  • Saludos amigos,

    Lamentablemente no me ha sido posible llevar a cabo el actualizar la vista parcial desde la vista padre, incluso incruste el codigo en el _Layout, pero no tuve exito.

    Les muestro el codigo actualizado de la vista padre quien llamara a la vista parcial que deseo actualizar:

    @model IEnumerable<GestorTurnosV2.Models.GeneraTurnos>
    @{
        Layout = "~/Views/Shared/_Layout.cshtml";
    }

    <script>
        function ActualizaTurnos() {
            setInterval('ListarLoad()', 5000);
        }

        function ListarLoad() {
        var laURLDeLaVista = '@Url.Action("VerTurnos", "LlamarTurnos")';
        $.ajax({
            cache: false,
            async: true,
            type: "GET",
            url: laURLDeLaVista,
            data: {},
            success: function (response) {
                $('#ContenedorTurno').html('');
                $('#ContenedorTurno').html(response);
            }
        });
    }
    </script>

    <button type="button" class="btn btn-primary" onclick="ActualizaTurnos();" data-target="#ContenedorTurno"></button>
    @Html.Partial("MuestraTurnos");

    Se ejecuta la primer ves todo, pero no activa el intervalo de tiempo para que se actualice la información de la vista parcial que contiene los turnos. Cabe resaltar que retome esta idea despues de intentarlo de la forma simple que tenia inicialmente hasta llegar a utilizar este codigo de una respuesta en foro stack overflow, así que mi ultimo intento fue actualizar el DIV que esta en la vista parcial desde la vista parcial padre.

    Que estoy haciendo mal?, Muchas gracias por la ayuda.

    miércoles, 24 de enero de 2018 22:27
  • Así a ojo tiene buen aspecto. Utiliza el debugger y mira por dónde se mete la ejecución: Si se ejecuta ActualizaTurnos, si se ejecuta ListarLoad, si da algún error o en caso contrario si trae el contenido correcto a la variable response, etc.

    Por cierto cerciórate de que el script lo tienes metido detrás de la carga de jQuery. Para ello, examina el _Layout.cshtml y cerciórate de que las librerías las carga antes del RenderBody. Si están detrás, entonces tendrás que mover los scripts a la región de Scripts.

    jueves, 25 de enero de 2018 7:32
  • Saludos !

    Aún me sigue sin funcionar bajo el esquema de que me actualice la vista parcial desde la vista padre, pero en intentos incruste todo el codigo a la vista padre y el script con el intervalo de tiempo lo coloque en el _layout:

    Codigo de _layout:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        ....
        ...
        .

        <link type="text/css" rel="stylesheet" href="~/Content/bootstrap/css/bootstrap.css" />
        <link href="~/Content/stylesheets/stylesheet.css" rel="stylesheet">
        <script src="~/Content/jQuery/jquery-3.1.1.js"></script>

        <script type="text/javascript">
            $(document).ready(function () {
                setInterval(
                    function () {
                        $('#ContenedorTurno').load('LlamarTurnos/Inicio');
                    }, 2000
                );
            });
        </script>
    </head>
    <body>
        <div class="container-fluid">
            <div class="row container-content">
                <video id="videoPlayer" autoplay loop>
                    <source id="mp4Source" src="~/Content/video/VideoPromocional.mp4"  type="video/mp4">
                </video>
                <img class="uaslp" src="~/Content/images/emblema.png" />
                <img class="aniversario" src="~/Content/images/aniv.jpg" />
                <img class="fish" src="~/Content/images/Logo.png"/>
                <div class="content">
                    @RenderBody()
                </div>
            </div>
        </div>
    </body>
    </html>

    Codigo de Vista:

    @model IEnumerable<GestorTurnosV2.Models.GeneraTurnos>

    @{
        Layout = "~/Views/Shared/_Layout.cshtml";
    }
    <div class="title-content">
        <h1>ENCABEZADO DE TURNOS</h1>
        <h1>ENERO 2018</h1>
    </div>

    @{
        var TurnoA = 0;
        var TurnoB = 0; }
    @foreach (var item in Model)
    {
        if (item.id_modulo == 1)    {     TurnoA = item.id_turno;    }
        if (item.id_modulo == 2)    {        TurnoB = item.id_turno;    }
        if ((TurnoB != 0) || (TurnoA != 0)) {<audio src="~/Content/sound/alerta.wav" autoplay="autoplay">/audio>}
    }
    <div class="title-content" id="ContenedorTurno">
        <h2><span style="float:right"> MODULO -B- </span></h2><h3>MODULO -A-</h3>
        <h4><span style="float:right">TURNO: @TurnoB</span></h4><h5>TURNO: @TurnoA</h5>
    </div>

    Con el codigo arriba descrito, el temporizador fue funcional llamado a la Vista Inicio cada 2 segundos y se actualiza con la información de la base de datos, pero existe un problema, que se recarga con lo elementos que incluye la vista inicio así como tambien recarga a Layout que tiene un video de fondo reiniciandolo.

    Si colo el codigo en la vista parcial y lo llamo desde la vista padre dejando el _Layout como esta, no me funciona que se este actualizando la vista parcial.

    Que estare haciendo mal ?, muchas gracias.


    jueves, 25 de enero de 2018 23:34
  • Tal como describes el problema me da la impresión de que tienes mal puesta la llamada en el .load(), y que estás llamando a otro método de acción que no es el que devuelve la vista parcial, sino que está devolviendo una vista más grande que incluye el Layout.

    Pero en realidad la opción buena sería la segunda, es decir, la de poner el código en la vista parcial y llamarlo desde la vista padre dejando el _Layout sin modificar. Esta tiene que funcionar con total seguridad, si no funciona indicaría que algo está mal configurado, tal vez algún script fuera de lugar.

    viernes, 26 de enero de 2018 6:41
  • Saludos !

    Alberto pues despues de varias horas en esto tan simple ya me di mi primer bautizo en MVC con esto tan sencillo que me costo un gran esfuerzo, pero le he logrado, dejare el codigo por aquí:

    Codigo _Layout.cshtml:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1 maximum-scale=1.0">
        <meta name="description" content="" />
        <meta name="author" content="" />
        <title> @ViewBag.Title</title>

        @Styles.Render("~/bundles/css")
        @Scripts.Render("~/bundles/js")
        <script type="text/javascript">
            $(document).ready(function () {
                setInterval(
                    function () {
                        $('#ContenedorTurno').load('LlamarTurnos/_vpTurnosX');
                    }, 10000
                );
            });
        </script>
    </head>
    <body>
        <div class="container-fluid">
            <div class="row container-content">
                <video id="videoPlayer" autoplay loop>
                    <source id="mp4Source" src="~/Content/video/VideoPromocional.mp4" type="video/mp4">
                </video>
                <img class="uaslp" src="~/Content/images/emblema.png" alt="UASLP" />
                <img class="aniversario" src="~/Content/images/33aniversario.jpg" alt="Aniversario" />
                <img class="fish" src="~/Content/images/LogoUAMZH.png" alt="UAMZH" />
                <div class="content">
                    <div class="title-content">
                        <h1>TURNOS 2018</h1>
                        <h1>GESTOR TURNOS</h1>
                        @RenderBody()
                    </div>
                </div>
            </div>
        </div>
    </body>
    </html>

    Codigo de Vista Parcial _vpTurnos.cshtml:

    @model IEnumerable<GestorTurnosV2.Models.GeneraTurnos>

    @{
        var TurnoA = 0;
        var TurnoB = 0;
    }
    @foreach (var item in Model)
    {
        if (item.id_modulo == 1)
        {
            TurnoA = item.id_turno;
        }
        if (item.id_modulo == 2)
        {
            TurnoB = item.id_turno;
        }
        if ((TurnoB != 0) || (TurnoA != 0))
        {
            <audio src="~/Content/sound/alerta.wav" autoplay="autoplay"></audio>
        }
    }
    <div class="title-content" id="ContenedorTurno">
        <h2><span style="float:right"> MODULO -B- </span></h2><h3>MODULO -A-</h3>
        <h4><span style="float:right">TURNO: @TurnoB</span></h4><h5>TURNO: @TurnoA</h5>
    </div>

    Tuve que definir a la vista parcial dentro de la misma carpeta del controlador, aqui RouteConfig.cs

    using System.Web.Mvc;
    using System.Web.Routing;

    namespace GestorTurnosV2
    {
        public class RouteConfig
        {
            public static void RegisterRoutes(RouteCollection routes)
            {
                routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

                routes.MapRoute(
                    name: "Default",
                    url: "{controller}/{action}/{id}",
                    defaults: new { controller = "LlamarTurnos", action = "Inicio", id = UrlParameter.Optional }
                );
            }
        }
    }

    Aquí codigo de controlador LlamarTurnosController.cs:

    using GestorTurnosV2.Models;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web.Mvc;


    namespace GestorTurnosV2.Controllers
    {
        public class LlamarTurnosController : Controller
        {
            // GET: LlamarTurnos
            public ActionResult Inicio()
            {
                TurnosContext db = new TurnosContext();
                List<GeneraTurnos> Lista = db.GeneraTurnos.Where(a => a.cestado_turno == "Llamado").ToList();

                return View(Lista);
            }
            public ActionResult _vpTurnosX()
            {
                TurnosContext db = new TurnosContext();
                List<GeneraTurnos> Lista = db.GeneraTurnos.Where(a => a.cestado_turno == "Llamado").ToList();

                return PartialView(Lista.ToList());
            }

        }
    }

    Muchas gracias Pablo por la orientación, y ahi disculpa la lata, empezare a crear otras aplicaciones sobre esta esta estructura MVC.

    Ya subi el proyecto en producción en nuestro servidor local, lo interesante es que en mi equipo donde desarrollo funciona adecuadamente, y en el equipo que no tiene herramientas de desarrollo como VS es una simple maquina donde abri el navegador, no se actualiza automaticamente (aclaro en mi PC lo estoy ejecutando como dirección local/Turnos) en ambos equipo accesar perfectamente, solo en el equipo como comente que no tiene herramientas de desarrollo no se actualiza...?, tendra que ver el usuario de la BD, las politicas de seguridad, es mas en el servidor Windows 2012 Server R2 / IIS 8.5 accesa pero no actualiza tampoco, solo si lo corro desde mi PC se actualiza correctamente... que componente me hara falta actualizar en el equipo cliente ?

    viernes, 26 de enero de 2018 20:46
  • Es difícil determinar así a ojo qué es lo que falta en el equipo cliente. Usa la F12 en el navegador de ese equipo, a ver si el javascript está arrojando algún error que nos ilustre el problema. Si no hay errores, usa también la F12 para capturar el tráfico de red, a ver si está enviando las peticiones ajax al servidor, y a ver si el servidor responde correctamente. Si fuese necesario, también puedes depurar el javascript localmente con las propias F12, aunque en ese equipo no tengas Visual Studio con el debugger.
    • Marcado como respuesta Marco Bueno viernes, 2 de marzo de 2018 2:42
    viernes, 26 de enero de 2018 21:36
  • talves tiene algo que ver con estas directivas en _layout:

    <environment names="Staging,Production">
            //this is  for Production environment
            <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
            <link rel="stylesheet" href="~/css/site.css" />
            <script src="~/lib/jquery/dist/jquery.js"></script>
            <script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
            <link href="~/css/carousel.css" rel="stylesheet" />
            <link href="~/css/mainLoader.css" rel="stylesheet" />
            <script src="~/js/modernizr-2.6.2.min.js"></script>
            <script src="~/js/bootstrap.min.js"></script>
        </environment>

    jueves, 15 de noviembre de 2018 13:22