Ritorna alla lista completa degli articoli

Invio dei dati al controller con AJAX e convalida dei dati di un form

ASP.NET CORE - settembre 15, 2022

In questo articolo, parleremo di come inviare i dati ad un Controller asp.net core utilizzando la tecnologia AJAX. In particolare, vedremo due scenari:

  1. Invio di un form con Ajax senza convalida dei dati inseriti,
  2. Invio di un form con Ajax con la convalida dei dati inseriti,

Ai fini dell'articolo non salveremo i dati in un database ma visualizzeremo solo i dati inviati al Controller.

Che cos'è Ajax

AJAX è l'acronimo di Asynchronous JavaScript and XML. AJAX consente di inviare e ricevere dati in modo asincrono senza ricaricare la pagina Web. Il vantaggio di questa tecnologia è che un utente può continuare ad utilizzare l'applicazione, poiché la richiesta effettuata dal client al server avviene in background. In questo modo si evita di ricaricare la pagina web, si migliora l'esperienza utente e le prestazioni del programma.

Per prima cosa creiamo un nuovo progetto in Visual Studio. Il progetto deve essere di tipo ASP.NET Core (Model-View-Controller).

ASP.NET CORE - Invio dei dati al controller con AJAX e convalida dei dati di un form

Il progetto si dovrà chiamare InviareDatiAjax.

ASP.NET CORE - Invio dei dati al controller con AJAX e convalida dei dati di un form

Confermiamo la versione .NET 6.0 e creiamo il progetto.

ASP.NET CORE - Invio dei dati al controller con AJAX e convalida dei dati di un form

Per prima cosa dobbiamo creare la nostra classe Studente.

ASP.NET CORE - Invio dei dati al controller con AJAX e convalida dei dati di un form

La classe Studente sarà composta dalle seguenti proprietà:

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

	public string? Nome { get; set; }

	public string? Cognome { get; set; }

	public string? Sesso { get; set; }
}

Creata la classe dobbiamo creare il nostro metodo di azione che riceve i dati dal form e li stampa a video. Andiamo nel Controller HomeController.cs e aggiungiamo il seguente codice:

[HttpPost]
public JsonResult SalvaStudenteSenzaConvalida(Studente studente)
{
	string riepilogo = string.Format("Perfetto!!! Hai aggiunto un nuovo studente.\n" +
		"Nome: {0}\nCognome: {1}\nSesso: {2}",
		studente.Nome,
		studente.Cognome,
		studente.Sesso);

	return Json(riepilogo);
}

Il metodo non fa altro che prendersi come parametro l'oggetto della classe Studente e restituire un risultato di tipo Json.

Nella view o vista del Controller HomeController.cs creiamo il nostro form in puro stile Bootstrap.

<h2 class="display-6">Form senza convalida dei dati</h2>
<div class="row">
    <div class="col-md-6">
        <form id="FormStudenteSenzaConvalida">
            <div class="form-group mb-2">
                <label for="Nome">Nome</label>
                <input type="text" class="form-control" id="Studente_Nome" name="Nome" aria-describedby="nomeStudente" placeholder="Nome studente">
            </div>

            <div class="form-group mb-2">
                <label for="Cognome">Cognome</label>
                <input type="text" class="form-control" id="Studente_Cognome" name="Cognome" aria-describedby="cognomeStudente" placeholder="Cognome studente">
            </div>

            <div class="form-group mb-2">
                <label for="Sesso">Sesso</label>
                <div class="form-check">
                    <input class="form-check-input" type="radio" name="Studente_Sesso" id="Studente_Sesso_Maschio" value="Maschio">
                    <label class="form-check-label" for="Studente_Sesso_Maschio">
                        Maschio
                    </label>
                </div>
                <div class="form-check">
                    <input class="form-check-input" type="radio" name="Studente_Sesso" id="Studente_Sesso_Femmina" value="Femmina">
                    <label class="form-check-label" for="Studente_Sesso_Femmina">
                        Femmina
                    </label>
                </div>
            </div>
            <div class="form-group mb-2">
                <button class="btn btn-primary" id="btn_formStudenteSenzaConvalida" type="button">Salva studente</button>
            </div>
        </form>
    </div>
</div>

Il framework Bootstrap è già integrato nel nostro progetto nel file _Layout.cshtml. Adesso non ci resta che creare la nostra funzione AJAX la quale invia i dati al metodo di azione SalvaStudenteSenzaConvalida. Nel primo scenario i dati che passeremo non saranno convalidati ne serializzati.

Il nostro progetto include già un file JavaScript dal nome site.js contenuto nella cartella wwwroot->js. Il file site.js è disponibile in tutte le nostre pagine poiché viene richiamato nel file _Layout.cshtml che si occupa del nostro layout principale ed è presente all'interno della cartella Views->Shared; pertanto, all'interno del file site.js scriveremo il seguente codice:

$(document).ready(function () {
    $("#btn_formStudenteSenzaConvalida").click(function () {
        SalvaStudente();
    });

    function SalvaStudente() {
        let formData = {
            Nome: $("#Studente_Nome").val(),
            Cognome: $("#Studente_Cognome").val(),
            Sesso: $("input[type='radio'][name='Studente_Sesso']:checked").val()
        }
        console.log(formData)
        $.ajax({
            url: "/Home/SalvaStudenteSenzaConvalida",
            type: "POST",
            data: formData,
            success: function (response) {
                alert(response);
            },
            error: function (request, status, error) {
                alert(request.responseText);
            }
        });
    }
});

Il risultato dovrebbe essere simile alla seguente immagine:

ASP.NET CORE - Invio dei dati al controller con AJAX e convalida dei dati di un form

Dopo aver creato il modulo che invia i dati di un nuovo studente, senza convalidarli, vediamo l'altro scenario dove inviamo dei dati da convalidare. In questo caso ci interessa capire come funziona la convalida dei dati e per non modificare la classe Studente creeremo la classe Professore che avrà le stesse proprietà della classe Studente.

public class Professore
{
	[Required(ErrorMessage = "Si prega di inserire un identificativo numerico.")]
	[Range(1, int.MaxValue, ErrorMessage = "Il valore deve essere maggiore di 0.")]
	public int Id { get; set; }

	[Required(ErrorMessage = "Si prega di inserire il nome.")]
	public string? Nome { get; set; }

	[Required(ErrorMessage = "Si prega di inserire il cognome.")]
	public string? Cognome { get; set; }

	[Required(ErrorMessage = "Si prega di selezionare il sesso.")]
	public string? Sesso { get; set; }
}

L'attributo Required indica che il campo è obbligatorio mentre l'attributo Range specifica che il valore deve essere un intero e maggiore di zero.

Spostiamoci nel Controller HomeController.cs e creiamo il nostro metodo di azione SalvaProfessoreConConvalida che si occuperà di ricevere come parametro un oggetto della classe Professore e di restituire un risultato di tipo JSON.

[HttpPost]
[ValidateAntiForgeryToken]
public JsonResult SalvaProfessoreConConvalida(Professore professore)
{
	if (!ModelState.IsValid)
		return Json("Attenzione!!! I dati non sono corretti");

	string riepilogo = string.Format("Perfetto!!! Hai aggiunto un nuovo professore.\n" +
		"Nome: {0}\nCognome: {1}\nSesso: {2}",
		professore.Nome,
		professore.Cognome,
		professore.Sesso);

	return Json(riepilogo);
}

Rispetto al form dello Studente abbiamo decorato il metodo con l'attributo ValidateAntiForgeryToken e aggiunto un ulteriore controllo sulla validità del nostro modello. Il Model State è un array che contiene gli errori originati durante l'associazione e la convalida del modello. Se ad esempio un campo di tipo Integer viene fornito con un valore di tipo String l'errore verrà memorizzato nel ModelState. Il ValidateAntiForgeryToken è anch'esso molto importante ai fini della sicurezza e della convalida dei dati. Questa importantissima funzionalità scrive un valore univoco in un cookie e in un campo nascosto compreso nel modulo che invia i dati al Controller. Ad esempio:

<input name="__RequestVerificationToken" type="hidden" value="CfDJ8PPol9u7eAtNnMr..." /></form>

Quando la pagina viene inviata, viene generato un errore se il valore del cookie non corrisponde al valore del modulo. Tale funzionalità impedisce che un altro sito o un programma malevolo possa inviare contenuti nascosti utilizzando, ad esempio, le credenziali di un utente autenticato. 

All'interno della view del nostro Controller HomeController.cs aggiungiamo il form che permette di aggiungere un nuovo professore:

@model Professore

<h2 class="display-6">Form con convalida dei dati</h2>
<div class="row">
    <div class="col-md-6">
        <form id="FormProfessoreConConvalida" asp-antiforgery="true">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group mb-2">
                <label for="Nome">ID</label>
                <input type="text" asp-for="Id" class="form-control" id="Professore_Id" aria-describedby="idProfessore" placeholder="Id professore">
                <span class="text-danger" asp-validation-for="Id"></span>
            </div>
            <div class="form-group mb-2">
                <label for="Nome">Nome</label>
                <input type="text" asp-for="Nome" class="form-control" id="Professore_Nome" aria-describedby="nomeProfessore" placeholder="Nome professore">
                <span class="text-danger" asp-validation-for="Nome"></span>
            </div>

            <div class="form-group mb-2">
                <label for="Cognome">Cognome</label>
                <input type="text" asp-for="Cognome" class="form-control" id="Professore_Cognome" aria-describedby="cognomeProfessore" placeholder="Cognome professore">
                <span class="text-danger" asp-validation-for="Cognome"></span>
            </div>

            <div class="form-group mb-2">
                <label for="Sesso">Sesso</label>
                <div class="form-check">
                    <input type="radio" asp-for="Sesso" class="form-check-input" id="Professore_Sesso_Maschio" value="Maschio">
                    <label class="form-check-label" for="Professore_Sesso_Maschio">
                        Maschio
                    </label>
                </div>
                <div class="form-check">
                    <input type="radio" asp-for="Sesso" class="form-check-input" id="Professore_Sesso_Femmina" value="Femmina">
                    <label class="form-check-label" for="Professore_Sesso_Femmina">
                        Femmina
                    </label>
                </div>
                <span class="text-danger" asp-validation-for="Sesso"></span>
            </div>
            <div class="form-group mb-2">
                <button class="btn btn-primary" id="btn_formProfessoreConConvalida" type="button">Salva professore</button>
            </div>
        </form>
    </div>
</div>

Il codice è cambiato leggermente. Cercate di confrontarlo con il codice del form Studente. Le differenze sono:

  1. Importazione del modello Professore attraverso la dicitura @model Professore,
  2. Aggiunta dell'attributo asp-antiforgery per prevenire gli attacchi XSRF o CSRF (Cross Site Request Forgery),
  3. Aggiunta dell'attributo asp-validation-summary che viene utilizzato per visualizzare gli errori di convalida aggiunti nel ModelState,
  4. Sostituzione degli attributi name di ogni campo del form con l'attributo asp-for,
  5. Aggiunta dell'attributo asp-validation-for per visualizzare il messaggio di errore.

Adesso possiamo aggiungere il codice necessario in JavaScript affinché il nostro form funzioni. Nel file site.js aggiungiamo la funzione SalvaProfessore:

$(document).ready(function () {
    
    //Form Professore
    $("#btn_formProfessoreConConvalida").click(function () {
        SalvaProfessore();
    });

    function SalvaProfessore() {
        if ($("#FormProfessoreConConvalida").valid()) {
            var formData = $("#FormProfessoreConConvalida").serialize();
            console.log(formData);
            $.ajax({
                url: "/Home/SalvaProfessoreConConvalida",
                type: "POST",
                data: formData,
                success: function (response) {
                    alert(response);
                },
                error: function (request, status, error) {
                    alert(request.responseText);
                }
            });
        }
    }
});

Nella funzione, prima di inviare il form al nostro Controller, viene fatto un controllo dei dati attraverso il metodo valid():

if ( $("#FormProfessoreConConvalida").valid()) {
	// I dati sono validi
}

Affinché il codice funzioni correttamente, è necessario includere due file di tipo .js che troviamo già nel nostro progetto ASP.NET e che dovremo richiamare nel file _Layout.cshtml:

<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>

Invio del modulo senza completare i campi:

ASP.NET CORE - Invio dei dati al controller con AJAX e convalida dei dati di un form

Invio del modulo con tutti i campi completati:

ASP.NET CORE - Invio dei dati al controller con AJAX e convalida dei dati di un form