martes, 27 de agosto de 2019

Tareas - Task

A continuación se detalla la manera de crear tareas, ademas con expresiones lambda:

En proyecto es un WPF

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    void CreateTask()
    {
        //Creando una tarea desde el delegado Action
        Task T;
        var Code = new Action(ShowMessage);

        T = new Task(Code);

        //Creando tarea desde un delegado anónimo
        Task T2 = new Task(delegate {
            MessageBox.Show("Ejecutando una tarea desde un delegado anónimo");
        });

        //Creando una tarea desde una expresion lambda delegada
        Task T3 = new Task(delegate { ShowMessage(); });

        //Creando una tarea desde una expresion lambda
        Task T3_1 = new Task(()=> { ShowMessage(); });

        //Expresion lambda con un metodo anonimo
        Task T4 = new Task(()=> { MessageBox.Show("Ejecutando la tarea 4"); });

        //Expresion lambda con bloque de codigo
        Task T5 = new Task(()=> {
            DateTime currentDate = DateTime.Today;
            DateTime startDate = currentDate.AddDays(30);
            MessageBox.Show($"Tarea 5. Fecha calculada: {startDate}");
        });

        //Expresion lambda con parametros
        Task T6 = new Task((message)=>MessageBox.Show(message.ToString()), "Expresion lambda con parametros");
    }

    void ShowMessage()
    {
        MessageBox.Show($"Ejecutando el metodo {MethodBase.GetCurrentMethod().ToString()}");
    }
}

miércoles, 21 de agosto de 2019

Claves foraneas en Code First

Las claves foraneas son relaciones entre tablas que guardan relacion mediante un Id

A continuacion se muestra una relacion de clave foranea entre las clases "BlogPost" y "Comentario"

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;

namespace EFCodeFirst.Models
{
    public class BlogPost
    {
        public int Id { get; set; }
        [Required]
        [StringLength(200)]
        [Display(Name = "Título")]
        public string Titulo { get; set; }
        [Required]
        [StringLength(500)]
        public string Contenido { get; set; }
        [Required]
        [StringLength(150)]
        public string Autor { get; set; }
        [Required]
        [Display(Name = "Fecha De Publicación")]
        public DateTime Publicacion { get; set; }
        public List<Comentario> Comentarios { get; set; }
    }
}

Clase Comentario.cs

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Web;

namespace EFCodeFirst.Models
{
    public class Comentario
    {
        public int Id { get; set; }
        public int Contenido { get; set; }
        public int Autor { get; set; }
        public int BlogPostId { get; set; }

        [ForeignKey("BlogPostId")]
        public BlogPost BlogPost { get; set; }
    }
}

De esta manera tanto las clases "BlogPost" como "Comentario" se unifican y pueden relacionar y consultar su data entre si.


Para vincular y relacionar post con comentarios hacemos lo siguiente:

Modificamos la clase "BlogPostRepository.cs" donde se observa que con include se incluye "Comentarios"


using System.Data.Entity;

namespace EFCodeFirst.Services
{
    public class BlogPostRepository
    {
        public List<BlogPost> ObtenerTodos()
        {
            using ( var db = new BlogContext() )
            {
                return db.BlogPosts.Include(x => x.Comentarios).ToList();
            }
        }
    }
}

En la clase "BlogPostController.cs" se muestra que dentro de la variable comentario estamos guardando el primer comentario del primer post

// GET: BlogPost
public ActionResult Index()
{
    var model = _repo.ObtenerTodos();
    var comentario = model[0].Comentarios[0];

    return View(model);
}











Code First con ASP.NET MVC y SQL SERVER

A continuacion se detalla la manera de crear una base de datos de tipo CodeFirst

1. Crear el proyecto de tipo ASP.NET MVC.

2. Una vez creado el proyecto, dentro de la carpeta Models creamos el modelo, en este caso "BlogPost.cs"


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace EFCodeFirst.Models
{
    public class BlogPost
    {
        public int Id { get; set; }
        public string Titulo { get; set; }
        public string Contenido { get; set; }
        public string Autor { get; set; }
        public DateTime Publicacion { get; set; }
    }
}

3. Igualmente en la carpeta Modelo creamos en DBContext que es que va hacer el crud con la base de datos.

Es importante tomar en cuenta que dentro de esta clase de deben crear los objetos DbSet que se encargaran de mapear las clases y convertirlas en tablas de la DB

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Web;

namespace EFCodeFirst.Models
{
    public class BlogContext: DbContext
    {
        public BlogContext() : base(nameOrConnectionString: "Contexto")
        {

        }

        public DbSet<BlogPost> BlogPosts { get; set; }
    }
}

4. Posterior a ello en el Web Config del aplicativo pegamos la cadena de conexion hacia a base de datos.

</configSections>
<connectionStrings>
  <add name="Contexto" connectionString="Data Source=EDPMER-V21-120\MSSQLSERVER01;Initial Catalog=EFCodeFirst;Integrated Security=True; Application Name=EntityFramework;" providerName="System.Data.SqlClient" />
</connectionStrings>


5. Posterior a ello vamos a /Herramientas/Administrador de paquetes Nuget/Consola de administracioon de paquetes.

6. Una vez abierta verificamos que el proyecto predeterminado sea en el cual queremos hacer el Code First.

7. Posterior a ello digitamos el comando: enable-migrations -Force, lo que creara una carpeta llamada "Migrations" que contendra la clase "Configuration".

8. Dentro de la clase cambiamos el parametro AutomaticMigrationsEnabled a true.



9. posterior a ello en la consola de nuget, preseleccionando nuestro proyecto digitamos el comando: update-database, y si todo ha salido de manera correcta se creara en sql server la base de datos.


------------------------

ACTUALIZAR CAMBIOS EN LA BASE DE DATOS

Posterior a cambiar la estructura de una tabla y querer ejecutar el comando "update-database" se presenta un error que indica que la data se puede dañar.

Para esto existen 2 opciones de solucion:

1. den tro de Migrations/Configuration.cs, dentro del constructor al final del metodo ponemos los siguiente, que hara que el error desaparezca, pero es peligroso:

AutomaticMigrationDataLossAllowed = true;

2. digitamos el comando update-database -Force lo cual forzara a que se actualice el esquema, lo cual seria lo correcto.












Vistas Parciales

Son partes de vistas que se pueden incluir en una vista general Html, ademas de que pueden recibir parámetros.

A continuación se muestra un ejemplo de paso de parámetros, entre una clase, una vista principal y vista parcial con parámetros:

Se declara la clase, se llenan los objetos y se envía la información a la vista principal:

public class Persona1
    {
        public string Nombre { get; set; }
        public int Edad { get; set; }
    }

se crean los objetos y se devuelve a la vista principal

[HttpGet]
        public ActionResult Index2()
        {
            var personas = new List<Persona1>
            {
                new Persona1
                {
                    Nombre = "Carlos",
                    Edad = 30
                },
                new Persona1
                {
                    Nombre = "Jhosef",
                    Edad = 22
                }
            };

            ViewBag.MiListado = personas;

            return View();
        }

En la vista principal se llama a la vista parcial, pasandole el objeto


@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index2</title>
</head>
<body>
    <div>
        @Html.Partial("_ListadoPersonas", (List<WebApplication2.Controllers.Persona1>)ViewBag.MiListado)
    </div>
</body>
</html>

En la vista parcial se lee la informacion enviada

@model List<WebApplication2.Controllers.Persona1>

@foreach (var persona in Model)
{
    <div><strong>Nombre: </strong>@persona.Nombre (@persona.Edad)</div>
}







Begin Form ASP.NET MVC

@BeginForm() : sirve para iniciarlizar formularios en asp.net.

En su forma basica a continuacion se detalla la manera en la cual mediante una clase "Estudiante.cs" se puede instanciar un formulario de tipo get y post

EJEMPLO:

Se crea la clase "Estudiante"con validaciones dentro del "HomeController.cs"

public class Estudiante
    {
        [Display(Name = "Ingresa un nombre")]
        [Required(ErrorMessage = "El campo nombre es requerido")]
        public string Nombre { get; set; }

        [Display(Name = "Ingresa tu apellido")]
        [Required(ErrorMessage = "El campo apellido es requerido")]
        public string Apellido { get; set; }

        [Display(Name = "Ingresa la edad")]
        [Required(ErrorMessage = "El campo edad es requerido")]
        public int Edad { get; set; }
    }

Posterior a ello se crea la vista dento del index1 de "HomeController.cs"

@model WebApplication2.Controllers.Estudiante

@{
//Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index1</title>
</head>
<body>
    <h3>@ViewBag.Nombre</h3>
    <div>
        @using (Html.BeginForm())
        {
            <div>
                @Html.LabelFor(model => model.Nombre)
                @Html.EditorFor(model => model.Nombre)
            </div>
            <div>
                @Html.LabelFor(model => model.Apellido)
                @Html.EditorFor(model => model.Apellido)
            </div>
            <div>
                @Html.LabelFor(model => model.Edad)
                @Html.EditorFor(model => model.Edad)
            </div>

            <input type="submit" value="Enviar Información" />
        }
    </div>
</body>
</html>

Echo esto, se observa los metodos GET y POST de index1 que son los que revuelven toda la lógica de este manejo.

[HttpGet]
        public ActionResult Index1()
        {
            return View();
        }

        [HttpPost]
        public ActionResult Index1(Estudiante estudiante)
        {
            ViewBag.Nombre = $"Bienvenido, {estudiante.Nombre} {estudiante.Apellido}";

            estudiante.Edad = 99;

            return View();
        }

Este metodo tiene as siguientes sobrecargas
@Html.BeginForm("ActionName", "Controller", "Metodo")





lunes, 19 de agosto de 2019

Display y DisplayTemplates

Display y DisplayTemplates sirven para pasar variables u objetos a las vistas y que a su vez estas puedan renderizar el contenido para que este sea legible para el usuario:

-------------------------------------------------------------------------------------------------------------------------
HomeController.cs
public ActionResult Index()
        {
            ViewBag.Propiedad = "Jhosef";

            return View();
        }

VISTA

@{
    ViewBag.Title = "Home Page";
}

@Html.Display("Propiedad")



-------------------------------------------------------------------------------------------------------------------------

Adicional se pueden crear DisplayTemplates para dar formato a los datos que se visualizan automáticamente mediante @Html.Display("property")

A continuación se crea la clase persona y se pasa mediante un ViewBag el objeto hacia la vista:

public class Persona
    {
        public string Nombre { get; set; }
        public string Apellido { get; set; }
        public bool Empleado { get; set; }
        public int Edad { get; set; }
        public DateTime FechaNacimiento { get; set;  }
    }

public class HomeController : Controller
{
    public ActionResult Index()
        {
            ViewBag.Propiedad = new Persona
            {
                Nombre = "Carlos",
                Apellido = "Flores",
                Edad = 30,
                Empleado = true,
                FechaNacimiento = new DateTime(1989, 3, 23)
            };

            return View();
        }
}

--VISTA QUE RECIBE LA INFORMACION

Index.cshtml

@{
    ViewBag.Title = "Home Page";
}

@Html.Display("Propiedad")


------------------------------------------------------------------------------------------------------------------

Como se observa anteriormente el campo empleado devuelve un "Si" en lugar de un check, esto ya que dentro de la carpeta "Home" que contiene las vistas se ha creado una carpeta de templates que debe llamarse "DisplayTemplates" que sirve para dar formato a los tipos de datos que se visualizan en las vistas de "HomeController".

En este caso por elemplo si se desea dar formato a un booleano se de crear la vista "Boolean.cshtml" y asi con los demas tipos que se desee formatear: String, DateTime, Int, etc.


A continuación se muestra un ejemplo de como formatear un booleano


Adicional si se mueve la carpeta DisplayTemplates dentro de la carpeta Shared las plantillas aplicarían a todas las vistas.

También se pueden crear templates para clases enteras como la clase Persona

@model WebApplication2.Controllers.Persona

<div class="form-group">
    @Html.LabelFor(model => model.Nombre)
    @Html.DisplayFor(model => model.Nombre)
</div>
<div class="form-group">
    @Html.LabelFor(model => model.Apellido)
    @Html.DisplayFor(model => model.Apellido)
</div>
<div class="form-group">
    @Html.LabelFor(model => model.Empleado)
    @Html.DisplayFor(model => model.Empleado)
</div>
<div class="form-group">
    @Html.LabelFor(model => model.Edad)
    @Html.DisplayFor(model => model.Edad)
</div>
<div class="form-group">
    @Html.LabelFor(model => model.FechaNacimiento)
    @Html.DisplayFor(model => model.FechaNacimiento)
</div>



wef
wef

ActionLink

Los actionLink son como los href, y cuentan con las siguientes sobrecargas:

@Html.ActionLink("Texto a mostrar", "Action", "Controlador")

-----------------------------------------------------------------------------------------------------------------

@Html.ActionLink("Texto a mostrar", "Action") -> se omite el nombre del controlador por asp-net asume que el action viene de determinado controlador.

-----------------------------------------------------------------------------------------------------------------
@Html.ActionLink("Texto a mostrar", "Action", "Controlador", null, "atributos html") -> por ejemplo se pueden poner atributos como el target o las clases css


-----------------------------------------------------------------------------------------------------------------

A continuación un ejemplo utilizando funciones de javascript

<body>
    <div style="padding-top: 30px;"> 
        @Html.ActionLink("Ira a Hola", "Hola", "Dashboard", null, new {target="blank", id="idUnico", @class = "btn btn-primary", onclick="Holamundo();"})
    </div>


    <script>
        function Holamundo() {
            alert("hola mundo");
        }
    </script>

</body>

-----------------------------------------------------------------------------------------------------------------

A continuación se muestra un ejemplo con routeAtributes que permite enviar desde el @Html.ActionLink variables que se mostraran de manera get en la url del navegador


el Action "Hola" de "Dashboard" recibe la variable.










miércoles, 14 de agosto de 2019

Vistas

Las vistas en ASP.NET MVC se corresponden a las acciones de los controladores.

Las visstas tienen un formato cshtml


Las vistas compartidas se ubican dentro de la carpeta Shared, y se comparten mediante:

@Html.Partial("_nombreDeLaVista");

[se crea la vista parcial]

[se invoca la vista parcial]


se muestra la vista parcial invocada











ViewBag y ViewData

Sirven para pasar variables a la vista y lo unico que los diferencia es la sintaxis

ViewBag.Mensaje = "Valor del mensaje";
ViewBag.Fecha = new DateTime(2019, 8, 14);

ViewData["Mensaje"] = "valor del mensaje de ViewData";




Pasar información a Actions con QueryString [HttpGet] [HttpPost]

Es un conjunto de valores que se pueden a pasar a la pagina mediante la URL, similares al paso de parametros tipo GET


La url al solicitar recibir estos parámetros mostrara la información





------------------------------
[HttpGet]: indica que lo que se viene es una peticion tipo Get
[HttpPost]: Indica que la peticion a procesar es de tipo post con parametros


petición [HttpGet]en el navegador


Respuesta [HttpPost] con el numero ingresado










sábado, 10 de agosto de 2019

ActionResult y sus tipos en MVC

El action result puede retornar vistas, json, archivos, statusCode etc.

  • // El método ActionResult devuelve una instancia que deriva de ActionResult. Puede crear un método de acción que puede devolver cualquier instancia que esté ajustada en el tipo de ActionResult apropiado.
  • // Los tipos de retorno de ActionResult incorporados son:
  • Ver(); // ViewResult renderiza una vista como una página web
  • Vista parcial(); // PartialViewResult presenta una vista parcial, que se puede utilizar como parte de otra vista.
  • Redirigir (); // RedirectResult redirige a otro método de acción utilizando su URL.
  • RediectToAction (); RedirectToRoute (); // RedirectToRouteResult redirige a otro método de acción.
  • Contenido(); // ContentResult devuelve un tipo de contenido definido por el usuario.
  • Json (); // JsonResult devuelve un objeto JSON serializado.
  • JavaScript (); // JavaScriptResult devuelve un script que puede ejecutarse en el lado del cliente.
  • Expediente(); // FileResult devuelve una salida binaria para escribir en la respuesta.
  • // EmptResult representa un valor de retorno que se utiliza si el método de acción debe devolver un resultado nulo.

los action result se dividen e los siguientes:

JsonResult: devuelve un objeto Json:



-------------------------------------------

ContentResult: Puede devulver texto incluso renderizado en html


----------------------------------------------
RedirectResult : Redirecciona a una url

public RedirectResult Redireccion()
{
    string url = "http://www.google.com.ec";

    return Redirect(url);

}


RedirectToAction: Redirije a una acion de algun controlador propio

public RedirectToRouteResult Redirecionaccion()
        {
            return RedirectToAction("Index");
        }

El siguiente codigo redirije a una accion de un controlador diferente

public RedirectToRouteResult Redirecionaccion()
{
    return RedirectToAction("Hola", "Dashboard");
}

RedirectToRoute : Redireciona a la ruta especificada dentro de RouteConfig

public RedirectToRouteResult Red()
{
    return RedirectToRoute("Ejemplo");
}

               routes.MapRoute(
                name: "Ejemplo",
                url: "Ejemplo",
                defaults: new {
                    controller = "Dashboard",
                    action = "Index"
                    }

                );


HttpStatusCodeResult : devuelve status html

public HttpStatusCodeResult Codigo()
{
    return new HttpStatusCodeResult(200);
}

FileResult: Permite descargar archivos desde el navegador del usuario.





Controladores y acciones y reglas de ruteo en ASP.NET MVC

Un controlador se encarga de coordinar las acciones de toda la aplicación.



ActionResult: Retorna todo tipo de datos a la vista:

public ActionResult Index()
{
       return View();
}

En mvc dentro de la carpeta App_Start, dentro de RouteConfig.cs se encuentra la configuracion del enrutado y su ruta por defecto.


REGLAS DE RUTEO

...........................................................

Las reglas de ruteo se leen de arriba hacia abajo del archivo RouteConfig.cs

En este caso primero se van a leer las reglas de "Dashboard" antes de las reglas de "Default"









------------------
A continuación se detalla en enrutado para tiendas virtuales







domingo, 4 de agosto de 2019

Crear pruebas unitarias con TDD y AAA

TDD (Test Driven Developer) con AAA (Arrange, Act, Assert)

Arrange: Definir los objetos que seran utilizados para las pruebas unitarias
Act: Ejecutar los objetos necesarios para llevar a cabo las pruebas unitarias
Assert: Comparar el resultado esperado con el resultado obtenido.



Creamos la clase del método que resuelve la lógica con el proyecto de tipo "Biblioteca de clases Net Framework" "XCalculadora":


CalculadoraDeImpuestos.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace XCalculadora
{
    public class CalculadoraDeImpuestos
    {
        public decimal IbtenerIVA(decimal montoReserva)
        {
            const decimal porcentaje = 0.16m;
            decimal ivaReserva = porcentaje * montoReserva;
            return ivaReserva;
        }
    }
}


----------------------------------------------------------------------

El mismo metodo pero utilizando expresiones lambda y delegados



namespace XCalculadora
{
    public class CalculadoraDeImpuestos
    {
        private const decimal porcentajeIva = 0.16m;
        public delegate decimal Lambda(decimal value);

        public Lambda ObtenerIVA = delegate (decimal value) { return porcentajeIva * value; };
    }

}