asp.net-mvc - RIP Tutorial · from: asp-net-mvc It is an unofficial and free asp.net-mvc ebook...

134
asp.net-mvc #asp.net- mvc

Transcript of asp.net-mvc - RIP Tutorial · from: asp-net-mvc It is an unofficial and free asp.net-mvc ebook...

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 [email protected]

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:

Ideal para desarrollar aplicaciones complejas pero ligeras.1. 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.

2.

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.

3.

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.

4.

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.

5.

No utiliza el concepto de estado de vista (que está presente en ASP.NET). Esto ayuda en la 6.

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= "[email protected]"; 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;} //... } }

o

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="[email protected]"> <network host="smtp-mail.outlook.com" port="587" userName="[email protected]" 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("[email protected]"); 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="[email protected]" /> <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: <input class="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: <label for="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

ConfirmarObtiene o establece el mensaje que se mostrará en una ventana de confirmación antes de que se envíe una solicitud.

HttpMethodObtiene o establece el método de solicitud HTTP ("Obtener" o "Publicar").

Modo de inserciónObtiene o establece el modo que especifica cómo insertar la respuesta en el elemento DOM de destino.

LoadingElementDurationObtiene o establece un valor, en milisegundos, que controla la duración de la animación al mostrar u ocultar el elemento de carga.

LoadingElementIdObtiene o establece el atributo id de un elemento HTML que se muestra mientras se carga la función Ajax.

OnBeginObtiene o establece el nombre de la función JavaScript para llamar inmediatamente antes de que se actualice la página.

OnCompleteObtiene o establece la función de JavaScript para llamar cuando se han creado instancias de datos de respuesta pero antes de que se actualice la página.

En el fracasoObtiene o establece la función de JavaScript para llamar si falla la actualización de la página.

OnSuccessObtiene o establece la función de JavaScript para llamar después de que la página se actualice correctamente.

https://riptutorial.com/es/home 44

Opciones de AJAX Descripción

UpdateTargetIdObtiene o establece el ID del elemento DOM para actualizar 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:

Global1. Controlador2. Acción3.

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:

Global1. Controlador2. Acción3.

Excelentes ejemplos de filtros colocados a nivel global incluyen:

Filtros de autentificación1. Filtros de autorizacion2. Filtros de registro3.

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

<!-- ... --> }

O

<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(DontCheckForAntiForgeryTokenAttribute),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 [email protected] 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 [email protected]</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 por Razor View Engine es System.Web.Razor

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

Las extensiones de archivo utilizadas por el motor de vista de Razor son diferentes de un motor de vista de formulario web. Utiliza cshtml con C # y vbhtml con vb para vistas, vista parcial, plantillas y páginas de diseño.

Las extensiones de archivo utilizadas por los motores de vista de formulario web son como los formularios web de ASP.Net. Utiliza la extensión ASPX para ver la extensión aspc para vistas parciales o Controles de usuario o plantillas y extensiones maestras para diseño / páginas maestras.

El motor Razor es compatible con el desarrollo guiado por pruebas (TDD).

El motor de vista de formulario web no es compatible con Test Driven Development (TDD) porque depende de la clase System.Web.UI.Page para hacer la prueba 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 .

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.

1.

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.

2.

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

ViewData [clave] = valor;1.

ViewBag.Key = valor;2.

TempData [clave] = valor;3.

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:

[email protected] ("~ / 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. No

Capítulos Contributors

1Empezando con asp.net-mvc

Aaron Hudon, Adil Mammadov, Aditya Korti, Ameya Deshpande, Ashley Medway, Community, Hywel Rees, Rifaj, Shog9, Shyju, Supraj v, Syed Farjad Zia Zaidi, SztupY

2 ActionResult hasan, SlaterCodes, Tetsuya Yamamoto

3 Anotaciones de datos

abiNerd, dotnetom, dove, Edathadan Chief aka Arun, Ehsan Sajjad, Felipe Oriani, gunr2171, Karthikeyan, LaCartouche, mmushtaq, Ollie P, Rion Williams, SailajaPalakodeti, Stephen Muecke, Tetsuya Yamamoto, The_Outsider, tmg, Tsahi Asher

4 Áreas Himaan Singh, Tetsuya Yamamoto

5Asp.net mvc enviar correo

Ashiquzzaman, hasan, sGermosen

6 Ayudantes htmlAshiquzzaman, Laurel, Lokesh_Ram, Pavel Pája Halbich, Peter Mortensen, QuantumHive, Tassadaque, Testing123, Tetsuya Yamamoto, The_Outsider, TheFallenOne

7Dockerización de la aplicación ASP.NET

SUMIT LAHIRI

8Empaquetado y Minificación

Ashley Medway, Beofett, hasan, Laurel, Lokesh_Ram, Paul DS, rageit, Rion Williams, Robban, Tetsuya Yamamoto, tmg

9 Enrutamiento

Alex Art., Andrei Rînea, chsword, Ciaran Bruen, Jarrod Dixon, Jason Evans, Karthikeyan, kkakkurt, Laurel, Lokesh_Ram, mstaessen, Pavel Voronin, SailajaPalakodeti, Sandro, Shyju, SlaterCodes, Stephen Muecke, Tetsuya Yamamoto, tmg, Tot Zam, user270576

10 Extensiones Ajax MVC rll

11 Filtros de accionAndrei Rînea, Dawood Awan, juunas, Laurel, Lokesh_Ram, Tolga Evcimen

12 Html.AntiForgeryTokenAaron Hudon, Andrei Rînea, Art, felickz, Hanno, Jakotheshadows, Joshua Leigh, Martin Costello, Minh Nguyen, Rion Williams, SailajaPalakodeti, SlaterCodes, viggity

13 Html.RouteLink Jason Evans

https://riptutorial.com/es/home 123

14Inyección de dependencia

Adil Mammadov, Andrei Dragotoniu, Cà phê đen, Dave, PedroSouki

15jQuery Ajax Call Con Asp MVC

Ashiquzzaman, hasan

16 Manejo de errores Http scgough

17 Maquinilla de afeitar

Aditya Korti, aeliusd, Anik Saha, Arendax, Ashley Medway, Big Fan, Brandon Wood, Braydie, Denis Elkhov, dove, James Haug, Julian, Kuldeep Prajapati, Lee Chengkai, lloyd, RamenChef, SadiRubaiyet, Sain Pradeep, Sandro, Thennarasan, Tim Coker, TKharaishvili, Tot Zam, usr

18 Modelo de enlaceAdil Mammadov, Andrei Rînea, dove, Ehsan Sajjad, James Haug, Md Dinar, PedroSouki, rdans, Tolga Evcimen

19 Modelo de validaciónAaron Hudon, Ankit Kumar Singh, GTown-Coder, hasan, Marimba, Nikunj Patel, Pavel Voronin, SlaterCodes, Stephen Muecke, The_Outsider, TheFallenOne, Vincentw

20MVC vs Formularios Web

DiegoS, Houssam Hamdan, The_Outsider

21 Operación CRUD EvenPrime, Krzyserious, PedroSouki, Tetsuya Yamamoto

22Plantillas de visualización y editor

Adnan Niloy, SailajaPalakodeti

23 Registro de errores Andrus, Leandro Soares, Saineshwar

24Reglas de reescritura de IIS

SlaterCodes

25 T4MVC James Haug

26Usando múltiples modelos en una vista

hasan, Travis Tubbs

27Validación automática del lado del cliente a partir de atributos

Slick86

28ViewData, ViewBag, TempData

bzlm, Daniel J.G., IanB, Rion Williams, SailajaPalakodeti, Shyju, TheFallenOne, tmg

29 Vistas parcialesAdnan Niloy, Ashiquzzaman, Edathadan Chief aka Arun, 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