Você está na página 1de 134

asp.

net-mvc

#asp.net-
mvc
Tabla de contenido
Acerca de 1

Capítulo 1: Empezando con asp.net-mvc 2

Observaciones 2

Versiones 2

Examples 3

Hola MVC! 3

Capítulo 2: ActionResult 6

Observaciones 6

Examples 6

Regresar una página de visualización 6

Devolver un archivo 6

Devuelve un json 7

Capítulo 3: ActionResult 8

Examples 8

Ver resultado 8

PartialViewResult 8

RedirectResult 9

RedirectToRouteResult 9

ContentResult 10

JsonResult 10

Capítulo 4: ActionResult 12

Sintaxis 12

Examples 12

Métodos de acción 12

Asignación de parámetros de acción-método 13

Llamando a un ActionResult en otro ActionResult 13

Capítulo 5: Anotaciones de datos 14

Introducción 14

Examples 14

Atributos básicos de validación utilizados en ViewModel 14


Modelo 14

Ver 14

Controlador 15

Validación remota 15

Validación remota utilizada para verificar si el contenido que se ingresa en el control de 15

RequiredAttribute 17

StringLengthAttribute 17

Atributo de rango 18

Atributo de expresión regular 18

Comparar atributo 19

Atributo de validación personalizado 20

Aquí está su DotNetFiddle Demo 21

Modelo EDMx - Anotación de datos 21

Anotaciones de datos para la primera implementación de la base de datos (código de modelo 22

Capítulo 6: Áreas 24

Introducción 24

Observaciones 24

Examples 24

Crear una nueva área 24

Configurar RouteConfig.cs 24

Cree un nuevo controlador y configure areanameAreaRegistration.cs maproute 24

Capítulo 7: Asp.net mvc enviar correo 26

Examples 26

Formulario de contacto en Asp MVC 26

Enviando correo electrónico desde la clase 27

Capítulo 8: Ayudantes html 29

Introducción 29

Examples 29

Ayudante HTML personalizado - Nombre para mostrar 29

Ayudante personalizado - botón Enviar de envío 29

Lista exhaustiva de ejemplos de HtmlHelper que incluye salida HTML 30

HtmlHelper.Action() 30
HtmlHelper.ActionLink() 30

@HtmlHelper.BeginForm() 30

Ayudantes HTML estándar con sus salidas HTML 30

Ayudante personalizado - Botón de radio renderizado con etiqueta 31

Ayudante personalizado - Selector de fecha y hora 32

Capítulo 9: Dockerización de la aplicación ASP.NET 33

Examples 33

Dockerfile y Nuget 33

Soporte POSTGRESQL. 33

Dockerización 34

Capítulo 10: Empaquetado y Minificación 36

Examples 36

Minificación 36

Ejemplo usando minificación 36

Guiones y paquetes de estilo 36

Capítulo 11: Enrutamiento 38

Introducción 38

Examples 38

Enrutamiento personalizado 38

Añadiendo ruta personalizada en mvc 39

Atributo de enrutamiento en MVC 39

Conceptos básicos de enrutamiento 40

Ruta de todo 41

Ruta completa para habilitar el enrutamiento del lado del cliente 42

Atributo de enrutamiento en áreas 42

Capítulo 12: Extensiones Ajax MVC 44

Introducción 44

Parámetros 44

Observaciones 45

Examples 45

Ajax Action Link 45

Formas de Ajax 45
Capítulo 13: Filtros de accion 46

Examples 46

Un filtro de acción de registro. 46

Filtro de acción de Control de sesión - solicitud de página y ajax 46

Ubicaciones de uso del filtro de acción (global, controlador, acción) 47

Atributo de manejador de excepciones 49

Capítulo 14: Html.AntiForgeryToken 51

Introducción 51

Sintaxis 51

Observaciones 51

Precaución 51

Examples 51

Uso básico 51

Maquinilla de afeitar (YourView.cshtml) 51

Controlador (YourController.cs) 52

Deshabilitar el control heurístico de identidad 52

Validando todas las publicaciones 52

Uso anticipado: aplique el filtro antiforgery predeterminado para cada POST 54

Uso de AntiForgeryToken con la solicitud de Ajax de Jquery 55

Capítulo 15: Html.RouteLink 56

Parámetros 56

Examples 56

Ejemplo básico usando el texto de enlace y el nombre de la ruta 56

Capítulo 16: Inyección de dependencia 57

Observaciones 57

Examples 58

Configuraciones de Ninject 58

Utilización de las interfaces. 59

Inyección de dependencia del constructor 60

Dependencia codificada 60

parámetro DI 60

Inyección De la Dependencia De Ninject 60


Capítulo 17: jQuery Ajax Call Con Asp MVC 65

Examples 65

Publicar objetos JavaScript con jQuery Ajax Call 65

Capítulo 18: Manejo de errores Http 67

Introducción 67

Examples 67

Configuración básica 67

Capítulo 19: Maquinilla de afeitar 69

Introducción 69

Sintaxis 69

Observaciones 69

Examples 69

Añadir comentarios 69

Mostrar HTML dentro del bloque de código Razor 70

Sintaxis basica 71

Escapando a @ personaje 72

Crear clases y métodos en línea usando funciones @ 72

Agregando un atributo personalizado con - (guión) en el nombre 73

Plantillas de editor 73

Pase el contenido de Razor a un @helper 75

Compartir @helpers a través de vistas 75

Capítulo 20: Modelo de enlace 77

Introducción 77

Observaciones 77

Examples 77

Enlace de valor de ruta 77

Enlace de cadena de consulta 77

Atadura a objetos 78

Ajax vinculante 78

Generic, enlace basado en modelo de sesión 78

Prevenir el enlace en PostModel 80

Subir archivo 81
Validación de campos de fecha manualmente con formatos dinámicos utilizando el cuaderno de 81

Capítulo 21: Modelo de validación 83

Examples 83

Validar modelo en ActionResult 83

Eliminar un objeto de la validación 83

Mensajes de error personalizados 84

Creando mensajes de error personalizados en el modelo y en el controlador 84

Validación de modelos en JQuery. 85

Capítulo 22: MVC vs Formularios Web 87

Introducción 87

Sintaxis 87

Observaciones 87

Examples 87

Ventajas de los formularios web ASP .NET 87

Ventajas de una aplicación web basada en MVC 88

Desventajas 88

Razor View Engine VS ASPX View Engine 88

Capítulo 23: Operación CRUD 90

Introducción 90

Observaciones 90

Examples 90

Crear - Parte del controlador 90

Crear - Ver parte 91

Detalles - parte del controlador 92

Detalles - Ver parte 93

Editar - parte del controlador 94

Eliminar - parte del controlador 95

Capítulo 24: Plantillas de visualización y editor 97

Introducción 97

Examples 97

Plantilla de pantalla 97

Plantilla de editor 98
Capítulo 25: Registro de errores 101

Examples 101

Atributo simple 101

devolviendo página de error personalizada 101

Cree un ErrorLogger personalizado en ASP.Net MVC 102

Capítulo 26: Reglas de reescritura de IIS 105

Examples 105

Forzar HTTPS usando la regla de reescritura 105

Capítulo 27: T4MVC 106

Introducción 106

Examples 106

Llamando a una acción 106

Capítulo 28: Usando múltiples modelos en una vista 109

Introducción 109

Examples 109

Uso de múltiples modelos en una vista con ExpandoObject dinámico 109

Capítulo 29: Validación automática del lado del cliente a partir de atributos 112

Observaciones 112

Examples 112

Modelo 112

configuración de web.config 112

Paquetes Nuget Requeridos 112

Vista de formulario 112

Configuración del paquete 113

Global.asax.cs 114

Capítulo 30: ViewData, ViewBag, TempData 115

Introducción 115

Sintaxis 115

Examples 115

¿Qué son ViewData, ViewBag y TempData? 115

Ciclo de vida de TempData 117


Capítulo 31: Vistas parciales 119

Introducción 119

Sintaxis 119

Examples 119

Vista parcial con modelo. 119

Vista parcial a una cadena - para contenido de correo electrónico, etc. 119

Html.Partial Vs Html.RenderPartial 120

Capítulo 32: Web.config cifrado 122

Examples 122

Cómo proteger su archivo web.config 122

Creditos 123
Acerca de
You can share this PDF with anyone you feel could benefit from it, downloaded the latest version
from: asp-net-mvc

It is an unofficial and free asp.net-mvc ebook created for educational purposes. All the content is
extracted from Stack Overflow Documentation, which is written by many hardworking individuals at
Stack Overflow. It is neither affiliated with Stack Overflow nor official asp.net-mvc.

The content is released under Creative Commons BY-SA, and the list of contributors to each
chapter are provided in the credits section at the end of this book. Images may be copyright of
their respective owners unless otherwise specified. All trademarks and registered trademarks are
the property of their respective company owners.

Use the content presented in this book at your own risk; it is not guaranteed to be correct nor
accurate, please send your feedback and corrections to info@zzzprojects.com

https://riptutorial.com/es/home 1
Capítulo 1: Empezando con asp.net-mvc
Observaciones
El patrón arquitectónico Modelo-Vista-Controlador (MVC) separa una aplicación en tres
componentes principales: el modelo, la vista y el controlador. El marco MVC de ASP.NET
proporciona una alternativa al patrón de formularios web de ASP.NET para crear aplicaciones
web. El marco de ASP.NET MVC es un marco de presentación ligero y altamente comprobable
que (al igual que con las aplicaciones basadas en Web Forms) se integra con las características
existentes de ASP.NET, como las páginas maestras y la autenticación basada en membresía. El
marco MVC se define en el ensamblado System.Web.Mvc.

El marco MVC incluye los siguientes componentes:

• Modelos Los objetos modelo son las partes de la aplicación que implementan la lógica para
el dominio de datos de la aplicación. A menudo, los objetos del modelo recuperan y
almacenan el estado del modelo en una base de datos. Por ejemplo, un objeto Producto
podría recuperar información de una base de datos, operar en ella y luego escribir
información actualizada en una tabla de Productos en una base de datos de SQL Server. En
aplicaciones pequeñas, el modelo es a menudo una separación conceptual en lugar de una
física. Por ejemplo, si la aplicación solo lee un conjunto de datos y lo envía a la vista, la
aplicación no tiene una capa de modelo físico y clases asociadas. En ese caso, el conjunto
de datos asume el rol de un objeto modelo.
• Vistas . Las vistas son los componentes que muestran la interfaz de usuario (UI) de la
aplicación. Normalmente, esta IU se crea a partir de los datos del modelo. Un ejemplo sería
una vista de edición de una tabla de Productos que muestra cuadros de texto, listas
desplegables y cuadros de verificación según el estado actual de un objeto Producto.
• Controladores Los controladores son los componentes que controlan la interacción del
usuario, trabajan con el modelo y, en última instancia, seleccionan una vista para
representar que muestra la interfaz de usuario. En una aplicación MVC, la vista solo
muestra información; El controlador maneja y responde a la entrada e interacción del
usuario. Por ejemplo, el controlador maneja los valores de cadena de consulta y pasa estos
valores al modelo, que a su vez podría usar estos valores para consultar la base de datos.

Versiones

Versión Versión .NET Fecha de lanzamiento

MVC 1.0 .NET 3.5 2009-03-13

MVC 2.0 .NET 3.5 / 4.0 2010-03-10

MVC 3.0 .NET 4.0 2011-01-13

MVC 4.0 .NET 4.0 / 4.5 2012-08-15

https://riptutorial.com/es/home 2
Versión Versión .NET Fecha de lanzamiento

MVC 5.0 .NET 4.5 2013-10-17

MVC 5.1 .NET 4.5 2014-01-17

MVC 5.2 .NET 4.5 2014-08-28

MVC 6.0 .NET 4.5 2015-11-18

Core MVC 1.0 .NET 4.5 2016-07-12

Core MVC 1.1 .NET 4.5 2016-11-18

Examples
Hola MVC!

ASP.NET MVC es un framework de aplicaciones web de código abierto. MVC en sí es un patrón


de diseño que se basa en tres componentes principales: model-view-controller .

Modelo : los modelos reflejan los objetos de su negocio y son un medio para pasar datos entre
controladores y vistas.

Vista : las vistas son las páginas que representan y muestran los datos del modelo al usuario. Las
vistas de ASP.NET MVC se escriben normalmente utilizando la sintaxis de Razor.

Controlador : los controladores manejan las solicitudes HTTP entrantes de un cliente y, por lo
general, devuelven uno o más modelos a una vista apropiada.

Las características de ASP.NET MVC:

1. Ideal para desarrollar aplicaciones complejas pero ligeras.


2. Proporciona un marco extensible y conectable que se puede reemplazar y personalizar
fácilmente. Por ejemplo, si no desea utilizar el motor de visualización Razor o ASPX
integrado, puede utilizar cualquier otro motor de visualización de terceros o incluso
personalizar los existentes.
3. Utiliza el diseño basado en componentes de la aplicación al dividirla lógicamente en los
componentes Modelo, Vista y Controlador. Esto permite a los desarrolladores gestionar la
complejidad de los proyectos a gran escala y trabajar en componentes individuales.
4. La estructura MVC mejora el desarrollo basado en pruebas y la capacidad de prueba de la
aplicación, ya que todos los componentes pueden diseñarse en función de la interfaz y
probarse utilizando objetos simulados. Por lo tanto, ASP.NET MVC Framework es ideal para
proyectos con un gran equipo de desarrolladores web.
5. Admite todas las funciones vastas de ASP.NET, como Autorización y autenticación, Páginas
maestras, Enlace de datos, Controles de usuario, Membresías, Enrutamiento de ASP.NET,
etc.
6. No utiliza el concepto de estado de vista (que está presente en ASP.NET). Esto ayuda en la

https://riptutorial.com/es/home 3
creación de aplicaciones que son ligeras y dan control total a los desarrolladores.

Aplicación MVC simple

Vamos a crear una aplicación MVC simple que muestra detalles personales. Crea un nuevo
proyecto MVC usando Visual Studio. Agregue un nuevo modelo llamado Person a la carpeta de
modelos como sigue:

public class Person


{
public string Surname { get; set; }
public string FirstName { get; set; }
public string Patronymic { get; set; }
public DateTime BirthDate { get; set; }
}

Agregar un nuevo controlador a la carpeta Controladores:

public class HomeController : Controller


{
//Action Method
public ActionResult Index()
{
// Initialize model
Person person = new Person
{
Surname = "Person_SURNAME",
FirstName = "Person_FIRSTNAME",
Patronymic = "Person_PATRONYMIC",
BirthDate = new DateTime(1990, 1, 1)
};

// Send model to View for displaying to user


return View(person);
}
}

Finalmente, agregue Ver a / Vistas / Inicio / carpeta llamada Index.cshtml :

@* Model for this view is Person *@


@model Hello_MVC.Models.Person

<h2>Hello @Model.FirstName !</h2>

<div>
<h5>Details:</h5>
<div>
@Html.LabelFor(m => m.Surname)
@Html.DisplayFor(m => m.Surname)
</div>
<div>
@Html.LabelFor(m => m.FirstName)
@Html.DisplayFor(m => m.FirstName)
</div>
<div>
@Html.LabelFor(m => m.Patronymic)
@Html.DisplayFor(m => m.Patronymic)

https://riptutorial.com/es/home 4
</div>
<div>
@Html.LabelFor(m => m.BirthDate)
@Html.DisplayFor(m => m.BirthDate)
</div>
</div>

Lea Empezando con asp.net-mvc en línea: https://riptutorial.com/es/asp-net-


mvc/topic/769/empezando-con-asp-net-mvc

https://riptutorial.com/es/home 5
Capítulo 2: ActionResult
Observaciones
Un ActionResult es el mejor punto de vista como un punto final web en MVC. Se puede acceder al
método Ever ActionResult escribiendo la dirección web adecuada según lo configurado por su
motor de enrutamiento.

Examples
Regresar una página de visualización

Este ActionResult devuelve una página de vista de Razor. Bajo la plantilla de enrutamiento
estándar, este método ActionResult se alcanzaría en http: // localhost / about / me

La vista se buscará automáticamente en su sitio en ~/Views/About/Me.cshtml

public class AboutController : Controller


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

Devolver un archivo

Un ActionResult puede devolver FileContentResult especificando la ruta del archivo y el tipo de


archivo según la definición de extensión, conocido como tipo MIME.

El tipo MIME se puede configurar automáticamente según el tipo de archivo usando el método
GetMimeMapping , o se puede definir manualmente en el formato adecuado, por ejemplo, "texto /
plano".

Como FileContentResult requiere que se FileContentResult una matriz de bytes como una
secuencia de archivos, System.IO.File.ReadAllBytes se puede usar para leer el contenido de los
archivos como una matriz de bytes antes de enviar el archivo solicitado.

public class FileController : Controller


{
public ActionResult DownloadFile(String fileName)
{
String file = Server.MapPath("~/ParentDir/ChildDir" + fileName);
String mimeType = MimeMapping.GetMimeMapping(path);

byte[] stream = System.IO.File.ReadAllBytes(file);


return File(stream, mimeType);
}
}

https://riptutorial.com/es/home 6
Devuelve un json

El resultado de la acción puede devolver Json.

1. Devolviendo a Json para transmitir json en ActionResult

public class HomeController : Controller


{
public ActionResult HelloJson()
{
return Json(new {message1="Hello", message2 ="World"});
}
}

2. Devolver contenido para transmitir json en ActionResult

public class HomeController : Controller


{
public ActionResult HelloJson()
{
return Content("Hello World", "application/json");
}
}

Lea ActionResult en línea: https://riptutorial.com/es/asp-net-mvc/topic/6246/actionresult

https://riptutorial.com/es/home 7
Capítulo 3: ActionResult
Examples
Ver resultado

public ActionResult Index()


{
// Renders a view as a Web page.
return View();
}

Los métodos de acción generalmente devuelven un resultado que se conoce como un resultado
de acción. La clase ActionResult es la clase base para todos los resultados de acción. El
ActionInvoker decide qué tipo de resultado de acción devolver según la tarea que realiza el
método de acción.

Es posible ser explícito sobre qué tipo devolver, pero generalmente no es necesario.

public ViewResult Index()


{
// Renders a view as a Web page.
return View();
}

PartialViewResult

public ActionResult PopulateFoods()


{
IEnumerable<Food> foodList = GetAll();

// Renders a partial view, which defines a section of a view that can be rendered inside
another view.
return PartialView("_foodTable", foodVms);;
}

Los métodos de acción generalmente devuelven un resultado que se conoce como un resultado
de acción. La clase ActionResult es la clase base para todos los resultados de acción. El
ActionInvoker decide qué tipo de resultado de acción devolver según la tarea que realiza el
método de acción.

Es posible ser explícito sobre qué tipo devolver, pero generalmente no es necesario.

public PartialViewResult PopulateFoods()


{
IEnumerable<Food> foodList = GetAll();

// Renders a partial view, which defines a section of a view that can be rendered inside
another view.

https://riptutorial.com/es/home 8
return PartialView("_foodTable", foodVms);
}

RedirectResult

public ActionResult Index()


{
//Redirects to another action method by using its URL.
return new RedirectResult("http://www.google.com");
}

Los métodos de acción generalmente devuelven un resultado que se conoce como un resultado
de acción. La clase ActionResult es la clase base para todos los resultados de acción. El
ActionInvoker decide qué tipo de resultado de acción devolver según la tarea que realiza el
método de acción.

Es posible ser explícito sobre qué tipo devolver, pero generalmente no es necesario.

public RedirectResult Index()


{
//Redirects to another action method by using its URL.
return new RedirectResult("http://www.google.com");
}

RedirectToRouteResult

public ActionResult PopulateFoods()


{
// Redirects to another action method. In this case the index method
return RedirectToAction("Index");
}

Los métodos de acción generalmente devuelven un resultado que se conoce como un resultado
de acción. La clase ActionResult es la clase base para todos los resultados de acción. El
ActionInvoker decide qué tipo de resultado de acción devolver según la tarea que realiza el
método de acción.

Es posible ser explícito sobre qué tipo devolver, pero generalmente no es necesario.

public RedirectToRouteResult PopulateFoods()


{
// Redirects to another action method. In this case the index method
return RedirectToAction("Index");
}

En caso de que desee redirigir a otra acción con un parámetro, puede usar la sobrecarga
RedirectToAction :

public ActionResult SomeActionWithParameterFromThisController(string parameterName)


{
// Some logic

https://riptutorial.com/es/home 9
}
.....................
.....................
.....................
return RedirectToAction("SomeActionWithParameterFromThisController", new { parameterName =
parameter });

ContentResult

public ActionResult Hello()


{
// Returns a user-defined content type, in this case a string.
return Content("hello world!");
}

Los métodos de acción generalmente devuelven un resultado que se conoce como un resultado
de acción. La clase ActionResult es la clase base para todos los resultados de acción. El
ActionInvoker decide qué tipo de resultado de acción devolver según la tarea que realiza el
método de acción.

Es posible ser explícito sobre qué tipo devolver, pero generalmente no es necesario.

public ContentResult Hello()


{
// Returns a user-defined content type, in this case a string.
return Content("hello world!");
}

Puede saber más sobre esto aquí: Asp.Net Mvc: ContentResult vs. string

JsonResult

public ActionResult LoadPage()


{
Student result = getFirst();

//Returns a serialized JSON object.


return Json(result, JsonRequestBehavior.AllowGet);
}

Los métodos de acción generalmente devuelven un resultado que se conoce como un resultado
de acción. La clase ActionResult es la clase base para todos los resultados de acción. El
ActionInvoker decide qué tipo de resultado de acción devolver según la tarea que realiza el
método de acción.

Es posible ser explícito sobre qué tipo devolver, pero generalmente no es necesario.

public JsonResult LoadPage()


{
Student result = getFirst();

//Returns a serialized JSON object.

https://riptutorial.com/es/home 10
return Json(result, JsonRequestBehavior.AllowGet);
}

Lea ActionResult en línea: https://riptutorial.com/es/asp-net-mvc/topic/6487/actionresult

https://riptutorial.com/es/home 11
Capítulo 4: ActionResult
Sintaxis
• // 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.

Examples
Métodos de acción

Cuando el usuario ingresa una URL, por ejemplo: http://example-


website.com/Example/HelloWorld , la aplicación MVC usará las reglas de enrutamiento para
analizar esta URL y extraer la ruta secundaria, que determinará el controlador, la acción y los
posibles parámetros. Para la url anterior, el resultado será / Example / HelloWorld, que, de
manera predeterminada, los resultados de las reglas de enrutamiento proporcionan el nombre del
controlador: Ejemplo y el nombre de la acción: HelloWorld.

public class ExampleController: Controller


{
public ActionResult HelloWorld()
{

https://riptutorial.com/es/home 12
ViewData["ExampleData"] = "Hello world!";
return View();
}
}

El método ActionResult anterior "HelloWorld" representará la vista llamada HelloWorld, donde


luego podemos usar los datos de ViewData.

Asignación de parámetros de acción-método

Si hubiera otro valor en la URL como: / Example / ProcessInput / 2, las reglas de enrutamiento
amenazarán el último número como un parámetro pasado a la acción ProcessInput del
controlador Ejemplo.

public ActionResult ProcessInput(int number)


{
ViewData["OutputMessage"] = string.format("The number you entered is: {0}", number);
return View();
}

Llamando a un ActionResult en otro ActionResult

Podemos llamar a un resultado de acción en otro resultado de acción.

public ActionResult Action1()


{
ViewData["OutputMessage"] = "Hello World";
return RedirectToAction("Action2","ControllerName");
//this will go to second action;
}

public ActionResult Action2()


{
return View();
//this will go to Action2.cshtml as default;
}

Lea ActionResult en línea: https://riptutorial.com/es/asp-net-mvc/topic/6635/actionresult

https://riptutorial.com/es/home 13
Capítulo 5: Anotaciones de datos
Introducción
Podemos agregar validaciones a nuestra aplicación al agregar Anotaciones de datos a nuestras
clases modelo. Las anotaciones de datos nos permiten describir las reglas que queremos que se
apliquen a las propiedades de nuestro modelo, y ASP.NET MVC se encargará de hacerlas
cumplir y mostrar los mensajes apropiados a los usuarios.

Examples
Atributos básicos de validación utilizados en ViewModel

Modelo

using System.ComponentModel.DataAnnotations;

public class ViewModel


{
[Required(ErrorMessage="Name is required")]
public string Name { get; set; }

[StringLength(14, MinimumLength = 14, ErrorMessage = "Invalid Phone Number")]


[Required(ErrorMessage="Phone Number is required")]
public string PhoneNo { get; set; }

[Range(typeof(decimal), "0", "150")]


public decimal? Age { get; set; }

[RegularExpression(@"^\d{5}(-\d{4})?$", ErrorMessage = "Invalid Zip Code.")]


public string ZipCode {get;set;}

[EmailAddress(ErrorMessage = "Invalid Email Address")]


public string Email { get; set; }

[Editable(false)]
public string Address{ get; set; }
}

Ver

// Include Jquery and Unobstructive Js here for client side validation

@using (Html.BeginForm("Index","Home") {

@Html.TextBoxFor(model => model.Name)


@Html.ValidationMessageFor(model => model.Name)

@Html.TextBoxFor(model => model.PhoneNo)


@Html.ValidationMessageFor(model => model.PhoneNo)

https://riptutorial.com/es/home 14
@Html.TextBoxFor(model => model.Age)
@Html.ValidationMessageFor(model => model.Age)

@Html.TextBoxFor(model => model.ZipCode)


@Html.ValidationMessageFor(model => model.ZipCode)

@Html.TextBoxFor(model => model.Email)


@Html.ValidationMessageFor(model => model.Email)

@Html.TextBoxFor(model => model.Address)


@Html.ValidationMessageFor(model => model.Address)

<input type="submit" value="submit" />


}

Controlador

public ActionResult Index(ViewModel _Model)


{
// Checking whether the Form posted is valid one.
if(ModelState.IsValid)
{
// your model is valid here.
// perform any actions you need to, like database actions,
// and/or redirecting to other controllers and actions.
}
else
{
// redirect to same action
return View(_Model);
}
}

Validación remota

Validación remota utilizada para verificar si el contenido que


se ingresa en el control de entrada es válido o no, enviando
una solicitud ajax al lado del servidor para verificarlo.
Trabajando

RemoteAttribute funciona al realizar una llamada AJAX desde el cliente a una acción del
controlador con el valor del campo que se está validando. La acción del controlador luego
devuelve una respuesta JsonResult indica el éxito o el fracaso de la validación. Devolviendo true
de su acción indica que la validación pasó. Cualquier otro valor indica falla. Si devuelve false , se
utiliza el mensaje de error especificado en el atributo. Si devuelve algo más, como una cadena o
incluso un entero, se mostrará como el mensaje de error. A menos que necesite que su mensaje
de error sea dinámico, tiene sentido devolver verdadero o falso y dejar que el validador use el
mensaje de error especificado en el atributo.

https://riptutorial.com/es/home 15
ViewModel

public class ViewModel


{
[Remote("IsEmailAvailable", "Group", HttpMethod = "POST", ErrorMessage = "Email already
exists. Please enter a different email address.")]
public string Email{ get; set; }
}

Controlador

[HttpPost]
public JsonResult IsEmailAvailable(string Email)
{
// Logic to check whether email is already registered or Not.
var emailExists = IsEmailRegistered();
return Json(!emailExists);
}

Live Demo Fiddle

Puede pasar propiedades adicionales del modelo al método del controlador utilizando la
propiedad AdditionalFields de RemoteAttribute . Un escenario típico sería pasar la propiedad de ID
del modelo en forma de 'Editar', de modo que la lógica del controlador pueda ignorar los valores
del registro existente.

Modelo

public int? ID { get; set; }


[Display(Name = "Email address")]
[DataType(DataType.EmailAddress)]
[Required(ErrorMessage = "Please enter you email address")]
[Remote("IsEmailAvailable", HttpMethod="Post", AdditionalFields="ID", ErrorMessage = "Email
already exists. Please enter a different email address.")]
public string Email { get; set; }

Controlador

[HttpPost]
public ActionResult Validate(string email, int? id)
{
if (id.HasValue)
{
return Json(!db.Users.Any(x => x.Email == email && x.ID != id);
}
else
{
return Json(!db.Users.Any(x => x.Email == email);
}
}

Demostración de trabajo - Campos adicionales

Nota adicional

https://riptutorial.com/es/home 16
El mensaje de error predeterminado es comprensiblemente vago, por lo que siempre recuerde
anular el mensaje de error predeterminado cuando use el RemoteAttribute .

RequiredAttribute

El atributo Required especifica que una propiedad es requerida. Se puede especificar un mensaje
de error al usar la propiedad ErrorMessage en el atributo.

Primero agregue el espacio de nombres:

using System.ComponentModel.DataAnnotations;

Y aplicar el atributo en una propiedad.

public class Product


{
[Required(ErrorMessage = "The product name is required.")]
public string Name { get; set; }

[Required(ErrorMessage = "The product description is required.")]


public string Description { get; set; }
}

También es posible utilizar recursos en el mensaje de error para aplicaciones globalizadas. En


este caso, el ErrorMessageResourceName debe especificarse con la clave de recurso de la clase de
recurso (archivo resx ) que debe ErrorMessageResourceType en el ErrorMessageResourceType :

public class Product


{
[Required(ErrorMessageResourceName = "ProductNameRequired",
ErrorMessageResourceType = typeof(ResourceClass))]
public string Name { get; set; }

[Required(ErrorMessageResourceName = "ProductDescriptionRequired",
ErrorMessageResourceType = typeof(ResourceClass))]
public string Description { get; set; }
}

StringLengthAttribute

El atributo StringLength especifica la longitud mínima y máxima de los caracteres permitidos en un


campo de datos. Este atributo se puede aplicar en propiedades, campos públicos y parámetros.
El mensaje de error se debe especificar en la propiedad ErrorMessage en el atributo. Las
propiedades MinimumLength y MaximumLength especifican el mínimo y el máximo respectivamente.

Primero agregue el espacio de nombres:

using System.ComponentModel.DataAnnotations;

Y aplicar el atributo en una propiedad.

https://riptutorial.com/es/home 17
public class User
{
// set the maximum
[StringLength(20, ErrorMessage = "The username cannot exceed 20 characters. ")]
public string Username { get; set; }

[StringLength(MinimumLength = 3, MaximumLength = 16, ErrorMessage = "The password must have


between 3 and 16 characters.")]
public string Password { get; set; }
}

También es posible utilizar recursos en el mensaje de error para aplicaciones globalizadas. En


este caso, el ErrorMessageResourceName debe especificarse con la clave de recurso de la clase de
recurso (archivo resx ) que debe ErrorMessageResourceType en el ErrorMessageResourceType :

public class User


{
[StringLength(20, ErrorMessageResourceName = "StringLength",
ErrorMessageResourceType = typeof(ResoucesKeys))]
public string Username { get; set; }

[StringLength(MinimumLength = 3,
MaximumLength = 16,
ErrorMessageResourceName = "StringLength",
ErrorMessageResourceType = typeof(ResoucesKeys))]
public string Password { get; set; }
}

Atributo de rango

El atributo Range puede decorar cualquier propiedad o campo público y especifica un rango en el
que un campo numérico debe estar entre para ser considerado válido.

[Range(minimumValue, maximumValue)]
public int Property { get; set; }

Además, acepta una propiedad opcional ErrorMessage que se puede usar para configurar el
mensaje recibido por el usuario cuando se ingresan datos no válidos:

[Range(minimumValue, maximumValue, ErrorMessage = "{your-error-message}")]


public int Property { get; set; }

Ejemplo

[Range(1,100, ErrorMessage = "Ranking must be between 1 and 100.")]


public int Ranking { get; set; }

Atributo de expresión regular

El atributo [RegularExpression] puede decorar cualquier propiedad o campo público y especifica


una expresión regular que debe coincidir para que la propiedad se considere válida.

https://riptutorial.com/es/home 18
[RegularExpression(validationExpression)]
public string Property { get; set; }

Además, acepta una propiedad opcional ErrorMessage que se puede usar para configurar el
mensaje recibido por el usuario cuando se ingresan datos no válidos:

[RegularExpression(validationExpression, ErrorMessage = "{your-error-message}")]


public string Property { get; set; }

Ejemplo (s)

[RegularExpression(@"^[a-z]{8,16}?$", ErrorMessage = "A User Name must consist of 8-16


lowercase letters")]
public string UserName{ get; set; }
[RegularExpression(@"^\d{5}(-\d{4})?$", ErrorMessage = "Please enter a valid ZIP Code (e.g.
12345, 12345-1234)")]
public string ZipCode { get; set; }

Comparar atributo

El atributo de Compare compara dos propiedades de un modelo.

El mensaje de error se puede especificar usando la propiedad ErrorMessage o usando archivos de


recursos.

Para usar el atributo Compare incluya using para el siguiente espacio de nombres:

using System.ComponentModel.DataAnnotations;

Luego puedes usar el atributo en tu modelo:

public class RegisterModel


{
public string Email { get; set; }

[Compare("Email", ErrorMessage = "The Email and Confirm Email fields do not match.")]
public string ConfirmEmail { get; set; }
}

Cuando se valida este modelo, si Email y ConfirmEmail tienen valores diferentes, la validación
fallará.

Mensajes de error localizados

Al igual que con todos los atributos de validación, es posible usar mensajes de error de archivos
de recursos. En este ejemplo, el mensaje de error se cargará desde los recursos del archivo de
Resources , el nombre del recurso es CompareValidationMessage :

public class RegisterModel


{
public string Email { get; set; }

https://riptutorial.com/es/home 19
["Email", ErrorMessageResourceType = typeof(Resources), ErrorMessageResourceName =
"CompareValidationMessage")]
public string ConfirmEmail { get; set; }
}

Evitar cadenas en nombres de propiedades

Para evitar utilizar la cadena para el valor de la propiedad, en C # 6+ puede usar la palabra clave
nameof :

public class RegisterModel


{
public string Email { get; set; }

[Compare(nameof(Email), ErrorMessage = "The Email and Confirm Email fields do not


match.")]
public string ConfirmEmail { get; set; }
}

Marcadores de posición en mensajes de error

Puede utilizar marcadores de posición en sus mensajes de error. El marcador de posición {0} se
reemplaza con el nombre de visualización de la propiedad actual y {1} se reemplaza con el
nombre de visualización de la propiedad relacionada:

public class RegisterModel


{
[Display(Name = "Email")]
public string Email { get; set; }

[Display(Name = "Confirm Email")]


[Compare("Email", ErrorMessage = "The '{1}' and '{0}' fields do not match.")]
public string ConfirmEmail { get; set; }
}

Si la validación del modelo falla, el mensaje de error será

Los campos 'Correo electrónico' y 'Confirmar correo electrónico' no coinciden.

Atributo de validación personalizado

Cuando se trata de validar algunas reglas que no son validación de datos genéricos, por ejemplo,
asegurarse de que se requiere un campo o algún rango de valores, pero que son específicos para
su lógica de negocios, puede crear su propio Validador personalizado . Para crear un atributo
de validación personalizado, solo necesita inherit clase ValidationAttribute y override su método
IsValid . El método IsValid toma dos parámetros, el primero es un object denominado como value
y el segundo es un ValidationContext object llamado validationContext . Value refiere al valor real
del campo que va a validar su validador personalizado.

Supongamos que desea validar el Email través de un Custom Validator

https://riptutorial.com/es/home 20
public class MyCustomValidator : ValidationAttribute
{
private static string myEmail= "admin@dotnetfiddle.net";

protected override ValidationResult IsValid(object value, ValidationContext


validationContext)
{
string Email = value.ToString();
if(myEmail.Equals(Email))
return new ValidationResult("Email Already Exist");
return ValidationResult.Success;
}
}

public class SampleViewModel


{
[MyCustomValidator]
[Required]
public string Email { get; set; }

public string Name { get; set; }


}

Aquí está su DotNetFiddle Demo

Modelo EDMx - Anotación de datos

Edmx modelo internel

public partial class ItemRequest


{
public int RequestId { get; set; }
//...
}

Agregando anotación de datos a esto: si modificamos este modelo directamente, cuando se


realiza una actualización del modelo, los cambios se pierden. asi que

Para agregar un atributo en este caso 'Requerido'

Crear una nueva clase - cualquier nombre Entonces

using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

//make sure the namespace is equal to the other partial class ItemRequest
namespace MvcApplication1.Models
{
[MetadataType(typeof(ItemRequestMetaData))]
public partial class ItemRequest
{
}

public class ItemRequestMetaData


{
[Required]

https://riptutorial.com/es/home 21
public int RequestId {get;set;}

//...
}
}

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

namespace YourApplication.Models
{
public interface IEntityMetadata
{
[Required]
Int32 Id { get; set; }
}

[MetadataType(typeof(IEntityMetadata))]
public partial class Entity : IEntityMetadata
{
/* Id property has already existed in the mapped class */
}
}

Anotaciones de datos para la primera implementación de la base de datos


(código de modelo generado automáticamente)

[MetadataType(typeof(RoleMetaData))]
public partial class ROLE
{
}

public class RoleMetaData


{
[Display(Name = "Role")]
public string ROLE_DESCRIPTION { get; set; }

[Display(Name = "Username")]
public string ROLE_USERNAME { get; set; }
}

Si utilizó la base de datos primero y su código de modelo se generó automáticamente, este


mensaje aparecerá sobre su código de modelo:

Este código fue generado a partir de una plantilla. Los cambios manuales en este
archivo pueden causar un comportamiento inesperado en su aplicación. Los cambios
manuales en este archivo se sobrescribirán si el código se regenera

Si desea usar anotaciones de datos y no desea que se sobrescriban si actualiza el edmx,


simplemente agregue otra clase parcial a su carpeta modelo que se parece al ejemplo anterior.

Lea Anotaciones de datos en línea: https://riptutorial.com/es/asp-net-mvc/topic/1961/anotaciones-

https://riptutorial.com/es/home 22
de-datos

https://riptutorial.com/es/home 23
Capítulo 6: Áreas
Introducción
¿Qué es el área?

Un área es una unidad más pequeña en la aplicación MVC que se utiliza como una forma de
separar una gran cantidad de módulos de aplicaciones en grupos funcionales. Una aplicación
puede contener múltiples áreas que se almacenan en la carpeta Áreas.

Cada área puede contener diferentes modelos, controladores y vistas según los requisitos. Para
usar un área, es necesario registrar el nombre del área en RouteConfig y definir el prefijo de la ruta.

Observaciones
Si quieres ir a esta área a través de tu controlador predeterminado

return RedirectToAction("Index","Home",new{area="areaname"});

Examples
Crear una nueva área

Haga clic derecho en la carpeta / nombre de su proyecto y cree un área nueva y asígnele un
nombre.

En la aplicación mvc internet / empty / basic se creará una carpeta con el nombre del área, que
contendrá tres carpetas diferentes llamadas controlador, modelo y vistas y un archivo de clase
llamado

" areaname AreaRegistration.cs"

Configurar RouteConfig.cs

En su carpeta App_start abra routeconfig.cs y haga esto

routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional
},
namespaces:new []{"nameofyourproject.Controllers"}// add this line ;
);

Cree un nuevo controlador y configure areanameAreaRegistration.cs

https://riptutorial.com/es/home 24
maproute

Crear un nuevo controlador foreg

ControllerName: "Home", ActionresultName: "Index"

abra AreaRegistraion.cs y agregue el nombre del controlador y el nombre de la acción que se


redireccionará a

context.MapRoute(
"nameofarea_default",
"nameofarea/{controller}/{action}/{id}", // url shown will be like this in
browser
new {controller="Home", action = "Index", id = UrlParameter.Optional }
);

Lea Áreas en línea: https://riptutorial.com/es/asp-net-mvc/topic/6310/areas

https://riptutorial.com/es/home 25
Capítulo 7: Asp.net mvc enviar correo
Examples
Formulario de contacto en Asp MVC

1. Modelo:

public class ContactModel


{
[Required, Display(Name="Sender Name")]
public string SenderName { get; set; }
[Required, Display(Name = "Sender Email"), EmailAddress]
public string SenderEmail { get; set; }
[Required]
public string Message { get; set; }
}

2. Controlador:

public class HomeController


{
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Contact(ContectModel model)
{
if (ModelState.IsValid)
{
var mail = new MailMessage();
mail.To.Add(new MailAddress(model.SenderEmail));
mail.Subject = "Your Email Subject";
mail.Body = string.Format("<p>Email From: {0} ({1})</p><p>Message:</p><p>{2}</p>",
model.SenderName, mail.SenderEmail, model.Message);
mail.IsBodyHtml = true;
using (var smtp = new SmtpClient())
{
await smtp.SendMailAsync(mail);
return RedirectToAction("SuccessMessage");
}
}
return View(model);
}

public ActionResult SuccessMessage()


{
return View();
}

3. Web.Config:

<system.net>
<mailSettings>

https://riptutorial.com/es/home 26
<smtp from="you@outlook.com">
<network host="smtp-mail.outlook.com"
port="587"
userName="you@outlook.com"
password="password"
enableSsl="true" />
</smtp>
</mailSettings>
</system.net>

4. Ver:

Contact.cshtml

@model ContectModel
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<h4>Send your comments.</h4>
<hr />
<div class="form-group">
@Html.LabelFor(m => m.SenderName, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.TextBoxFor(m => m.SenderName, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.SenderName)
</div>
</div>
<div class="form-group">
@Html.LabelFor(m => m.SenderEmail, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.TextBoxFor(m => m.SenderEmail, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.SenderEmail)
</div>
</div>
<div class="form-group">
@Html.LabelFor(m => m.Message, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.TextAreaFor(m => m.Message, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.Message)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" class="btn btn-default" value="Send" />
</div>
</div>
}

SuccessMessage.cshtml

<h2>Your message has been sent</h2>

Enviando correo electrónico desde la clase

De esta manera, puede ser muy útil, pero algunas personas (como yo) tienen un código de
repetición, y como usted nos muestra, significa que necesito crear un controlador de contacto con

https://riptutorial.com/es/home 27
el mismo código en cada proyecto que tenemos, por lo que , Creo que esto puede ser útil también

Esta es mi clase, que puede estar en una DLL o lo que sea

public class Emails


{
public static void SendHtmlEmail(string receiverEmail, string subject, string body,
bool Ssl = false)
{
//Those are read it from webconfig or appconfig
var client = new SmtpClient(ConfigurationManager.AppSettings["MailServer"],
Convert.ToInt16

(ConfigurationManager.AppSettings["MailPort"]))
{
Credentials = new
NetworkCredential(ConfigurationManager.AppSettings["MailSender"],
ConfigurationManager.AppSettings["MailSenderPassword"]),
EnableSsl = Ssl
};

MailMessage message = new MailMessage();


message.From = new MailAddress(ConfigurationManager.AppSettings["MailSender"]);
message.To.Add(receiverEmail);
// message.To.Add("sgermosen@praysoft.net");
message.Subject = subject;
message.IsBodyHtml = true;
message.Body = body;
client.Send(message);
}

Como se ve, se leerá desde el webconfig, así que necesitamos configurarlo, esta configuración es
para Gmail, pero cada host tiene su propia configuración.

<appSettings>
<add key="webpages:Version" value="3.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
<add key="AdminUser" value="sgrysoft@gmail.com" />
<add key="AdminPassWord" value="123456789" />
<add key="SMTPName" value="smtp.gmail.com" />
<add key="SMTPPort" value="587" />

</appSettings>

Lea Asp.net mvc enviar correo en línea: https://riptutorial.com/es/asp-net-mvc/topic/9736/asp-net-


mvc-enviar-correo

https://riptutorial.com/es/home 28
Capítulo 8: Ayudantes html
Introducción
Los ayudantes de HTML son métodos utilizados para representar elementos HTML en una vista.
Son parte del espacio de nombres System.Web.Mvc.HtmlHelper .

Hay diferentes tipos de ayudantes de HTML:

Ayudantes HTML estándar : se utilizan para representar elementos HTML normales, por
ejemplo, Html.TextBox() .

Ayudantes HTML fuertemente tipados : estos ayudantes representan elementos HTML


basados en las propiedades del modelo, por ejemplo, Html.TextBoxFor() .

Ayudantes HTML personalizados : el usuario puede crear un método auxiliar personalizado que
devuelve MvcHtmlString .

Examples
Ayudante HTML personalizado - Nombre para mostrar

/// <summary>
/// Gets displayName from DataAnnotations attribute
/// </summary>
/// <typeparam name="TModel"></typeparam>
/// <typeparam name="TProperty"></typeparam>
/// <param name="htmlHelper"></param>
/// <param name="expression"></param>
/// <returns></returns>
public static MvcHtmlString GetDisplayName<TModel, TProperty>(this HtmlHelper<TModel>
htmlHelper, Expression<Func<TModel, TProperty>> expression)
{
var metaData = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
var value = metaData.DisplayName ?? (metaData.PropertyName ??
ExpressionHelper.GetExpressionText(expression));
return MvcHtmlString.Create(value);
}

Ayudante personalizado - botón Enviar de envío

/// <summary>
/// Creates simple button
/// </summary>
/// <param name="poHelper"></param>
/// <param name="psValue"></param>
/// <returns></returns>
public static MvcHtmlString SubmitButton(this HtmlHelper poHelper, string psValue)
{
return new MvcHtmlString(string.Format("<input type=\"submit\" value=\"{0}\">", psValue));

https://riptutorial.com/es/home 29
}

Lista exhaustiva de ejemplos de HtmlHelper que incluye salida HTML

HtmlHelper.Action()

• @Html.Action(actionName: "Index")
salida: el HTML representado por un método de acción denominado Index()

• @Html.Action(actionName: "Index", routeValues: new {id = 1})


salida: el HTML representado por un método de acción llamado Index(int id)

• @(Html.Action("Index", routeValues: new RouteValueDictionary(new Dictionary<string,


object>{ {"id", 1} })))
salida: el HTML representado por un método de acción llamado Index(int id)

• @Html.Action(actionName: "Index", controllerName: "Home")


salida: el código HTML representado por un método de acción denominado Index() en
el HomeController

• @Html.Action(actionName: "Index", controllerName: "Home", routeValues: new {id = 1})


salida: el HTML representado por un método de acción denominado Index(int id) en el
HomeController

• @Html.Action(actionName: "Index", controllerName: "Home", routeValues: new


RouteValueDictionary(new Dictionary<string, object>{ {"id", 1} }))
salida: el HTML representado por un método de acción denominado Index(int id) en el
HomeController

HtmlHelper.ActionLink()

• @Html.ActionLink(linkText: "Click me", actionName: "Index")


salida: <a href="Home/Index">Click me</a>

• @Html.ActionLink(linkText: "Click me", actionName: "Index", routeValues: new {id = 1})


salida: <a href="Home/Index/1">Click me</a>

• @Html.ActionLink(linkText: "Click me", actionName: "Index", routeValues: new {id = 1},


htmlAttributes: new {@class = "btn btn-default", data_foo = "bar")
salida: <a href="Home/Index/1" class="btn btn-default" data-foo="bar">Click me</a>

• @Html.ActionLink()
salida: <a href=""></a>

@HtmlHelper.BeginForm()

• @using (Html.BeginForm("MyAction", "MyController", FormMethod.Post, new {id="form1",@class


= "form-horizontal"}))
salida: <form action="/MyController/MyAction" class="form-horizontal" id="form1"
method="post">

Ayudantes HTML estándar con sus salidas HTML

Html.TextBox ()

https://riptutorial.com/es/home 30
• @Html.TextBox("Name", null, new { @class = "form-control" })
salida: <inputclass="form-control" id="Name"name="Name"type="text"value=""/>
• @Html.TextBox("Name", "Stack Overflow", new { @class = "form-control" })
salida: <input class="form-control" id="Name"name="Name"type="text" value="Stack Overflow"/>

Html.TextArea ()

• @Html.TextArea("Notes", null, new { @class = "form-control" })


salida: <textarea class="form-control" id="Notes" name="Notes" rows="2"
cols="20"></textarea>
• @Html.TextArea("Notes", "Please enter Notes", new { @class = "form-control" })
salida: <textarea class="form-control" id="Notes" name="Notes" rows="2" cols="20" >Please
enter Notes</textarea>

Html.Label ()

• @Html.Label("Name","FirstName")
output: <labelfor="Name"> FirstName </label>
• @Html.Label("Name", "FirstName", new { @class = "NameClass" })
output: <label for="Name" class="NameClass">FirstName</label>

Html.Hidden ()

• @Html.Hidden("Name", "Value")
salida: <input id="Name" name="Name" type="hidden" value="Value" />

Html.CheckBox ()

• @Html.CheckBox("isStudent", true)
salida: <input checked="checked" id="isStudent" name="isStudent" type="checkbox"
value="true" />

Html.Password ()

• @Html.Password("StudentPassword")
salida: <input id="StudentPassword" name="StudentPassword" type="password" value="" />

Ayudante personalizado - Botón de radio renderizado con etiqueta

public static MvcHtmlString RadioButtonLabelFor<TModel, TProperty>(this


HtmlHelper<TModel> self, Expression<Func<TModel, TProperty>> expression, bool value, string
labelText)
{
// Retrieve the qualified model identifier
string name = ExpressionHelper.GetExpressionText(expression);
string fullName = self.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);

// Generate the base ID


TagBuilder tagBuilder = new TagBuilder("input");
tagBuilder.GenerateId(fullName);
string idAttr = tagBuilder.Attributes["id"];

// Create an ID specific to the boolean direction


idAttr = string.Format("{0}_{1}", idAttr, value);

// Create the individual HTML elements, using the generated ID

https://riptutorial.com/es/home 31
MvcHtmlString radioButton = self.RadioButtonFor(expression, value, new { id = idAttr
});
MvcHtmlString label = self.Label(idAttr, labelText);

return new MvcHtmlString(radioButton.ToHtmlString() + label.ToHtmlString());


}

Ejemplo: @Html.RadioButtonLabelFor(m => m.IsActive, true, "Yes")

Ayudante personalizado - Selector de fecha y hora

public static MvcHtmlString DatePickerFor<TModel, TProperty>(this HtmlHelper<TModel>


htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes)
{
var sb = new StringBuilder();
var metaData = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
var dtpId = "dtp" + metaData.PropertyName;
var dtp = htmlHelper.TextBoxFor(expression, htmlAttributes).ToHtmlString();
sb.AppendFormat("<div class='input-group date' id='{0}'> {1} <span class='input-group-
addon'><span class='glyphicon glyphicon-calendar'></span></span></div>", dtpId, dtp);
return MvcHtmlString.Create(sb.ToString());
}

Ejemplo:

@Html.DatePickerFor(model => model.PublishedDate, new { @class = "form-control" })

Si usa Bootstrap.v3.Datetimepicker, su JavaScript es como el siguiente:

$('#dtpPublishedDate').datetimepicker({ format: 'MMM DD, YYYY' });

Lea Ayudantes html en línea: https://riptutorial.com/es/asp-net-mvc/topic/2290/ayudantes-html

https://riptutorial.com/es/home 32
Capítulo 9: Dockerización de la aplicación
ASP.NET
Examples
Dockerfile y Nuget

La aplicación Dockerization de ASP.NET requiere un Dockerfile para su configuración y su


ejecución como contenedor de ventana acoplable.

FROM microsoft/dotnet:latest

RUN apt-get update && apt-get install sqlite3 libsqlite3-dev

COPY . /app

WORKDIR /app

RUN ["dotnet", "restore"]

RUN ["dotnet", "build"]

RUN npm install && npm run postscript

RUN bower install

RUN ["dotnet", "ef", "database", "update"]

EXPOSE 5000/tcp

ENTRYPOINT ["dotnet", "run", "--server.urls", "http://0.0.0.0:5000"]

Un archivo de configuración de alimentación de nuget ayuda a recuperar de la fuente correcta. El


uso de este archivo depende de la configuración actual del proyecto y puede cambiar a los
requisitos del proyecto de la suite.

<?xml version="1.0" encoding="utf-8"?>


<configuration>
<packageSources>
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
<packageSources>
<packageRestore>
<add key="enabled" value="True" />
<add key="automatic" value="True" />
<packageRestore>
<bindingRedirects>
<add key="skip" value="False" />
</bindingRedirects>
</configuration>

Soporte POSTGRESQL.

https://riptutorial.com/es/home 33
"Data": {
"DefaultConnection": {
"ConnectionString":
"Host=localhost;Username=postgres;Password=******;Database=postgres;Port=5432;Pooling=true;"
}
},

Dockerización

Es necesario tener .NET o un paquete mono-aspnet.

Es importante entender la importancia de la dockerización. Instale dotnet en ubuntu o en el


sistema operativo en el que está trabajando.

Instalando DOTNET

$ sudo sh -c 'echo "deb [arch=amd64] https://apt-mo.trafficmanager.net/repos/dotnet-release/


trusty main" > /etc/apt/sources.list.d/dotnetdev.list'
$ sudo apt-key adv --keyserver apt-mo.trafficmanager.net --recv-keys 417A0893
$ sudo apt-get update

Ubuntu 16.04

$ sudo sh -c 'echo "deb [arch=amd64] https://apt-mo.trafficmanager.net/repos/dotnet-release/


xenial main" > /etc/apt/sources.list.d/dotnetdev.list'
$ sudo apt-key adv --keyserver apt-mo.trafficmanager.net --recv-keys 417A0893
$ sudo apt-get update

Instalar .NET Core SDK

$ sudo apt-get install dotnet-dev-1.0.0-preview2-003121

CORTESÍA: https://www.microsoft.com/net/core#ubuntu

Para la instalación de Docker, siga https://docs.docker.com/engine/installation/linux/ubuntulinux/

POR PUERTO:

Kestrel server port : 5000


Docker Deamon will listen to port :

EXPOSE 5000/tcp

Para la construcción de docker:

$ sudo docker build -t myapp .

Para ejecutar el contenedor docker:

$ sudo docker run -t -d -p 8195:5000 myapp

https://riptutorial.com/es/home 34
Para visitar el sitio:

$ ifconfig

eth0 : ***.***.**
server-ip-address

El sitio estará disponible en (dada esta configuración):

http://server-ip-address:8195

Procesos Docker. Se listarán los procesos en ejecución.

$ sudo docker ps

Para eliminar el proceso o el contenedor.

$ sudo docker rm -rf <process_id>

Lea Dockerización de la aplicación ASP.NET en línea: https://riptutorial.com/es/asp-net-


mvc/topic/6740/dockerizacion-de-la-aplicacion-asp-net

https://riptutorial.com/es/home 35
Capítulo 10: Empaquetado y Minificación
Examples
Minificación

La minificación se utiliza para reducir el tamaño de los archivos CSS y Javascript para acelerar
los tiempos de descarga. Este proceso se realiza mediante la eliminación de todos los espacios
en blanco, comentarios y cualquier otro contenido no esencial de los archivos.

Este proceso se realiza automáticamente cuando se utiliza un objeto ScriptBundle o StyleBundle .


Si necesita deshabilitarlo, debe usar un objeto Bundle básico.

Ejemplo usando minificación


El siguiente código usa directivas de preprocesador para aplicar el agrupamiento solo durante las
versiones a fin de permitir una depuración más fácil durante las versiones no liberadas (ya que los
archivos no empaquetados suelen ser más fáciles de navegar):

public static void RegisterBundles(BundleCollection bundles)


{
#if DEBUG
bundles.Add(new Bundle("~/bundles/jquery").Include("~/Scripts/jquery-{version}.js"));
bundles.Add(new Bundle("~/Content/css").Include("~/Content/site.css"));
#else
bundles.Add(new ScriptBundle("~/bundles/jquery").Include("~/Scripts/jquery-
{version}.js"));
bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/site.css"));
#endif
}

Guiones y paquetes de estilo

El siguiente es el fragmento de código predeterminado para el archivo BundleConfig.cs.

using System.Web.Optimization;

public class BundleConfig


{
// For more information on Bundling, visit http://go.microsoft.com/fwlink/?LinkId=254725
public static void RegisterBundles(BundleCollection bundles)
{
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
"~/Scripts/jquery-{version}.js"));

// Use the development version of Modernizr to develop with and learn from. Then, when
you're
// ready for production, use the build tool at http://modernizr.com to pick only the tests
you need.
bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(

https://riptutorial.com/es/home 36
"~/Scripts/modernizr-*"));

bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/site.css"));

bundles.Add(new StyleBundle("~/Content/themes/base/css").Include(
"~/Content/themes/base/jquery.ui.core.css",
"~/Content/themes/base/jquery.ui.resizable.css",
}
}

Los paquetes se registran en el archivo Global.asax dentro del método Application_Start ():

using System.Web.Optimization;

protected void Application_Start()


{
BundleConfig.RegisterBundles(BundleTable.Bundles);
}

Los paquetes deben ser representados en tus Vistas como tal:

@using System.Web.Optimization

@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/modernizr")
@Styles.Render("~/Content/css")
@Styles.Render("~/Content/themes/base/css")

Tenga en cuenta que la agrupación no se produce cuando está en modo de desarrollo (donde el
elemento de compilación en el archivo Web.config se establece en debug = "true"). En su lugar,
las declaraciones de Render en sus Vistas incluirán cada archivo individual en un formato no
agrupado, no minificado, para facilitar la depuración.

Una vez que la aplicación está en modo de producción (donde el elemento de compilación en el
archivo Web.config se establece en debug = "false"), se realizará la agrupación.

Esto puede llevar a complicaciones para los scripts que hacen referencia a rutas relativas de otros
archivos, como las referencias a los archivos de iconos de Twitter Bootstrap. Esto se puede
abordar utilizando la clase CssRewriteUrlTransform de System.Web.Optimization:

bundles.Add(new StyleBundle("~/bundles/css").Include(
"~/Content/css/*.css", new CssRewriteUrlTransform()));

La clase CssRewriteUrlTransform reescribirá las URL relativas dentro de los archivos agrupados
en rutas absolutas, de modo que las referencias permanecerán intactas después de que la
referencia de llamada se mueva a la ubicación del paquete (p. Ej., Utilizando el código anterior,
pasando de "~ / Content / css / bootstrap.css "a" ~ / bundles / css / bootstrap.css ").

Lea Empaquetado y Minificación en línea: https://riptutorial.com/es/asp-net-


mvc/topic/1959/empaquetado-y-minificacion

https://riptutorial.com/es/home 37
Capítulo 11: Enrutamiento
Introducción
El enrutamiento es cómo ASP.NET MVC hace coincidir un URI con una acción. El módulo de
enrutamiento es responsable de asignar las solicitudes entrantes del navegador a las acciones
particulares del controlador MVC.

MVC 5 admite un nuevo tipo de enrutamiento, llamado enrutamiento de atributos. Como su


nombre lo indica, el enrutamiento de atributos utiliza atributos para definir rutas. El enrutamiento
de atributos le brinda más control sobre los URI en su aplicación web.

Examples
Enrutamiento personalizado

El enrutamiento personalizado proporciona una necesidad especializada de enrutamiento para


manejar solicitudes entrantes específicas.

Para definir rutas personalizadas, tenga en cuenta que el orden de las rutas que agrega a la tabla
de rutas es importante.

public static void RegisterRoutes(RouteCollection routes)


{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

// this is an advanced custom route


// you can define custom URL with custom parameter(s) point to certain action method
routes.MapRoute(
"CustomEntry", // Route name
"Custom/{entryId}", // Route pattern
new { controller = "Custom", action = "Entry" } // Default values for defined parameters
above
);

// this is a basic custom route


// any custom routes take place on top before default route
routes.MapRoute(
"CustomRoute", // Route name
"Custom/{controller}/{action}/{id}", // Route pattern
new { controller = "Custom", action = "Index", id = UrlParameter.Optional } // Default
values for defined parameters above
);

routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // Route pattern
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Default
values for defined parameters above
);
}

https://riptutorial.com/es/home 38
controller y action nombres de action están reservados. Por defecto, MVC asigna {controller}
parte de la URL a la <controller>Controller y luego busca un método con el nombre <action> sin
agregar ningún sufijo.

Aunque puede ser tentador crear una familia de rutas utilizando la plantilla
{controller}/{action}/{parameter} al hacer esto usted revela la estructura de su aplicación y hace
que las URL sean algo frágiles porque cambiar el nombre del controlador cambia la configuración.
Ruta y rompe los enlaces guardados por el usuario.

Prefiere configuración de ruta explícita:

routes.MapRoute(
"CustomRoute", // Route name
"Custom/Index/{id}", // Route pattern
new { controller = "Custom", action = nameof(CustomController.Index), id =
UrlParameter.Optional }
);

(no puede usar el nameof operador para el nombre del controlador, ya que tendrá un sufijo
adicional Controller ) que se debe omitir al configurar el nombre del controlador en la ruta.

Añadiendo ruta personalizada en mvc

El usuario puede agregar una ruta personalizada, asignando una URL a una acción específica en
un controlador. Esto se utiliza para propósitos de optimización de motores de búsqueda y hace
que las URL sean legibles.

routes.MapRoute(
name: "AboutUsAspx", // Route name
url: "AboutUs.aspx", // URL with parameters
defaults: new { controller = "Home", action = "AboutUs", id = UrlParameter.Optional } //
Parameter defaults
);

Atributo de enrutamiento en MVC

Junto con la forma clásica de definición de ruta, MVC WEB API 2 y luego MVC 5 introdujeron el
Attribute routing :

public class RouteConfig


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

// This enables attribute routing and must go before other routes are added to the
routing table.
// This makes attribute routes have higher priority
routes.MapMvcAttributeRoutes();
}
}

https://riptutorial.com/es/home 39
Para rutas con el mismo prefijo dentro de un controlador, puede establecer un prefijo común para
todos los métodos de acción dentro del controlador utilizando el atributo RoutePrefix .

[RoutePrefix("Custom")]
public class CustomController : Controller
{
[Route("Index")]
public ActionResult Index()
{
...
}
}

RoutePrefix es opcional y define la parte de la URL que tiene el prefijo de todas las acciones del
controlador.

Si tiene varias rutas, puede establecer una ruta predeterminada al capturar la acción como
parámetro y luego aplicarla a todo el controlador, a menos que se defina el atributo de Route
específico en ciertos métodos de acción que anulan la ruta predeterminada.

[RoutePrefix("Custom")]
[Route("{action=index}")]
public class CustomController : Controller
{
public ActionResult Index()
{
...
}

public ActionResult Detail()


{
...
}
}

Conceptos básicos de enrutamiento

Cuando solicite la url yourSite/Home/Index través de un navegador, el módulo de enrutamiento


dirigirá la solicitud al método de acción Index de la clase HomeController . ¿Cómo sabe enviar la
solicitud al método específico de esta clase específica? Ahí viene la RouteTable.

Cada aplicación tiene una tabla de ruta donde almacena el patrón de ruta e información sobre
dónde dirigir la solicitud. Así que cuando creas tu aplicación mvc, hay una ruta predeterminada ya
registrada en la tabla de enrutamiento. Puedes ver eso en la clase RouteConfig.cs .

public static void RegisterRoutes(RouteCollection routes)


{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute("Default", "{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional });
}

Puedes ver que la entrada tiene un nombre y una plantilla. La plantilla es el patrón de ruta que

https://riptutorial.com/es/home 40
debe verificarse cuando llega una solicitud. La plantilla predeterminada tiene Home como el valor
del segmento url del controlador y el Index como el valor del segmento de acción. Eso significa
que, si no pasa explícitamente un nombre y una acción del controlador en su solicitud, utilizará
estos valores predeterminados. Esta es la razón por la que obtiene el mismo resultado cuando
accede a su yourSite/Home/Index y su yourSite

Es posible que haya notado que tenemos un parámetro llamado id como el último segmento de
nuestro patrón de ruta. Pero en los valores por defecto, especificamos que es opcional. Esa es la
razón por la que no tuvimos que especificar el valor de id int url que intentamos.

Ahora, vuelva al método de acción de índice en HomeController y agregue un parámetro a ese

public ActionResult Index(int id)


{
return View();
}

Ahora pon un punto de vista visual de estudio en este método. Ejecute su proyecto y acceda a su
yourSite/Home/Index/999 en su navegador. Se alcanzará el punto de interrupción y debería poder
ver que el valor 999 ahora está disponible en el parámetro id .

Creando un segundo patrón de ruta

Digamos que nos gustaría configurarlo para que se llame al mismo método de acción para un
patrón de ruta diferente. Podemos hacerlo agregando una nueva definición de ruta a la tabla de
rutas.

public static void RegisterRoutes(RouteCollection routes)


{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

// New custom route definition added


routes.MapRoute("MySpecificRoute",
"Important/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional });

//Default catch all normal route definition


routes.MapRoute("Default", "{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional });
}

La nueva definición que agregué tiene un patrón Important/{id} donde id es nuevamente opcional.
Eso significa que cuando solicite su yourSiteName\Important o su yourSiteName\Important\888 , se
enviará a la acción del Índice de HomeController.

Orden de registro de definición de ruta

El orden de registro de ruta es importante. Siempre debe registrar los patrones de ruta específicos
antes de la ruta genérica predeterminada.

Ruta de todo

https://riptutorial.com/es/home 41
Supongamos que queremos tener una ruta que permita un número ilimitado de segmentos así:

• http://example.com/Products/ (ver todos los productos)


• http://example.com/Products/IT
• http://example.com/Products/IT/Laptops
• http://example.com/Products/IT/Laptops/Ultrabook
• http://example.com/Products/IT/Laptops/Ultrabook/Asus
• etc.

Tendríamos que agregar una ruta, normalmente al final de la tabla de rutas, ya que esto
probablemente detectaría todas las solicitudes, de este modo:

routes.MapRoute("Final", "Route/{*segments}",
new { controller = "Product", action = "View" });

En el controlador, una acción que podría manejar esto, podría ser:

public void ActionResult View(string[] segments /* <- the name of the parameter must match the
name of the route parameter */)
{
// use the segments to obtain information about the product or category and produce data
to the user
// ...
}

Ruta completa para habilitar el enrutamiento del lado del cliente

Es una buena práctica codificar el estado de la aplicación de página única (SPA) en url:

my-app.com/admin-spa/users/edit/id123

Esto permite guardar y compartir el estado de la aplicación.


Cuando el usuario coloca la url en la barra de direcciones del navegador y los clics en el servidor
deben ignorar la parte del cliente de la url solicitada. Si sirve su SPA como una vista Razor
renderizada (resultado de la acción del controlador de llamada) en lugar de como un archivo html
estático, puede usar una ruta de acceso directo:

public class AdminSpaController


{
[Route("~/admin-spa/{clienSidePart*}")]
ActionResult AdminSpa()
{
...
}
}

En este caso, el servidor solo devuelve SPA y luego se inicializa de acuerdo con la ruta. Este
enfoque es más flexible, ya que no depende del módulo url-rewrite .

Atributo de enrutamiento en áreas

https://riptutorial.com/es/home 42
Para usar el enrutamiento de atributos en áreas, se requieren áreas de registro y las
[RouteArea(...)] .

En RouteConfig.cs :

public class RouteConfig


{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapMvcAttributeRoutes();
AreaRegistration.RegisterAllAreas();
}
}

En una definición de enrutamiento de atributos de controlador de área de muestra:

[RouteArea("AreaName", AreaPrefix = "AreaName")]


[RoutePrefix("SampleAreaController")]
public class SampleAreaController : Controller
{
[Route("Index")]
public ActionResult Index()
{
return View();
}
}

Para utilizar enlaces de Url.Action en Áreas:

@Url.Action("Index", "SampleAreaController", new { area = "AreaName" })

Lea Enrutamiento en línea: https://riptutorial.com/es/asp-net-mvc/topic/1534/enrutamiento

https://riptutorial.com/es/home 43
Capítulo 12: Extensiones Ajax MVC
Introducción
Esto documenta el uso de la biblioteca System.Web.Mvc.Ajax .

Citando documentos de MSDN "Cada método de extensión representa un elemento HTML. El


método ActionLink representa un elemento anchor (a) que se vincula a un método de acción. El
método RouteLink representa un elemento anchor (a) que se vincula a una URL, que puede
resolverse a una método de acción, un archivo, una carpeta o algún otro recurso. Esta clase
también contiene los métodos BeginForm y BeginRouteForm que le ayudan a crear formularios
HTML que son compatibles con las funciones AJAX.

Parámetros

Opciones de AJAX Descripción

Obtiene o establece el mensaje que se mostrará en una ventana


Confirmar
de confirmación antes de que se envíe una solicitud.

Obtiene o establece el método de solicitud HTTP ("Obtener" o


HttpMethod
"Publicar").

Obtiene o establece el modo que especifica cómo insertar la


Modo de inserción
respuesta en el elemento DOM de destino.

Obtiene o establece un valor, en milisegundos, que controla la


LoadingElementDuration duración de la animación al mostrar u ocultar el elemento de
carga.

Obtiene o establece el atributo id de un elemento HTML que se


LoadingElementId
muestra mientras se carga la función Ajax.

Obtiene o establece el nombre de la función JavaScript para


OnBegin
llamar inmediatamente antes de que se actualice la página.

Obtiene o establece la función de JavaScript para llamar cuando


OnComplete se han creado instancias de datos de respuesta pero antes de
que se actualice la página.

Obtiene o establece la función de JavaScript para llamar si falla la


En el fracaso
actualización de la página.

Obtiene o establece la función de JavaScript para llamar después


OnSuccess
de que la página se actualice correctamente.

https://riptutorial.com/es/home 44
Opciones de AJAX Descripción

Obtiene o establece el ID del elemento DOM para actualizar


UpdateTargetId
utilizando la respuesta del servidor.

Url Obtiene o establece la URL para realizar la solicitud.

Observaciones
El paquete Jquery.Unobtrusive-Ajax es obligatorio en el proyecto. Los archivos javascript
correspondientes deben incluirse en un paquete ( jquery.unobtrusive-ajax.js o
jquery.unobtrusive-ajax.min.js ). Finalmente, debe activarse también en el archivo web.config :

<appSettings>
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>

Las acciones invocadas ( SomeAction en los ejemplos) deben devolver un Json o PartialView .

Examples
Ajax Action Link

@* Renders an anchor (a) element that links to an action method.


* The innerHTML of "target-element" is replaced by the result of SomeAction.
*@
@Ajax.ActionLink("Update", "SomeAction", new AjaxOptions{UpdateTargetId="target-element" })

Formas de Ajax

@* Adds AJAX functions support to a form.


* The innerHTML of "target-element" is replaced by the result of SomeAction.
*@
@using ( Ajax.BeginForm("SomeAction", "SomeController",
new AjaxOptions {
UpdateTargetId="target-element",
OnSuccess = "some_js_fun(context)"
})
)
{
<!-– my form contents -->
}

Lea Extensiones Ajax MVC en línea: https://riptutorial.com/es/asp-net-


mvc/topic/9007/extensiones-ajax-mvc

https://riptutorial.com/es/home 45
Capítulo 13: Filtros de accion
Examples
Un filtro de acción de registro.

public class LogActionFilter : ActionFilterAttribute


{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
Log("OnActionExecuting", filterContext.RouteData);
}

public override void OnActionExecuted(ActionExecutedContext filterContext)


{
Log("OnActionExecuted", filterContext.RouteData);
}

public override void OnResultExecuting(ResultExecutingContext filterContext)


{
Log("OnResultExecuting", filterContext.RouteData);
}

public override void OnResultExecuted(ResultExecutedContext filterContext)


{
Log("OnResultExecuted", filterContext.RouteData);
}

private void Log(string methodName, RouteData routeData)


{
var controllerName = routeData.Values["controller"];
var actionName = routeData.Values["action"];
var message = String.Format("{0} controller:{1} action:{2}", methodName,
controllerName, actionName);
Debug.WriteLine(message, "Action Filter Log");
}
}

Filtro de acción de Control de sesión - solicitud de página y ajax

Por lo general, los procesos de autenticación y autorización se realizan mediante cookies y token
compatibles en .net MVC. Pero si decide hacerlo usted mismo con Session , puede usar la lógica
siguiente para las solicitudes de página y las solicitudes de ajax.

public class SessionControl : ActionFilterAttribute


{
public override void OnActionExecuting ( ActionExecutingContext filterContext )
{
var session = filterContext.HttpContext.Session;

/// user is logged in (the "loggedIn" should be set in Login action upon a successful
login request)
if ( session["loggedIn"] != null && (bool)session["loggedIn"] )

https://riptutorial.com/es/home 46
return;

/// if the request is ajax then we return a json object


if ( filterContext.HttpContext.Request.IsAjaxRequest() )
{
filterContext.Result = new JsonResult
{
Data = "UnauthorizedAccess",
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}
/// otherwise we redirect the user to the login page
else
{
var redirectTarget = new RouteValueDictionary { { "Controller", "Login" }, {
"Action", "Index" } };
filterContext.Result = new RedirectToRouteResult(redirectTarget);
}
}

public override void OnResultExecuting ( ResultExecutingContext filterContext )


{
base.OnResultExecuting(filterContext);

/// we set a field 'IsAjaxRequest' in ViewBag according to the actual request type
filterContext.Controller.ViewBag.IsAjaxRequest =
filterContext.HttpContext.Request.IsAjaxRequest();
}
}

Ubicaciones de uso del filtro de acción (global, controlador, acción)

Puede colocar filtros de acción en tres niveles posibles:

1. Global
2. Controlador
3. Acción

Colocar un filtro global significa que se ejecutará en las solicitudes a cualquier ruta. La colocación
de uno en un controlador hace que se ejecute en las solicitudes de cualquier acción en ese
controlador. Colocar uno en una acción significa que se ejecuta con la acción.

Si tenemos este simple filtro de acción:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]


public class CustomActionFilterAttribute : FilterAttribute, IActionFilter
{
private readonly string _location;

public CustomActionFilterAttribute(string location)


{
_location = location;
}

public void OnActionExecuting(ActionExecutingContext filterContext)


{
Trace.TraceInformation("OnActionExecuting: " + _location);

https://riptutorial.com/es/home 47
}

public void OnActionExecuted(ActionExecutedContext filterContext)


{
Trace.TraceInformation("OnActionExecuted: " + _location);
}
}

Podemos agregarlo a nivel global agregándolo a la colección de filtro global. Con la configuración
típica del proyecto MVC de ASP.NET, esto se hace en App_Start / FilterConfig.cs.

public class FilterConfig


{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new CustomActionFilterAttribute("Global"));
}
}

También podemos agregarlo en el controlador y en el nivel de acción, como en un controlador:

[CustomActionFilter("HomeController")]
public class HomeController : Controller
{
[CustomActionFilter("Index")]
public ActionResult Index()
{
return View();
}
}

Si ejecutamos la aplicación y miramos la ventana de resultados, veremos los siguientes


mensajes:

iisexpress.exe Information: 0 : OnActionExecuting: Global


iisexpress.exe Information: 0 : OnActionExecuting: HomeController
iisexpress.exe Information: 0 : OnActionExecuting: Index
iisexpress.exe Information: 0 : OnActionExecuted: Index
iisexpress.exe Information: 0 : OnActionExecuted: HomeController
iisexpress.exe Information: 0 : OnActionExecuted: Global

Como puede ver, cuando llega la solicitud, los filtros se ejecutan:

1. Global
2. Controlador
3. Acción

Excelentes ejemplos de filtros colocados a nivel global incluyen:

1. Filtros de autentificación
2. Filtros de autorizacion
3. Filtros de registro

https://riptutorial.com/es/home 48
Atributo de manejador de excepciones

Este atributo maneja todas las excepciones no manejadas en el código, (esto es principalmente
para solicitudes Ajax - que tratan con JSON - pero pueden extenderse)

public class ExceptionHandlerAttribute : HandleErrorAttribute


{
/// <summary>
/// Overriden method to handle exception
/// </summary>
/// <param name="filterContext"> </param>
public override void OnException(ExceptionContext filterContext)
{
// If exeption is handled - return ( don't do anything)
if (filterContext.ExceptionHandled)
return;

// Set the ExceptionHandled to true ( as you are handling it here)


filterContext.ExceptionHandled = true;

//TODO: You can Log exception to database or Log File

//Set your result structure


filterContext.Result = new JsonResult
{
Data = new { Success = false, Message = filterContext .Exception.Message, data =
new {} },
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};

}
}

Digamos que siempre tienes que enviar una respuesta JSON similar a esto:

Success: true, // False when Error

data: {},

Message:"Success" // Error Message when Error

Así que en lugar de manejar excepciones en las acciones del controlador, como esto:

public ActionResult PerformMyAction()


{
try
{
var myData = new { myValue = 1};

throw new Exception("Handled", new Exception("This is an Handled Exception"));

return Json(new {Success = true, data = myData, Message = ""});

https://riptutorial.com/es/home 49
}
catch(Exception ex)
{
return Json(new {Success = false, data = null, Message = ex.Message});
}
}

Puedes hacerlo:

[ExceptionHandler]
public ActionResult PerformMyAction()
{
var myData = new { myValue = 1};

throw new Exception("Unhandled", new Exception("This is an unhandled Exception"));

return Json(new {Success = true, data = myData, Message = ""});


}

O puede agregar a nivel de controlador

[ExceptionHandler]
public class MyTestController : Controller
{

public ActionResult PerformMyAction()


{
var myData = new { myValue = 1};

throw new Exception("Unhandled", new Exception("This is an unhandled Exception"));

return Json(new {Success = true, data = myData, Message = ""});


}
}

Lea Filtros de accion en línea: https://riptutorial.com/es/asp-net-mvc/topic/1450/filtros-de-accion

https://riptutorial.com/es/home 50
Capítulo 14: Html.AntiForgeryToken
Introducción
El token anti-falsificación se puede usar para ayudar a proteger su aplicación contra la
falsificación de solicitudes entre sitios. Para usar esta función, llame al método AntiForgeryToken
desde un formulario y agregue el atributo ValidateAntiForgeryTokenAttribute al método de acción
que desea proteger.

Genera un campo de formulario oculto (token anti-falsificación) que se valida cuando se envía el
formulario.

Sintaxis
• @ Html.AntiForgeryToken ()

Observaciones
Al enviar una solicitud ajax con el token CSRF ( __RequestVerificationToken ), asegúrese de que el
tipo de contenido no esté establecido en application/json . Si está utilizando jQuery,
automáticamente establece el tipo de contenido en application/x-www-form-urlencoded que luego
es reconocido por ASP.NET MVC.

Precaución
Tenga cuidado al establecer este valor. Su uso inadecuado puede abrir vulnerabilidades de
seguridad en la aplicación.

Examples
Uso básico

El método de ayuda @Html.AntiForgeryToken() protege contra ataques de falsificación de


solicitudes entre sitios (o CSRF).

Se puede usar simplemente usando el ayudante Html.AntiForgeryToken() dentro de uno de sus


formularios existentes y decorando su Acción de controlador correspondiente con el atributo
[ValidateAntiForgeryToken] .

Maquinilla de afeitar (YourView.cshtml)

@using (Html.BeginForm("Manage", "Account")) {


@Html.AntiForgeryToken()

https://riptutorial.com/es/home 51
<!-- ... -->
}

<form>
@Html.AntiForgeryToken()
<!-- ... -->
</form>

Controlador (YourController.cs)
El método de acción objetivo:

[ValidateAntiForgeryToken]
[HttpPost]
public ActionResult ActionMethod(ModelObject model)
{
// ...
}

Deshabilitar el control heurístico de identidad

Muchas veces verá una excepción

Anti forgery token is meant for user "" but the current user is "username"

Esto se debe a que el token de Anti-falsificación también está vinculado al usuario que ha iniciado
sesión actualmente. Este error aparece cuando un usuario inicia sesión pero su token sigue
vinculado a ser un usuario anónimo para el sitio.

Hay algunas formas de solucionar este comportamiento, pero si prefiere no tener los tokens
CSRF vinculados al estado de inicio de sesión de un usuario, puede desactivar esta función.

Coloque esta línea en su archivo Global.asax o en una lógica de inicio de aplicación similar.

AntiForgeryConfig.SuppressIdentityHeuristicChecks = true;

Validando todas las publicaciones

Debido a la vulnerabilidad causada por CSRF, generalmente se considera una buena práctica
verificar un AntiForgeryToken en todos los HttpPosts, a menos que haya una buena razón para
no hacerlo (algún problema técnico con la publicación, hay otro mecanismo de autenticación y / o
el la publicación no muta el estado como guardarlo en un db o archivo). Para asegurarse de no
olvidar, puede agregar un GlobalActionFilter especial que verifique automáticamente todos los
HttpPosts a menos que la acción esté decorada con un atributo especial de "ignorar".

[AttributeUsage(AttributeTargets.Class)]

https://riptutorial.com/es/home 52
public class ValidateAntiForgeryTokenOnAllPosts : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
var request = filterContext.HttpContext.Request;

// Only validate POSTs


if (request.HttpMethod == WebRequestMethods.Http.Post)
{
bool skipCheck =
filterContext.ActionDescriptor.IsDefined(typeof(DontCheckForAntiForgeryTokenAttribute), true)
||
filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(DontCheckForAntiForgeryTokenAttrib
true);

if (skipCheck)
return;

// Ajax POSTs and normal form posts have to be treated differently when it comes
// to validating the AntiForgeryToken
if (request.IsAjaxRequest())
{
var antiForgeryCookie = request.Cookies[AntiForgeryConfig.CookieName];

var cookieValue = antiForgeryCookie != null


? antiForgeryCookie.Value
: null;

AntiForgery.Validate(cookieValue,
request.Headers["__RequestVerificationToken"]);
}
else
{
new ValidateAntiForgeryTokenAttribute()
.OnAuthorization(filterContext);
}
}
}
}

/// <summary>
/// this should ONLY be used on POSTS that DO NOT MUTATE STATE
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false,
Inherited = true)]
public sealed class DontCheckForAntiForgeryTokenAttribute : Attribute { }

Para asegurarse de que se verifique en todas las solicitudes, solo agréguelo a sus filtros de
acción global

public class FilterConfig


{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
//...
filters.Add(new ValidateAntiForgeryTokenOnAllPosts());
//...
}
}

https://riptutorial.com/es/home 53
Uso anticipado: aplique el filtro antiforgery predeterminado para cada POST

Podemos olvidar aplicar el Antiforgery attribute para cada solicitud POST por lo que deberíamos
hacerlo por defecto. Esta muestra asegurará que el Antiforgery filter siempre se aplique a cada
solicitud POST .

Primero crea un nuevo filtro AntiForgeryTokenFilter :

//This will add ValidateAntiForgeryToken Attribute to all HttpPost action methods


public class AntiForgeryTokenFilter : IFilterProvider
{
public IEnumerable<Filter> GetFilters(ControllerContext controllerContext,
ActionDescriptor actionDescriptor)
{
List<Filter> result = new List<Filter>();

string incomingVerb = controllerContext.HttpContext.Request.HttpMethod;

if (String.Equals(incomingVerb, "POST", StringComparison.OrdinalIgnoreCase))


{
result.Add(new Filter(new ValidateAntiForgeryTokenAttribute(), FilterScope.Global,
null));
}

return result;
}
}

Luego registre este filtro personalizado a MVC, Application_Start:

public class FilterConfig


{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
//Cactch generic error
filters.Add(new HandleErrorAttribute());

//Anti forgery token hack for every post request


FilterProviders.Providers.Add(new AntiForgeryTokenFilter());
}
}

public class MvcApplication : System.Web.HttpApplication


{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}

Por lo tanto, ahora todas sus solicitudes POST están protegidas de forma predeterminada mediante
los atributos de Antiforgery, por lo que ya no necesitamos tener el atributo

https://riptutorial.com/es/home 54
[ValidateAntiForgeryToken] en cada método POST.

Uso de AntiForgeryToken con la solicitud de Ajax de Jquery

Primero creas el formulario

@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
}

Método de acción

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Test(FormViewModel formData)
{
// ...
}

Guión

<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<script>
var formData = new FormData($('form')[0]);
$.ajax({
method: "POST",
url: "/demo/test",
data: formData ,
success: function (data) {
console.log(data);
},
error: function (jqXHR, textStatus, errorThrown) {
console.log(errorThrown);
}
})
</script>

Asegúrese de que contentType no esté configurado para nada aparte de application/x-www-form-


urlencoded y si Jquery no está especificado por defecto es application/x-www-form-urlencoded

Lea Html.AntiForgeryToken en línea: https://riptutorial.com/es/asp-net-mvc/topic/1997/html-


antiforgerytoken

https://riptutorial.com/es/home 55
Capítulo 15: Html.RouteLink
Parámetros

Parámetro Detalles

Texto del enlace El texto que se mostrará para el enlace.

routeName El nombre de la ruta para devolver una ruta virtual para.

Examples
Ejemplo básico usando el texto de enlace y el nombre de la ruta

Como alternativa al uso de Html.ActionLink para generar enlaces en una vista, puede usar

Html.RouteLink

Para utilizar esta función, necesita configurar una ruta, por ejemplo:

public static void RegisterRoutes(RouteCollection routes)


{
routes.MapRoute(
"SearchResults",
"{controller}/{action}",
new { controller = "Search", action = "Results" });
}

Luego, en una vista, puede crear un enlace a esa ruta así:

@Html.RouteLink("Search Results", "SearchResults");

Usar RouteLink() es conveniente si termina cambiando los nombres del controlador o los nombres
de los métodos de acción, ya que usar Html.ActionLink() significa tener que cambiar los
parámetros del controlador y el nombre del método de acción en la llamada, para que coincidan
con los nuevos nombres que tienen ha cambiado

Con RouteLink() puede cambiar los detalles de la ruta en la llamada MapRoute() , en otras palabras,
en una ubicación, y no se requerirá que ningún código que haga referencia a esa ruta a través de
RouteLink() cambie.

Lea Html.RouteLink en línea: https://riptutorial.com/es/asp-net-mvc/topic/6209/html-routelink

https://riptutorial.com/es/home 56
Capítulo 16: Inyección de dependencia
Observaciones
Todo el punto de la inyección de dependencia (DI) es reducir el acoplamiento de código. Imagine
cualquier tipo de interacción que implique la creación de algo como en el "Ejemplo de
dependencia de código duro".

Una gran parte de escribir código es la capacidad de probarlo. Cada vez que creamos una nueva
dependencia, hacemos que nuestro código sea difícil de probar porque no tenemos control sobre
esa dependencia.

¿Cómo probaría el código que depende de DataTime.Now por ejemplo? Siempre cambia así que
no tienes referencia. Esto es cuando se inyecta un parámetro estable como su punto de partida.
Puede controlarlo, puede escribir pruebas basadas en varios valores y asegurarse de que
siempre obtenga el resultado correcto.

Por lo tanto, una buena opción es pasar una interfaz o una clase abstracta como un parámetro en
el constructor DI.

Una interfaz representa un contrato bien definido, siempre puede confiar en los métodos para
estar allí y siempre puede confiar en las firmas del método.

Una vez que empieces a usar DI se abrirán otros aspectos. Por ejemplo, incluso si pasa una
interfaz en algún momento, necesitará una implementación real para realizar cualquier trabajo.
Aquí es donde aparecen otros conceptos. Podemos usar IOC (Inversión de control) para resolver
nuestras dependencias. Esto significa que le indicamos a nuestro código que siempre use una
implementación específica para cualquier contrato. Por supuesto que hay otras formas de hacer
esto. Siempre podríamos crear una instancia de cada contrato con una implementación específica
y, a partir de ese momento, nuestro código puede usar esa parte:

public ILogging Logging { get; set }

En algún momento lo inicializamos.

Logging = new FileLogging();

esto siempre funcionará siempre y cuando nuestra clase cumpla con el contrato esperado:

public class FileLogging : ILogging

a partir del momento de inicialización siempre utilizamos el objeto de registro. Esto hace la vida
más fácil porque si alguna vez decidimos cambiar y usar un DatabaseLogging, por ejemplo, solo
tenemos que cambiar el código en un lugar y aquí es exactamente donde inicializamos la clase de
registro.

https://riptutorial.com/es/home 57
¿Es DI solo bueno para la prueba? No, DI también es importante al escribir código mantenible.
Permite que la separación de inquietudes sea clara.

Cuando escriba cualquier código, piense ... es comprobable, puedo escribir una prueba, es
cuando se inyecta un valor DateTime en lugar de usar DateTime. Ahora tiene sentido.

Examples
Configuraciones de Ninject

Después de la instalación de un contenedor IoC (Inversión de control), se necesitan algunos


ajustes para que funcione. En este caso, usaré Ninject. En el archivo NinjectWebCommon, que se
encuentra en la carpeta App_Start, sustituya el método CreateKernel con:

private static IKernel CreateKernel()


{
// Create the kernel with the interface to concrete bindings
var kernel = RegisterServices();
try
{
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

return kernel;
}
catch
{
kernel.Dispose();
throw;
}
}

Y el método RegisterServices con:

private static StandardKernel RegisterServices()


{
Container container = new Container();
// encapsulate the interface to concrete bindings in another class or even in
another layer
StandardKernel kernel = container.GetServices();
return kernel;
}

Cree una nueva clase para el enlace que en este caso se llama Container:

public class Container


{
public StandardKernel GetServices()
{
// It is good practice to create a derived class of NinjectModule to organize the
binding by concerns. In this case one for the repository, one for service and one for app
service bindings
return new StandardKernel(new NinjectRepositoryModule(),
new NinjectServiceModule(),

https://riptutorial.com/es/home 58
new NinjectAppServiceModule());
}
}

Finalmente, en cada clase de NinjectModule derivada modifique los enlaces que sobrecargan el
método de carga como:

public class NinjectRepositoryModule: NinjectModule


{
public override void Load()
{
// When we need a generic IRepositoryBase<> to bind to a generic RepositoryBase<>
// The typeof keyword is used because the target method is generic
Bind(typeof (IRepositoryBase<>)).To(typeof (RepositoryBase<>));

// When we need a IUnitOfWorkbind to UnitOfWork concrete class that is a singleton


Bind<IUnitOfWork>().To<UnitOfWork>().InSingletonScope();
}
}

Otro ejemplo de NinjectModule derivado:

public class NinjectServiceModule :NinjectModule


{
public override void Load()
{
// When we need a IBenefitService to BenefitService concrete class
Bind<IBenefitService>().To<BenefitService>();

// When we need a ICategoryService to CategoryService concrete class


Bind<ICategoryService>().To<CategoryService>();

// When we need a IConditionService to ConditionService concrete class


Bind<IConditionService>().To<ConditionService>();
}
}

Utilización de las interfaces.

En la clase concreta que necesita el servicio, use la interfaz para acceder al servicio en lugar de
su implementación como:

public class BenefitAppService


{
private readonly IBenefitService _service;
public BenefitAppService(IBenefitService service)
{
_service = service;
}

public void Update(Benefit benefit)


{
if (benefit == null) return
_service.Update(benefit);
_service.Complete();
}

https://riptutorial.com/es/home 59
}

Ahora, si necesita algo en la clase concreta, no interferirá en el código anterior. Puede cambiar la
implementación del servicio por otra diferencia completamente, y siempre que satisfaga la
interfaz, estará listo. También hace que sea muy fácil probarlo.

Inyección de dependencia del constructor

La Inyección de dependencia del constructor requiere parámetros en el constructor para inyectar


dependencias. Así que tienes que pasar los valores cuando creas un nuevo objeto.

public class Example


{
private readonly ILogging _logging;

public Example(ILogging logging)


{
this._logging = logging;
}
}

Dependencia codificada

public class Example


{
private FileLogging _logging;

public Example()
{
this._logging = new FileLogging();
}
}

parámetro DI

public DateTime SomeCalculation()


{
return DateTime.Now.AddDays(3);
}

vs

public DateTime SomeCalculation(DateTime inputDate)


{
return inputDate.AddDays(3);
}

Inyección De la Dependencia De Ninject

El resolvedor de dependencias se utiliza para evitar clases estrechamente acopladas, mejorar la


flexibilidad y facilitar las pruebas. Puede crear su propio inyector de dependencia (no

https://riptutorial.com/es/home 60
recomendado) o usar uno de los inyectores de dependencia bien escritos y probados. En este
ejemplo voy a usar Ninject .

Paso uno: Crear resolución de dependencias.

En primer lugar, descargue Ninject desde NuGet. Cree una carpeta llamada Infraestructura y
agregue una clase llamada NinjectDependencyResolver :

using Ninject;
using System;
using System.Collections.Generic;
using System.Web.Mvc;

public class NinjectDependencyResolver


: IDependencyResolver
{
private IKernel kernel;

public NinjectDependencyResolver()
{
// Initialize kernel and add bindings
kernel = new StandardKernel();
AddBindings();
}

public object GetService(Type serviceType)


{
return kernel.TryGet(serviceType);
}

public IEnumerable<object> GetServices(Type serviceType)


{
return kernel.GetAll(serviceType);
}

private void AddBindings()


{
// Bindings added here
}
}

El MVC Framework llamará a los métodos GetService y GetServices cuando necesite un aviso de
una clase para atender una solicitud entrante.

Paso dos: Registrar resolución de dependencias.

Ahora tenemos nuestro sistema de resolución de dependencias personalizado y debemos


registrarlo para que el marco MVC use nuestro sistema de resolución de dependencias. Registre
el resolvedor de dependencias en el archivo Global.asax.cs :

protected void Application_Start()


{
AreaRegistration.RegisterAllAreas();
DependencyResolver.SetResolver(new NinjectDependencyResolver());

// .....

https://riptutorial.com/es/home 61
}

Paso tres: Añadir los enlaces.

Imagina que tenemos la siguiente interfaz e implementación:

public interface ICustomCache


{
string Info { get; }
}

public class CustomCache : ICustomCache


{
public string Info
{
get
{
return "Hello from CustomCache.";
}
}
}

Si queremos usar CustomCache en nuestro controlador sin acoplarlo estrechamente con


CustomCache, entonces debemos vincular ICustomCache a CustomCache e inyectarlo usando
Ninject. Lo primero es lo primero, vincule ICustomCache a CustomCache agregando el siguiente
código al método AddBindings () de NinjectDependencyResolver :

private void AddBindings()


{
// Bindings added here
kernel.Bind<ICustomCache>().To<CustomCache>();
}

Luego prepare su controlador para inyección como se muestra a continuación:

public class HomeController : Controller


{
private ICustomCache CustomCache { get; set; }

public HomeController(ICustomCache customCacheParam)


{
if (customCacheParam == null)
throw new ArgumentNullException(nameof(customCacheParam));

CustomCache = customCacheParam;
}

public ActionResult Index()


{
// cacheInfo: "Hello from CustomCache."
string cacheInfo = CustomCache.Info;

return View();
}
}

https://riptutorial.com/es/home 62
Este es un ejemplo de inyección costructora y es una forma de inyección de dependencia . Como
puede ver, nuestro controlador de inicio no depende de la clase CustomCache itslef. Si queremos
usar otra implementación de ICustomCache en nuestra aplicación, lo único que debemos cambiar
es vincular a ICustomCache con otra implementación y ese es el único paso que debemos tomar.
¿Qué ha pasado aquí es, MVC marco pidió a nuestro solucionador de dependencias registrado
para crear una instancia de la clase HomeController a través del método GetService. El método
GetService le pide al kernel de Ninject que cree el objeto solicitado y el kernel de Ninject examina
el tipo en su término y descubre que el constructor de HomeController vuelve a poner un
ICustomCache y el enlace ya se ha agregado para el ICustomCache . Ninject crea una instancia
de clase enlazada, la usa para crear HomeController y la devuelve MVC Framework.

Cadenas de dependencia.

Cuando Ninject intenta crear un tipo, examina otras dependencias entre el tipo y otros tipos y, si
existe, Ninject intenta crearlos también. Por ejemplo, si nuestra clase CustomCache requiere
ICacheKeyProvider y si se agrega la combinación de ICacheKeyProvider, Ninject puede
proporcionarlo para nuestra clase.

Interfaz ICacheKeyProvider e implementación de SimpleCacheKeyProvider :

public interface ICacheKeyProvider


{
string GenerateKey(Type type);
}

public class SimpleCacheKeyProvider


: ICacheKeyProvider
{
public string GenerateKey(Type type)
{
if (type == null)
throw new ArgumentNullException(nameof(type));

return string.Format("{0}CacheKey", type.Name);


}
}

Clase modificada de CustomCache

public class CustomCache : ICustomCache


{
private ICacheKeyProvider CacheKeyProvider { get; set; }

public CustomCache(ICacheKeyProvider keyProviderParam)


{
if (keyProviderParam == null)
throw new ArgumentNullException(nameof(keyProviderParam));

CacheKeyProvider = keyProviderParam;
}

...........
}

https://riptutorial.com/es/home 63
Añadir enlace para ICacheKeyProvider :

private void AddBindings()


{
// Bindings added here
kernel.Bind<ICustomCache>().To<CustomCache>();
kernel.Bind<ICacheKeyProvider>().To<SimpleCacheKeyProvider>();
}

Ahora, cuando navegamos a HomeController, Ninject crea la instancia de


SimpleCacheKeyProvider la usa para crear CustomCache y usa la instancia de CustomCache
para crear HomeController .

Ninject tiene varias características excelentes, como la inyección de dependencia encadenada, y


debes examinarlas si quieres usar Ninject.

Lea Inyección de dependencia en línea: https://riptutorial.com/es/asp-net-


mvc/topic/6392/inyeccion-de-dependencia

https://riptutorial.com/es/home 64
Capítulo 17: jQuery Ajax Call Con Asp MVC
Examples
Publicar objetos JavaScript con jQuery Ajax Call

Ajax llama, solicita y recupera datos para brindar al usuario la sensación de una mejor experiencia
de interfaz de usuario interactiva. Este artículo le mostrará cómo usar jQuery y enviar datos a
través de llamadas Ajax. Para este ejemplo, vamos a enviar el siguiente objeto JavaScript a
nuestro servidor.

var post = {
title: " Posting JavaScript objects with jQuery Ajax Call",
content: " Posting JavaScript objects with jQuery Ajax Call",
tags: ["asp mvc", "jquery"]
};

El lado del servidor

El modelo del lado del servidor correspondiente al objeto javascript.

public class Post


{
public string Title { get; set; }
public string Content { get; set; }
public string[] Tags { get; set; }
}

Todo lo que necesitamos hacer es crear un método de controlador MVC ASP.NET estándar que
tome un solo parámetro del tipo Persona, como tal.

public class PostController : BaseController


{
public bool Create(Post model)
{
//Do somthing
}
}

El lado del cliente

Para enviar objetos de JavaScript, necesitamos usar el método JSON.stringify () para enviar el
objeto a la opción de datos.

$.ajax({
url: '@Url.Action("create", "Post")',
type: "POST",
contentType: "application/json",
data: JSON.stringify({ model: post })
}).done(function(result){

https://riptutorial.com/es/home 65
//do something
});

Lea jQuery Ajax Call Con Asp MVC en línea: https://riptutorial.com/es/asp-net-


mvc/topic/9734/jquery-ajax-call-con-asp-mvc

https://riptutorial.com/es/home 66
Capítulo 18: Manejo de errores Http
Introducción
Cada sitio web necesita para manejar los errores. Puede permitir que sus usuarios vean las
páginas de error 404 o 500 que IIS distribuye o, utilizando el Web.Config y un simple Controlador,
puede capturar estos errores y entregar sus propias páginas de error personalizadas.

Examples
Configuración básica

Este ejemplo cubrirá la creación de una página de error personalizada para 404 Página no
encontrada y 500 Error de servidor. Puede extender este código para capturar cualquier código
de error que necesite.

Web.Config

Si está utilizando IIS7 y superior, ignore el nodo <CustomError.. y use <httpErrors... lugar.

Agregue lo siguiente en el nodo system.webServer :

<httpErrors errorMode="Custom" existingResponse="Replace">


<remove statusCode="404" />
<remove statusCode="500" />
<error statusCode="404" path="/error/notfound" responseMode="ExecuteURL" />
<error statusCode="500" path="/error/servererror" responseMode="ExecuteURL" />
</httpErrors>

Esto le indica al sitio que dirija cualquier error 404 a ~/error/notfound y cualquier error 500 a
~/error/servererror . También conservará la URL solicitada (piense en transferir en lugar de
redirigir ) para que el usuario nunca vea la URL de la página ~/error/...

A continuación, necesita un nuevo controlador de Error así que ...

public class ErrorController : Controller


{
public ActionResult servererror()
{
Response.TrySkipIisCustomErrors = true;
Response.StatusCode = (int)HttpStatusCode.InternalServerError;
return View();
}

public ActionResult notfound()


{
Response.TrySkipIisCustomErrors = true;
Response.StatusCode = (int)HttpStatusCode.NotFound;
return View();
}

https://riptutorial.com/es/home 67
}

La clave a tener en cuenta aquí es el Response.TrySkipIisCustomErrors = true; . Esto evitará IIS y


forzará su página de error.

Por último, cree las NotFound correspondientes de NotFound y NotFound y ServerError estilo para que
todo esté bien y sin problemas con el diseño de tu sitio.

Hola presto - páginas de error personalizadas.

Lea Manejo de errores Http en línea: https://riptutorial.com/es/asp-net-mvc/topic/9137/manejo-de-


errores-http

https://riptutorial.com/es/home 68
Capítulo 19: Maquinilla de afeitar
Introducción
¿Qué es Razor?

Razor es una sintaxis de marcado que le permite incrustar código basado en servidor (Visual
Basic y C #) en páginas web.

El código basado en servidor puede crear contenido web dinámico sobre la marcha, mientras que
una página web se escribe en el navegador. Cuando se llama a una página web, el servidor
ejecuta el código basado en el servidor dentro de la página antes de devolver la página al
navegador. Al ejecutarse en el servidor, el código puede realizar tareas complejas, como acceder
a bases de datos.

Sintaxis
• @ {...}
• @nombre de la variable
• @(nombre de la variable)
• @para(...){ }
• @ (Expresión explícita)
• @ * comentarios * @

Observaciones
ASP.NET Razor incluye motores de visualización para C # y VB.

El motor de visualización C # procesa archivos con una extensión .cshtml , mientras que el motor
de visualización VB funciona con archivos .vbhtml .

Examples
Añadir comentarios

Razor tiene su propia sintaxis de comentario que comienza con @* y termina con *@ .

Comentario en línea:

<h1>Comments can be @*hi!*@ inline</h1>

Comentario multilínea:

@* Comments can spread


over multiple

https://riptutorial.com/es/home 69
lines *@

Comentario HTML

También puede usar la sintaxis de comentario HTML normal comenzando con <!-- y terminando
con --> en las vistas de Razor. Pero a diferencia de otros comentarios, el código Razor dentro de
un comentario HTML todavía se ejecuta normalmente.

@{
var hello = "Hello World!";
}
<!-- @hello -->

El ejemplo anterior produce el siguiente resultado HTML:

<!-- Hello World! -->

Comentarios dentro de un bloque de código:

@{
// This is a comment
var Input = "test";
}

Mostrar HTML dentro del bloque de código Razor

Mientras se encuentre dentro de un bloque de código de Razor, el navegador solo reconocerá el


código HTML si se escapa el código.

Use @: para una sola línea:

@foreach(int number in Model.Numbers)


{
@:<h1>Hello, I am a header!</h1>
}

Utilice <text> ... </text> para multilínea:

@{
var number = 1;

<text>
Hello, I am text
<br / >
Hello, I am more text!
</text>
}

Tenga en cuenta que Razor, cuando está dentro de un bloque de código, entenderá las etiquetas
HTML. Por lo tanto, agregar la etiqueta de text alrededor de las etiquetas HTML es innecesario
(aunque sigue siendo correcto), como por ejemplo:

https://riptutorial.com/es/home 70
@{
var number = 1;
<text>
<div>
Hello, I am text
<br / >
Hello, I am more text!
</div>
</text>
}

Sintaxis basica

El código Razor se puede insertar en cualquier lugar dentro del código HTML. Los bloques de
código de la maquinilla de afeitar están incluidos en @{ ... } . Las variables y funciones en línea
comienzan con @ . El código dentro de los soportes de Razor sigue las reglas normales de C # o
VB.

Declaración de una sola línea:

@{ var firstNumber = 1; }

Bloque de código multilínea:

@{
var secondNumber = 2;
var total = firstNumber + secondNumber;
}

Usando una variable en línea:

<h1>The total count is @total</h1>

Usando una variable en línea explícitamente :

<h2>Item@(item.Id)</h2>

Para este ejemplo en particular, no podremos usar la sintaxis implícita porque Item@item.Id parece
un correo electrónico y Razor lo procesará como tal.

Adjuntar código dentro de las declaraciones de flujo de control:

<h1>Start with some HTML code</h1>

@for (int i = 0; i < total; i++){


Console.Write(i);
}

<p>Mix in some HTML code for fun!</p>


<p>Add a second paragraph.</p>

@if (total > 3)

https://riptutorial.com/es/home 71
{
Console.Write("The total is greater than 3");
}
else
{
Console.Write("The total is less than 3");
}

Esta misma sintaxis se usaría para todas las declaraciones como for , foreach , while , if , switch ,
etc.

Agregando código dentro del código:

@if (total > 3)


{
if(total == 10)
{
Console.Write("The total is 10")
}
}

Tenga en cuenta que no necesita escribir la @ en el segundo if . Después del código,


simplemente puede escribir otro código detrás del código existente.

Si desea agregar código después de un elemento HTML , debe escribir a @ .

Escapando a @ personaje

En muchos casos, el analizador Razor es lo suficientemente inteligente como para determinar


cuándo el signo @ debe utilizarse como parte del código, en lugar de ser parte de algo como una
dirección de correo electrónico. En el siguiente ejemplo, no es necesario escapar del signo @ :

<p>Reach out to us at contact@mail.com</p>

Sin embargo, en algunos casos, el uso del signo @ es más ambiguo, y debe evitarse
explícitamente con @@ , como se muestra en el siguiente ejemplo:

<p>Join us @@ Stack Overflow!</p>

Alternativamente, podemos usar un carácter @ codificado en HTML

<p>Join us &#64; Stack Overflow!</p>

Crear clases y métodos en línea usando funciones @

El uso de la palabra clave Razor @functions brinda la capacidad de introducir clases y métodos
para el uso en línea dentro de un archivo Razor:

@functions
{

https://riptutorial.com/es/home 72
string GetCssClass(Status status)
{
switch (status)
{
case Status.Success:
return "alert-success";
case Status.Info:
return "alert-info";
case Status.Warning:
return "alert-warning";
case Status.Danger:
default:
return "alert-danger";
}
}
}

<label class="alert @GetCssClass(status)"></label>

Lo mismo se puede hacer para las clases:

@functions
{
class Helpers
{
//implementation
}
}

Agregando un atributo personalizado con - (guión) en el nombre

Si necesita agregar un atributo a través de la maquinilla de afeitar que tiene un - (guión) en el


nombre, simplemente no puede hacer

@Html.DropDownListFor(m => m.Id, Model.Values, new { @data-placeholder = "whatever" })

no compilará Los atributos de data- * son válidos y comunes en html5 para agregar valores extra
a los elementos.

Sin embargo lo siguiente funcionará

@Html.DropDownListFor(m => m.Id, Model.Values, new { @data_placeholder = "whatever" })

ya que "_" se reemplaza con "-" cuando se procesa.

Esto funciona bien ya que los guiones bajos no son aceptables en los nombres de atributos en
html.

Plantillas de editor

Las plantillas de editor son una buena manera de reutilizar el código Razor. Puede definir
plantillas de editor como vistas parciales de Razor y luego usarlas en otras vistas.

https://riptutorial.com/es/home 73
Las plantillas de editor generalmente existen en la carpeta Views/Shared/EditorTemplates/ , aunque
también se pueden guardar en la carpeta Views/ControllerName/EditorTemplates/ . El nombre de la
vista suele ser el nombre del objeto para el que desea utilizar la plantilla, como <type>.cshtml .

Aquí hay una plantilla de editor simple para DateTime:

@model DateTime
<div>
<span>
@Html.TextBox("", Model.ToShortDateString(), new { data_date_picker="true" })
</span>
</div>

Guarde el archivo como Views / Shared / EditorTemplate / DateTime.cshtml .

Luego, use EditorFor para llamar a este código de plantilla en otra vista:

@Html.EditorFor(m => m.CreatedDate)

También hay un atributo UIHint para especificar el nombre del archivo:

public class UiHintExampleClass


{
[UIHint("PhoneNumber")]
public string Phone { get; set; }
}

Defina esta plantilla de número de teléfono en Views / Shared / EditorTemplates /


PhoneNumber.cshtml .

Las plantillas de editor también se pueden definir para tipos personalizados.

Aquí hay un tipo personalizado llamado SubModel :

public class SubModel


{
public Guid Id { get; set;}
public string FirstName { get; set; }
public string LastName { get; set; }
}

public class Model


{
public Guid Id { get; set; }
public DateTime Created {get; set; }

public SubModel SubModel{get; set; }


}

Este es el EditorTemplate para SubModel:

https://riptutorial.com/es/home 74
@model SubModel
<div class="form-group">
@Html.LabelFor(m => m.FirstName)
@Html.TextBoxFor(m => m.FirstName)
</div>
<div class="form-group">
@Html.LabelFor(m => m.LastName)
@Html.TextBoxFor(m => m.LastName)
</div>

Ahora, la vista para el modelo simplemente se convierte en:

@model Model
@Html.EditorFor(m => m.CreatedDate)
@Html.EditorFor(m => m.SubModel, new { @Prefix = "New"})
@* the second argument is how you can pass viewdata to your editor template*@

Pase el contenido de Razor a un @helper

Envía una parte de Razor a un @helper, por ejemplo, un div HTML.

@helper WrapInBox(Func<Object, HelperResult> content)


{
<div class="box">@content(null) </div>
}

//call
@WrapInBox(@<div>
I'm a inner div
</div>)

Compartir @helpers a través de vistas

@Ayudantes podrían ser compartidos entre vistas.

Deben ser creados en la carpeta App_Code

@helper CreatePrimaryBootstrapButton(string label)


{
<button type="button" class="btn btn-primary">@label</button>
}

//call

@MenuHelpers.CreatePrimaryBootstrapButton("my button")

Los globales @Url y @Html no están disponibles de forma predeterminada en @Helper definido en
App_code. Puede agregarlos de la siguiente manera (para cada .cshtml en su carpeta App_code)

https://riptutorial.com/es/home 75
@* Make @Html and @Url available *@
@functions
{
private new static HtmlHelper<object> Html
{
get { return ((WebViewPage)CurrentPage).Html; }
}

private static UrlHelper Url


{
get { return ((WebViewPage)CurrentPage).Url; }
}
}

Lea Maquinilla de afeitar en línea: https://riptutorial.com/es/asp-net-mvc/topic/5266/maquinilla-de-


afeitar

https://riptutorial.com/es/home 76
Capítulo 20: Modelo de enlace
Introducción
El enlace de modelo es el proceso de tomar parámetros HTTP, normalmente en la Cadena de
consulta de una solicitud GET, o dentro del cuerpo POST, y aplicarlo en un objeto que luego
puede validarse y consumirse de una manera orientada a objetos sin la necesidad de acciones
del Controlador tener un conocimiento íntimo de cómo recuperar los parámetros HTTP.

En otras palabras, el enlace de modelo es lo que permite que las acciones, en MVC, tengan
cualquiera de los parámetros, ya sea un tipo de valor o un objeto.

Observaciones
Para intentar crear una instancia en la acción, el proceso del modelo de enlace buscará datos en
varios lugares:

• Datos del formulario


• Datos de ruta
• Cadena de consulta
• Archivos personalizados (cookies, por ejemplo)

Examples
Enlace de valor de ruta

Dado algún enrutamiento predeterminado como {controller=Home}/{action=Index}/{id?} Si tiene la


url https://stackoverflow.com/questions/1558902

Esto iría al QuestionsController y el valor 1558902 se asignaría a un parámetro id de una acción


de índice, es decir,

public ActionResult Index(int? id){


//id would be bound to id of the route
}

Enlace de cadena de consulta

Para ampliar la vinculación de ruta, diga que tiene una URL como
https://stackoverflow.com/questions/1558902?sort=desc

y enrutamiento como {controller=Home}/{action=Index}/{id?}

public ActionResult Index(int? id, string sort){


//sort would bind to the value in the query string, i.e. "desc"
}

https://riptutorial.com/es/home 77
Atadura a objetos

A menudo, estarías trabajando con clases de viewmodel en asp.net-mvc y querrías unirte a las
propiedades en estas. Esto funciona de manera similar a la asignación a parámetros individuales.

Digamos que tienes un modelo de vista simple llamado PostViewModel como este

public class PostViewModel{


public int Id {get;set;}
public int SnappyTitle {get;set;}
}

Luego, publicó los valores de Id y SnappyTitle desde un formulario en la solicitud http y luego se
mapearían directamente en ese modelo si el modelo en sí fuera el parámetro de acción, por
ejemplo

public ActionResult UpdatePost(PostViewModel viewModel){


//viewModel.Id would have our posted value
}

Vale la pena señalar que el enlace no distingue entre mayúsculas y minúsculas para los nombres
de parámetros y propiedades. También emitirá valores cuando sea posible. Estoy dejando más
casos de borde para ejemplos específicos

Ajax vinculante

Estos son valores de formulario que van en la solicitud HTTP usando el método POST. (incluidas
las solicitudes POST de jQuery).

Digamos que hiciste un post de ajax como

$.ajax({
type: 'POST',
url: window.updatePost,
data: { id: 21, title: 'snappy title' },
//kept short for clarity
});

Aquí los dos valores en json, id y title, estarían vinculados a la acción correspondiente, por
ejemplo,

public JsonResult UpdatePost(int id, string title) {


...
}

Generic, enlace basado en modelo de sesión

A veces necesitamos preservar todo el modelo y transferirlo a través de acciones o incluso


controladores. Almacenamiento de modelo en la sesión buena solución para este tipo de

https://riptutorial.com/es/home 78
requisitos. Si combinamos esto con las poderosas características de unión de modelos de MVC,
obtendremos una forma elegante de hacerlo. Podemos crear un enlace de modelo basado en
sesión genérica en tres sencillos pasos:

Paso uno: Crear carpeta de modelos

Crear un cuaderno de modelo en sí. Personalmente creé la clase SessionDataModelBinder en la


carpeta / Infrastructure / ModelBinders .

using System;
using System.Web.Mvc;

public class SessionDataModelBinder<TModel>


: IModelBinder
where TModel : class
{
private string SessionKey { get; set; }

public SessionDataModelBinder(string sessionKey)


{
if (string.IsNullOrEmpty(sessionKey))
throw new ArgumentNullException(nameof(sessionKey));
SessionKey = sessionKey;
}

public object BindModel(


ControllerContext controllerContext,
ModelBindingContext bindingContext)
{
// Get model from session
TModel model = controllerContext
.HttpContext
.Session[SessionKey] as TModel;
// Create model if it wasn't found from session and store it
if (model == null)
{
model = Activator.CreateInstance<TModel>();
controllerContext.HttpContext.Session[SessionKey] = model;
}
// Return the model
return model;
}
}

Paso dos: registrar carpeta

Si tenemos modelo como abajo:

public class ReportInfo


{
public int ReportId { get; set; }
public ReportTypes TypeId { get; set; }
}

public enum ReportTypes


{
NotSpecified,

https://riptutorial.com/es/home 79
Monthly, Yearly
}

Podemos registrar el cuaderno de modelos basado en sesión para este modelo en Global.asax
en el método Application_Start :

protected void Application_Start()


{
.........

// Model binders.
// Remember to specy unique SessionKey
ModelBinders.Binders.Add(typeof(ReportInfo),
new SessionDataModelBinder<ReportInfo>("ReportInfo"));
}

Paso tres: ¡úsalo!

Ahora podemos beneficiarnos de este modelo de carpeta simplemente agregando un parámetro a


nuestras acciones :

public class HomeController : Controller


{
public ActionResult Index(ReportInfo reportInfo)
{
// Simply set properties
reportInfo.TypeId = ReportTypes.Monthly;

return View();
}

public ActionResult About(ReportInfo reportInfo)


{
// reportInfo.TypeId is Monthly now because we set
// it previously in Index action.
ReportTypes currentReportType = reportInfo.TypeId;

return View();
}
}

Prevenir el enlace en PostModel

Considerando un modelo (post):

public class User


{
public string FirstName { get; set; }
public bool IsAdmin { get; set; }
}

Con una vista así:

@using (Html.BeginForm()) {

https://riptutorial.com/es/home 80
@Html.EditorFor(model => model.FirstName)
<input type="submit" value="Save" />
}

Para evitar que un usuario malintencionado asigne IsAdmin, puede usar el atributo Bind en la
acción:

[HttpPost]
public ViewResult Edit([Bind(Exclude = "IsAdmin")] User user)
{
// ...
}

Subir archivo

Modelo:

public class SampleViewModel


{
public HttpPostedFileBase file {get;set;}
}

Ver:

@model HelloWorldMvcApp.SampleViewModel

@using (Html.BeginForm("Index","Home",FormMethod.Post, new { enctype = "multipart/form-data"


}))
{
<div class="form-group">
@Html.TextBoxFor(model => model.file, new {@class="form-control", type="file"})
@Html.ValidationMessageFor(model => model.file)
</div>

<button type="submit" class="btn btn-success submit">Upload</button>


}

Acción:

[HttpPost]
public ActionResult Index(SampleViewModel model)
{

if (model.file.ContentLength > 0)
{
string fileName = Path.GetFileName(model.file.FileName);
string fileLocation = "~/App_Data/uploads/"+ fileName;
model.file.SaveAs(Server.MapPath(fileLocation));
}
return View(model);
}

Validación de campos de fecha manualmente con formatos dinámicos

https://riptutorial.com/es/home 81
utilizando el cuaderno de modelos

Si diferentes usuarios necesitan un formato de fecha y hora diferente, es posible que deba
analizar su cadena de fecha entrante a la fecha real de acuerdo con el formato. En este caso este
fragmento puede ayudarte.

public class DateTimeBinder : DefaultModelBinder


{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext
bindingContext)
{

var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);


DateTime date;
var displayFormat = Session["DateTimeFormat"];
if (value.AttemptedValue != "")
{
if (DateTime.TryParseExact(value.AttemptedValue, displayFormat,
CultureInfo.InvariantCulture, DateTimeStyles.None, out date))
{
return date;
}
else
{
bindingContext.ModelState.AddModelError(bindingContext.ModelName,
"Invalid date format");
}
}
}

return base.BindModel(controllerContext, bindingContext);


}

Lea Modelo de enlace en línea: https://riptutorial.com/es/asp-net-mvc/topic/1258/modelo-de-


enlace

https://riptutorial.com/es/home 82
Capítulo 21: Modelo de validación
Examples
Validar modelo en ActionResult

[HttpPost]
public ActionResult ContactUs(ContactUsModel contactObject)
{
// This line checks to see if the Model is Valid by verifying each Property in the Model
meets the data validation rules
if(ModelState.IsValid)
{
}
return View(contactObject);
}

La clase modelo

public class ContactUsModel


{
[Required]
public string Name { get; set; }
[Required]
[EmailAddress] // The value must be a valid email address
public string Email { get; set; }
[Required]
[StringLength(500)] // Maximum length of message is 500 characters
public string Message { get; set; }
}

Eliminar un objeto de la validación

Digamos que tienes el siguiente modelo:

public class foo


{
[Required]
public string Email { get; set; }

[Required]
public string Password { get; set; }

[Required]
public string FullName { get; set; }
}

Pero desea excluir FullName de la validación del modelo porque está utilizando el modelo
también en un lugar donde FullName no está completo, puede hacerlo de la siguiente manera:

ModelState.Remove("FullName");

https://riptutorial.com/es/home 83
Mensajes de error personalizados

Si desea proporcionar mensajes de error personalizados, lo haría así:

public class LoginViewModel


{
[Required(ErrorMessage = "Please specify an Email Address")]
[EmailAddress(ErrorMessage = "Please specify a valid Email Address")]
public string Email { get; set; }

[Required(ErrorMessage = "Type in your password")]


public string Password { get; set; }
}

Cuando sus mensajes de error están en un archivo de recursos (.resx), debe especificar el tipo de
recurso y el nombre del recurso:

public class LoginViewModel


{
[Required(ErrorMessageResourceType = typeof(ErrorResources), ErrorMessageResourceName =
"LoginViewModel_RequiredEmail")]
[EmailAddress(ErrorMessageResourceType = typeof(ErrorResources), ErrorMessageResourceName
= "LoginViewModel_ValidEmail")]
public string Email { get; set; }

[Required(ErrorMessageResourceType = typeof(ErrorResources), ErrorMessageResourceName =


"LoginViewModel_RequiredPassword")]
public string Password { get; set; }
}

Creando mensajes de error personalizados en el modelo y en el controlador

Digamos que tienes la siguiente clase:

public class PersonInfo


{
public int ID { get; set; }

[Display(Name = "First Name")]


[Required(ErrorMessage = "Please enter your first name!")]
public string FirstName{ get; set; }

[Display(Name = "Last Name")]


[Required(ErrorMessage = "Please enter your last name!")]
public string LastName{ get; set; }

[Display(Name = "Age")]
[Required(ErrorMessage = "Please enter your Email Address!")]
[EmailAddress(ErrorMessage = "Invalid Email Address")]
public string EmailAddress { get; set; }
}

Estos mensajes de error personalizados aparecerán si su ModelState.IsValid devuelve falso.

Pero tanto usted como yo sabemos que solo puede haber 1 dirección de correo electrónico por

https://riptutorial.com/es/home 84
persona, o bien enviará correos electrónicos a personas potencialmente equivocadas y / o varias
personas. Aquí es donde entra en juego el control del controlador. Así que asumamos que las
personas están creando cuentas para que las guarde a través de Crear acción.

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "ID, FirstName, LastName, EmailAddress")]
PersonInfo newPerson)
{
if(ModelState.IsValid) // this is where the custom error messages on your model will
display if return false
{
if(database.People.Any(x => x.EmailAddress == newPerson.EmailAddress)) // checking if
the email address that the new person is entering already exists.. if so show this error
message
{
ModelState.AddModelError("EmailAddress", "This email address already exists!
Please enter a new email address!");
return View(newPerson);
}

db.Person.Add(newPerson);
db.SaveChanges():
return RedirectToAction("Index");
}

return View(newPerson);
}

Espero que esto sea capaz de ayudar a alguien!

Validación de modelos en JQuery.

En los casos en que necesite asegurar la validación del modelo utilizando Jquery, se puede usar
la función .valid ().

Los campos de la clase modelo.

[Required]
[Display(Name = "Number of Hospitals")]
public int Hospitals{ get; set; }
[Required]
[Display(Name = "Number of Beds")]
public int Beds { get; set; }

El código de vista

@using (Html.BeginForm(new {id = "form1", @class = "form-horizontal" }))


{

<div class="divPanel">
<div class="row">
<div class="col-md-3">
@Html.LabelFor(m => m.Hospitals)
@Html.TextBoxFor(m => m.Hospitals, new { @class = "form-control", @type =

https://riptutorial.com/es/home 85
"number"})
@Html.ValidationMessageFor(m => m.Hospitals)

</div>
<div class="col-md-3">

@Html.LabelFor(m => m.Beds)


@Html.TextBoxFor(m => m.Beds, new { @class = "form-control", @type = "number"})
@Html.ValidationMessageFor(m => m.Beds)
</div>
<div class="col-md-3">
<button type=button class="btn btn-primary" id="btnCalculateBeds"> Calculate
Score</button>
</div>
</div>

</div>
}

El script para la verificación de validación.

$('#btnCalculateBeds').on('click', function (evt) {


evt.preventDefault();

if ($('#form1').valid()) {
//Do Something.
}
}

Asegúrese de que los archivos jquery.validate y jquery.validate.unobtrusive estén presentes en


la solución.

Lea Modelo de validación en línea: https://riptutorial.com/es/asp-net-mvc/topic/2683/modelo-de-


validacion

https://riptutorial.com/es/home 86
Capítulo 22: MVC vs Formularios Web
Introducción
Antes de saltar a ASP. Para desarrollar su aplicación web con NET MVC, debe considerar las
ventajas y desventajas del marco y debe saber que existe otro marco web creado y mantenido
por Microsoft que es ASP .NET Web Forms.

El que debe elegir es una cuestión de conocimiento de ambas tecnologías.

Sintaxis
• El motor de vista ASPX utiliza "<% =%>" o "<%:%>" para representar el contenido del lado
del servidor.

• El Razor View Engine usa @ para representar el contenido del lado del servidor.

Observaciones
https://www.asp.net/web-forms

https://www.asp.net/mvc

Examples
Ventajas de los formularios web ASP .NET

• Controles previos a la compilación para manejar cuadrículas, entradas, gráficos, árboles,


etc.

• Admite un modelo de evento que conserva el estado a través de HTTP, lo que beneficia el
desarrollo de aplicaciones web de línea de negocio. La aplicación basada en Web Forms
proporciona docenas de eventos que son compatibles con cientos de controles de servidor.

• Utiliza un patrón de controlador de página que agrega funcionalidad a páginas individuales.


Para obtener más información, consulte Controlador de página en el sitio web de MSDN.

• Utiliza el estado de vista o los formularios basados en servidor, lo que puede facilitar la
administración de la información de estado.

• Funciona bien para pequeños equipos de desarrolladores y diseñadores web que desean
aprovechar la gran cantidad de componentes disponibles para el rápido desarrollo de
aplicaciones.

• En general, es menos complejo para el desarrollo de aplicaciones, porque los componentes

https://riptutorial.com/es/home 87
(la clase de página, los controles, etc.) están estrechamente integrados y generalmente
requieren menos código que el modelo MVC.

• Modelo de desarrollo fácil para aquellos desarrolladores que vienen del desarrollo de
WindowsForm.

¿Qué es Web Forms?

Ventajas de una aplicación web basada en MVC

• Facilita la administración de la complejidad al dividir una aplicación en el modelo, la vista y


el controlador (Separación de inquietudes).

• No utiliza el estado de vista ni los formularios basados en servidor. Esto hace que el marco
MVC sea ideal para los desarrolladores que desean un control total sobre el
comportamiento de una aplicación.

• Utiliza un patrón de controlador frontal que procesa las solicitudes de aplicaciones web a
través de un solo controlador. Esto le permite diseñar una aplicación que admita una
infraestructura de enrutamiento enriquecida. Para obtener más información, consulte Front
Controller en el sitio web de MSDN.

• Proporciona un mejor soporte para el desarrollo guiado por pruebas (TDD).

• Funciona bien para aplicaciones web que son compatibles con grandes equipos de
desarrolladores y diseñadores web que necesitan un alto grado de control sobre el
comportamiento de la aplicación.

¿Qué es Web Forms?

Desventajas

Formularios Web:

• Ciclo de vida de la página compleja: cada vez que se realiza una solicitud al servidor,
existen al menos 5 métodos para ejecutar antes del controlador de eventos.
• Es difícil trabajar con marcos del lado del cliente como JQuery o Angular.
• Difícil trabajar con Javascript asíncrono y XML (AJAX)
• Manejo de ViewState
• El lado del cliente de la página y el código posterior están estrechamente acoplados.

MVC:

• Se tarda más tiempo en desarrollarse en comparación con Web Forms.


• Los datos se envían en formato de texto sin cifrar al servidor, mientras que en los
formularios web, los datos de estado se cifran de forma predeterminada.

Razor View Engine VS ASPX View Engine

https://riptutorial.com/es/home 88
Razor (MVC) ASPX (Formularios Web)

El espacio de nombres utilizado


El espacio de nombres utilizado por ASPX View Engine
por Razor View Engine es
es System.Web.Mvc.WebFormViewEngine
System.Web.Razor

Las extensiones de archivo


Las extensiones de archivo utilizadas por los motores de
utilizadas por el motor de vista
vista de formulario web son como los formularios web de
de Razor son diferentes de un
ASP.Net. Utiliza la extensión ASPX para ver la extensión
motor de vista de formulario web.
aspc para vistas parciales o Controles de usuario o
Utiliza cshtml con C # y vbhtml
plantillas y extensiones maestras para diseño / páginas
con vb para vistas, vista parcial,
maestras.
plantillas y páginas de diseño.

El motor de vista de formulario web no es compatible con


El motor Razor es compatible
Test Driven Development (TDD) porque depende de la
con el desarrollo guiado por
clase System.Web.UI.Page para hacer la prueba
pruebas (TDD).
compleja.

ASPX View Engine VS Razor View Engine

Lea MVC vs Formularios Web en línea: https://riptutorial.com/es/asp-net-mvc/topic/8584/mvc-vs-


formularios-web

https://riptutorial.com/es/home 89
Capítulo 23: Operación CRUD
Introducción
La operación CRUD se refiere a las operaciones clásicas (crear, leer, actualizar, eliminar)
relacionadas con los datos.

En el contexto de ASP MVC, hay varias formas de CRUD sus datos utilizando Modelos y,
posteriormente, vistas, Controladores.

Una forma sencilla es hacer uso de la función de andamiaje proporcionada por las plantillas de
Visual Studio y personalizarla según sus necesidades.

Tenga en cuenta que CRUD está muy bien definido y tiene muchas variaciones para satisfacer
sus necesidades. Por ejemplo, primero la base de datos, primero la entidad, etc.

Observaciones
Para simplificar, esta operación CRUD utiliza un contexto de marco de entidad en el controlador.
No es una buena práctica, pero está fuera del alcance de este tema. Haga clic en el marco de la
entidad si desea obtener más información al respecto.

Examples
Crear - Parte del controlador

Para implementar la funcionalidad de crear necesitamos dos acciones: GET y POST .

1. La acción GET utilizada para devolver la vista muestra un formulario que permite al usuario
ingresar datos usando elementos HTML. Si hay algunos valores predeterminados que
deben insertarse antes de que el usuario agregue datos, debe asignarse a las propiedades
del modelo de vista en esta acción.

2. Cuando el usuario complete el formulario y haga clic en el botón "Guardar", trataremos los
datos del formulario. Por eso ahora necesitamos la acción POST . Este método será
responsable de administrar los datos y guardarlos en la base de datos. En caso de cualquier
error, la misma vista devuelta con datos de formulario almacenados y mensaje de error
explica qué problema ocurre después de enviar la acción.

Implementaremos estos dos pasos dentro de dos métodos Create () dentro de nuestra clase de
controlador.

// GET: Student/Create
// When the user access this the link ~/Student/Create a get request is made to controller
Student and action Create, as the page just need to build a blank form, any information is
needed to be passed to view builder

https://riptutorial.com/es/home 90
public ActionResult Create()
{
// Creates a ViewResult object that renders a view to the response.
// no parameters means: view = default in this case Create and model = null
return View();
}

// POST: Student/Create
[HttpPost]
// Used to protect from overposting attacks, see
http://stackoverflow.com/documentation/asp.net-mvc/1997/html-antiforgerytoke for details
[ValidateAntiForgeryToken]
// This is the post request with forms data that will be bind the action, if in the data
post request have enough information to build a Student instance that will be bind
public ActionResult Create(Student student)
{
try
{
//Gets a value that indicates whether this instance received from the view is valid.
if (ModelState.IsValid)
{
// Adds to the context
db.Students.Add(student);
// Persist the data
db.SaveChanges();
// Returns an HTTP 302 response to the browser, which causes the browser to
make a GET request to the specified action, in this case the index action.
return RedirectToAction("Index");
}
}
catch
{
// Log the error (uncomment dex variable name and add a line here to write a log).
ModelState.AddModelError("", "Unable to save changes. Try again, and if the
problem persists see your system administrator.");
}
// view = default in this case Create and model = student
return View(student);
}

Crear - Ver parte

@model ContosoUniversity.Models.Student

//The Html.BeginForm helper Writes an opening <form> tag to the response. When the user
submits the form, the request will be processed by an action method.
@using (Html.BeginForm())
{
//Generates a hidden form field (anti-forgery token) that is validated when the form is
submitted.
@Html.AntiForgeryToken()

<div class="form-horizontal">
<h4>Student</h4>
<hr />

//Returns an unordered list (ul element) of validation messages that are in the
ModelStateDictionary object.
@Html.ValidationSummary(true, "", new { @class = "text-danger" })

https://riptutorial.com/es/home 91
<div class="form-group">
//Returns an HTML label element and the property name of the property that is
represented by the specified expression.
@Html.LabelFor(model => model.LastName, htmlAttributes: new { @class = "control-label
col-md-2" })

<div class="col-md-10">
//Returns an HTML input element for each property in the object that is
represented by the Expression expression.
@Html.EditorFor(model => model.LastName, new { htmlAttributes = new { @class =
"form-control" } })

//Returns the HTML markup for a validation-error message for each data field that
is represented by the specified expression.
@Html.ValidationMessageFor(model => model.LastName, "", new { @class = "text-
danger" })
</div>
</div>

<div class="form-group">
@Html.LabelFor(model => model.FirstMidName, htmlAttributes: new { @class = "control-
label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.FirstMidName, new { htmlAttributes = new { @class =
"form-control" } })
@Html.ValidationMessageFor(model => model.FirstMidName, "", new { @class = "text-
danger" })
</div>
</div>

<div class="form-group">
@Html.LabelFor(model => model.EnrollmentDate, htmlAttributes: new { @class = "control-
label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.EnrollmentDate, new { htmlAttributes = new { @class
= "form-control" } })
@Html.ValidationMessageFor(model => model.EnrollmentDate, "", new { @class =
"text-danger" })
</div>
</div>

<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}

<div>
//Returns an anchor element (a element) the text is Back to List and action is Index
@Html.ActionLink("Back to List", "Index")
</div>

Detalles - parte del controlador

Al ser url ~/Student/Details/5 : (~: raíz del sitio, Student: Controller, Details: Action, 5: student id),
es posible recuperar al alumno por su id.

https://riptutorial.com/es/home 92
// GET: Student/Details/5
public ActionResult Details(int? id)
{
// it good practice to consider that things could go wrong so,it is wise to have a
validation in the controller
if (id == null)
{
// return a bad request
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Student student = db.Students.Find(id);
if (student == null)
{
// if doesn't found return 404
return HttpNotFound();
}
return View(student);
}

Detalles - Ver parte

// Model is the class that contains the student data send by the controller and will be
rendered in the view
@model ContosoUniversity.Models.Student

<h2>Details</h2>

<div>
<h4>Student</h4>
<hr />
<dl class="dl-horizontal">
<dt>
//Gets the display name for the model.
@Html.DisplayNameFor(model => model.LastName)
</dt>

<dd>
//Returns HTML markup for each property in the object that is represented by the
Expression expression.
@Html.DisplayFor(model => model.LastName)
</dd>

<dt>
@Html.DisplayNameFor(model => model.FirstMidName)
</dt>

<dd>
@Html.DisplayFor(model => model.FirstMidName)
</dd>

<dt>
@Html.DisplayNameFor(model => model.EnrollmentDate)
</dt>

<dd>
@Html.DisplayFor(model => model.EnrollmentDate)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Enrollments)

https://riptutorial.com/es/home 93
</dt>
<dd>
<table class="table">
<tr>
<th>Course Title</th>
<th>Grade</th>
</tr>
@foreach (var item in Model.Enrollments)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Course.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.Grade)
</td>
</tr>
}
</table>
</dd>
</dl>
</div>
<p>
//Returns an anchor element (a element) the text is Edit, action is Edit and the route
value is the model ID property.
@Html.ActionLink("Edit", "Edit", new { id = Model.ID }) |
@Html.ActionLink("Back to List", "Index")
</p>

Editar - parte del controlador

// GET: Student/Edit/5
// It is receives a get http request for the controller Student and Action Edit with the id
of 5
public ActionResult Edit(int? id)
{
// it good practice to consider that things could go wrong so,it is wise to have a
validation in the controller
if (id == null)
{
// returns a bad request
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}

// It finds the Student to be edited.


Student student = db.Students.Find(id);
if (student == null)
{
// if doesn't found returns 404
return HttpNotFound();
}
// Returns the Student data to fill out the edit form values.
return View(student);
}

Este método es muy similar al método de acción de detalles, que es un buen candidato para una
refactorización, pero está fuera del alcance de este tema.

https://riptutorial.com/es/home 94
// POST: Student/Edit/5
[HttpPost]

//used to To protect from overposting attacks more details see


http://stackoverflow.com/documentation/asp.net-mvc/1997/html-antiforgerytoke
[ValidateAntiForgeryToken]

//Represents an attribute that is used for the name of an action.


[ActionName("Edit")]
public ActionResult Edit(Student student)
{
try
{
//Gets a value that indicates whether this instance received from the view is
valid.
if (ModelState.IsValid)
{
// Two thing happens here:
// 1) db.Entry(student) -> Gets a DbEntityEntry object for the student entity
providing access to information about it and the ability to perform actions on the entity.
// 2) Set the student state to modified, that means that the student entity is
being tracked by the context and exists in the database, and some or all of its property
values have been modified.
db.Entry(student).State = EntityState.Modified;

// Now just save the changes that all the changes made in the form will be
persisted.
db.SaveChanges();

// Returns an HTTP 302 response to the browser, which causes the browser to
make a GET request to the specified action, in this case the index action.
return RedirectToAction("Index");
}
}
catch
{
//Log the error add a line here to write a log.
ModelState.AddModelError("", "Unable to save changes. Try again, and if the
problem persists, see your system administrator.");
}

// return the invalid student instance to be corrected.


return View(student);
}

Eliminar - parte del controlador

Es una buena práctica resistir la tentación de realizar la acción de eliminación en la solicitud de


obtención. Sería un gran error de seguridad, se debe hacer siempre en el método posterior.

// GET: Student/Delete/5
public ActionResult Delete(int? id)
{
// it good practice to consider that things could go wrong so,it is wise to have a
validation in the controller
if (id == null)
{
// returns a bad request
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);

https://riptutorial.com/es/home 95
}

// It finds the Student to be deleted.


Student student = db.Students.Find(id);
if (student == null)
{
// if doesn't found returns 404
return HttpNotFound();
}
// Returns the Student data to show the details of what will be deleted.
return View(student);
}

// POST: Student/Delete/5
[HttpPost]

//Represents an attribute that is used for the name of an action.


[ActionName("Delete")]

//used to To protect from overposting attacks more details see


http://stackoverflow.com/documentation/asp.net-mvc/1997/html-antiforgerytoke
[ValidateAntiForgeryToken]
public ActionResult Delete(int id)
{
try
{
// Finds the student
Student student = db.Students.Find(id);

// Try to remove it
db.Students.Remove(student);

// Save the changes


db.SaveChanges();
}
catch
{
//Log the error add a line here to write a log.
ModelState.AddModelError("", "Unable to save changes. Try again, and if the
problem persists, see your system administrator.");
}

// Returns an HTTP 302 response to the browser, which causes the browser to make a GET
request to the specified action, in this case the index action.
return RedirectToAction("Index");
}

Lea Operación CRUD en línea: https://riptutorial.com/es/asp-net-mvc/topic/6380/operacion-crud

https://riptutorial.com/es/home 96
Capítulo 24: Plantillas de visualización y
editor
Introducción
Al tratar con objetos en una aplicación MVC, si algún objeto se muestra en varios lugares con el
mismo formato, necesitaríamos algún tipo de diseño estandarizado. ASP.NET MVC ha hecho que
este tipo de estandarización sea fácil de hacer con la inclusión de plantillas de visualización y
editor. En resumen, las plantillas de visualización y editor se utilizan para estandarizar el diseño
que se muestra al usuario al editar o mostrar ciertos tipos o clases.

Examples
Plantilla de pantalla

Modelo:

public class User


{
public int ID { get; set; }
public string FirstName { get; set; }
public DateTime DateOfBirth { get; set; }
}

Si queremos mostrar a los usuarios en diferentes Vistas, sería mejor crear un diseño
estandarizado para estos usuarios donde sea necesario. Podemos lograr esto utilizando plantillas
de pantalla.

Una plantilla de visualización es simplemente una vista parcial que está vinculada con el modelo
al objeto que desea mostrar y existe en la carpeta Views/Shared/DisplayTemplates (aunque también
puede ponerla en Views/ControllerName/DisplayTemplates ). Además, el nombre de la vista (de
forma predeterminada) debe ser el nombre del objeto para el que desea utilizarlo como
plantilla .

Vistas / Shared / DisplayTemplates / User.cshtml

@model TemplatesDemo.Models.User

<div style="padding-bottom: 10px">


<p><strong>ID:</strong> @Html.DisplayFor(m => m.ID)</p>
<p><strong>Name:</strong> @Html.DisplayFor(m => m.FirstName)</p>
<p><strong>Date of Birth:</strong> @Html.DisplayFor(m => m.DateOfBirth)</p>
</div>
<hr/>

Ahora, si queremos mostrar a todos los usuarios de la base de datos y mostrarlos en diferentes
Vistas, simplemente podemos enviar la lista de usuarios a la Vista y usar la Plantilla de

https://riptutorial.com/es/home 97
Visualización para mostrarlos. Podemos usar uno de los dos métodos para hacerlo:

Html.DisplayFor()
Html.DisplayForModel()

DisplayFor llama a la plantilla de pantalla para el tipo de propiedad seleccionada (por ejemplo,
Html.DisplayFor(x => x.PropertyName) . DisplayForModel llama a la plantilla de pantalla para el @model
de la vista

Ver

@model IEnumerable<TemplatesDemo.Models.User>
@{
ViewBag.Title = "Users";
}

<h2>Users</h2>

@Html.DisplayForModel()

Plantilla de editor

Las Plantillas de visualización se pueden usar para estandarizar el diseño de un objeto, así que
ahora veamos cómo podemos hacer lo mismo para estos objetos al editarlos. Al igual que las
plantillas de visualización, hay dos formas de llamar a las plantillas de editor para un tipo dado:

Html.EditorFor()
Html.EditorForModel()

Las plantillas de editor, al igual que las plantillas de visualización, deben existir en Views /
Shared / EditorTemplates o Views / ControllerName / EditorTemplates . Para esta
demostración, los crearemos en la carpeta Compartida. Nuevamente, el nombre de la vista (de
manera predeterminada) debe ser el nombre del objeto para el que desea usarla como
plantilla.

Modelo

public class User


{
public int Id { get; set; }
public string Name { get; set; }
public DateTime DateOfBirth { get; set; }
public Roles Roles { get; set; }
public int RoleId { get; set; }
}

public class Roles


{
public int Id { get; set; }
public string Role { get; set; }
}

https://riptutorial.com/es/home 98
Digamos que queremos poder editar cualquier usuario desde la base de datos en múltiples vistas.
Usaremos un ViewModel para este propósito.

ViewModel

public class UserEditorViewModel


{
public User User { get; set; }
public IEnumerable<Roles> Roles { get; set; }
}

Usando este ViewModel , crearemos una plantilla de editor

Vistas / Shared / EditorTemplates / UserEditorViewModel.cshtml

@model TemplatesDemo.Models.UserEditorViewModel

<div class="form-group">
@Html.DisplayNameFor(m => m.User.Id)
@Html.EditorFor(m => m.User.Id)
</div>
<div class="form-group">
@Html.DisplayNameFor(m => m.User.Name)
@Html.EditorFor(m => m.User.Name)
</div>
<div class="form-group">
@Html.DisplayNameFor(m => m.User.DateOfBirth)
@Html.EditorFor(m => m.User.DateOfBirth)
</div>
<div class="form-group">
@Html.DisplayNameFor(m => m.User.Roles.Role)
@Html.DropDownListFor(m => m.User.RoleId, new SelectList(Model.Roles,"Id","Role"))
</div>

Obtendremos el usuario deseado y la lista de roles disponibles y los vincularemos en viewModel


UserEditorViewModel en Controller Action y enviaremos el viewModel a la vista. Para simplificar,
estoy iniciando el viewModel desde la Acción.

Acción

public ActionResult Editor()


{
var viewModel = new UserEditorViewModel
{
User = new User
{
Id = 1,
Name = "Robert",
DateOfBirth = DateTime.Now,
RoleId = 1
},
Roles = new List<Roles>()
{
new Roles
{
Id = 1,

https://riptutorial.com/es/home 99
Role = "Admin"
},
new Roles
{
Id = 2,
Role = "Manager"
},
new Roles
{
Id = 3,
Role = "User"
}
}
};

return View(viewModel);
}

Podemos usar la plantilla de editor creada en cualquier vista que deseemos.

Ver

@model TemplatesDemo.Models.UserEditorViewModel

@using (Html.BeginForm("--Your Action--", "--Your Controller--"))


{
@Html.EditorForModel()
<input type="submit" value="Save" />
}

Lea Plantillas de visualización y editor en línea: https://riptutorial.com/es/asp-net-


mvc/topic/9784/plantillas-de-visualizacion-y-editor

https://riptutorial.com/es/home 100
Capítulo 25: Registro de errores
Examples
Atributo simple

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

namespace Example.SDK.Filters
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
public sealed class CustomErrorHandlerFilter : HandleErrorAttribute
{
public override void OnException(ExceptionContext filterContext)
{
// RouteDate is useful for retrieving info like controller, action or other route
values
string controllerName = filterContext.RouteData.Values["controller"].ToString();
string actionName = filterContext.RouteData.Values["action"].ToString();

string exception = filterContext.Exception.ToString(); // Full exception stack


string message = filterContext.Exception.Message; // Message given by the
exception

// Log the exception within database


LogExtensions.Insert(exception.ToString(), message, controllerName + "." +
actionName);

base.OnException(filterContext);
}
}
}

Luego FilterConfig.cs en FilterConfig.cs

filters.Add(new CustomErrorHandlerFilter());

devolviendo página de error personalizada

public ActionResult Details( string product)


{
....
if (productNotFound) {
// http://www.eidias.com/blog/2014/7/2/mvc-custom-error-pages
Response.Clear();
Response.TrySkipIisCustomErrors = true;
Response.Write(product + " product not exists");
Response.StatusCode = (int)HttpStatusCode.NotFound;
Response.End();
return null;
}

https://riptutorial.com/es/home 101
}

Cree un ErrorLogger personalizado en ASP.Net MVC

Paso 1: Crear un filtro de registro de errores personalizado que escribirá errores en


archivos de texto de acuerdo con DateWise.

public class ErrorLogger : HandleErrorAttribute


{
public override void OnException(ExceptionContext filterContext)
{

string strLogText = "";


Exception ex = filterContext.Exception;
filterContext.ExceptionHandled = true;
var objClass = filterContext;
strLogText += "Message ---\n{0}" + ex.Message;

if (ex.Source == ".Net SqlClient Data Provider")


{
strLogText += Environment.NewLine + "SqlClient Error ---\n{0}" + "Check Sql
Error";
}
else if (ex.Source == "System.Web.Mvc")
{
strLogText += Environment.NewLine + ".Net Error ---\n{0}" + "Check MVC Code For
Error";
}
else if (filterContext.HttpContext.Request.IsAjaxRequest() == true)
{
strLogText += Environment.NewLine + ".Net Error ---\n{0}" + "Check MVC Ajax Code
For Error";
}
strLogText += Environment.NewLine + "Source ---\n{0}" + ex.Source;
strLogText += Environment.NewLine + "StackTrace ---\n{0}" + ex.StackTrace;
strLogText += Environment.NewLine + "TargetSite ---\n{0}" + ex.TargetSite;
if (ex.InnerException != null)
{
strLogText += Environment.NewLine + "Inner Exception is {0}" +
ex.InnerException;//error prone
}
if (ex.HelpLink != null)
{
strLogText += Environment.NewLine + "HelpLink ---\n{0}" + ex.HelpLink;//error
prone
}

StreamWriter log;

string timestamp = DateTime.Now.ToString("d-MMMM-yyyy", new CultureInfo("en-GB"));

string error_folder = ConfigurationManager.AppSettings["ErrorLogPath"].ToString();

if (!System.IO.Directory.Exists(error_folder))
{
System.IO.Directory.CreateDirectory(error_folder);
}

if (!File.Exists(String.Format(@"{0}\Log_{1}.txt", error_folder, timestamp)))

https://riptutorial.com/es/home 102
{
log = new StreamWriter(String.Format(@"{0}\Log_{1}.txt", error_folder,
timestamp));
}
else
{
log = File.AppendText(String.Format(@"{0}\Log_{1}.txt", error_folder, timestamp));
}

var controllerName = (string)filterContext.RouteData.Values["controller"];


var actionName = (string)filterContext.RouteData.Values["action"];

// Write to the file:


log.WriteLine(Environment.NewLine + DateTime.Now);
log.WriteLine("-----------------------------------------------------------------------
-------------------------");
log.WriteLine("Controller Name :- " + controllerName);
log.WriteLine("Action Method Name :- " + actionName);
log.WriteLine("-----------------------------------------------------------------------
-------------------------");
log.WriteLine(objClass);
log.WriteLine(strLogText);
log.WriteLine();

// Close the stream:


log.Close();
filterContext.HttpContext.Session.Abandon();
filterContext.Result = new RedirectToRouteResult
(new RouteValueDictionary
{
{"controller", "Errorview"}, {"action", "Error"}
});

Paso 2: Agregar ruta física en el servidor o en la unidad local donde se almacenará el


archivo de texto

<add key="ErrorLogPath" value="C:\ErrorLog\DemoMVC\" />

Paso 3: Agregar Errorview Controller con Error ActionMethod

Paso 4: Agregar error.cshtml Ver y mostrar mensaje de error personalizado en la


vista

Paso 5: Registrar el filtro ErrorLogger en la clase FilterConfig

public class FilterConfig


{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new ErrorLogger());
}
}

https://riptutorial.com/es/home 103
Paso 6: Registrar FilterConfig en Global.asax

Lea Registro de errores en línea: https://riptutorial.com/es/asp-net-mvc/topic/2268/registro-de-


errores

https://riptutorial.com/es/home 104
Capítulo 26: Reglas de reescritura de IIS
Examples
Forzar HTTPS usando la regla de reescritura

Este ejemplo muestra cómo puede usar las reglas de IIS Rewrite para forzar HTTPS haciendo
que todas las solicitudes HTTP devuelvan un Redireccionamiento 301 (Permanente) a la página
HTTPS.

Esto suele ser mejor que usar el atributo [RequireHttps] porque el atributo usa una redirección
302, y al estar en el canal de MVC es mucho más lento que hacerlo a nivel de IIS.

<rewrite xdt:Transform="Insert">
<rules>
<rule name="Enforce HTTPS WWW" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="true">
<add input="{HTTP_HOST}" pattern="^(?!www)(.*)"/>
<add input="{URL}" pattern="^(.*)"/>
<!-- {URL} Gives the base portion of the URL, without any querystring or extra
path information, for example, "/vdir/default.asp". -->
</conditions>
<action type="Redirect" url="https://www.{C:1}{C:2}" appendQueryString="true"
redirectType="Permanent" />
</rule>
</rules>
</rewrite>

Lea Reglas de reescritura de IIS en línea: https://riptutorial.com/es/asp-net-mvc/topic/6358/reglas-


de-reescritura-de-iis

https://riptutorial.com/es/home 105
Capítulo 27: T4MVC
Introducción
T4MVC es una plantilla T4 que genera ayudantes fuertemente tipados para usar en los
mecanismos de enrutamiento MVC, a diferencia de las cadenas mágicas. T4MVC detectará los
diversos controladores, acciones y vistas, y creará referencias a esas vistas, cometiendo errores
en tiempo de compilación en el caso de que un intento de enrutar o acceder a una vista no sea
válido.

Examples
Llamando a una acción

En MVC, hay algunos escenarios donde desea especificar una acción para propósitos de
enrutamiento, ya sea para un enlace, una acción de formulario o una redirección a la acción.
Puede especificar una acción a través del espacio de nombres MVC.

Cuando se le da un controlador, como HomeController :

public class HomeController : Controller


{
public ActionResult Index()
{
...
}
public ActionResult MyAction()
{
...
}
public ActionResult MyActionWithParameter(int parameter)
{
...
}
}

T4MVC generará un controlador heredado que anula la acción. Esta anulación establecerá los
datos de la ruta correctamente para que UrlHelper de MVC genere la URL correcta. Puede llamar
a este método y pasarlo a varios métodos para UrlHelper . Los siguientes ejemplos suponen que
se está utilizando la ruta MVC predeterminada:

Enlazar

Para generar una a etiqueta con el texto especificado:

@Html.ActionLink("Link Text", MVC.Home.Index() )


//result: <a href="/">Link Text</a>
@Html.ActionLink("Link Text", MVC.Home.MyAction() )
//result: <a href="/Home/MyAction">Link Text</a>

https://riptutorial.com/es/home 106
//T4MVC also allows you to specify the parameter without creating an anonymous object:
@Html.ActionLink("Link Text", MVC.Home.MyActionWithParameter(1) )
//result: <a href="/Home/MyActionWithParameter/1">Link Text</a>

Para generar un url:

@Url.Action( MVC.Home.Index() )
//result: /
@Url.Action("Link Text", MVC.Home.MyAction() )
//result: /Home/MyAction
@Url.Action("Link Text", MVC.Home.MyActionWithParameter(1) )
//result: /Home/MyActionWithParameter/1

Tenga en cuenta que T4MVC sigue las mismas reglas que MVC Routing: no especificará las
variables de ruta predeterminadas, por lo que la acción del Index en el HomeController no genera
/Home/Index sino la forma abreviada y perfectamente válida de / .

Método de formulario

Para generar una etiqueta de form con la action correcta especificada:

@Html.BeginForm( MVC.Home.Index(), FormMethod.Get /* or FormMethod.Post */ )


{
//my form
}
//result:
<form action="/" method="GET">
//my form
</form>
@Html.BeginForm( MVC.Home.MyActionWithParameter(1), FormMethod.Get /* or FormMethod.Post */ )
{
//my form
}
//result:
<form action="/Home/MyActionWithParameter/1" method="GET">
//my form
</form>

Redirigir a la acción

Cuando esté en un controlador, es posible que desee redirigir a una acción de la acción actual.
Esto se puede hacer, likeso:

public class RedirectingController : Controller


{
public ActionResult MyRedirectAction()
{
...
return RedirectToAction( MVC.Redirecting.ActionToRedirectTo() );
//redirects the user to the action below.
}
public ActionResult ActionToRedirectTo()
{
...
}

https://riptutorial.com/es/home 107
}

Lea T4MVC en línea: https://riptutorial.com/es/asp-net-mvc/topic/9147/t4mvc

https://riptutorial.com/es/home 108
Capítulo 28: Usando múltiples modelos en
una vista
Introducción
El enfoque principal de este tema es usar una clase de modelo múltiple en la capa de
visualización de MVC

Examples
Uso de múltiples modelos en una vista con ExpandoObject dinámico

ExpandoObject (el espacio de nombres System.Dynamic ) es una clase que se agregó a .Net
Framework 4.0 . Esta clase nos permite agregar y eliminar dinámicamente propiedades en un
objeto en tiempo de ejecución. Al utilizar el objeto Expando, podemos agregar nuestras clases de
modelo en el objeto Expando creado dinámicamente. El siguiente ejemplo explica cómo podemos
usar este objeto dinámico.

Modelo de profesor y alumno:

public class Teacher


{
public int TeacherId { get; set; }
public string Name { get; set; }
}

public class Student


{
public int StudentId { get; set; }
public string Name { get; set; }
}

Métodos de lista de profesores y alumnos:

public List<Teacher> GetTeachers()


{
List<Teacher> teachers = new List<Teacher>();
teachers.Add(new Teacher { TeacherId = 1, Name = "Teacher1" });
teachers.Add(new Teacher { TeacherId = 2, Name = "Teacher2" });
teachers.Add(new Teacher { TeacherId = 3, Name = "Teacher3" });
return teachers;
}

public List<Student> GetStudents()


{
List<Student> students = new List<Student>();
students.Add(new Student { StudentId = 1, Name = "Student1"});
students.Add(new Student { StudentId = 2, Name = "Student2"});
students.Add(new Student { StudentId = 3, Name = "Student3"});

https://riptutorial.com/es/home 109
return students;
}

Controlador (usando el modelo dinámico):

public class HomeController : Controller


{
public ActionResult Index()
{
ViewBag.Message = "Hello World";
dynamic mymodel = new ExpandoObject();
mymodel.Teachers = GetTeachers();
mymodel.Students = GetStudents();
return View(mymodel);
}
}

Ver:

@using ProjectName ; // Project Name


@model dynamic
@{
ViewBag.Title = "Home Page";
}
<h2>@ViewBag.Message</h2>

<h2>Teacher List</h2>

<table>
<tr>
<th>Id</th>
<th>Name</th>
</tr>
@foreach (Teacher teacher in Model.Teachers)
{
<tr>
<td>@teacher.TeacherId</td>
<td>@teacher.Name</td>
</tr>
}
</table>

<h2>Student List</h2>

<table>
<tr>
<th>Id</th>
<th>Name</th>
</tr>
@foreach (Student student in Model.Students)
{
<tr>
<td>@student.StudentId</td>
<td>@student.Name</td>
</tr>
}
</table>

https://riptutorial.com/es/home 110
Lea Usando múltiples modelos en una vista en línea: https://riptutorial.com/es/asp-net-
mvc/topic/10144/usando-multiples-modelos-en-una-vista

https://riptutorial.com/es/home 111
Capítulo 29: Validación automática del lado
del cliente a partir de atributos
Observaciones
Por defecto, Safari no impone la validación de elementos HTML5. Debe anular esto manualmente
utilizando otros medios.

Examples
Modelo

public class UserModel


{

[Required]
[StringLength(6, MinimumLength = 3)]
[RegularExpression(@"(\S)+", ErrorMessage = "White space is not allowed")]
public string UserName { get; set; }

[Required]
[StringLength(8, MinimumLength = 3)]
public string FirstName { get; set; }

[Required]
[StringLength(9, MinimumLength = 2)]
public string LastName { get; set; }

[Required]
public string City { get; set; }

configuración de web.config

<appSettings>
<add key="ClientValidationEnabled" value="true"/>
<add key="UnobtrusiveJavaScriptEnabled" value="true"/>
</appSettings>

Paquetes Nuget Requeridos

<package id="jQuery" version="1.10.2" targetFramework="net452" />


<package id="jQuery.Validation" version="1.11.1" targetFramework="net452" />
<package id="Microsoft.jQuery.Unobtrusive.Validation" version="3.2.3" targetFramework="net452"
/>

Vista de formulario

https://riptutorial.com/es/home 112
@model WebApplication4.Models.UserModel
@{
ViewBag.Title = "Register";
}

<h2>@ViewBag.Title.</h2>

@using (Html.BeginForm("Register", "Account", FormMethod.Post, new { @class = "form-


horizontal", role = "form" }))
{
@Html.AntiForgeryToken()
<h4>Create a new account.</h4>
<hr />
@Html.ValidationSummary("", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(m => m.FirstName, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.TextBoxFor(m => m.FirstName, new { @class = "form-control" })
@Html.ValidationMessageFor(m=>m.FirstName)
</div>
</div>
<div class="form-group">
@Html.LabelFor(m => m.LastName, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.TextBoxFor(m => m.LastName, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.LastName)
</div>
</div>
<div class="form-group">
@Html.LabelFor(m => m.UserName, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.TextBoxFor(m => m.UserName, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.UserName)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" class="btn btn-default" value="Register" />
</div>
</div>
}

@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}

Configuración del paquete

public class BundleConfig


{

public static void RegisterBundles(BundleCollection bundles)


{
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
"~/Scripts/jquery-{version}.js"));

bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
"~/Scripts/jquery.validate*"));

https://riptutorial.com/es/home 113
}
}

Global.asax.cs

public class MvcApplication : System.Web.HttpApplication


{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);

// Need to include your bundles


BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}

Lea Validación automática del lado del cliente a partir de atributos en línea:
https://riptutorial.com/es/asp-net-mvc/topic/6044/validacion-automatica-del-lado-del-cliente-a-
partir-de-atributos

https://riptutorial.com/es/home 114
Capítulo 30: ViewData, ViewBag, TempData
Introducción
ViewData y ViewBag se utilizan para transferir datos desde el controlador para ver.

ViewData no es más que un diccionario de objetos y es accesible por cadena como clave.

ViewBag es muy similar a ViewData. ViewBag es una propiedad dinámica. ViewBag es solo una
envoltura alrededor de ViewData.

TempData mantiene los datos durante el tiempo de la solicitud HTTP, lo que significa que
mantiene los datos entre dos solicitudes consecutivas. TempData nos ayuda a transferir datos
entre controladores o entre acciones. Usos de sesión interna.

Sintaxis
1. ViewData [clave] = valor;

2. ViewBag.Key = valor;

3. TempData [clave] = valor;

Examples
¿Qué son ViewData, ViewBag y TempData?

ViewData es el mecanismo para que un controlador proporcione datos a la vista que presenta, sin
usar ViewModel. Específicamente, ViewData es un diccionario que está disponible tanto en los
métodos de acción MVC como en las vistas. Puede usar ViewData para transferir algunos datos
de su método de acción a la vista devuelta por el método de acción.

Como es un diccionario, puede usar el diccionario como sintaxis para configurar y obtener datos
de él.

ViewData[key] = value; // In the action method in the controller

Por ejemplo, si desea pasar un mensaje de cadena de su método de acción de índice a su vista
de índice Index.cshtml , puede hacer esto.

public ActionResult Index()


{
ViewData["Message"] = "Welcome to ASP.NET MVC";
return View(); // notice the absence of a view model
}

https://riptutorial.com/es/home 115
Para acceder a esto en su vista Index.cshtml , simplemente puede acceder al diccionario
ViewData con la tecla utilizada en el método de acción.

<h2>@ViewData["Message"]</h2>

ViewBag es el equivalente dinámico del diccionario ViewData sin tipo. Aprovecha el tipo dynamic
C # para la experiencia del azúcar sintáctico.

La sintaxis para configurar algunos datos para ViewBag es

ViewBag.Key = Value;

Entonces, si queremos pasar la cadena de mensaje en nuestro ejemplo anterior usando ViewBag,
será

public ActionResult Index()


{
ViewBag.Message = "Welcome to ASP.NET MVC";
return View(); // not the absence of a view model
}

y en su vista de índice,

<h2>@ViewBag.Message</h2>

Los datos no se comparten entre ViewBag y ViewData. ViewData requiere encasillado para
obtener datos de tipos de datos complejos y buscar valores nulos para evitar errores cuando View
Bag no requiere encasillado.

TempData se puede usar cuando desea conservar datos entre una solicitud http y la siguiente
solicitud HTTP solamente. La vida útil de los datos almacenados en TempDataDictionary finaliza
después de la segunda solicitud. Por lo tanto, TempData es útil en situaciones en las que estás
siguiendo el patrón PRG.

[HttpPost]
public ActionResult Create(string name)
{
// Create a user
// Let's redirect (P-R-G Pattern)
TempData["Message"] = "User created successfully";
return RedirectToAction("Index");
}
public ActionResult Index()
{
var messageFromPreviousCall = TempData["Message"] as String;
// do something with this message
// to do : Return something
}

Cuando return RedirectToAction("SomeActionMethod") , el servidor enviará una respuesta 302 al


cliente (navegador) con el valor del encabezado de ubicación establecido en la URL a

https://riptutorial.com/es/home 116
"SomeActionMethod" y el navegador le enviará una solicitud totalmente nueva. ViewBag /
ViewData no funcionará en ese caso para compartir algunos datos entre estas 2 llamadas.
Necesitas usar TempData en tales escenarios.

Ciclo de vida de TempData

Los datos guardados en TempData se almacenan en la sesión y se eliminarán automáticamente


al final de la primera solicitud donde se accede a los datos. Si nunca se lee, se mantendrá hasta
que finalmente se lea o la sesión se agote.

El uso típico se parece a la siguiente secuencia (donde cada línea se invoca desde una solicitud
diferente):

//first request, save value to TempData


TempData["value"] = "someValueForNextRequest";

//second request, read value, which is marked for deletion


object value = TempData["value"];

//third request, value is not there as it was deleted at the end of the second request
TempData["value"] == null

Este comportamiento puede ser más controlado con los métodos Peek y Keep .

• Con Peek puede recuperar los datos almacenados en TempData sin marcarlos para
eliminarlos, por lo que los datos seguirán estando disponibles en una futura solicitud.

//first request, save value to TempData


TempData["value"] = "someValueForNextRequest";

//second request, PEEK value so it is not deleted at the end of the request
object value = TempData.Peek("value");

//third request, read value and mark it for deletion


object value = TempData["value"];

• Con Keep , puede especificar que una clave que se marcó para su eliminación debería
conservarse. En este caso, recuperar los datos y guardarlos para eliminarlos requiere 2
llamadas de método:

//first request, save value to TempData


TempData["value"] = "someValueForNextRequest";

//second request, get value marking it from deletion


object value = TempData["value"];
//later on decide to keep it
TempData.Keep("value");

//third request, read value and mark it for deletion


object value = TempData["value"];

Con esto en mente, use Peek cuando siempre quiera conservar el valor para otra solicitud y use
Keep cuando el valor se Keep dependiendo de la lógica adicional.

https://riptutorial.com/es/home 117
Lea ViewData, ViewBag, TempData en línea: https://riptutorial.com/es/asp-net-
mvc/topic/1286/viewdata--viewbag--tempdata

https://riptutorial.com/es/home 118
Capítulo 31: Vistas parciales
Introducción
Una vista parcial es una vista que se representa dentro de otra vista. Las vistas parciales se
pueden reutilizar y así evitar la duplicación de código. Pueden ser renderizados por Html.Partial o
Html.RenderPartial

Sintaxis
• @ Html.Partial ("ViewName")

@ Html.Partial ("ViewName", ViewModel)

@ {Html.RenderPartial ("ViewName");}

Si su vista parcial se encuentra en una carpeta diferente a la compartida, entonces deberá


mencionar la ruta completa de la vista como se muestra a continuación:

-@Html.RenderPartial ("~ / Areas / Admin / Views / Shared / partial / _subcat.cshtml")

Examples
Vista parcial con modelo.

También se puede agregar un modelo a la vista parcial:

@model Solution.Project.Namespace.MyModelClass
<p>@Model.Property</p>

En la Vista ahora solo puedes usar:

<div>
@Html.Partial("PartialViewExample", new MyModelClass(){Property="my property value"})
</div>
<div>
@{ Html.RenderPartial("PartialViewExample", new MyModelClass(){Property="my property
value"}); }
</div>

Vista parcial a una cadena - para contenido de correo electrónico, etc.

Llamando a la función

string InvoiceHtml = myFunction.RenderPartialViewToString("PartialInvoiceCustomer",


ToInvoice); // ToInvoice is a model, you can pass parameters if needed

https://riptutorial.com/es/home 119
Función para generar HTML

public static string RenderPartialViewToString(string viewName, object model)


{
using (var sw = new StringWriter())
{
BuyOnlineController controller = new BuyOnlineController(); // instance of the
required controller (you can pass this as a argument if needed)

// Create an MVC Controller Context


var wrapper = new HttpContextWrapper(System.Web.HttpContext.Current);

RouteData routeData = new RouteData();

routeData.Values.Add("controller",
controller.GetType().Name.ToLower().Replace("controller", ""));

controller.ControllerContext = new ControllerContext(wrapper, routeData, controller);

controller.ViewData.Model = model;

var viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext,


viewName);

var viewContext = new ViewContext(controller.ControllerContext, viewResult.View,


controller.ViewData, controller.TempData, sw);
viewResult.View.Render(viewContext, sw);

return sw.ToString();
}
}

Vista parcial - PartialInvoiceCustomer

@model eDurar.Models.BuyOnlineCartMaster
<h2>hello customer - @Model.CartID </h2>

Html.Partial Vs Html.RenderPartial

Html.Partial devuelve una cadena por otro lado Html.RenderPartial devuelve void.

Html.RenderPartial

Este método devuelve void y el resultado se escribe directamente en el flujo de respuesta HTTP.
Eso significa que usa el mismo objeto TextWriter que se usa en la página web / plantilla actual.
Por este motivo, este método es más rápido que el método parcial. Este método es útil cuando los
datos que se muestran en la vista parcial ya están en el modelo de vista correspondiente.

Ejemplo: en un blog para mostrar los comentarios de un artículo, nos gustaría usar el método
RenderPartial ya que la información de un artículo con comentarios ya está completa en el
modelo de vista.

@{Html.RenderPartial("_Comments");}

https://riptutorial.com/es/home 120
Html.parcial

Este método devuelve una cadena codificada en HTML. Esto se puede almacenar en una
variable. Al igual que el método RenderPartial, el método Parcial también es útil cuando los datos
que se muestran en la vista parcial ya están en el modelo de vista correspondiente.

Ejemplo: en un blog para mostrar los comentarios de un artículo, puede usar el método Parcial,
ya que la información de un artículo con comentarios ya se ha completado en el modelo de vista.

@Html.Partial("_Comments")

Lea Vistas parciales en línea: https://riptutorial.com/es/asp-net-mvc/topic/2171/vistas-parciales

https://riptutorial.com/es/home 121
Capítulo 32: Web.config cifrado
Examples
Cómo proteger su archivo web.config

Es una buena práctica cifrar su archivo Web.config si tiene información confidencial allí, por
ejemplo, una cadena de conexión con contraseña.

Con la herramienta de registro IIS de ASP.NET (Aspnet_regiis.exe) puede cifrar fácilmente


secciones específicas del archivo Web.config. Se requiere un comando con privilegios elevados.

Ejemplo utilizando DataProtectionConfigurationProvider . Este proveedor utiliza DPAPI para cifrar


y descifrar datos:

aspnet_regiis.exe -pef "connectionStrings" c:\inetpub\YourWebApp -prov


"DataProtectionConfigurationProvider"

Ejemplo utilizando RSAProtectedConfigurationProvider :

aspnet_regiis.exe -pef "connectionStrings" c:\inetpub\YourWebApp -prov


"RSAProtectedConfigurationProvider"

Si no especifica el parámetro -prov, utiliza RSAProtectedConfigurationProvider como


predeterminado. Este proveedor se recomienda para los escenarios de Web Farm.

Para obtener la sección connectionStrings de nuevo para borrar el texto:

aspnet_regiis.exe -pdf "connectionStrings" c:\inetpub\YourWebApp

Más información sobre el aspnet_regiis.exe está disponible en MSDN .

Lea Web.config cifrado en línea: https://riptutorial.com/es/asp-net-mvc/topic/6373/web-config-


cifrado

https://riptutorial.com/es/home 122
Creditos
S.
Capítulos Contributors
No

Aaron Hudon, Adil Mammadov, Aditya Korti, Ameya


Empezando con
1 Deshpande, Ashley Medway, Community, Hywel Rees, Rifaj,
asp.net-mvc
Shog9, Shyju, Supraj v, Syed Farjad Zia Zaidi, SztupY

2 ActionResult hasan, SlaterCodes, Tetsuya Yamamoto

abiNerd, dotnetom, dove, Edathadan Chief aka Arun, Ehsan


Sajjad, Felipe Oriani, gunr2171, Karthikeyan, LaCartouche,
3 Anotaciones de datos
mmushtaq, Ollie P, Rion Williams, SailajaPalakodeti, Stephen
Muecke, Tetsuya Yamamoto, The_Outsider, tmg, Tsahi Asher

4 Áreas Himaan Singh, Tetsuya Yamamoto

Asp.net mvc enviar


5 Ashiquzzaman, hasan, sGermosen
correo

Ashiquzzaman, Laurel, Lokesh_Ram, Pavel Pája Halbich,


6 Ayudantes html Peter Mortensen, QuantumHive, Tassadaque, Testing123,
Tetsuya Yamamoto, The_Outsider, TheFallenOne

Dockerización de la
7 SUMIT LAHIRI
aplicación ASP.NET

Empaquetado y Ashley Medway, Beofett, hasan, Laurel, Lokesh_Ram, Paul


8
Minificación DS, rageit, Rion Williams, Robban, Tetsuya Yamamoto, tmg

Alex Art., Andrei Rînea, chsword, Ciaran Bruen, Jarrod Dixon,


Jason Evans, Karthikeyan, kkakkurt, Laurel, Lokesh_Ram,
9 Enrutamiento mstaessen, Pavel Voronin, SailajaPalakodeti, Sandro, Shyju,
SlaterCodes, Stephen Muecke, Tetsuya Yamamoto, tmg, Tot
Zam, user270576

10 Extensiones Ajax MVC rll

Andrei Rînea, Dawood Awan, juunas, Laurel, Lokesh_Ram,


11 Filtros de accion
Tolga Evcimen

Aaron Hudon, Andrei Rînea, Art, felickz, Hanno,


12 Html.AntiForgeryToken Jakotheshadows, Joshua Leigh, Martin Costello, Minh Nguyen
, Rion Williams, SailajaPalakodeti, SlaterCodes, viggity

13 Html.RouteLink Jason Evans

https://riptutorial.com/es/home 123
Inyección de Adil Mammadov, Andrei Dragotoniu, Cà phê đen, Dave,
14
dependencia PedroSouki

jQuery Ajax Call Con


15 Ashiquzzaman, hasan
Asp MVC

16 Manejo de errores Http scgough

Aditya Korti, aeliusd, Anik Saha, Arendax, Ashley Medway,


Big Fan, Brandon Wood, Braydie, Denis Elkhov, dove, James
17 Maquinilla de afeitar Haug, Julian, Kuldeep Prajapati, Lee Chengkai, lloyd,
RamenChef, SadiRubaiyet, Sain Pradeep, Sandro,
Thennarasan, Tim Coker, TKharaishvili, Tot Zam, usr

Adil Mammadov, Andrei Rînea, dove, Ehsan Sajjad, James


18 Modelo de enlace
Haug, Md Dinar, PedroSouki, rdans, Tolga Evcimen

Aaron Hudon, Ankit Kumar Singh, GTown-Coder, hasan,


19 Modelo de validación Marimba, Nikunj Patel, Pavel Voronin, SlaterCodes, Stephen
Muecke, The_Outsider, TheFallenOne, Vincentw

MVC vs Formularios
20 DiegoS, Houssam Hamdan, The_Outsider
Web

21 Operación CRUD EvenPrime, Krzyserious, PedroSouki, Tetsuya Yamamoto

Plantillas de
22 Adnan Niloy, SailajaPalakodeti
visualización y editor

23 Registro de errores Andrus, Leandro Soares, Saineshwar

Reglas de reescritura
24 SlaterCodes
de IIS

25 T4MVC James Haug

Usando múltiples
26 hasan, Travis Tubbs
modelos en una vista

Validación automática
27 del lado del cliente a Slick86
partir de atributos

ViewData, ViewBag, bzlm, Daniel J.G., IanB, Rion Williams, SailajaPalakodeti,


28
TempData Shyju, TheFallenOne, tmg

Adnan Niloy, Ashiquzzaman, Edathadan Chief aka Arun,


29 Vistas parciales glacasa, Jason Evans, Laurel, Lokesh_Ram, Marimba,
SailajaPalakodeti, The_Outsider

https://riptutorial.com/es/home 124
30 Web.config cifrado glaubergft, Jack Spektor

https://riptutorial.com/es/home 125

Você também pode gostar