ASP.NET MVC

[ASP.NET MVC] Implementando el helper chart de Kendo UI

Posted on

Hola a todos, hoy quiero mostrarles como es de sencillo crear un chart utilizando los helpers de Kendo UI para ASP.NET MVC, lo primero es referenciar la dll Kendo.Mvc:

referencia kendo

Luego los archivos JavaScript y CSS:

css.js.kendo

Creamos los bundles correspondientes en la clase BundleConfig:

bundles.Add(new ScriptBundle("~/bundles/kendo").Include(
	"~/Scripts/kendo/kendo.all.min.js",
	"~/Scripts/kendo/kendo.aspnetmvc.min.js"));
	
bundles.Add(new StyleBundle("~/Content/kendocss").Include(
	"~/Content/kendo.common.min.css",
	"~/Content/kendo.flat.min.css",
	"~/Content/kendo.dataviz.flat.min.css"));

Y los referenciamos en la sección head del layout:

@Styles.Render("~/Content/css")
@Styles.Render("~/Content/kendocss")
@Scripts.Render("~/bundles/modernizr")

@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/bootstrap")
@Scripts.Render("~/bundles/kendo")

Ahora, un sencillo modelo:

public class Values
{
	public int Id { get; set; }

	public int Value { get; set; }

	public DateTime Date { get; set; }
}

Luego en el controlador retornamos una colección de elementos:

public class HomeController : Controller
{
	private List<Values> values = new List<Values>() 
	{ 
		new Values (){ Id = 1, Date = DateTime.Now, Value = 10},
		new Values (){ Id = 2, Date = DateTime.Now.AddMinutes(10), Value = 5},
		new Values (){ Id = 2, Date = DateTime.Now.AddMinutes(20), Value = 15},
		new Values (){ Id = 2, Date = DateTime.Now.AddMinutes(30), Value = 0},
		new Values (){ Id = 2, Date = DateTime.Now.AddMinutes(40), Value = 20}
	};

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

Y finalmente la vista:

@using Kendo.Mvc.UI;
@model IEnumerable<KendoUIChartMvcWrapper.Models.Values>

@{
    ViewBag.Title = "Index";
}

@(Html.Kendo().Chart(Model)
    .Name("chart")
    .Title("Kendo UI Chart")
    .Legend(legend => legend
        .Position(ChartLegendPosition.Bottom)
    )
    .ChartArea(chartArea => chartArea
        .Background("transparent")
    )
    .SeriesDefaults(seriesDefaults =>
        seriesDefaults.Line()
    )
    .Series(series =>
    {
        series.Line(model => model.Value)
            .Name("Cantidad")
            .Labels(true)
            .Opacity(0.8);
    })
    .CategoryAxis(axis => axis
        .Categories(model => model.Date)
        .MajorGridLines(lines => lines.Visible(false))
        .Labels(labels => labels.Rotation(-90))
        .Date()
        .BaseUnitStep(10)
        .MinorGridLines(lines => lines.Visible(true))
    )
    .Tooltip(tooltip => tooltip
        .Visible(true)
        .Format("{0}")
    )
)

En la vista hacemos uso del helper Html.Kendo().Chart(Model) y simplemente le pasamos el modelo que estamos usando, que en este caso es una colección de elementos, luego solo parametrizamos algunas propiedades del helper como el nombre (Name), el título (Title) entre otras…. y finalmente el resultado:

chart kendo

Espero les sea interesante, saludos!

[ASP.NET MVC] Inyectando dependencias con Microsoft Unity

Posted on Actualizado enn

Hola a todos, en el anterior post (míralo acá) vimos como podemos crear una factoría de controladores personalizada para poder instanciar controladores que tienen un constructor que recibe parámetros, hoy vamos a ver algo muy parecido, solo que en este caso vamos a utilizar un DI Container (contenedor de inyección de dependencias).

El ejemplo, básicamente consiste en que vamos a inyectar un objecto que nos va a permitir escribir en un log, entonces en el controlador tenemos:

public class HomeController : Controller
{
	private ILog log;
	
	public HomeController(ILog log)
	{
		this.log = log;
	}
	
	public ActionResult Index()
	{
		log.Log("Escribiendo en el log");
		return View();
	}
}

Revisando el anterior código, vemos que HomeController requiere un objeto de tipo ILog, es decir que vamos a poder inyectar cualquier clase que implemente dicha interfaz, recuerden que uno de los principios de la inyección de dependencias es trabajar contra abstracciones y no implementaciones.

Ahora vamos con la interfaz ILog:

public interface ILog
{
	void Log(string str);
}

Y ahora una clase que implementa dicha interfaz (la lógica para el ejemplo no es importante):

public class LogFile : ILog
{
	public void Log(string str)
	{
		Debug.Write(str);
	}
}

Ahora viene lo interesante, como DI Container vamos a utilizar Microsoft Unity, así que añadimos por Nuget el paquete Unity.MVC4:

Unity

La ventaja de añadir dicho paquete es que en la raíz del sitio nos añade la clase Bootstrapper donde vamos a poder registrar los componentes:

public static class Bootstrapper
{
	public static IUnityContainer Initialise()
	{
	  var container = BuildUnityContainer();
	  DependencyResolver.SetResolver(new UnityDependencyResolver(container));

	  return container;
	}

	private static IUnityContainer BuildUnityContainer()
	{
	  var container = new UnityContainer();
	  RegisterTypes(container);

	  return container;
	}

	public static void RegisterTypes(IUnityContainer container) {}
}

Ahora es tiempo de registrar nuestras dependencias, para ello hacemos uso del método RegisterTypes de la clase Bootstrapper, para ello usamos container.RegisterType:

public static void RegisterTypes(IUnityContainer container)
{
	container.RegisterType<ILog, LogFile>();
}

Finalmente solo resta realizar el llamado a nuestro DI Container, en este caso usamos el evento Application_Start del Global.asax:

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

	Bootstrapper.Initialise();
}

Y eso es todo, la dependecia es inyectada gracias al uso del DI Container!

[ASP.NET MVC] Creando una factoria de controladores personalizada

Posted on Actualizado enn

Hola a todos, como ya sabemos, un controlador en ASP.NET MVC no es más que una clase, la cual hereda de la clase Controller, sin embargo dicha clase no tiene un constructor definido, o bueno no al menos uno que podamos ver, dicho esto cuando una clase no tiene un constructor definido (o varios) por defecto si se tiene un constructor para esa clase que no recibe parámetros, ahora bien, en MVC tenemos algo que se conoce como factoría de controladores, cuya principal función es inicializar los controladores usando ese constructor vacío que todos tienen…y de que va todo esto? simple, que pasa cuando tenemos un controlador pero este requiere un constructor personalizado? Por ejemplo, si tenemos el siguiente controlador con un constructor personalizado:

public class HomeController : Controller
{
	private string username = string.Empty;
	public HomeController(string username)
	{
		this.username = username;
	}
}

Ahora si intentamos ejecutar, vamos a obtener el siguiente error:

controllererror

El error anterior se da porque el controlador no tiene un constructor sin parámetros por lo tanto no es posible inicializarlo. Pero y el constructor vacío que tienen todas las clases? Bueno, pues resulta que eso solo aplica cuando no se ha definido ningún constructor en la clase, y como nuestro controlador le definimos uno el otro ahora si desaparece.

Debido al problema anterior, necesitamos definir una nueva forma de inicializar el controlador HomeController y pasarle el parámetro que requiere, y para ello podemos crear una factoría personalizada, básicamente debemos crear una nueva clase que implemente la interfaz IControllerFactory, y en la función CreateController definimos como inicializar el controlador anterior.

Por organización vamos a crear una nueva carpeta llamada Factory, y allí dentro una nueva clase con el nombre CustomControllerFactory que implementa IControllerFactory:

public class CustomControllerFactory : IControllerFactory
{
	public IController CreateController(RequestContext requestContext, string controllerName)
	{
		// TODO: Implement this method
		throw new NotImplementedException();
	}

	public SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName)
	{
		// TODO: Implement this method
		throw new NotImplementedException();
	}

	public void ReleaseController(IController controller)
	{
		// TODO: Implement this method
		throw new NotImplementedException();
	}
}

Ya con la clase creada, vamos a iniciar a definir lógica para cada método, iniciemos con ReleaseController, cuya función es liberar recursos:

public void ReleaseController(IController controller)
{
	var disposable = controller as IDisposable;
	if (disposable != null)
		disposable.Dispose();
}

Luego vamos con GetControllerSessionBehavior, por el momento vamos a dejar el comportamiento por defecto:

public SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName)
{
	return SessionStateBehavior.Default;
}

Y finalmente CreateController, donde vamos a especificar la nueva forma de instanciar el controlador que hemos modificado anteriormente:

public IController CreateController(RequestContext requestContext, string controllerName)
{
	if (controllerName.ToLower() == "home")
	{
		var controller = new HomeController("julitogtu");
		return controller;
	}

	var defaultFactory = new DefaultControllerFactory();
	return defaultFactory.CreateController(requestContext, controllerName);
}

Lo que hace el código anterior es validar si el controlador que se esta requiriendo en Home, en caso afirmativo lo instanciamos usando el constructor que hemos creado, en caso que no sea el controlador Home, entonces dejamos que la factoría por defecto haga su trabajo. Ahora el código completo de nuestra factoría:

public class CustomControllerFactory : IControllerFactory
{
	public IController CreateController(RequestContext requestContext, string controllerName)
	{
		if (controllerName.ToLower() == "home")
		{
			var controller = new HomeController("julitogtu");
			return controller;
		}

		var defaultFactory = new DefaultControllerFactory();
		return defaultFactory.CreateController(requestContext, controllerName);
	}

	public SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName)
	{
		return SessionStateBehavior.Default;
	}

	public void ReleaseController(IController controller)
	{
		var disposable = controller as IDisposable;
		if (disposable != null)
			disposable.Dispose();
	}
}

Finalmente, para que la factoría funcione, la llamamos en el evento Application_Start de el Global.asax:

ControllerBuilder.Current.SetControllerFactory(new CustomControllerFactory());

Espero el ejemplo les sea interesante, saludos!

[ASP.NET MVC] Soporte para enumeraciones en ASP.NET MVC 5.1

Posted on Actualizado enn

Hola a todos, uno de las características que le hacia falta a ASP.NET MVC era el soporte nativo para trabajar con enumeraciones, sin embargo ya en la versión 5.1 (ojo que todavía es RC) ya se dispone de un helper dedicado para trabajar con enumeraciones, así que vamos a verlo (Revisa más características en este link).

Lo primero que debes hacer es descargar e instalar el update Visual Studio 2013 Update 1 RC, una vez instalado creamos un nuevo proyecto y añadimos el paquete Microsoft ASP.NET MVC, como todavía no es oficial asegúrate de seleccionar Include Prerelease:

enums

O bien por el Package Manager Console con: Install-Package Microsoft.AspNet.Mvc -Version 5.1.0-rc1 –Pre

Ahora, vamos a crear una enumeración que va a manejar los tipos de clientes:

public enum ClientType
{ 
	Free = 0,
	VIP = 1,
	Gold = 2,
	Platinum = 3
}

Y un modelo:

public class Client
{
	public int ClientId { get; set; }

	public string Name { get; set; }

	public ClientType ClientType { get; set; }
}

Ahora creamos un controlador, para el ejemplo solo voy a crear las acciones para crear (no te fijes si crea o no, porque no lo hace):

public class ClientController : Controller
{
	// GET: /Client/Create
	public ActionResult Create()
	{
		return View();
	}

	 // POST: /Client/Create
	[HttpPost]
	public ActionResult Create(Client client)
	{
		ViewBag.type = client.ClientType;
		return View();
	} 
}

Y finalmente la vista:

@model Enums.Models.Client

@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>

@using (Html.BeginForm()) 
{
    @Html.AntiForgeryToken()
    
    <div class="form-horizontal">
        <h4>Client</h4>
        <hr />
        @Html.ValidationSummary(true)

        <div class="form-group">
            @Html.LabelFor(model => model.Name, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Name)
                @Html.ValidationMessageFor(model => model.Name)
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.ClientType, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EnumDropDownListFor(model => model.ClientType)
                @Html.ValidationMessageFor(model => model.ClientType)
            </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>
}

Ahora al probar la aplicación, se genera correctamente una lista con las opciones de la enumeración:

client

Y si damos click en Create y revisamos lo que pasa en la acción Create, observamos que el valor seleccionado se mapea correctamente con la propiedad del modelo:

modelo

Espero el post les sea interesante, saludos!

[ASP.NET MVC] Implementando Cache con Windows Azure Cache

Posted on Actualizado enn

Hola a todos, hoy quiero mostrarles como es de fácil implementar Windows Azure Cache como proveedor de cache para una aplicación ASP.NET MVC.

Lo primero es crear el servicio de cache en Windows Azure, para ello vamos a New -> Data Services -> Cache -> Quick Create y allí ingresamos los datos correspondientes:

cache1

Luego seleccionamos Create a new cache y esperamos que finalice la creación de la cache.

Ahora ya en Visual Studio y en el proyecto de MVC buscamos el paquete Nuget Windows Azure Cache y lo agregamos:

cache2

Una vez instalado, el paquete agrega las secciones correspondientes en el web.config, aspi que vamos a dicho archivo, buscamos la sección Windows Azure Cache session state provider y descomentariamos las siguientes línes:

<sessionState mode="Custom" customProvider="AFCacheSessionStateProvider">
  <providers>
    <add name="AFCacheSessionStateProvider" 
		type="Microsoft.Web.DistributedCache.DistributedCacheSessionStateStoreProvider, Microsoft.Web.DistributedCache" 
		cacheName="default" dataCacheClientName="default" 
		applicationName="AFCacheSessionState"/>
  </providers>
</sessionState>

Paso siguiente, en el mismo archivo de configuración, dentro del nodo dataCacheClients en identifier le damos el valor del Endpoint, dicho valor lo pueden consultar en el servicio de Cache en Windows Azure:

<autoDiscover isEnabled="true" identifier="democache.cache.windows.net" />

cache3

En el mismo nodo dataCacheClients, descomentariamos la parte de securityProperties y en authorizationInfo definimos el valor correspondiente a la Primary Access Key:

<securityProperties mode="Message" sslEnabled="false">
    <messageSecurity authorizationInfo="YWNzOmh0dHBzOi8vZ....." />
</securityProperties>

cache4

Por último solo resta comenzar a utilizar dicho servicio, para lo cual simplemente debemos ir creando/leyendo objetos de session:

//Añadir Objeto
Session.Add("key", value);

//Leer Objeto
var item = Session["key"];

Espero les sea de utilidad el post, saludos!

[ASP.NET MVC] Implementando autenticación con Windows Azure Active Directory

Posted on Actualizado enn

Hola a todos, con el release de Visual Studio 2013, Microsoft ha lanzado características super interesantes para los desarrolladores Web, y una de ellas trata sobre el concepto de 1 solo ASP.NET, en donde podemos realizar una mezcla bien cool de las diferentes opciones disponibles, adicionalmente, se ha incluido un pequeño wizard para poder configurar el sistema de autenticación (algo de lo que tratará este post), y lo mejor de todo es que lo podemos trabajar con Windows Azure Active Directory.

Lo primero que necesitamos es crear un nuevo Acitve Directory en Windows Azure, así que una vez logueados vamos a New > App Services > Active Directory > Directory > Custom Create:

Create AD

En la ventana modal que se abre ingresamos la información relacionada:

Add AD

Luego ya solo queda navegar a la opción Active Directory, seleccionar el directorio que acabamos de crear e iniciar la creación de usuarios:

testmvc ad

Ahora, vamos a Visual Studio 2013 donde se va a crear una nueva aplicación ASP.NET:

Visual Studio 2013

Ahora para el ejemplo, solo seleccionaré el template MVC:

Template MVC

En la misma pantalla, se va a cambiar el tipo de autenticación, así que click en Change Authentication, se abre una ventana en la cual se debe como primera medida seleccionar Organizational Accounts, y en la parte derecha para el campo Domain se ingresa la cuenta de Active Directoy creada anteriormente:

Change Authentication

Una vez ingresada la información anterior, al dar OK se debe ingresar la información de autenticación del Active Directory:

login

Una vez autenticados ya se crea el template de la aplicación, dicha aplicación ya tiene todo implementando para conectarnos con el Active Directory creado, como punto importante, para que la aplicación se ejecute correctamente dicha aplicación debe ejecutarse sobre https, afortunadamente cuando se ejecuta la aplicación desde Visual Studio, podemos simular el https:

https

Simplemente le decimos continuar a este sitio Web, una vez logueados somo redirigidos  a nuestra aplicación ya logueados (super no?):

mvc + ad

Espero el post les haya gustado, saludos!

[ASP.NET MVC] Implementando el helper autocomplete de Kendo UI

Posted on Actualizado enn

Hola a todos, una de las características que más me gustan de Kendo UI es que tenemos la posibilidad de utilizar una serie de helpers para enriquecer la interfaz de usuario (las vistas), y en esta oportunidad quiero mostrar como es de sencillo implementar el helper autocomplete.

Como primer paso, vamos a crear una sencilla clase que actuará como nuestro modelo:

public class Country
{
	public int CountryId { get; set; }
	public string Name { get; set; }
}

Luego, en el controlador definimos algunos datos:

private readonly List<Country> countries = new List<Country>(){
	new Country { CountryId = 1, Name = "Colombia"},
	new Country { CountryId = 2, Name = "Argentina"},
	new Country { CountryId = 3, Name = "Brazil"},
	new Country { CountryId = 4, Name = "Bolivia"},
	new Country { CountryId = 5, Name = "España"},
	new Country { CountryId = 6, Name = "Chile"},
	new Country { CountryId = 7, Name = "Francia"},
	new Country { CountryId = 8, Name = "Alemania"},
	new Country { CountryId = 9, Name = "Italia"},
	new Country { CountryId = 10, Name = "China"}
};

Finalmente creamos una función que retorne los resultados en formato JSON:

public JsonResult GetCountries()
{
	return Json(countries.ToList(), JsonRequestBehavior.AllowGet);
}

Ahora, en la vista en la cual vamos a implementar el helper:

@using Kendo.Mvc.UI;

@{
    ViewBag.Title = "Autocomplete";
}

<div class="jumbotron">
    <h1>Kendo UI - Autocomplete</h1>
    @(Html.Kendo().AutoComplete()
        .Name("country")
        .Placeholder("Choose a country...")
        .DataTextField("Name")
        .Filter("contains")
        .DataSource(source =>
        {
            source.Read(read =>
            {
                read.Action("GetCountries", "Home");
            });
        })
    )
</div>

Revisando el código de la vista se tienen varias puntos importantes:

  • Agregar un using al namespace Kendo.Mvc.UI
  • Definir el helper con Html.Kendo.Autocomplete
  • La propiedad que se encarga de realizar la llamada a la función GetCountries es DataSource, allí utilizando una expresión lambda se define la acción a llamar y como segundo parámetro el controlador en el cual se encuentra la acción: read.Action(“GetCountries”, “Home”);

Y ahora una pequeña imagen de como se ve el autocomplete ya funcionando:

KendoUI Autocomplete

Saludos!

Código en GitHub!

[ASP.NET MVC] Manejando peticiones AJAX en una sola acción

Posted on Actualizado enn

Hola a todos, hoy quiero mostrar un pequeño tip con el cual podemos responder correctamente a una petición sin importar si dicha petición se realiza utilizando Ajax o no, lo primero que vamos a tener son dos helpers, uno con una petición tradicional @Html.ActionLink y el otro con una de tipo Ajax @Ajax.ActionLink:

@Ajax.ActionLink("Ajax About ", "About", new AjaxOptions { UpdateTargetId = "divAbout" })    
@Html.ActionLink("Normal About", "About")

Luego vamos a la acción About:

public ActionResult About()
{
	ViewBag.Message = "Your application description page.";
	if (Request.IsAjaxRequest())
		return PartialView("About");
	else
		return View("About");
}

Como se puede ver, simplemente se utiliza el método Request.IsAjaxRequest() para determinar si la petición se realizó utilizando Ajax o no, en caso afirmativo se retorna un PartialView, de lo contrario el View tradicional.

Te recomiendo leer este post sobre Vistas Parciales!

Saludos.

Descarga el ejemplo!

[ASP.NET MVC] Encapsulando lógica con Helpers

Posted on Actualizado enn

Hola a todos, hoy quiero compartirles un pequeño post de cómo es posible encapsular lógica que usamos en las vistas en MVC utilizando Helpers, no tocare el detalle de cómo utilizar Helpers, ya que algunos amigos has escrito excelentes artículos al respecto (Refrito de helpers en ASP.NET MVC), sin embargo hoy aportare un poco a tan buenos artículos.

Bueno, iniciemos con un modelo bastante simple:

public class Client
{
	public int ClientId { get; set; }

	public string Name { get; set; }

	public int State { get; set; }
}

Luego un controlador con la acción Home y allí retornamos un pequeño listado de clientes:

public class HomeController : Controller
{
	private readonly List<Client> clients = new List<Client>()
	{
		new Client { ClientId = 1, Name = "Julio", State = 0},
		new Client { ClientId = 2, Name = "Julio", State = 1}
	};

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

y finalmente la vista:

@model IEnumerable<HelpersIf.Models.Client>

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<table>
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.Name)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.State)
        </th>
        <th></th>
    </tr>

@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.Name)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.State)
        </td>
        <td>
            @if (item.State == 0)
            {
                <b style="color:red;">Disable</b>
            }
            else if (item.State == 1)
            { 
                <b style="color:green;">Enable</b>
            }
        </td>
    </tr>
}

</table>

Revisando el código de la vista, se utiliza una sentencia if para validar el estado del cliente y mostrar si esta activo o no dependiendo del valor de la propiedad State, aunque en este caso solo tenemos dos posibles estados, en una aplicación real se pueden tener bastantes opciones, y en mi opinión se estaría contaminando demasiado la vista con lógica de aplicación (entre otros puntos que no me gustan del todo). Para solucionar el problema anterior, es posible crear un Helper que encapsule dicha lógica y deje permita dejar la vista mucho más limpia, así que el siguiente código realizará tal función:

public static class ClientHelper
{
	public static HtmlString ClientState(this HtmlHelper helper, Client client)
	{
		string state = string.Empty;

		if (client.State == 0)
		{
			state = "<b style='color:red;'>Disable</b>";
		}
		else if (client.State == 1)
		{
			state = "<b style='color:green;'>Enable</b>";
		}

		return new HtmlString(state);
	}
}

Una vez que tenemos listo el Helper, vamos a la vista y allí realizamos dos pequeños cambios, el primero es hacer using del namespace donde esta el Helper y el segundo es utilizarlo, por lo tanto luego del cambio la vista quedaría:

@model IEnumerable<HelpersIf.Models.Client>
@using HelpersIf.Helpers

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<table>
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.Name)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.State)
        </th>
        <th></th>
    </tr>

@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.Name)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.State)
        </td>
        <td>
            @Html.ClientState(item)
        </td>
    </tr>
}

</table>

Espero el post les sea de interés, nos vemos!

Descarga el ejemplo!

[ASP.NET MVC] Manejando páginas/controladores/acciones no encontradas

Posted on Actualizado enn

Hola a todos, uno de los errores más comunes en las aplicaciones/sitios Web es el de página no encontrada, y en ASP.NET MVC aplica también para controlador/acción no encontrada, así que les quiero mostrar una manera muy simple de poder manejar este tipo de error, lo primero es crear un nuevo proyecto ASP.NET MVC (yo he seleccionado la plantilla básica), en este momento no se tiene ningún controlador:

image

Y al ejecutar obtenemos el siguiente error (lógico no?):

image

Ahora por medio de Nuget añadimos el paquete NotFound MVC:

image

El cual nos añade la vista NotFound.cshtml dentro de Views/Shared:

image

Y si ejecutamos de nuevo:

image

Nos lleva a la vista NotFound.cshtml, ahora ya es solo que la personalicen con un mejor diseño!

Descarga el ejemplo!

PD: Si te ha gustado el post no olvides compartirlo :D