Traduction du MVC Music Store Partie 9 : Enregistrement et encaissement
Date de publication : 10/01/2012. Date de mise à jour : 10/01/2012.
Par
Jon Galloway (Blog)
Jean-Michel Ormes (Traduction) (Home) (Blog)
Le MVC Music Store est une application d'étude qui introduit et explique étape par étape comment utiliser ASP.NET MVC et Visual Web Developer pour faire du développement web.
Le MVC Music Store est un exemple simplifié d'application de magasin qui vend des albums de musique en ligne, implémente l'administration du site, l'authentification d'utilisateurs et la fonctionnalité d'achat sous forme de panier.
Ce tutoriel détaille toutes les étapes à suivre pour construire le MVC Music Store. La partie 9 du tutoriel s'intitule "Enregistrement et encaissement".
Retrouvez l'ensemble des articles de la série sur cette page :
MVC Music Store
N'hésitez pas à laisser votre avis sur le contenu de l'article directement via le forum :
5 commentaires
Traduction
1. Introduction
2. Migration du Panier
3. Création du CheckoutController
4. Ajout de la vue AddressAndPayment
5. Définition des règles de validation pour la commande
6. Ajout de la vue Checkout Complete
7. Mise à jour de la vue Error
Remerciements
Traduction
1. Introduction
Dans cette section, nous allons créer un CheckoutController qui va recueillir les informations concernant l'adresse et le paiement de l'acheteur. Nous allons demander aux utilisateurs de s'inscrire sur notre site avant les vérifications, donc le contrôleur sera soumis à autorisation.
Les utilisateurs pourront accéder au processus de paiement de leur panier en cliquant sur le bouton "Checkout".
Si l'utilisateur n'est pas connecté, Il sera invité à le faire.
Si la connexion réussit, on affiche la vue AddressAndPayment à l'utilisateur.
Une fois qu'ils ont rempli le formulaire et soumis la commande, ils pourront voir apparaître l'écran de confirmation de la commande.
Si l'on tente d'afficher la vue pour une commande qui n'existe pas ou qui ne nous appartient pas, la vue Error nous sera retournée.
2. Migration du Panier
Alors que le processus d'achat est anonyme, lorsque les utilisateurs cliquent sur le bouton Checkout, ils seront tenus de s'inscrire et s'identifier. Les utilisateurs s'attendront à ce que l'on conserve les informations du panier entre deux visites, nous aurons donc besoin d'associer les informations des paniers aux utilisateurs lorsqu'ils se seront enregistrés ou connectés.
C'est vraiment très simple à faire, car notre classe ShoppingCart a déjà une méthode qui va associer tous les éléments du panier courant à un nom d'utilisateur. Nous aurons juste besoin d'appeler cette méthode lorsqu'un utilisateur s'enregistre ou se connecte.
Ouvrez la classe AccountController que nous avons ajouté quand nous mettions en place le membership et les autorisations. Ajouter une instruction using qui référence MvcMusicStore.Models, puis ajoutez la méthode suivante MigrateShoppingCart :
|
private void MigrateShoppingCart (string UserName)
{
var cart = ShoppingCart. GetCart (this . HttpContext);
cart. MigrateCart (UserName);
Session[ ShoppingCart. CartSessionKey] = UserName;
}
|
Puis, modifiez l'action LogOn afin d'appeler MigrateShoppingCart une fois que l'utilisateur aura été validé, comme suit :
|
[ HttpPost]
public ActionResult LogOn (LogOnModel model, string returnUrl)
{
if (ModelState. IsValid)
{
if (Membership. ValidateUser (model. UserName, model. Password))
{
MigrateShoppingCart (model. UserName);
FormsAuthentication. SetAuthCookie (model. UserName,
model. RememberMe);
if (Url. IsLocalUrl (returnUrl) & & returnUrl. Length > 1
& & returnUrl. StartsWith (" / " )
& & ! returnUrl. StartsWith (" // " ) & &
! returnUrl. StartsWith (" /\\ " ))
{
return Redirect (returnUrl);
}
else
{
return RedirectToAction (" Index " , " Home " );
}
}
else
{
ModelState. AddModelError (" " , " The user name or password provided is incorrect. " );
}
}
return View (model);
}
|
Effectuez la même modification pour l'action Register, immédiatement après que le compte de l'utilisateur ait été créé avec succès :
|
[ HttpPost]
public ActionResult Register (RegisterModel model)
{
if (ModelState. IsValid)
{
MembershipCreateStatus createStatus;
Membership. CreateUser (model. UserName, model. Password, model. Email,
" question " , " answer " , true , null , out
createStatus);
if (createStatus = = MembershipCreateStatus. Success)
{
MigrateShoppingCart (model. UserName);
FormsAuthentication. SetAuthCookie (model. UserName, false
);
return RedirectToAction (" Index " , " Home " );
}
else
{
ModelState. AddModelError (" " , ErrorCodeToString (createStatus));
}
}
return View (model);
}
|
C'est tout - maintenant un panier anonyme sera automatiquement transféré à un compte d'utilisateur lors d'un enregistrement réussi ou une connexion.
3. Création du CheckoutController
Faites un clic droit sur le dossier Controllers et ajoutez un nouveau contrôleur au projet appelé CheckoutController en utilisant le template " Empty controller ".
Tout d'abord, ajoutez l'attribut Authorize au-dessus de la déclaration de la classe contrôleur pour obliger les utilisateurs à s'inscrire avant le paiement :
|
namespace MvcMusicStore. Controllers
{
[ Authorize]
public class CheckoutController : Controller
|
Note: Ceci est similaire au changement que nous avons effectué auparavant dans le StoreManagerController, mais dans ce cas l'attribut Authorize nécessite que l'utilisateur soit dans un rôle Administrator. Dans le CheckoutController, nous exigeons que l'utilisateur soit connecté mais nous n'exigeons pas qu'il soit administrateur.
Par souci de simplicité, nous n'allons pas traiter les informations de paiement dans ce tutoriel. Au lieu de cela, nous allons autoriser les utilisateurs à utiliser un code promo. Nous allons stocker ce code promo en utilisant une constante appelée PromoCode.
Comme dans le StoreController, nous allons déclarer un champ qui sera une instance de la classe MusicStoreEntities, appelé storeDB. Afin d'utiliser la classe MusicStoreEntities, nous aurons besoin d'ajouter une instruction using pour l'espace de noms MvcMusicStore.Models. Le début de notre contrôleur Checkout apparaît comme suit.
|
using System;
using System. Linq;
using System. Web. Mvc;
using MvcMusicStore. Models;
namespace MvcMusicStore. Controllers
{
[ Authorize]
public class CheckoutController : Controller
{
MusicStoreEntities storeDB = new MusicStoreEntities ();
const string PromoCode = " FREE " ;
|
Le CheckoutController aura les actions suivantes :
AddressAndPayment (GET method) va afficher un formulaire qui permet à l'utilisateur d'entrer ses informations.
AddressAndPayment (POST method) va valider les saisies et procéder à la commande.
Complete sera affichée une fois que l'utilisateur aura finalisé avec succès le processus de paiement. Cette vue incluera le numéro de commande de l'utilisateur, comme confirmation.
En premier lieu, renommons l'action Index (qui a été générée lorsque nous avons créé le contrôleur) de AddressAndPayment. Cette action affiche juste le formulaire de paiement, et ne nécessite aucune information sur le modèle.
|
public ActionResult AddressAndPayment ()
{
return View ();
}
|
Notre méthode POST AddressAndPayment va suivre le même pattern que celui que nous avons utilisé dans le StoreManagerController : il va essayer d'accepter la soumission du formulaire et remplir la commande, et va ré-afficher le formulaire si cela échoue.
Une fois que la validation des saisies du formulaire répond à nos exigences de validation d'une commande, nous allons vérifier la valeur PromoCode du formulaire directement. En supposant que tout est correct, nous allons sauvegarder les informations mises à jour avec la commande, indiquer à l'objet ShoppingCart de completer le processus de commande, et de rediriger vers l'action Complete.
|
[ HttpPost]
public ActionResult AddressAndPayment (FormCollection values)
{
var order = new Order ();
TryUpdateModel (order);
try
{
if (string . Equals (values[ " PromoCode " ] , PromoCode,
StringComparison. OrdinalIgnoreCase) = = false )
{
return View (order);
}
else
{
order. Username = User. Identity. Name;
order. OrderDate = DateTime. Now;
storeDB. Orders. Add (order);
storeDB. SaveChanges ();
var cart = ShoppingCart. GetCart (this . HttpContext);
cart. CreateOrder (order);
return RedirectToAction (" Complete " ,
new { id = order. OrderId } );
}
}
catch
{
return View (order);
}
}
|
Après avoir réussi le processus de paiement, les utilisateurs vont être redirigés vers l'action Complete du contrôleur. Cette action va effectuer une simple vérification afin de valider que la commande appartient bien à l'utilisateur connecté avant d'afficher le numéro de commande pour confirmation.
|
public ActionResult Complete (int id)
{
bool isValid = storeDB. Orders. Any (
o = > o. OrderId = = id & &
o. Username = = User. Identity. Name);
if (isValid)
{
return View (id);
}
else
{
return View (" Error " );
}
}
|
Note : La vue Error a été automatiquement créée pour nous dans le dossier /Views/Shared lorsque nous avons commencé le projet.
Le code complet du CheckoutController est le suivant :
|
using System;
using System. Linq;
using System. Web. Mvc;
using MvcMusicStore. Models;
namespace MvcMusicStore. Controllers
{
[ Authorize]
public class CheckoutController : Controller
{
MusicStoreEntities storeDB = new MusicStoreEntities ();
const string PromoCode = " FREE " ;
public ActionResult AddressAndPayment ()
{
return View ();
}
[ HttpPost]
public ActionResult AddressAndPayment (FormCollection values)
{
var order = new Order ();
TryUpdateModel (order);
try
{
if (string . Equals (values[ " PromoCode " ] , PromoCode,
StringComparison. OrdinalIgnoreCase) = = false )
{
return View (order);
}
else
{
order. Username = User. Identity. Name;
order. OrderDate = DateTime. Now;
storeDB. Orders. Add (order);
storeDB. SaveChanges ();
var cart = ShoppingCart. GetCart (this . HttpContext);
cart. CreateOrder (order);
return RedirectToAction (" Complete " ,
new { id = order. OrderId } );
}
}
catch
{
return View (order);
}
}
public ActionResult Complete (int id)
{
bool isValid = storeDB. Orders. Any (
o = > o. OrderId = = id & &
o. Username = = User. Identity. Name);
if (isValid)
{
return View (id);
}
else
{
return View (" Error " );
}
}
}
}
|
4. Ajout de la vue AddressAndPayment
Maintenant, nous allons créer la vue AddressAndPayment. Faites un clic droit sur une des actions du contrôleur AddressAndPayment et ajoutez une vue appelée AddressAndPayment qui est fortement typée à une commande et qui utilise le template Edit, comme montré ci-dessous.
Cette vue se servira de deux des techniques que nous avons observées pendant la construction de la vue StoreManagerEdit :
- Nous allons utiliser Html.EditorForModel() pour afficher les champs du formulaire pour le modèle Order
- Nous allons tirer parti des règles de validation en utilisant la classe Order avec les attributs de validation
Nous allons commencer par mettre à jour le code du formulaire en utilisant Html.EditorForModel(), suivi d'une textbox supplémentaire pour le code promo. Le code complet de la vue AddressAndPayment est montré ci-dessous.
|
@model MvcMusicStore. Models. Order
@{
ViewBag. Title = " Address And Payment " ;
}
< script src= " @Url.Content( " ~ / Scripts/ jquery. validate. min. js" ) "
type= " text/javascript " > < / script>
< script src= " @Url.Content( " ~ / Scripts/ jquery. validate. unobtrusive. min. js" ) "
type= " text/javascript " > < / script>
@using (Html. BeginForm ()) {
< h2> Address And Payment< / h2>
< fieldset>
< legend> Shipping Information< / legend>
@Html. EditorForModel ()
< / fieldset>
< fieldset>
< legend> Payment< / legend>
< p> We' re running a promotion: all music is free
with the promo code: " FREE " < / p>
< div class = " editor-label " >
@Html. Label (" Promo Code " )
< / div>
< div class = " editor-field " >
@Html. TextBox (" PromoCode " )
< / div>
< / fieldset>
< input type= " submit " value= " Submit Order " / >
}
|
5. Définition des règles de validation pour la commande
Maintenant que notre vue est prête, nous allons mettre en place les règles de validation pour notre modèle Commande comme nous l'avons fait précédemment pour le modèle Album. Faites un clic droit sur le dossier Models et ajoutez une classe appelée Order. En plus des attributs de validation que nous avons auparavant utilisés pour l'album, nous allons également utiliser une expression régulière pour valider l'adresse e-mail de l'utilisateur.
|
using System. Collections. Generic;
using System. ComponentModel;
using System. ComponentModel. DataAnnotations;
using System. Web. Mvc;
namespace MvcMusicStore. Models
{
[ Bind (Exclude = " OrderId " )]
public partial class Order
{
[ ScaffoldColumn (false )]
public int OrderId { get; set; }
[ ScaffoldColumn (false )]
public System. DateTime OrderDate { get; set; }
[ ScaffoldColumn (false )]
public string Username { get; set; }
[ Required (ErrorMessage = " First Name is required " )]
[ DisplayName (" First Name " )]
[ StringLength (160 )]
public string FirstName { get; set; }
[ Required (ErrorMessage = " Last Name is required " )]
[ DisplayName (" Last Name " )]
[ StringLength (160 )]
public string LastName { get; set; }
[ Required (ErrorMessage = " Address is required " )]
[ StringLength (70 )]
public string Address { get; set; }
[ Required (ErrorMessage = " City is required " )]
[ StringLength (40 )]
public string City { get; set; }
[ Required (ErrorMessage = " State is required " )]
[ StringLength (40 )]
public string State { get; set; }
[ Required (ErrorMessage = " Postal Code is required " )]
[ DisplayName (" Postal Code " )]
[ StringLength (10 )]
public string PostalCode { get; set; }
[ Required (ErrorMessage = " Country is required " )]
[ StringLength (40 )]
public string Country { get; set; }
[ Required (ErrorMessage = " Phone is required " )]
[ StringLength (24 )]
public string Phone { get; set; }
[ Required (ErrorMessage = " Email Address is required " )]
[ DisplayName (" Email Address " )]
[ RegularExpression (@" [A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4} " ,
ErrorMessage = " Email is is not valid. " )]
[ DataType (DataType. EmailAddress)]
public string Email { get; set; }
[ ScaffoldColumn (false )]
public decimal Total { get; set; }
public List< OrderDetail> OrderDetails { get; set; }
}
}
|
Le fait de tenter de soumettre le formulaire avec des informations manquantes ou invalides va maintenant afficher un message d'erreur en utilisant la validation côté client.
Ok, nous avons fait le plus dur du travail pour le processus de paiement ; nous avons juste quelques bricoles à finaliser. Nous avons besoin d'ajouter deux vues simples, et nous avons besoin de prendre soin de la non-intervention des informations du panier durant le processus de connexion.
6. Ajout de la vue Checkout Complete
La vue Checkout Complete est assez simple, car elle a juste besoin d'afficher l'ID de la commande. Faites un clic droit sur l'action Complete et ajoutez une vue appelée Complete qui est fortement typée en tant qu'entier.
Maintenant, nous allons mettre à jour le code de la vue pour afficher l'ID de la commande, comme ci-dessous.
|
@model int
@{
ViewBag. Title = " Checkout Complete " ;
}
< h2> Checkout Complete< / h2>
< p> Thanks for your order! Your order number is : @Model< / p>
< p> How about shopping for some more music in our
@Html. ActionLink (" store " ,
" Index " , " Home " )
< / p>
|
7. Mise à jour de la vue Error
Le template de base inclut une vue Error qui se trouve dans le dossier vue Shared afin qu'elle puisse être réutilisée n'importe où dans le site. Cette vue Error contient une très simple erreur et n'utilise pas la mise en page de notre site, donc nous allons la mettre à jour.
Comme il s'agit d'une page d'erreur générique, le contenu est très simple. Nous allons inclure un message et un lien pour accéder à la page précédente de notre historique si les utilisateurs veulent réessayer leur action.
|
@{
ViewBag. Title = " Error " ;
}
< h2> Error< / h2>
< p> We' re sorry, we ' ve hit an unexpected error.
< a href= " javascript:history.go(-1) " > Click here< / a>
if you' d like to go back and try that again.</p>
|
Remerciements