Construire un web service avec son client Windows pour gerer et consulter une bibliothèque de livres
Un web service de stockage et de gestion de livres en ligne
Un logiciel sous Windows pour consulter et lire les livres
Langages autorisés : C#, HTML, Javascript, CSS, TypeScript
Serveur web : ASP.Net Core
Logiciel Windows : WPF
Votre solution devra être basé sur le projet Library.sln
La partie server est dans le projet ASP.Server
La partie client est dans le projet WPF.Reader
La connexion entre votre client et votre serveur est dans le projet WPF.Reader.OpenApi
- Pour éviter les boucles infinies entre genre et livre lors de la conversion en JSON:
- Utiliser un ou plusieur DTO (voir plus bas)
- Pour renvoyer un objet différent de celui contenu dans votre base utilisé un DTO
- Vous fait votre DTO à la main: https://learn.microsoft.com/en-us/aspnet/web-api/overview/data/using-web-api-with-entity-framework/part-5
- Vous utiliser la librairie AutoMapper: https://automapper.org/
-
Pour que Entity Framework retourne les genres avec les livres :
- Utilisez la méthode Include :
libraryDbContext.Books.Include(b => b.Genres).Where(x => x.Price > 0)
- Utiliser le LazyLoading
- Utilisez la méthode Include :
- En WPF certain évenements ne suportent pas les comandes utilisez le package Microsoft.Xaml.Behaviors.Wpf
- Exemple
view.xamlviewmodel.cs<page xmlns:behaviours="http://schemas.microsoft.com/xaml/behaviors"> ... <ListBox ItemsSource="{Binding ChangeMe}"> <behaviours:Interaction.Triggers> <behaviours:EventTrigger EventName="SelectionChanged"> <behaviours:InvokeCommandAction Command="{Binding SelectionChangedCommand}" PassEventArgsToCommand="True"/> </behaviours:EventTrigger> </behaviours:Interaction.Triggers> </ListBox> ... </page>
private RelayCommand selectionChangedCommand; public ICommand SelectionChangedCommand => selectionChangedCommand ??= new RelayCommand(SelectionChanged); private void SelectionChanged(object commandParameter) { }
- Exemple
Stocker une bibliothèque de livres consistant en :
- Une liste de livres accessibles à la lecture
- Une liste de genres permettant de caractériser les livres
Sachant que :
- Un livre contient au minimum :
- Un Id
- Un titre
- Un contenu
- Un prix
- Des genres
- Un livre peut avoir plusieurs genres
Il est nécessaire pour ces fonctionnalités de mettre à disposition de l’utilisateur une interface web
Un utilisateur doit pouvoir :
- ajouter des livres dans la bibliothèque
- supprimer des livres de la bibliothèque
- Consulter la liste de tous les livres
- Consulter la liste de tous les genres
- Faire une interface pour ajouter de nouveaux genres
- Modifier un livre existant
Options :
- Remplacer le champs autheur (de type string) de la classe livre par une laison vers une classe Autheur
- On considère qu'un livre n'a qu'un seul et unique autheur (même si dans la réalité ce n'est pas vrai)
- La class autheur à besoin d'au minimum du nom de l'autheur
- Afficher des filtres dans la liste des livres pour filtrer par autheurs / genres
- Une page affichants les statistiques sur :
- le nombre de libres total disponible
- le nombre de livres par autheur
- Le nombre maximum, minmum, median et moyen de mots d'un livre
- Importer les details d'un livre par l'OpenLibrary
- https://openlibrary.org/
- Pouvoir rentrer un contenu + isbn
- récupéré l'auteur + description et l'ecrire en base
- BONUS PAR NOUS: Pendant la Création d'un Genre, il est possible de lui associer un livre déjà existant. - Il est possible de filtrer les livres par nom.
Une ébauche de ce qui est attendu ce trouve dans ASP.Server/Controllers/BookController.cs et GenreController.cs
Une api REST doit être mis à disposition pour permettre à des clients externes de consulter la librairie
Une ébauche de ce qui est attendu ce trouve dans le fichier ASP.Server/Api/BookController.cs
Cette api doit permettre de :
- Récupérer un livre avec son contenu
- Lister les genres disponibles
- Lister les livres (sans le contenu)
Options:
- Utiliser un plugin pour changer le format de sortie
- le plugin ne doit pas faire partie de la solution. Il doit etre charger à partir d'un dossier en contenant plusieurs.
- Mettez a disposition un moyen pour pouvoir créer un nouveau plugin compatible avec votre solution
- Vous ne conaissez pas la liste des plugins en avance, il doivent être chargés dynamiquement
- les paramètres de l'API permettent de choisir le plugin a utiliser (/book/{id}?output=xxx)
- Pas de package exterieur autorisé !
- Faite pareil mais avec des plugins codés dans un language compilé (C, C++, RUST, ...)
- Rajouter la possibilité de décharger la DLL
Exemple:
{
"Id": 1, "Name": "titre", "Prix": 10.5, "Content": "contenu",
"Genres": [{ "Id": 1, "Name": "Genre" }]
}
Exemple:
[{
"Id": 1, "Name": "Genre"
}, {
"Id": 2, "Name": "Genre2"
}, {
…
}]
- Le résultat doit être paginé
- La recherche doit aussi pouvoir être faite en spécifiant un genre
- La réponse doit contenir un header qui contient l'index de début et de fin des livres que vous retournez ainsi que le nombre total de livres de votre séléction
Exemple Header:
- /book?offset=10&limit=15
HTTP/1.1 200
Content-Type: application/json
Pagination: 10-25/536
Exemple Body :
- /book
[{
…
}, {
"Id": 5, "Name": "titre", "Prix": 10.5,
"Genres": [{ "Id": 3, "Name": "Genre" }]
}, {
…
}, {
"Id": 15, "Name": "titre2", "Prix": 12.5,
"Genres": [{ "Id": 3, "Name": "Genre" }]
}, {
…
}, {
"Id": 20, "Name": "titre2", "Prix": 13.5,
"Genres": [{ "Id": 3, "Name": "Genre" }]
}]
- /book?limit=10&offset=20
[{
"Id": 10, "Name": "titre", "Prix": 10.5,
"Genres": [{ "Id": 3, "Name": "Genre" }]
}, {
"Id": 11, "Name": "titre2", "Prix": 12.5,
"Genres": [{ "Id": 6, "Name": "Genre6" }]
}]
- /book?genre=3
[{
"Id": 5, "Name": "titre", "Prix": 10.5,
"Genres": [{ "Id": 3, "Name": "Genre" }]
}, {
"Id": 15, "Name": "titre2", "Prix": 12.5,
"Genres": [{ "Id": 3, "Name": "Genre" }]
}, {
"Id": 20, "Name": "titre2", "Prix": 13.5,
"Genres": [{ "Id": 3, "Name": "Genre" }]
}]
- /book?limit=2&offset=20&genre=3 ->
[{
"Id": 5, "Name": "titre", "Prix": 10.5,
"Genres": [{ "Id": 3, "Name": "Genre" }]
}, {
"Id": 15, "Name": "titre2", "Prix": 12.5,
"Genres": [{ "Id": 3, "Name": "Genre" }]
}]
Il est conseiller d’utiliser :
pour générer un fichier OpenApi automatiquement, cela accélèrera grandement le développement du client.
La solution fournie intègre NSwag par défaut
L’application doit pouvoir permettre de :
- Lister les N premiers livres (vous pouvez définir la limite comme bon vous semble)
- Afficher les détails d’un livre
- Lire un livre
Options :
- Lister tous les genres
- Afficher les N premiers livres d’un genre (vous pouvez définir la limite comme bon vous semble)
- Gerer la pagination de vos livres (Scroll infini, pages ou autres)
- Afficher un livre avec formatage: Style de police, couleur, taille du texte, ...
- Pensé au RTF, HTML, PDF, ...
- Dans un premier temps gérez uniquement 1 format. Si vous avez finit, vous pouvez gérer plusieurs formats en même temps
- Lire le livre grace à l'API System.Speech.SpeechSynthesizer
- Géré la lecture / l'arrêt / la pause / la reprise
- Changer les boutons de controle en fonction de l'état de la lecture (comme un lecteur vidéo, ex: youtube)
- Commencer à lire a partir de la séléction de l'utilisateur, L'utilisateur doit pouvoir faire un clic droit sur un mot et lancer la lecture a partir de ce mot
À tout moment l’utilisateur doit pouvoir revenir à l’accueil, il n’est pas nécessaire de faire un bouton pour revenir à la page précédente
Les écrans doivent s’articuler de la façon suivante :
Les carrés bleus représentent un écran Les carrés blancs représentent une fonctionnalité disponible sur l’écran Les carrés verts sont optionnels
L’application doit pouvoir recevoir les livres depuis le serveur développé dans la partie précédente
Pour générer le code client vous pouvez utiliser :
- Utiliser la librairie WPF.Reader.OpenApi (mettez la à jour par contre !)
- Assurer vous que votre serveur fonctionne
- Depuis Visual Studio selectionner le projet WPF.Reader.OpenApi -> Clicker sur projet depuis le menu -> Services connectés -> Gérer les services connectés -> Clicker sur les 3 points (...) sur la ligne <swagger - Client> -> Actualiser
- OpenAPI Generator Plugin (https://marketplace.visualstudio.com/items?itemName=ChristianResmaHelle.ApiClientCodeGenerator2022)
- OpenApi Generator (https://github.com/OpenAPITools/openapi-generator)
- Unchased NSwag (https://marketplace.visualstudio.com/items?itemName=Unchase.unchaseopenapiconnectedservice)
- NswagStudio (https://github.com/RicoSuter/NSwag/wiki/NSwagStudio)
- ou un autre
Vous pouvez sinon faire les requêtes à la main grâce à :
- HttpClient (System.Net.Http)
- Restsharp (https://www.nuget.org/packages/RestClient.Net/)