Está en la página 1de 43

//INICIO DEL PROYECTO - ASP.

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.

Todos los controladores se encuentra dentro de la carpeta Controllers y esta se consigue


dentro de la solución creada.

Un controlador es una clase de C# y su estructura es la siguiente y poseen métodos


públicos los cuales definen el mismo:

namespace HolaMundo.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
return View(); //esto retorna una vista
}

public ActionResult About()


{
ViewBag.Message = "Your application description page.";

var PeliculaService = new PeliculaService();

var model = PeliculaService.ObtenerPeliculas();

return View(model);
}

public ActionResult Contact()


{
ViewBag.Message = "Your contact page.";

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

Posee un método llamado RegisterRoutes que recibe un RouteCollection routes, que es


una colección de reglas de rutas las cuales se pueden definir para indicarles a ASP.NET
que controlador y acción queremos invocar según lo que tengamos en la URL

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}");

routes.MapRoute( //invocamos a MapRoute que es una regla de mapeo


name: "Default", //Nombre del mapeo
url: "{controller}/{action}/{id}", //url de acceso o template de ruta
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
// si no consigue la url por defecto utilizará el defaults. Usará el controlador “Home”, y el
action (método dentro del controlador) usará “Index” y el {id} es opcional
);
}
}
}

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 }
);

//ACTION RESULT MVC

Un ActionResult es un mètodo de un controlador que retorna contenido al usuario. Abarca


una clase amplia la cual permite devolver cualquier elemento, es decir, puede retornar una
vista, un archivo un status code entre otro.

public ActionResult Index()


{
//return new HttpStatusCodeResult(404);
return View(); //retorna una simple vista html
}

public FileResult Index() //retorna un archivo


{
return File(Url.Content("~/Files/testfile.txt"), "text/plain");
}

public ViewResult Index() //retorna un archivo


{
return View(); // solo retorna una vista
}

public ContentResult Content()


{
return Content("<h3>Here's a custom content header</h3>", "text/html");
}

public EmptyResult Empty()


{
return new EmptyResult();
}

public ActionResult NothingReturned()


{
return null; //Returns an EmptyResult
}
public JsonResult Json()
{
return Json(new { Name = "John Smith", ID = 4, DateOfBirth = new DateTime(1999,
12, 31) });
}

public JavaScriptResult LoadScript()


{
return JavaScript("alert('Hello! This popup shows that we can return JavaScript from
controller actions.')");
}

public RedirectResult RedirectToOtherSite()


{
return Redirect("http://www.exceptionnotfound.net");
}

public RedirectToRouteResult RedirectToRoute()


{
return RedirectToRoute(new { controller = "Home", action = "Route" });
}

public RedirectToRouteResult RedirectToAction()


{
return RedirectToAction("Action");
}

public HttpStatusCodeResult UnauthorizedStatusCode()


{
return new HttpStatusCodeResult(HttpStatusCode.Unauthorized, "You are not
authorized to access this controller action.");
}

public HttpStatusCodeResult BadGateway()


{
return new HttpStatusCodeResult(HttpStatusCode.BadGateway, "I have no idea
what this error means.");
}

public HttpStatusCodeResult UnauthorizedResult()


{
return new HttpUnauthorizedResult("You are not authorized to access this controller
action.");
}
public HttpNotFoundResult NotFound()
{ return HttpNotFound("We didn't find that action, sorry!"); }

ASP.NET has a description of these methods

● ContentResult – Represents a text result.


● EmptyResult – Represents no result.
● FileContentResult – Represents a downloadable file (with the binary content).
● FilePathResult – Represents a downloadable file (with a path).
● FileStreamResult – Represents a downloadable file (with a file stream).
● JavaScriptResult – Represents a JavaScript script.
● JsonResult – Represents a JavaScript Object Notation result that can be used in an
AJAX application.
● PartialViewResult – Represents HTML and markup rendered by a partial view.
● RedirectResult – Represents a redirection to a new URL.
● RedirectToRouteResult – Represents a result that performs a redirection by using the
specified route values dictionary.
● ViewResult – Represents HTML and markup rendered by a view
Action Result Helper Method Description

ViewResult View Renders a view as web page

PartialViewResult PartialView Renders a partial view, which defines a


section of a view that can be rendered
inside another view.

RedirectResult Redirect Redirects to another action method by


using URL

RedirectToRouteResult RedirectToAction or Redirects to another action method


RedirectToRoute

ContentResult Contnet Returns a user-defined contnet type

JsonResult Json Returns serilized json object

JavaScriptResult JavaScript Returns a script that can be executed on


the client.

HttpStatusCodeResult (None) Returns a specific HTTP response code


and description.

HttpUnauthorizedResult (None) Returns the result of an unauthorized


HTTP request.

HttpNotFoundResult HttpNotFound Indicates the requested resource was not


found.

FileResult File Returns binary output to write to the


response.

FileContentResult Controller.File(Byte[], Sends the contents of a binary file to the


String) or response.
Controller.File(Byte[],
String, String)

FilePathResult Controller.File(String, Sends the contents of a file to the


String) or response.
Controller.File(String,
String, String)

FileStreamResult Controller.File(Stream, Sends binary content to the response


String) or through a stream.
Controller.File(Stream,
String, String)

EmptyResult (None) Represents a return value that is used if


the action method must return a ​null
result (void).
//CONTENT RESULT MVC

Solo devuelve un contenido html o string en vez de devolver una vista.

public ContentResult Content()


{
return Content("<h3>Here's a custom content header</h3>", "text/html");
}

//JSON Y JSON RESULT


Los Json siempre son enviados mediante POST y es por ello para que se pueda ver en este
ejemplo se le deben pasar unos parámetros adicionales al return.

public JsonResult Index() //puede usarse la clase ActionResult


{
var persona1 = new Personas() { nombre = "Ramon", edad = 35 };
var persona2 = new Personas() { nombre = "Ramon", edad = 35 };

return Json(persona, ​JsonRequestBehavior.AllowGet​); // agregar el


JsonRequestBehavior.AllowGe
}

Un ejemplo con Lista sería la siguiente:

public class Personas


{
public string nombre { get; set; }
public int edad { get; set; }
}
public ActionResult Index()
{
List<Personas> persona = new List<Personas>()
{
new Personas()
{
nombre = "Ramon", edad = 35
},
new Personas()
{
nombre = "Adrian", edad = 9
},
new Personas()
{
nombre = "Andrea", edad = 36
}
};
return Json(persona, JsonRequestBehavior.AllowGet);
}

//REDIRECT Y REDIRECT ACTION Y REDIRECT ROUTE

Me permite realizar diferentes tipos de redireccionamientos a través de mi controlador.

public RedirectResult Index() //podemos usar la clase ActionResult


{
return Redirect("​https://warairasoft.net​"); //redirecciona a una web en especifico
}

public RedirectToRouteResult Index() // devuelve una ruta


{

return RedirectToAction("Register", "Account"); //le paso el controlador y el método


}

public ActionResult Index()


{

return RedirectToRoute("EjemploRuta"); //nombre de la ruta definido en el archivo


RouteConfig.cs
}

//HTTP STATUS CODE - HTTP STATUS CODE RESULT

Permite mostrar los diferentes estatus de acuerdo al requerimiento solicitado y encontrado

public HttpStatusCodeResult Index() //Puede usarse la clase ActionResult


{
return new HttpStatusCodeResult(200); //404, 200, 301 códigos de error y
notificación http. status http
//return new HttpStatusCodeResult(404, “Recurso no encontrado”); //puedo pasar un texto
de igual forma
}

//DESCARGA ARCHIVO ASP.NET

public FileResult Index() //Puede usarse la clase ActionResult


{

var ruta = Server.MapPath("guia.pdf"); //se crea la ruta del archivo


return File(ruta, "application/pdf", "guia-google.pdf"); //primero se pasa la ruta, luego
el mime y después el nombre del archivo a descargar
}

//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();
}

//HTTP GET Y POST


Notese que se están utilizando dos métodos llamados ​Contact ​pero uno es Get y el otro es
Post, El post recibirá una variable ​edad ​la cual será procesa. Para que esto funcione desde
la vista Contact introduciremos un formulario y dentro de su action colocaremos el
controlador y el método al cual corresponda ese controlador para procesar dicho formulario,
en este caso usaremos el mismo Contact.

[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">

<input type="number" name="edad" />


<button type="submit">Enviar</button>
</form>

//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

Así se usa en el Controlador


public ActionResult Contact()
{
ViewBag.Message = "Your contact page. ";
ViewBag.Fecha = new DateTime(2019, 06, 11);
ViewBag.Entero = 10;

ViewData["MiMensaje"] = "Este es un mensaje desde ViewData";


return View();
}

Así se usa en la vista:


<h2>@ViewBag.Title.</h2>
<h3>@ViewBag.Message</h3>
<h4>@ViewBag.Fecha.ToString("yyyy/MM/dd")</h4>
<h5>@ViewBag.Entero</h5>
<h2>ViewData: @ViewData["MiMensaje"]</h2>
//INTRODUCCIÓN A LAS VISTAS

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:

public ActionResult ​Index​()


{
return View();
}
public ActionResult ​About​()
{
return View();
}
public ActionResult ​Contact​()
{
return View();
}

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# }

//LAYOUT Y SHARE FOLDER

El Layout Page se encuentra en la subcarpeta Shared de la carpeta Views . Esta carpeta


Shared contiene todos los elementos que se van a compartir entre las vistas. De igual forma
posee el archivo ​_Layout.cshtml​ donde posee todo el archivo.

@Html.Partial(“_LoginPartial”) //Sirve para mostrar una vista parcial de html dentro de mi


aplicación.

@RenderBody() //Es donde se va a renderizar la vista de mi aplicación.


Action---------| _________ Controlador
| |
<li>@Html.ActionLink("Inicio", "Index", "Home")</li> //muestra un link en el menú
|
|_____ Nombre visible del link

@DateTime.Now.Year //muestra el año actual

@Scripts.Render("~/bundles/modernizr") // carga los archivos css de mi aplicación

@Scripts.Render("~/bundles/jquery") //carga los archivos jquery o javascript de mi aplicación

//ESCRIBIENDO CÓDIGO EN UNA VISTA RAZOR


Models -> Pelicula.cs

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; }

}
}

Services -> PeliculaServices.cs

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

namespace HolaMundo.Services
{
public class PeliculaService : Pelicula
{

public Pelicula ObtenerPelicula()


{
return new PeliculaService()
{
Titulo = "Plan de Escape",
Anio = 2018,
Genero = "Acción",
Pais = "USA",
Fecha = new DateTime(2013, 12, 5)
};
}

public List<Pelicula> ObtenerPeliculas()


{
var Pelicula1 = new Pelicula()
{
Titulo = "Plan de Escape",
Anio = 2018,
Genero = "Acción",
Pais = "USA",
Fecha = new DateTime(2018, 12, 5)
};

var Pelicula2 = new Pelicula()


{
Titulo = "Atentado en París",
Anio = 2019,
Genero = "Comedia",
Pais = "Reino Unido",
Fecha = new DateTime(2019, 5, 5)
};

var Pelicula3 = new Pelicula()


{
Titulo = "Locos y Peligrosos",
Anio = 2017,
Genero = "Comedia y Acción",
Pais = "Venezuela",
Fecha = new DateTime(2017, 3, 1)
};
return new List<Pelicula> { Pelicula1, Pelicula2, Pelicula3 };
}
}
}

Action dentro del HomeController.cs

public ActionResult Peliculas()


{
var PeliculaService = new PeliculaService();

var model = PeliculaService.ObtenerPeliculas();

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 @

//MÉTODO RAW VISTAS


Sirve para mostrar estilos html u otros argumentos html y de javascript. No es recomendable
@Html.Raw(pelicula.Titulo)

//ENTENDIENDO Y USANDO LOS ACTIONLINK


Es una manera de crear anchors que se adaptan a nuestra página

Action---------| _________ Controlador


| |
<li>@Html.ActionLink("Inicio", "Index", "Home")</li> //muestra un link en el menú
|
|_____ Nombre visible del link

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:

@Html.Action(“Contact”, “Home”); //devuelve un string de toda la vista

@{ Html.RenderAction("Contact");} // Al RenderAction le pasamos la vista de Contact sin


controller

@{ Html.RenderAction("Contact", "Home");} //con controller

@{
ViewBag.Title = "Contact";
Layout = null; //Agregamos esta linea para no cargar la vista con el Layout sino dará error
}

[ChildActionOnly] //Este atributo permite utilizar este metodo unica y exclusivamente


dentro de una vista
public ActionResult Contact()
{
ViewBag.Message = "Your contact page. ";
ViewBag.Fecha = new DateTime(2019, 06, 11);
ViewBag.Entero = 10;

ViewData["MiMensaje"] = "Este es un mensaje desde ViewData";


return View();
}

//ENTENDIENDO DISPLAY Y DISPLAY TEMPLATES

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.

Para el ejemplo aunque la clase Animales no es un booleano pero sus propiedades si


poseen booleano. Cuando vaya a leer la propiedad Booleano, ASP.NET va a apuntar a esa
carpeta y a la vista correspondiente para hacer los cambios correspondientes.

Para el caso de DateTime.cshtml este archivo se encuentra en la misma carpeta


DisplayTemplates creado dentro de la vista Home

@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>

De esta forma devolverá los atributos del correspondientes en negrita y ordenados de la


forma correspondiente.

Nombre​: Ramon

Raza​: Pincher

Color​: Marron

Adoptado​: Sí

FechaNacimiento​: 2019-05-12

//ENTENDIENDO EDITOR Y EDITOR TEMPLATE

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)

<input type="date" id="@ViewData.TemplateInfo.GetFullHtmlFieldId("")"


name="@ViewData.TemplateInfo.GetFullHtmlFieldName("")" />

}
else {

<input type="date" id="@ViewData.TemplateInfo.GetFullHtmlFieldId("")"


name="@ViewData.TemplateInfo.GetFullHtmlFieldName("")"
value="@Model.Value.ToString("yyyy-MM-dd")" />

//HACIENDO UN DROP DOWN LIST (SELECT)

@{
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.

public List<SelectListItem> ObtenerListado()


{
return new List<SelectListItem>() {
new SelectListItem()
{
Text = "Si",
Value = "1"
},
new SelectListItem()
{
Text = "No",
Value = "0",
Disabled = true
},
new SelectListItem()
{
Text = "Quizás",
Value = "2",
Selected = true
}
};
}

Llamo el método dentro del action y lo almaceno en un ViewBag.

ViewBag.MiListado = ObtenerListado();

Y desde la vista para poder mostrarlo dentro del DropdownList agrego


(List<SelectListItem>)ViewBag.MiListado

@Html.DropDownList("miDropDownList", ​(List<SelectListItem>)ViewBag.MiListado​, new {


@class = "form-control"})

//DROP DOWN LIST DESDE UN ENUM


ver video 22 nuevamente

//FORMULARIO EN RAZOR CON BEGINFORM

Esto es la vista Index.cshtml


@model HolaMundo.Controllers.Animales
@{
ViewBag.Title = "Home Page";
}

<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="col-lg-2 col-sm-2">


@Html.LabelFor(Model => Model.Adoptado, new { htmlAttributes = new { @class =
"checkbox-inline" } })
@Html.EditorFor(Model => Model.Adoptado)
</div>
</div>

<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

public class Animales


{
public string Nombre { get; set; }
public string Raza { get; set; }
public string Color { get; set; }
public Boolean Adoptado { get; set; }
public DateTime FechaNacimiento { get; set; }

Ejemplo del Index.cshtml con EditorForModel


@model HolaMundo.Controllers.Animales
@{
ViewBag.Title = "Home Page";
}

<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>

//URL POR DEFECTO EJECUCION DE APLICACION ASP.NET

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.

//MODELOS, SCAFFOLDING Y ENTITY FRAMEWORK

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:

public class Pelicula //Pelicula es un objeto


{
public int Id { get; set; }
[Required] // si deseo que la propiedad título sea requerida
public string Titulo { get; set; }
public bool EstaEnCartelera { get; set; }
[StringLength(120)]
public string Genero { get; set; }
}

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​.

Primero debo crear un modelo en la carpeta Models.


public class Pelicula
{
public int Id { get; set; }
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; }

}
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.

//INTRODUCCIÓN A ENTITY FRAMEWORK CODE FIRST

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.

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; }
}

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

Esta clase BlogContext debe heredar de la clase DbContext

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")
{

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


}

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​.

Para continuar debo crear un ​ConnectionString ​para conectarnos a la base de datos y


para ello nos dirigimos al archivo ​Web.Config​ y si no existe se debe crear debajo de las
etiquetas de <configSections></configSections>

<add name="defaultConnection" connectionString="Data


Source=LAPTOP-9UJ8HKAK\SQLEXPRESS;Initial Catalog=Blog;Integrated Security=True"
providerName="System.Data.SqlClient"/>

enable-migrations
update-database
update-database -force
//PROPIEDADES OBLIGATORIAS [REQUIRED]

El atributo [Required] me permite indicar que propiedades de un módelo son obligatorias.


Los corchetes me permite definir atributos.

public class Comentario


{

public int Id { get; set; }


[Required(​ErrorMessage = “Este Campo es obligatorio” )​] -> Requerido con msj.
public string Contenido { get; set; }
public string Autor { get; set; }
public int BlogPostId { get; set; }

}
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.

[Required(ErrorMessage = "Este campo es obligatorio")] //solo muestra los datos de la


pagina
[Required(ErrorMessage = "Este {0} es obligatorio")] //Este personaliza con el nombre del
campo

//DELIMITANDO CAMPOS DE TEXTO CON STRINGLENGTH

El StringLength sirve para indicar la longitud de un string con la finalidad de validar la


cantidad de caracteres que debe tener un input.

[StringLength(6, MinimumLength=5, ErrorMessage=”El campo debe tener una longitud


minima de 5 y máxima de 6”)]

[StringLength(6, MinimumLength=5, ErrorMessage=”El campo {0} debe tener una longitud


mínima de {2} y máxima de {1}”)]

//VALIDANDO RANGO DE NÚMEROS CON RANGE

[Range(18, 100)]//el rango es de 18 a 100


[Range(18, int.MaxValue)]//De 18 al número entero más grande que soporta C#
[Range(18, double.MaxValue)]//De 18 al número double más grande que soporta C#
//COMPARANDO PROPIEDADES CON COMPARE

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; }

//VALIDANDO TARJETAS DE CREDITO


[CreditCard(ErrorMessage=”Tarjeta invalida”)]
public int TarjetaDeCredito { get; set; }

//VALIDACION CON JAVASCRIPT CON REMOTE


Ver nuevamente el video 39

//VALIDACIONES
Ver video 40 - 41

//PERSONALIZANDO LOS CAMPOS CON DISPLAY


[Display(Name = “Tarjeta de Crédito”)]
[CreditCard(ErrorMessage=”Tarjeta invalida”)]
public int TarjetaDeCredito { get; set; }

//APS.NET MULTI IDIOMA


Ver video 43 (interesante)

//OCULTANDO CAMPOS CON SCAFFOLDING

[Scaffolding(false)] //oculta el campo para la vista


public int TarjetaDeCredito { get; set; }

//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; }

//CREANDO UNA BASE DE DATOS CON ENTITY FRAMEWORK


La clase DbContext nos permite configurar algunas características y propiedades que
tendrá nuestra base de datos. Nos permite por ejemplo a interceptar querys antes de que se
envíen a la base de datos.

public class AplicationDbContext : DbContext

{
​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.

Una vez ejecutado el comando ​enable-migrations​ se creará un archivo llamado


Configuration.cs​ dentro de la carpeta ​Migrations

Dentro del archivo Configuration.cs tenemos lo siguiente:

public Configuration()
{
AutomaticMigrationsEnabled = true; //se encuentra en false y lo pasamos a true
}
Para crear la base de datos utilizamos el comando ​update-database.

//FUNCIONES ESPECIALES DE DBCONTEXT


Ver video 47 nuevamente
//INSERTANDO REGISTROS CON ENTITY FRAMEWORK

public ActionResult Create([Bind(Include =


"Id,Nombrep,Identificacion,Correo,FechaNac")] Persona persona)
{
if (ModelState.IsValid)
{
var personas = new List<Persona>() { persona };
personas.Add(new Persona() { Nombrep = "Ramon", Identificacion = 123456,
Correo = "ramon@gmail.com", FechaNac = new DateTime(2019,05,12) });

db.Personas.AddRange(personas);
db.SaveChanges();
return RedirectToAction("Index");
}

return View(persona);
}

//ACTUALIZAR REGISTRO CON ENTITY FRAMEWORK


Ver video 49

//BORRANDO REGISTROS ENTITY FRAMEWORK


Ver video 50

db.Personas.RemoveRange();

//SELECCIONAR VARIAS COLUMNAS

// GET: Personas
public ActionResult Index()
{

//LISTADO GENERAL DE PERSONAS


var ListadoPersonas = db.Personas.ToList();
//LISTADO DE SOLO NOMBRES DE PERSONAS
var ListadoPersonasNombres = db.Personas.Select(x => x.Nombrep).ToList();
//LISTADO DE PERSONAS PROYECTADO CON COLUMNAS SELECCIONADAS
var ListadoPersonasVariasColumnasAnonimo = db.Personas.Select(x => new {
Nombrep = x.Nombrep, Identificacion = x.Identificacion }).ToList();
//LISTADO DE PERSONAS PROYECTADO CON COLUMNAS SELECCIONADAS
HACIA PERSONAS
var ListadoPersonasVariasColumnasProyectado = db.Personas.Select(x => new {
Nombrep = x.Nombrep, Identificacion = x.Identificacion }).ToList().Select(x => new Persona()
{ Nombrep = x.Nombrep, Identificacion = x.Identificacion }).ToList();
return View(db.Personas.ToList());
}

//LLAVES FORÁNEAS Y PROPIEDADES DE NAVEGACIÓN

Una propiedad de navegación es una propiedad que nos permite navegar de un modelo a
otro siempre y cuando estos estén relacionados.

public class Telefono


{
public int Id { get; set; }
public int Numero { get; set; }
public Persona IdPersona { get; set; }
}
public int Id { get; set; }
public string Nombrep { get; set; }
public int Identificacion { get; set; }
public string Correo { get; set; }
public DateTime FechaNac { get; set; }
public ​virtual ​List<Telefono> Telefonos { get; set; }

con virtual puedo hacer esta consulta desde el controlador

var personas = db.Personas.​Include​("Telefonos");


return View(personas);

namespace CursoASPNETEF.Models
{
public class AplicationDbContext : DbContext
{
public DbSet<Persona> Personas { get; set; }

public DbSet<Telefono> Telefonos { get; set; }

protected override void OnModelCreating(DbModelBuilder modelBuilder)


{

modelBuilder.Entity<Telefono>().HasRequired(x => x.IdPersona); //relacion de uno a


muchos y crea una columna ejemplo Personas_Id
base.OnModelCreating(modelBuilder);
}
}
}
//AQUI SELECCIONO UNA PERSONA CON ID 2
var personas = db.Personas.FirstOrDefault(x => x.Id == 2);
//AQUI BUSCO LOS TELEFONOS DE ESA PERSONA CONSULTADA
var telefonos = personas.Telefonos;

//INNER JOIN - JOIN - GROUP JOIN


Son métodos que me permiten realizar asociaciones de modelos relacionados.

//ejemplo de JOIN (Esta consulta trae todas las columnas consultadas)


var personasTelefonos = db.Telefono.Join(db.Personas, tel => tel.IdPersona, per => per.Id,
(dir,per) => new {dir, per}).Where(x => x.dir.Id == 1).ToList();

var personasTelefonos = db.Telefono.Join(db.Personas, tel => tel.IdPersona, per => per.Id,


(tel,per) => new {tel, per}).FirstOrDefault(x => x.tel.Id == 1).ToList();

No funciona el JOIN ver video nuevamente y buscar material.

//VER QUERY GENERADO POR ENTITY FRAMEWORK

var personas = db.Personas.ToString();//me almacena en la variable personas el query


realizado por entity framework

//ENTITY FRAMEWORK QUERY ARBITRARIO SQL QUERY

SqlQuery ​nos permite enviar un string con la consulta sql que deseamos realizar

var personas = db.Personas.​SqlQuery​("​SELECT * FROM dbo.Personas​").ToList();

var telefonos = db.Telefonos.SqlQuery<Direccion>

Pendiente con esto, e


​ l firstordefault puede retornar null si es que no
encuentra ningun item que coincida con la búsqueda por eso la validación

var​ mostrarPermiso ​=​ db.​ u


​ suarios.​ ​FirstOrDefault​(​p​=>​ p.​ ​usuario ​==​ usuarioWindows​);

if(​ m
​ ostrarPermiso ​!=​ n
​ ull)​ {

​ViewBag​.c
​ ontrol ​=​ mostrarPermiso​.​cod_permiso;​

}
Hago un método enum Sexo para enumerar las opciones

public enum Sexo


{
Masculino = 1,
Femenino = 2
}

Hago una clase con las propiedades correspondientes. Esta clase debe ser pública para poder
acceder desde la vista al pasar los parámetros.

public class Estadisticas


{
public Sexo Sexo { get; set; }
public int Cantidad { get; set; }

Tenemos dentro del action la consulta SqlQuery

public ActionResult Index()


{

Asigno el resultado a una variable llamada estadística


var ​estadistica ​= db.Database.SqlQuery<Estadisticas>(@"SELECT Sexo, count(*) AS Cantidad
FROM dbo.Personas GROUP BY Sexo").ToList();
Asigno el resultado al ViewBag
ViewBag.Estadistica = ​estadistica​;
return View(db.Personas.ToList());
}

En la vista agregamos iteramos el ViewBag

@foreach (var resultado in ​ViewBag.Estadistica​)


{
<p>@resultado.Sexo - @resultado.Cantidad</p>
}

//ENTENDIENDO EAGER LOADING


Así relaciono dos tablas dentro de ApplicationDbContext

modelBuilder.Entity<Telefono>().HasRequired(x => x.IdPersona);


public class AplicationDbContext : DbContext
{
public DbSet<Persona> Personas { get; set; }
public DbSet<Telefono> Telefonos { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Telefono>().HasRequired(x =>
x.IdPersona).WithMany().HasForeignKey(x => x.IdPersona); //relacion de uno a muchos y
crea una columna ejemplo Personas_Id

base.OnModelCreating(modelBuilder);
}
}

var persona = db.Personas.Include(“Telefonos”);

Ver video 56 como referencia nuevamente.

//ENTENDIENDO LAZY LOADING


Se refiere que las propiedades relacionadas estarán a disposición a partir del momento que
deseamos acceder a ellas.

Para que una propiedad sea utilizada por el Lazy Loading debe ser configurada como virtual
por ejemplo:

public virtual List<Telefono> Telefonos {get; set; }

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.

var personas = db.Personas.FirstOrDefault();


var telefonos = personas.Telefonos[0];

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.

var persona = db.Personas.ToList();


var personaJSON = Newtonsoft.Json.JsonConvert.SerializeObject(persona);

//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.

var personasLazy = db.Personas.Take(15000).ToList(); //Take(15000) toma los primeros


15000 registros

foreach (var persona in personasLazy){


var calle = persona.Direcciones[0].Calle; //toma la primera direccion y la primera calle de la
persona
}
Esta consulta demoró 2 minutos con 47 segundos.
El código anteriormente es válido pero es muy lento en su ejecución. A este tipo de query se
le llama ​n+1​ ya que realizo mi primer query y lo almaceno en la variable ​personasLazy ​y
luego ejecuto el código 15000 veces con el foreach.

Para evitar ese problema es importante utilizar Eager Loading y aquí vemos el ejemplo de
código.

var personas = db.Personas.Include(x => x.Direcciones).ToList();

foreach (var persona in personas)


{
var calle = personas.Direcciones[0].Calle;
}

Esta consulta demoró 22 segundos

var horaActual = DateTime.Now; //me da la fecha y hora actual

//HACIENDO Y REVERSANDO MIGRACIONES


Ver video 59 para referencia.

//CREANDO INDICES ASC Y DESC


Para crear un índice solo basta con agregar el atributo [Index] arriba de la propiedad creada.

[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.

public class Persona


{

public int Id { get; set; }


[Index]
public string Nombrep { get; set; }
[Index(“IX_Identificacion_Correo”, Order = 1)]
public int Identificacion { get; set; }
[Index(“IX_Identificacion_Correo”, Order = 2)]
public string Correo { get; set; }
public int Sexo { get; set; }
public DateTime FechaNac { get; set; }
public virtual List<Telefono> Telefonos { get; set; }

}
//API FLUENT CONVENCIONES
Ver video 61 nuevamente.

//API FLUENT RELACIONES


Ver video 62 nuevamente.

//EJEMPLO DATABASE FIRST


Me permite utilizar una base de datos ya creada en mi proyecto. Ver video 63

//PROCEDIMIENTOS ALMACENADOS Y ENTITY FRAMEWORK


Ver video 64 nuevamente

public class NombreEdad


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

var personas = db.Database.SqlQuery<NombreEdad>("sp_Personas_por_Edad @Edad",


new SqlParameter("@Edad", 999)).ToList();

db.Database.ExecuteSqlCommand(RecursosSQL.sp_Borra_Personas_Menores_Nombre);

//PAGINANDO EN ASP.NET CON ENTITY FRAMEWORK


Ver video 65 y 66

//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 se aplique la autorización a todo el controlador simplemente cambio la


posición de ​[Authorize] ​y lo colocó encima de la clase.
namespace Microsoft.AspNet.Identity
{
public static class IdentityExtensions
{
public static string FindFirstValue(this ClaimsIdentity identity, string claimType);
public static T GetUserId<T>(this IIdentity identity) where T : IConvertible;
public static string GetUserId(this IIdentity identity);
public static string GetUserName(this IIdentity identity);
}
}

User.Identity.GetUserName() //muestra el nombre

Primero, para saber el nombre del usuario autenticado podemos usar:

string userName = HttpContext.Current.User.Identity.Name;

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

[Authorize(Users = “ramoncarrasquel844@gmail.com, ramoncarrasquel844.ec@gmail.com”,


Roles = “Administrador”)]

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.

//MANEJANDO USUARIOS Y MEMBRESIAS

Ver video 70 MUY IMPORTANTE


Ver video 78 MUY IMPORTANTE
//LLENAR SELECT DESDE BASE DE DATOS

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

public class Provincia


{
[Key]
public int IdPr { get; set; }
[Required(ErrorMessage = "Este Campo es obligatorio")]
[StringLength(80)]
public string NombrePro { get; set; }
public virtual List<Canton> Cantones { get; set; }
}
public class Canton
{
[Key]
public int IdCa { get; set; }
[Required(ErrorMessage = "Este Campo es obligatorio")]
[StringLength(80)]
public string NombreCan { get; set; }
[Required(ErrorMessage = "Este Campo es obligatorio")]
public virtual Provincia IdProvincia { get; set; }
public virtual List<Parroquia> Parroquias { get; set; }
}

[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);
}

Si revisas la propiedad la defines como

public ​Provincia ​IdProvincia { get; set; }

o sea no es un int

deberias tener mapeada ambas propiedades

public class Canton


{
[Key]
public int IdCa { get; set; }
[StringLength(80)]
public string NombreCan { get; set; }

public int IdProvincia { get; set; }


public Provincia Provincia { get; set; }

public virtual List<Parroquia> Parroquias { get; set; }


}

para poder navegar por la entidad asociada y por también por el id

Sino la otra seria usar

List<Canton> Cantones = db.Cantones.Where(x => x.​Provincia.IdPr​ == provincia);


//BLANQUEAR BASE DE DATOS Y DEVOLVER VALOR CERO CONTADOR LLAVE
PRIMARIA
DELETE FROM dbo.Cantons
DBCC CHECKIDENT ('Optimus.dbo.Cantons',RESEED, 0)

//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;

La clase UserManager no permite gestionar la configuración que tenemos en los usuarios.

Para crear un nuevo usuario debemos de realizar lo siguiente:

using (ApplicationDbContext db = new ApplicationDbContext())


{
var ​userManager ​= new UserManager<ApplicationUser>( new
UserStore<ApplicationUser>(db));

var user = new AplicationUser();


user.UserName = “ramon”;
user.Email = “ramoncarrasquel844@gmail.com”;

var resultado = ​UserManager​.Create(user, “MiPasswordSecreto”);


}

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.

using (ApplicationDbContext db = new ApplicationDbContext())


{
var IdUsuarioActual = User.Identity.GetUserId();

var roleManager = new RoleManager<IdentityRole>(new


RoleStore<IdentityRole>(db)); //instanciamos RoleManager

//crear un rol
var resultado = roleManager.Create( new IdentityRole(“Administrador”));

var ​userManager ​= new UserManager<ApplicationUser>( new


UserStore<ApplicationUser>(db));

//agregar usuario a un rol


resultado = UserManager.AddToRole(IdUsuarioActual, “Administrador”)
//usuario está en rol?
var usuarioEstaEnRol = userManager.IsInRole(IdUsuarioActual, “Administrador”);
var usuarioEstaEnRol2 = userManager.IsInRole(IdUsuarioActual, “Ventas”);

//ver los roles que tiene asignado un usuario


var roles = userManager.GetRoles(IdUsuarioActual);

//remover un rol a un usuario


resultado = userManager.RemoveFromRole(IdUsuarioActual, “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

[Authorize(Roles = “Administrador, Procurador, Abogado, Asistente”)]

//AGREGAR UN COLUMNAS A AspNetUsers

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:

public class ApplicationUser : IdentityUser


{
[StringLength(120)]
public string LugarNacimiento {get; set;}

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.

Si quiero saber desde cualquier lugar el lugar de nacimiento realizo lo siguiente:

if(User.Identity.IsAuthenticated)
{
using (ApplicationDbContext db = new ApplicationDbContext())
{
var IdUsuarioActual = User.Identity.GetUserId();

var ​userManager ​= new UserManager<ApplicationUser>( new


UserStore<ApplicationUser>(db));

var usuario = userManager.FindById(IdUsarioActual);


var lugarNacimiento = usuario.LugarNacimiento;
}

}
//ENCRIPTANDO EL CONNECTIONSTRING
Aprenderemos a encriptar el connection String de un web.config.

Abrir la consola cmd como administrador.

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

//VALIDAR SI LA DATA EXISTE O NO Y REDIRECCIONAR

public ActionResult InformacionCuenta(int id)


{
var cuenta = db.Cuentas.FirstOrDefault(x => x.Id == id);

if(cuenta == null)
{
return RedirectToAction(“Index”);
}

//esto es un simple control de acceso para aplicar


var userId = User.Identity.GetUserId();
if(cuenta.UserId != userId)
{
return RedirectToAction(“Login”, “Account”);
}

return View(cuenta);
}
//CSRF Y ANTIFORGERYTOKEN
Colocar el atributo [ValidateAntiForgeryToken] encima del Action el cual recibirá la información
del formulario

y dentro del formulario @Html.AntiForgeryToken();

[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”);
}

ver video 81 nuevamente

//OPCIONES EXTRAS PARA UN DROPDOWNLIST

● @Html.DropDownList(​"Gender"​, ​new​ List<SelectListItem>


● {
● ​new​ SelectListItem { Text = ​"Male"​,
Value=​"Male"​ },
● ​new​ SelectListItem { Text = ​"Female"​,
Value=​"Female"​ }
● }, ​"Select Gender"​, ​new​ { @​class​ =
"form-control"​ })

//PARA RECIBIR UN ARREGLO DE UN FORMULARIO DINAMICO


var idpersona = formCollection["idpersona"]; //recibo con el formCollection
var tipo = formCollection["tipo"];
var condicion = formCollection["condicion"];
string[] words = idpersona.Split(',');//separo por comas y lo ingreso en un arreglo de tipo string/int
var count = words.Count();

//JOIN MAS DE 2 TABLAS


In your view you are trying to access a ​pd​ property but such property doesn't exist. The
property is called ​ProjectData​.

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:

​ lass​ ​MyViewModel​ { ​public​ ​ProjectData​ ​ProjectData​ { get; ​set​; }


public​ c
public​ P​ roject​ ​Project​ { get; ​set​; } }
and then inside your controller action populate this view model and pass to the view:

public​ ​ActionResult​ ​Index​() { ​var​ viewModel = ​from​ pd ​in​ db.​ProjectsData​ join


p ​in​ db.​Projects​ on pd.​ProjectId​ equals p.ID ​where​ pd.​UserName​ ==
this​.​HttpContext​.​User​.​Identity​.​Name​ ​orderby​ p.​Name​, p.​ProjectNo​ ​select​ ​new
MyViewModel​ { ​ProjectData​ = pd, ​Project​ = p }; ​return​ ​View​(viewModel); }

and finally inside your strongly typed view use the view model:

@model​ ​IEnumerable​<​AppName​.​Models​.​MyViewModel​> ​@foreach​ (​var​ item ​in​ ​Model​) {


<div>@item​.​ProjectData​.​UserName​</div> }

//OBTENER LA RUTA URL


string​ url = ​HttpContext​.​Current​.​Request​.​Url​.​AbsoluteUri​;

// http://localhost:1302/TESTERS/Default6.aspx

string​ path = ​HttpContext​.​Current​.​Request​.​Url​.​AbsolutePath​;

// /TESTERS/Default6.aspx

string​ host = ​HttpContext​.​Current​.​Request​.​Url​.​Host​;

// localhost

Ejemplo href:
<a asp-controller="Generales"
asp-action="Editar"
asp-route-id="@item.Id">@item.CodigoParametro</a>

También podría gustarte