Creación del proyecto
Desde VS Express 2013 para Web he creado un nuevo proyecto de tipo aplicación ASP.Net MVC con autenticación de tipo cuentas de usuario individuales (es el defecto).
Al crear el proyecto se muestra una página con información sobre los siguientes pasos a realizar en el proyecto. A tener en cuenta en mi proyecto:
- La opción Autenticación, si se selecciona, muestra cómo registrarse e iniciar sesión
- Creación de temas mediante Bootstrap
- Asegurarse de que la aplicación esté lista para el entorno de producción
Si clicamos cualquiera de los 2 primeros nos redirige a:
[…]
This topic explains the options for creating ASP.NET web projects in Visual Studio 2013 with Update 2.
The new dialogs and templates include the following new features compared to earlier versions of Visual Studio:
- A simple UI for creating projects that offer support for multiple ASP.NET frameworks (Web Forms, MVC, and Web API).
- ASP.NET Identity, a new ASP.NET membership system that works the same in all ASP.NET frameworks and works with web hosting software other than IIS.
- The use of Bootstrap to provide responsive design and theming capabilities.
- New features for Web Forms that used to be offered only for MVC, such as automatic test project creation and an Intranet site template.
[…]
En este momento nos centraremos en el apartado ASP.Net Identity.
Autenticación mediante ASP.Net Identity
ASP.Net Identity es el nuevo sistema de autenticación para ASP.Net, tal como se explica en ASP.Net Identity. Para añadirlo a mi proyecto sigo los pasos que se explican en el link:
Adding ASP.NET Identity to an Empty or Existing Web Forms Project
A modo de resumen:
- Para añadir ASP.Net Identity al proyecto, se puede utilizar NuGet tal como muestra la siguiente figura:
- Para mi proyecto cambio la conexión que viene por defecto por una a mi propia base de datos lo cual hace que se generen automáticamente en ella las tablas necesarias.
- De momento no necesito utilizar proveedores externos (facebook, gmail…)
Bootstrap (responsive web)
Las plantillas de proyecto de Visual Studio 2013 utilizan Bootstrap para proporcionar un diseño responsive, lo que significa que los diseños pueden adaptarse dinámicamente a los diferentes tamaños de ventana del navegador, y por tanto, al tamaño de los diferentes dispositivos consumidores.
En bootswatch.com podemos encontrar temas alternativos al que aparece por defecto en nuestra nueva aplicación (aquí se explica en detalle cómo proceder). Además de los temas free también existen otros mucho más elaborados de pago (rondan los 8$ a 18$). Es el caso de los que podemos encontrar en {wrap}bootstrap. Para nuestro mini-CRM hemos comprado la plantilla denominada Ace.
Aquí hemos tenido que dedicar unas cuantas horas a encajar la nueva plantilla.
- Descomprimir el paquete descargado y añadirlo al proyecto
- A partir de index.html de la nueva plantilla, crear una nueva vista _LayoutAce.cshtml con la que reemplazar la actual _Layout.cshtml. Para que el proyecto use la nueva plantilla, cambiar la una por la otra en _ViewStart.cshtml.
@{
Layout = "~/Views/Shared/_LayoutAce.cshtml";
} - Crear los bundles de la nueva plantilla (ver bundling and minification). Para ello en AppStart/BundleConfig.cs añadir las siguientes líneas:
// Bundles de wrapbootstrap-Ace
bundles.Add(new ScriptBundle("~/bundles/wrapbootstrap-ace/js").Include(
"~/templates/wrapbootstrap_ace/assets/js/*.js", "~/templates/wrapbootstrap_ace/assets/js/uncompressed/*.js"));
bundles.Add(new StyleBundle("~/bundles/wrapbootstrap-ace/css").Include(
"~/templates/wrapbootstrap_ace/assets/css/*.css", "~/templates/wrapbootstrap_ace/assets/css/ace.min.css")); - Adaptar _LayoutAce.cshtml. Cambios principales:
- Adaptar la pantalla de inicio de sesión Account/Login.cshtml:
@model NeumaliaCRM.Models.LoginViewModel
@{
Layout = null;
}
@{
ViewBag.Title = "Inicio de sesión";
}
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="utf-8" />
<title>CRM Neumalia - @ViewBag.Title</title>
<meta name="description" content="User login page" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- basic styles -->
<link href="~/templates/wrapbootstrap_ace/assets/css/bootstrap.min.css" rel="stylesheet" />
<link rel="stylesheet" href="~/templates/wrapbootstrap_ace/assets/css/font-awesome.min.css" />
<!--[if IE 7]>
<link rel="stylesheet" href="~/templates/wrapbootstrap_ace/assets/css/font-awesome-ie7.min.css" />
<![endif]-->
<!-- page specific plugin styles -->
<!-- fonts -->
<link rel="stylesheet" href="~/templates/wrapbootstrap_ace/assets/css/ace-fonts.css" />
<!-- ace styles -->
<link rel="stylesheet" href="~/templates/wrapbootstrap_ace/assets/css/ace.min.css" />
<link rel="stylesheet" href="~/templates/wrapbootstrap_ace/assets/css/ace-rtl.min.css" />
<!--[if lte IE 8]>
<link rel="stylesheet" href="~/templates/wrapbootstrap_ace/assets/css/ace-ie.min.css" />
<![endif]-->
<!-- inline styles related to this page -->
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="~/templates/wrapbootstrap_ace/assets/js/html5shiv.js"></script>
<script src="~/templates/wrapbootstrap_ace/assets/js/respond.min.js"></script>
<![endif]-->
@*extraído de site.css...*@
<style>
/* styles for validation helpers */
.field-validation-error {
color: #b94a48;
font-size:small;
}
.field-validation-valid {
display: none;
}
input.input-validation-error {
border: 1px solid #b94a48;
}
input[type="checkbox"].input-validation-error {
border: 0 none;
}
.validation-summary-errors {
color: #b94a48;
}
.validation-summary-valid {
display: none;
}
</style>
</head>
<body class="login-layout">
<div class="main-container">
<div class="main-content">
<div class="row">
<div class="col-sm-10 col-sm-offset-1">
<div class="login-container">
<div class="center">
<h1>
<i class="icon-group green"></i>
<span class="red">CRM</span>
<span class="white">Neumalia</span>
</h1>
<h4 class="blue">© AutoEquip</h4>
</div>
<div class="space-6"></div>
<div class="position-relative">
<div id="login-box" class="login-box visible widget-box no-border">
<div class="widget-body">
<div class="widget-main">
<h4 class="header blue lighter bigger">
<i class="icon-coffee green"></i>
Introduce tus credenciales
</h4>
<div class="space-6"></div>
@using (Html.BeginForm("Login", "Account", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
{
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)
<fieldset>
<label class="block clearfix">
<span class="block input-icon input-icon-right">
@Html.TextBoxFor(m => m.UserName, new { @class = "form-control", @placeholder="Nombre de usuario" })
@Html.ValidationMessageFor(m => m.UserName)
<i class="icon-user"></i>
</span>
</label>
<label class="block clearfix">
<span class="block input-icon input-icon-right">
@Html.PasswordFor(m => m.Password, new { @class = "form-control", @placeholder="Contraseña" })
@Html.ValidationMessageFor(m => m.Password)
<i class="icon-lock"></i>
</span>
</label>
<div class="space"></div>
<div class="clearfix">
@Html.CheckBoxFor(m => m.RememberMe)
@Html.LabelFor(m => m.RememberMe)
<button type="submit" class="width-45 pull-right btn btn-sm btn-primary">
<i class="icon-key"></i>
Iniciar sesión
</button>
</div>
<div class="space-4"></div>
</fieldset>
}
</div><!-- /widget-main -->
</div><!-- /widget-body -->
</div><!-- /login-box -->
</div><!-- /position-relative -->
</div>
</div><!-- /.col -->
</div><!-- /.row -->
</div>
</div><!-- /.main-container -->
</body>
</html>
Adaptar _LoginPartial.cshtml:@using Microsoft.AspNet.Identity
@if (Request.IsAuthenticated)
{
using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm", @class = "navbar-right" }))
{
@Html.AntiForgeryToken()
}
<a data-toggle="dropdown" href="#" class="dropdown-toggle">
<img class="nav-user-photo" src="~/templates/wrapbootstrap_ace/assets/avatars/avatar2.png" alt="Foto usuario" />
<span class="user-info">
<small>Hola,</small>
@User.Identity.GetUserName()
</span>
<i class="icon-caret-down"></i>
</a>
<ul class="user-menu pull-right dropdown-menu dropdown-yellow dropdown-caret dropdown-close">
<li>
<a href="/Account/Manage">
<i class="icon-cog"></i>
Configurar cuenta
</a>
</li>
<li>
<a href="#">
<i class="icon-user"></i>
Perfil
</a>
</li>
<li class="divider"></li>
<li>
<a href="javascript:document.getElementById('logoutForm').submit()">
<i class="icon-off"></i>
Cerrar sesión
</a>
</li>
</ul>
}
else
{
<ul class="nav navbar-nav navbar-right">
@*<li>@Html.ActionLink("Registrarse", "Register", "Account", routeValues: null, htmlAttributes: new { id = "registerLink" })</li>*@
<li>@Html.ActionLink("Iniciar sesión", "Login", "Account", routeValues: null, htmlAttributes: new { id = "loginLink" })</li>
</ul>
}
[…]
<head>
<meta charset="utf-8" />
<title>Mi CRM</title>
<meta name="description" content="Common form elements and layouts" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
@Styles.Render("~/bundles/wrapbootstrap-ace/css")
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/jqueryval")
@Scripts.Render("~/bundles/modernizr")
@Scripts.Render("~/bundles/bootstrap")
@Scripts.Render("~/bundles/wrapbootstrap-ace/js")
[…]
<li class="light-blue">
@Html.Partial("_LoginPartial")
</li><!—login-->
[…]
<div class="page-content">
@RenderBody()
</div><!-- /.page-content -->