Documente Academic
Documente Profesional
Documente Cultură
NET MVC
Para crear un proyecto nuevo, nos vamos a Archivo, Nuevo Proyecto, Visual C#, Web,
Aplicación Web ASP.NET (.NET Framework)
// CONTROLADORES Y ACCIONES
Controlador: se encarga de coordinar la comunicación entre los distintos elementos de la
aplicación. El controlador recibe las peticiones http del usuario, hace la consulta al modelo
correspondiente y envía la respuesta a la vista y dicha vista crea el html que será
visualizado por el usuario final.
namespace HolaMundo.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
return View(); //esto retorna una vista
}
return View(model);
}
return View();
}
}
}
Una acción (ActionResult) es un método de un controlador que le retorna un contenido al
usuario. El contenido puede ser un Html, un documento, o un simple string.
//ROUTING Y ROUTECONFIG
Para configurar las rutas de mi proyecto debo ir hasta la carpeta App_Start y dentro de la
misma existe un archivo que se llama RouteConfig.cs
La URL de la ruta se define de la siguiente forma: Controlador luego sigue una Acción y
opcionalmente colocamos un Id en caso de requerir.
namespace HolaMundo
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
Para crear una ruta nueva basta con copiar arriba de la ruta establecida por el sistema.
//ruta nueva creada y es específica nótese que cambian los parámetros del name y la url
pero mantiene el controller=”Home” y el action = “Contact”
routes.MapRoute(
name: "Ejemplo",
url: "Ejemplo",
defaults: new { controller = "Home", action = "Contact" }
);
//ruta creada inicialmente con por el sistema y es una regla muy general ya que abarca
todos los casos
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
//PARÁMETROS DE UN ACTION
Veremos como pasar parametros a un Action mediante query string. Query String es un
conjunto de valores que podemos pasar a nuestro servidor web. Por ejemplo:
http://localhost:49846/?nombre1=valor1&nombre2=valor2 //
(?nombre1=valor1&nombre2=valor2) esto es un query string
http://localhost:49846/Ejemplo?nombre=Ramon
public ActionResult Contact(string Nombre) //El ActionResult recibe una variable tipo
string la cual la paso mediante la url que se describe anteriormente
{
ViewBag.Message = "Your contact page. " + Nombre;
return View();
}
[HttpGet]
public ActionResult Contact()
{
ViewBag.Message = "Your contact page. ";
return View();
}
[HttpPost]
public ActionResult Contact(int edad)
{
ViewBag.Message = "Your contact page. La edad ingresada es: " + edad;
return View();
}
Ejemplo del formulario:
<form action="/home/contact" method="post">
//VIEWBAG Y VIEWDATA
ViewBag es un objeto especial que nos permite enviar información de forma fácil desde el
action hasta la vista.
ViewData es similar a ViewBag lo único que cambia es su sintaxis. ViewBag utiliza un punto
para pasar el parámetro y ViewData usa corchetes para hacerlo.
Los valores asignados a cada objeto sólo serán accesibles desde la vista definida en ese
controlador
Las vistas (Views) es la parte de la aplicación Web que se encarga de construir el código
html la cual el usuario va a utilizar. las vistas se encuentran dentro del proyecto en la
carpeta Views y dentro de ella se encuentran varias subcarpetas por cada vista creda por
ejemplo:
La subcarpeta Home posee tres archivos dentro de la misma la cual corresponde a las
vistas relacionadas para este. los archivos posee extensión .cshtml es decir el nombre del
archivo completo sería About.cshtml, Contact.cshtml, Index.cshtml. Esto a su vez
corresponden a los Controladores que se encuentran en la carpeta Controller About.cs,
Contact.cs, Index.cs pero a su vez debe de coincidir con los actions de los controllers
ejemplo:
controller Home:
Dentro de las vistas (Archivos html) puedo combinar tanto código Html como código C# y
esto lo realizamos utilizando la sintaxis de Razor que consiste en mezclar ambos tipos de
código. Lo que se encuentra delante de un arroba @ es código C#
@{ // aqui va código C# }
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace HolaMundo.Models
{
public class Pelicula
{
public string Titulo { get; set; }
public int Anio { get; set; }
public string Genero { get; set; }
public string Pais { get; set; }
public DateTime Fecha { get; set; }
}
}
using HolaMundo.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace HolaMundo.Services
{
public class PeliculaService : Pelicula
{
return View(model);
}
Vista Peliculas.cshtml
@model List<HolaMundo.Models.Pelicula>
@{
ViewBag.Title = "Peliculas";
}
<h3>Peliculas</h3>
<h5 class="pull-right">Mostrando @Model.Count películas</h5>
<table class="table table-striped table-bordered">
<thead>
<tr>
<td>Titulo</td>
<td>Genero</td>
<td>Año</td>
<td>País</td>
<td>Fecha Publicación</td>
</tr>
</thead>
<tbody>
@foreach (var pelicula in Model)
{
@*AQUI VA COMENTARIO DE C#*@
//puedo utilizar en vez del if la siguiente operador ternario
//var claseFila = (pelicula.Pais) ? “danger” : string.Empty;
var claseFila = String.Empty;
if (pelicula.Pais == "USA")
{
claseFila = "success";
}
<tr class="@claseFila">
<td>@pelicula.Titulo</td>
<td>@pelicula.Genero</td>
<td>@pelicula.Anio</td>
<td>@pelicula.Pais</td>
<td>@pelicula.Fecha.ToString("yyyy/MM/dd")</td>
</tr>
}
</tbody>
</table>
Razor es la tecnología que nos permite mezclar código html y código C# utilizando la
notación de @
Para este ejemplo solo me estoy dirigiendo al Action ya que estas vistas pertenecen al
mismo controlador.
|--------------Action
@Html.ActionLink("Nuevo Enlace", "About")
|
|_____ Nombre visible del link
_____Controlador
Action---------| | _________Variables
| | |
@Html.ActionLink("Inicio", "Index", "Home", new { edad = 9}, new { @class="danger"})
| |______ Clase html
|_____ Nombre visible del link
//ENTENDIENDO RENDER ACTION Y ACTION
RenderAction es un método void, es decir no devuelve nada. Permite ingresar una vista
dentro de otra por ejemplo:
@{
ViewBag.Title = "Contact";
Layout = null; //Agregamos esta linea para no cargar la vista con el Layout sino dará error
}
El método Display es un helper que se encuentra en el Html Helper, es decir que lo vamos a
utilizar en la vista.
Para trabajar los DisplayTemplates es importante crear una carpeta para poder tener
identificado y separado cada uno. En el caso de usar se crear dicha subcarpeta dentro de la
carpeta perteneciente a la vista, en este caso será la subcarpeta Home que se encuentra
de la carpeta Views. Con los DisplayTemplate podemos configurar algunas propiedades con
la finalidad de predeterminar valores en caso de un booleano podemos definir que diga Si o
No, o en el caso de la fecha se puede formatear a fin de mejorar la experiencia del usuario.
Creamos una carpeta dentro de la vista Home que diga: DisplayTemplates y dentro de esta
creamos una vista sin importar el Layout.
Dentro del archivo vista borramos lo que trae por defecto el archivo y agregamos lo
siguiente:
@model Boolean
@if (Model)
{
<span>Sí</span>
}
else {
<span>No</span>
}
La vista creada debe llevar el mismo nombre del modelo en este caso se llama
Boolean.cshtml, ASP.NET reconocerá y utilizará dicha vista al momento de llamarla.
@model DateTime
<span>@Model.ToString("yyyy-MM-dd")</span>
Para poder aplicar el DisplayTemplates en todo el proyecto, debo crear dicha carpeta dentro
de la carpeta Shared
Creamos una nueva vista llamada Animales.cshtml la cual la utilizaremos para la clase
Animales creada en el proyecto.
@model HolaMundo.Controllers.Animales
<div class="form-group">
@Html.LabelFor(model => model.Nombre):
@Html.DisplayFor(model => model.Nombre)
</div>
<div class="form-group">
@Html.LabelFor(model => model.Raza):
@Html.DisplayFor(model => model.Raza)
</div>
<div class="form-group">
@Html.LabelFor(model => model.Color):
@Html.DisplayFor(model => model.Color)
</div>
<div class="form-group">
@Html.LabelFor(model => model.Adoptado):
@Html.DisplayFor(model => model.Adoptado)
</div>
<div class="form-group">
@Html.LabelFor(model => model.FechaNacimiento):
@Html.DisplayFor(model => model.FechaNacimiento)
</div>
Nombre: Ramon
Raza: Pincher
Color: Marron
Adoptado: Sí
FechaNacimiento: 2019-05-12
Sirven para abstraer la interfaz de usuario que nos sirve para crear o editar elementos de
nuestra aplicación. Para su uso debemos de crear dentro de la vista a trabajar una carpeta
llamada EditorTemplates. Es muy parecido al ejemplo utilizado para los DisplayTemplates, se
crea una vista dentro de la carpeta Editortemplates con el modelo a utilizar ejemplo:
DateTime.cshtml
@model DateTime? //El signo de interrogación cerrado servirá para declarar como nulo el
modelo, es decir puede que tenga o no valores asignados el elemento DateTime, si no se hace
esa validación es probable que genere un error.
@if (!Model.HasValue)
}
else {
@{
var listado = new List<SelectListItem>() {
new SelectListItem()
{
Text = "Si",
Value = "1"
},
new SelectListItem()
{
Text = "No",
Value = "0",
Disabled = true //deshabilitado
},
new SelectListItem()
{
Text = "Quizás",
Value = "2",
Selected = true //seleccionado predeterminado
}
};
<br />
<label>Escoja una opción:</label>
@Html.DropDownList("miDropDownList", listado) //simple
@Html.DropDownList("miDropDownList", listado,new { @class = "form-control"}) // con clase
bootstrap
<br />
Es mejor trabajarlo de la siguiente forma, creamos una función para llamar desde cualquier lado
en caso de requerirlo.
ViewBag.MiListado = ObtenerListado();
<h4>@ViewBag.Message</h4>
@using (Html.BeginForm())
{
<div class="row">
<div class="col-lg-2 col-sm-2">
@Html.LabelFor(Model => Model.Nombre)
@Html.EditorFor(Model => Model.Nombre, new { htmlAttributes = new { @class =
"form-control" } })
</div>
</div>
<div class="row">
<div class="col-lg-2 col-sm-2">
@Html.LabelFor(Model => Model.Raza)
@Html.EditorFor(Model => Model.Raza, new { htmlAttributes = new { @class =
"form-control" } })
</div>
</div>
<div class="row">
<div class="col-lg-2 col-sm-2">
@Html.LabelFor(Model => Model.Color)
@Html.EditorFor(Model => Model.Color, new { htmlAttributes = new { @class =
"form-control" } })
</div>
</div>
<div class="row">
<div class="col-lg-2 col-sm-2">
@Html.LabelFor(Model => Model.FechaNacimiento)
@Html.EditorFor(Model => Model.FechaNacimiento, new { htmlAttributes = new {
@class = "form-control" } })
</div>
</div>
<div class="row">
<div class="row">
<div class="col-lg-2 col-sm-2">
<button type="submit" class='btn btn-success'>Enviar</button>
</div>
</div>
}
Coloco los actions de la siguiente manera:
Notese que un método es Get y el otro es Post que es donde se va a procesar el formulario
[HttpGet]
public ActionResult Index() //Puede usarse la clase ActionResult
{
return View();
}
[HttpPost]
public ActionResult Index(Animales animales)
{
ViewBag.Message = "Exitoso";
return View(animales);
}
Para este ejemplo usamos la clase Animales la cual invocamos desde ActionResult Post
<h4>@ViewBag.Message</h4>
@using (Html.BeginForm())
{
@Html.EditorForModel()
<div class="row">
<div class="col-lg-2 col-sm-2">
<button type="submit" class='btn btn-success'>Enviar</button>
</div>
</div>
}
//CREANDO VISTAS PARCIALES
Al igual que DisplayTemplates y EditorTemplates, las vistas parciales son una forma de
abstraer en un template un pedazo de código de cshtml permitiendo encapsular en una vista
y replicarlo en diferentes vistas.
@foreach (var persona in (List<HolaMundo.Controllers.Animales>)ViewBag.MiListado)
{
<div>
<span>@persona.Nombre @persona.Raza</span>
</div>
Para usar una url por defecto en mi proyecto y que cargue siempre en el index por ejemplo
debemos hacer lo siguiente: dar click derecho sobre el proyecto nos vamos a la pestaña
web e indicamos en el campo url por defecto para que cargue nuestro proyecto.
Un modelo no es más que una clase que contiene información la cual típicamente le
queremos mostrar a un usuario de una manera u otra. por ejemplo:
Scaffolding es una tecnología que ofrece ASP.NET MVC para a partir de un modelo poder
crear un formulario entre otras opciones (CRUD).
Entity Framework code first permite crear tablas a partir de un modelo ya creado por
nosotros.
//INTRODUCCIÓN A SCAFFOLDING
Para crear un nuevo controlador, le damos botón derecho arriba de la carpeta Controllers de
nuestro proyecto, agregar nuevo Controller y seleccionamos la opción Controlador MVC 5
con vistas que usa Entity Framework.
}
Hay que acotar que para usar Scaffolding debo utilizar una propiedad Id sino devolverá un
error al momento de crear un nuevo controlador mvc con entity framework.
Es una tecnología que nos sirve desde nuestro lenguaje de programación C# hacer querys
a una base de datos Sql, MySql, Oracle entre otros. Code First lo que hace es que a partir
de un modelo de C# podemos crear tablas en una base de datos.
Para este nuevo proyecto vamos a crear un modelo que se llama BlogPost el cual nos
servirá para inicialmente crear nuestra tabla.
Posterior a ello debemos verificar que en la carpeta Referencia del proyecto se encuentra
Entity Framework y de no ser así agregarlo.
Luego vamos a crear una clase DbContext en la cual indicaremos cuales son los modelos
que Entity Framework utilizará o tomará en cuenta para crear nuestra base de datos. Esta
clase la crearemos dentro de la carpeta Model perteneciente al proyecto. Se llamará
BlogContext.cs
using System;
using System.Collections.Generic;
using System.Data.Entity; //carga esta referencia
using System.Linq;
using System.Web;
namespace EFCodefirst.Models
{
public class BlogContext : DbContext //aqui hereda
{
public BlogContext() //cosntructor del DbContext el cual sirve para indicarle el
connectionString a utilizar
: base("DefaultConnection")
{
DbSet sirve para para hacer querys desde C# se le pasa el tipo del modelo en este caso es
BlogPost y se coloca el nombre de la tabla que va a crear que se llamará BlogPosts.
enable-migrations
update-database
update-database -force
//PROPIEDADES OBLIGATORIAS [REQUIRED]
}
Para su uso recuerda usar using System.ComponentModel.DataAnnotations; para
importar la clase correspondiente.
una vez colocado el atributo debo hacer un update-database para que se apliquen los
cambios correspondientes. La idea es que al actualizar el modelo se altera la estructura de
la base de datos.
El atributo [Compare] permite comparar propiedades de un modelo. Por ejemplo: sirve para
comprar que en dos inputs este escrito el correo como se ingresó anteriormente al igual que
comparación de los inputs de contraseña.
[StringLength(200)]
public int Email { get; set; }
[NotMapped] //este atributo te permite no mapear en una columna o propiedad en la base
de datos
[Compare(“Email”, ErrorMessage = “Los Emails no concuerdan”)]
public int ConfirMail { get; set; }
//VALIDACIONES
Ver video 40 - 41
//PASSWORDS Y TEXTAREA
Para especificar el tipo de dato utilizamos el atributo [DataType(DataType.MultilineText)]
guardamos y se renderizará la vista.
[DataType(DataType.MultilineText)] //textarea
public int Contenido{ get; set; }
[DataType(DataType.Password)] // contraseñas
public int Contrsenia { get; set; }
{
Clase creada (Singular) -----| ___________ Nombre de la tabla (Plural)
| |
public DbSet<Persona> Personas { get; set; } //corresponde a una tabla
Para crear una tabla es importante ir a herramientas > Administrador de Paquetes NuGet >
Consola de administrador de paquetes.
Desde la consola abierta debemos de escribir enable-migrations que servirá para habilitar
las migraciones desde nuestro sistema.
Básicamente el comando indica que vamos a usar Entity Framework Code First en nuestra
aplicación.
public Configuration()
{
AutomaticMigrationsEnabled = true; //se encuentra en false y lo pasamos a true
}
Para crear la base de datos utilizamos el comando update-database.
db.Personas.AddRange(personas);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(persona);
}
db.Personas.RemoveRange();
// GET: Personas
public ActionResult Index()
{
Una propiedad de navegación es una propiedad que nos permite navegar de un modelo a
otro siempre y cuando estos estén relacionados.
namespace CursoASPNETEF.Models
{
public class AplicationDbContext : DbContext
{
public DbSet<Persona> Personas { get; set; }
SqlQuery nos permite enviar un string con la consulta sql que deseamos realizar
if( m
ostrarPermiso != n
ull) {
ViewBag.c
ontrol = mostrarPermiso.cod_permiso;
}
Hago un método enum Sexo para enumerar las opciones
Hago una clase con las propiedades correspondientes. Esta clase debe ser pública para poder
acceder desde la vista al pasar los parámetros.
base.OnModelCreating(modelBuilder);
}
}
Para que una propiedad sea utilizada por el Lazy Loading debe ser configurada como virtual
por ejemplo:
Esta propiedad es de navegación ya que nos permite navegar de una entidad a otra. en
este caso podemos navegar desde Teléfonos a la entidad Teléfono.
Un problema con Lazy Loading es la serialización y un error común que se llama n+1. hay
que recordar que para usar el Lazy Loading debemos usar la palabra virtual en la
propiedad, cosa que no sucede con EAGER LOADING y si se podría utilizar fácilmente la
serialización a Json.
//PROBLEMA N+1
Este problema es ocasionado por Lazy Loading y no arroja ningún exception por lo que la
aplicación se vuelve lenta y no sabemos decifrarlo.
Para evitar ese problema es importante utilizar Eager Loading y aquí vemos el ejemplo de
código.
[Index]
public int Identificacion { get; set; }
a ese atributo se le puede pasar varias opciones como si se desea colocar un nombre al
índice, si es cluster, si es único y el orden.
}
//API FLUENT CONVENCIONES
Ver video 61 nuevamente.
db.Database.ExecuteSqlCommand(RecursosSQL.sp_Borra_Personas_Menores_Nombre);
//AUTENTICACION Y MEMBRESIA
//AUTHORIZE Y ALLOWANONIMUS MEMBRESIAS
Para que una persona tenga acceso a los métodos Actions es importante colocar un atributo
encima de este indicado lo siguiente:
[ Authorize]
public ActionResult About()
{
ViewBag.Message = "Your application description page.";
return View();
}
Si la persona no ha iniciado sesión, el sistema lo redirigirá a una vista predeterminada.
Si deseo que crear roles de usuario y si deseo que un usuario solo tenga acceso a una vista
o al controlador completamente simplemente agregamos la siguiente información al atributo:
[ Authorize(Users = “ramoncarrasquel844@gmail.com,
ramoncarrasquel844.ec@gmail.com”)]
public ActionResult About()
{
ViewBag.Message = "Your application description page.";
return View();
}
Puedo especificar los usuarios que desee separados por coma y entre comillas dobles
Puedo especificar los roles que desee separados por coma y entre comillas dobles
[Authorize(Roles = “Administrador, Vendedor”)]
Si yo aplico los roles o permisos a todo el controlador y deseo aplicar un permiso extra a un
usuario en específico simplemente debo colocar el atributo [AllowAnonymous] en el actions
correspondiente.
Esto es el controlador
public ActionResult Create()
{
// Create Makes view data
var provList = new SelectList(db.Provincias.ToList(), "IdPr", "NombrePro");
var cantList = new SelectList(db.Cantones.ToList(), "IdCa", "NombreCan");
ViewBag.Provincias = provList;
ViewBag.Cantones = cantList;
return View();
}
Esto es la Vista
<div class="form-group">
@Html.Label("Provincia", htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownList("Seleccione la Provincia", ViewBag.Provincias as SelectList,
new { htmlAttributes = new { @class = "form-control" } })
</div>
</div>
<div class="form-group">
@Html.Label("Cantón", htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownList("Seleccione el Cantón", ViewBag.Cantones as SelectList, new
{ htmlAttributes = new { @class = "form-control" } })
</div>
</div>
//VALIDACION DE RELACIONES
[HttpGet]
public JsonResult ListadoCanton(int provincia)
{
db.Configuration.ProxyCreationEnabled = false;
List<Canton> Cantones =
db.Database.SqlQuery<Canton>("sp_Buscar_Cantones_IdProvincia @IdProvincia", new
SqlParameter("@IdProvincia", provincia)).ToList();
List<Canton> Cantons = db.Cantones.Where(x => x.IdProvincia.IdPr ==
provincia).ToList();
return Json(Cantones, JsonRequestBehavior.AllowGet);
}
o sea no es un int
//MANEJO DE USUARIOS
var autenticado = User.Identity.IsAuthenticated; // valida si el usuario está autenticado o no
var nombre = User.Identity.Name; //muestra el nombre del usuario
var id = User.Identity.GetUserId(); //devuelve el id del usuario. Se necesita using
Microsoft.AspNet.Identity;
con userManager puedo agregar un rol, cambiar password, confirmar email, buscar mediante un
id a un usuario, entre otros.
En el archivo IdentityConfig.cs puedo configurar las opciones del tipo de contraseña ingresado,
cantidad de ingresos fallidos, requerir el email, entre otros.
//MANEJANDO ROLES
Los roles son responsabilidades asignadas a un usuario en especifico que me permitirá dar
acceso a diferentes vistas o controladores de acuerdo la funcionalidad requerida.
//crear un rol
var resultado = roleManager.Create( new IdentityRole(“Administrador”));
//borrar un rol
var rolVendedor = roleManager.FindByName(“Ventas”); //FindById
roleManager.Delete(rolVendedor);
}
Recordar que para autorizar mis actions debo colocar en la parte superior el atributo Authorize
Para hacerlo debemos abrir el archivo IdentityModels.cs y luego agregar la nueva propiedad
despues de la primera llave abierta de la siguiente función:
ahora debemos de ir a la vista de Registro y le damos F12 encima del modelo y este lo abrirá,
agregamos el atributo nuevo y lo guardamos, luego agregamos en la vista el nuevo campo de
forma manual lo mismo para recibir los datos en el controlador en el área de registro para este
caso.
if(User.Identity.IsAuthenticated)
{
using (ApplicationDbContext db = new ApplicationDbContext())
{
var IdUsuarioActual = User.Identity.GetUserId();
}
//ENCRIPTANDO EL CONNECTIONSTRING
Aprenderemos a encriptar el connection String de un web.config.
Encripta:
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\aspnet_regiis.exe -pef
"connectionStrings" Carpeta_Con_Web.Config
Desencripta:
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\aspnet_regiis.exe -pdf
"connectionStrings" Carpeta_Con_Web.Config
Proteger la información del Connection String es importante, pues en esta se pueden encontrar
credenciales a servidores de bases de datos.
[ValidateInput(false)]
[ValidateInput(true)]
valida la información que está recibiendo desde el input
if(cuenta == null)
{
return RedirectToAction(“Index”);
}
return View(cuenta);
}
//CSRF Y ANTIFORGERYTOKEN
Colocar el atributo [ValidateAntiForgeryToken] encima del Action el cual recibirá la información
del formulario
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult CrearCuenta (decimal monto){
var userId = User.Identity.GetUserId();
var cuenta = new Cuenta(){MontoCuenta= monto, UserId=userId};
db.Cuentas.Add(cuenta);
db.SaveChanges();
return RedirectToAction(“Index”);
}
This being said I would strongly recommend you to use view models and strongly typed
views instead of ViewBag. This way you will also get Intellisense in your view which
would have helped you pick the correct names.
So you could start by defining a view model that will hold all the information your view
would need:
and finally inside your strongly typed view use the view model:
// http://localhost:1302/TESTERS/Default6.aspx
// /TESTERS/Default6.aspx
// localhost
Ejemplo href:
<a asp-controller="Generales"
asp-action="Editar"
asp-route-id="@item.Id">@item.CodigoParametro</a>