Server

http.createServer(function (req, res) {

    let url = "";
    let type = "text/html";
    if (req.url.endsWith(".css")) {
        url = "." + req.url;
        type = "text/css";
    } else if (req.url.endsWith(".js")) {
        url = "." + req.url;
        type = "text/javascript";
    } else {
        url = "pages" + (req.url=="/"?"/index":req.url) + ".html";
    }
    console.log(url);
    fs.readFile(url, function (err, data) {
        if (!err) {
            res.writeHead(200, { "Content-Type": type });
            res.end(data);
        }
        else {
            res.writeHead(404, { "Content-Type": "text/html" });
            res.end("<h1>Not found</h1>");
        }
    });
}).listen(port);

Empezando con express

npm i express

var express = require('express');
var app = express();

app.get('/', function (req, res) {
  res.send('Hello World!');
});

app.listen(3000, function () {
  console.log('Example app listening on port 3000!');
});

The general syntax for a route is shown below

app.METHOD(PATH, HANDLER)
Wherein,

1) app is an instance of the express module

2) METHOD is an HTTP request method (GET, POST, PUT or DELETE)

3) PATH is a path on the server.

4) HANDLER is the function executed when the route is matched

var express = require('express');
var app = express();
app.route('/Node').get(function(req,res)
{
    res.send("Tutorial on Node");
});
app.route('/Angular').get(function(req,res)
{
    res.send("Tutorial on Angular");
});
app.get('/',function(req,res){
    res.send('Welcome to Guru99 Tutorials');
}));
app.get("/items/:vegetable", (req, res) => {
let veg = req.params.vegetable;
res.send(`This is the page for ${veg}`);
});

middleware:

app.use((req, res, next) => {
console.log(`request made to: ${req.url}`);
next();
});
// An example middleware function
var a_middleware_function = function(req, res, next) {
  // ... perform some operations
  next(); // Call next() so Express will call the next middleware function in the chain.
}

// Function added with use() for all routes and verbs
app.use(a_middleware_function);

// Function added with use() for a specific route
app.use('/someroute', a_middleware_function);

// A middleware function added for a specific HTTP verb and route
app.get('/', a_middleware_function);

Para archivos estáticos:

app.use(express.static('public'));

Servidor muy sencillo

const routeResponseMap = {
  "/info": "<h1>Info Page</h1>",
  "/contact": "<h1>Contact Us</h1>",
  "/about": "<h1>Learn More About Us.</h1>",
  "/hello": "<h1>Say hello by emailing us here</h1>",
  "/error": "<h1>Sorry the page you are looking for is not here.</h1>"
};

const port = 3000,
  http = require("http"),

  app = http.createServer((req, res) => {
    res.writeHead(200, {
      "Content-Type": "text/html"
    });
    if (routeResponseMap[req.url]) {
      res.end(routeResponseMap[req.url]);
    } else {
      res.end("<h1>Welcome!</h1>");
    }
  });
app.listen(port);
console.log(`The server has started and is listening on port number:${port}`);

Chat: un ejemplo

Necesitamos instalar express y socket:

npm i express

npm i socket.io

 

server.js


var app = require('express')();
var http = require('http').createServer(app);
var io = require('socket.io')(http);

app.get('/', function (req, res) {
res.sendFile(__dirname + '/index.html');
});

io.on('connection', function (socket) {
socket.on('chat message', function (msg) {
io.emit('chat message', msg);
});
});

http.listen(1337, function () {
console.log('escuchando en *:1337');
});

index.html


<!doctype html>
<html>
<head>
<title>Socket.IO chat</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}

body {
font: 13px Helvetica, Arial;
}

form {
background: #000;
padding: 3px;
position: fixed;
bottom: 0;
width: 100%;
}

form input {
border: 0;
padding: 10px;
width: 90%;
margin-right: .5%;
}

form button {
width: 9%;
background: rgb(130, 224, 255);
border: none;
padding: 10px;
}

#messages {
list-style-type: none;
margin: 0;
padding: 0;
}

#messages li {
padding: 5px 10px;
}

#messages li:nth-child(odd) {
background: #eee;
}
</style>
</head>
<body>
<ul id="messages"></ul>
<form action="">
<input id="m" autocomplete="off" /><button>Send</button>
</form>
<script src="/socket.io/socket.io.js"></script>
<script src="https://code.jquery.com/jquery-1.11.1.js"></script>
<script>
$(function () {
var socket = io();
$('form').submit(function (e) {
e.preventDefault(); // prevents page reloading
socket.emit('chat message', $('#m').val());
$('#m').val('');
return false;
});
socket.on('chat message', function (msg) {
$('#messages').append($('<li>').text(msg));
});
});
</script>
</body>
</html>

Añadimos log. En server.js:

var fs = require('fs');

fs.open('log.txt', 'w', function (err, file) {
    if (err) throw err;
    console.log('Creado!');
});
app.get('/', function (req, res) {
    res.sendFile(__dirname + '/index.html');
});

Después del emit:

  fs.appendFile('log.txt', msg+"\r\n", function (err) {
            if (err) throw err;
            console.log('Guardado!');
        });

Node

Por qué usar Node
https://www.toptal.com/nodejs/por-que-demonios-usaria-node-js-un-tutorial-caso-por-caso

Un tutorial en castellano:

https://www.nodebeginner.org/index-es.html

w3school nos quiere:

https://www.w3schools.com/nodejs/

Crear una api:

https://www.imaginaformacion.com/tutorial/aprende-nodejs-tutorial-de-primeros-pasos/

Tutorial completo:

https://www.guru99.com/node-js-tutorial.html

Oficial:
https://nodejs.org/api/synopsis.html

Ampliación ejercicio Razor

Cada producto puede tener una serie de pedidos. Los pedidos tienen los siguientes campos:

Fecha de pedido (no puede ser ni menor que el día de hoy, ni mayor que dentro de 30 días)
Urgente (true/false)
Modo de envío: Seleccionar entre Correo normal, certificado o recogida en tienda
Observaciones: Campo libre de texto (grande)

Dentro del detalle de producto tendremos un botón para añadir un pedido.
También tendremos, dentro del detalle del producto, la lista de pedidos de ese producto. En esa lista tenemos la posibilidad de borrarlos.

En la pantalla principal de la lista de productos se verá el número de pedidos que tiene cada producto.

HTML helpers en razor

https://www.tutorialsteacher.com/mvc/html-helpers

@Html.TextBox("StudentName", null, new { @class = "form-control" })  

<input class="form-control"
id="StudentName"
name="StudentName"
type="text"
value="" />

@Html.TextBoxFor(m => m.StudentName, new { @class = "form-control" })  
<input class="form-control" 
        id="StudentName" 
        name="StudentName" 
        type="text" 
        value="John" />


@Html.CheckBox("isNewlyEnrolled", true)


<input checked="checked" 
        id="isNewlyEnrolled" 
        name="isNewlyEnrolled" 
        type="checkbox" 
        value="true" />

Male:   @Html.RadioButton("Gender","Male")  
Female: @Html.RadioButton("Gender","Female")  

Male: <input checked="checked" 
        id="Gender" 
        name="Gender" 
        type="radio" 
        value="Male" />

Female: <input id="Gender" 
        name="Gender" 
        type="radio" 
        value="Female" />

@Html.DropDownList("StudentGender", 
                    new SelectList(Enum.GetValues(typeof(Gender))),
                    "Select Gender",
                    new { @class = "form-control" })

<select class="form-control" id="StudentGender" name="StudentGender">
<
option>Select Gender</option>
<option>Male</option>
<option>Female</option>
</select>

Editor:
https://www.tutorialsteacher.com/mvc/htmlhelper-editor-editorfor

Asistentes de etiquetas

Delimitadoras: https://docs.microsoft.com/es-es/aspnet/core/mvc/views/tag-helpers/built-in/anchor-tag-helper?view=aspnetcore-3.1

asp-controller El nombre del controlador.
asp-action El nombre del método de acción.
asp-area El nombre del área.
asp-page El nombre de la página de Razor.
asp-page-handler El nombre del controlador de páginas de Razor.
asp-route El nombre de la ruta.
asp-route-{value} Un valor único de ruta de dirección URL. Por ejemplo: asp-route-id="1234".
asp-all-route-data Todos los valores de ruta.
asp-fragment El fragmento de dirección URL.

Ejemplos:

<a asp-controller="Speaker"
asp-action="Index">All Speakers</a>

<a href="/Speaker">All Speakers</a>

<a asp-controller="Speaker"
asp-action="Evaluations">Speaker Evaluations</a>

<a href="/Speaker/Evaluations">Speaker Evaluations</a>



De formulario:

https://docs.microsoft.com/es-es/aspnet/core/mvc/views/working-with-forms?view=aspnetcore-3.1#the-form-tag-helper


<form asp-controller="Demo" asp-action="Register" method="post">
<!-- Input and Submit elements -->
</form>

<form method="post" action="/Demo/Register">
<!-- Input and Submit elements -->
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>


Entrada:

https://docs.microsoft.com/es-es/aspnet/core/mvc/views/tag-helpers/built-in/image-tag-helper?view=aspnetcore-3.1


@model RegisterViewModel

<form asp-controller="Demo" asp-action="RegisterInput" method="post">
Email: <input asp-for="Email" /> <br />
Password: <input asp-for="Password" /><br />
<button type="submit">Register</button>
</form>

<br data-mce-bogus="1">

<form method="post" action="/Demo/RegisterInput">
Email:
<input type="email" data-val="true"
data-val-email="The Email Address field is not a valid email address."
data-val-required="The Email Address field is required."
id="Email" name="Email" value=""><br>
Password:
<input type="password" data-val="true"
data-val-required="The Password field is required."
id="Password" name="Password"><br>
<button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>


Para crear select:

https://docs.microsoft.com/es-es/aspnet/core/mvc/views/working-with-forms?view=aspnetcore-3.1#the-select-tag-helper


<select asp-for="Country" asp-items="Model.Countries"></select>

<span class="hljs-tag"><<span class="hljs-name">select</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"Country"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"Country"</span>></span> <span class="hljs-tag"><<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"MX"</span>></span>Mexico<span class="hljs-tag"></<span class="hljs-name">option</span>></span> <span class="hljs-tag"><<span class="hljs-name">option</span> <span class="hljs-attr">selected</span>=<span class="hljs-string">"selected"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"CA"</span>></span>Canada<span class="hljs-tag"></<span class="hljs-name">option</span>></span> <span class="hljs-tag"><<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"US"</span>></span>USA<span class="hljs-tag"></<span class="hljs-name">option</span>></span> <span class="hljs-tag"></<span class="hljs-name">select</span>></span>


Mensajes validación:

https://docs.microsoft.com/es-es/aspnet/core/mvc/views/working-with-forms?view=aspnetcore-3.1#the-validation-message-tag-helper



<span asp-validation-for="Email"></span>

<span class="field-validation-valid"
data-valmsg-for="Email"
data-valmsg-replace="true"></span>

Ejercicio Razor Pages

Añadir en cada línea de producto en el index el precio con IVA (21%) El iva lo guardaremos como propiedad en el IndexModel.

Crear una página llamada ‘Caro’ que nos muestre el producto más caro. Si hay varios productos que tienen el mismo precio mostrarlos todos.

Crear en la página de nuevo producto un botón nuevo que nos cree tres copias del producto que estamos añadiendo. Es decir, tendremos el guardar normal y el crear copias que nos lo añade y tres copias más.

Ejercicios Razor

1.- Sucesión fibonacci. En un input introducimos un número y mostramos la sucesión de fibonacci hasta ese número.

2.- Anillos. En un input ponemos un tamaño y mostramos una tabla cuadrada con lado de ese tamaño y de colores negro y blanco alternando en forma de anillo.

3.- Generador de contraseñas. Ponemos un select que tiene: 1) letras 2)letras y números 3) letras números y símbolos. Un input para el tamaño. Al enviar nos genera una contraseña aleatoria con el tamaño y el juego de caracteres indicado.