Fermer

septembre 10, 2020

Utilisation de l'API Telerik Report Server dans ASP.NET MVC


Apprenez à utiliser l'API Telerik Report Server pour améliorer les fonctionnalités de vos applications en donnant à l'utilisateur une liste des rapports qu'il peut consulter.

Le Telerik Report Server est évidemment un référentiel pour les rapports que vous affichez dans vos applications. Cependant, il comprend également une API riche qui vous permet de tirer parti de ce référentiel pour incorporer des fonctionnalités supplémentaires dans vos applications. Vous pouvez, par exemple, donner aux utilisateurs une liste de tous les rapports qu'ils sont autorisés à consulter, puis afficher le rapport sélectionné. Ce n'est pas aussi simple que vous pourriez le souhaiter, mais cela vous évitera d'avoir à créer une vue dédiée pour chaque rapport de votre application ASP.NET MVC.

Pour mettre en œuvre ce plan, vous devrez probablement utiliser deux vues car ReportViewer a tendance à prendre le contrôle de toute votre page: une vue pour afficher la liste déroulante des rapports et une autre vue pour afficher le rapport réel. Je vais commencer par créer la vue avec la liste déroulante des rapports.

Configuration pour appeler l'API Report Server

Pour donner à l'utilisateur une liste de rapports, vous devez d'abord récupérer cette liste à partir du Telerik Report Server . Bien que vous puissiez utiliser l'objet standard .NET HttpClient et créer vos propres requêtes RESTful au serveur, Telerik Report Server fournit un client dédié (ReportServerClient) qui facilite grandement l'utilisation de l'API du serveur.

Pour utiliser le client Telerik , vous devrez ajouter des références à Telerik.ReportServer.HttpClient.dll et Telerik.ReportServer.Services.Models.dll. Ceux-ci sont installés avec le Telerik Report Server et se trouvent dans le dossier Tools du dossier d’installation du Report Server (sur mon ordinateur, je les ai trouvés dans C: Program Files (x86) Progress Telerik Report Server Tools). Vous aurez également besoin des packages NuGet pour Microsoft.AspNet.WebApi.Client et Newtonsoft.Json.

La prochaine étape évidente consiste à récupérer un ensemble d'objets ReportInfo sur le serveur à l'aide du client. Cependant, c'est là que vous rencontrerez un problème. L’objet ReportInfo possède un certain nombre de propriétés, notamment le nom du fichier de rapport (dans la propriété Name), l’extension du fichier de rapport (propriété Extension) et l’ID de la catégorie à laquelle appartient le rapport (CategoryId). Cependant, pour utiliser le rapport avec le ReportViewer de Telerik, vous devez transmettre à ReportViewer l’URI du rapport, composé du nom de la catégorie du rapport, du nom de fichier et de l’extension de fichier. Cela signifie que vous devez assembler l’URI à partir des propriétés de ReportInfo.

Ce n’est pas quelque chose que vous voudrez faire plusieurs fois, il est donc logique de stocker les URI générés dans l’objet Session. Pour prendre en charge cela (et, éventuellement, pour afficher les rapports dans une liste déroulante ASP.NET), j'ai créé une classe pour contenir le nom et l'URI d'un ReportInfo:

 public class ReportName
{
    chaîne publique Name {get; ensemble; }
    chaîne publique Uri {get; ensemble; }
}

Avec cela en place, la première chose que je fais est d'essayer de récupérer ma collection d'objets ReportName à partir de l'objet Session. Si je ne le trouve pas ici (si c'est la première fois que l'utilisateur visite cette page de rapport), je lance le processus de création de la collection de ReportNames:

 public ActionResult Index ()
{
   Liste  rNames = (Liste ) Session ["ReportNames"];
   if (rNames == null)
  {

Appel de l'API Report Server

Je lance le processus de récupération des objets ReportInfo en créant un objet Settings et en définissant son BaseAddress sur l'URL du Report Server (cet exemple suppose que vous exécutez sur un Report Server fonctionnant sur le même ordinateur que le client):

 var st = new Settings ();
s.BaseAddress = "http: // localhost: 83";

Je suis maintenant prêt à créer l'objet ReportServerClient qui gère la conversation avec le ReportServer, en lui passant l'objet de paramètres que j'ai créé. Le client a une méthode Dispose donc je la crée dans un bloc using afin que je puisse m'assurer que la méthode Dispose est appelée. Après avoir créé le client, ma prochaine étape consiste à utiliser sa méthode de connexion, en transmettant un nom d'utilisateur et un mot de passe qui ont été configurés sur le serveur de rapports. Cela garantit que l'utilisateur ne voit que les rapports qu'il est autorisé à exécuter.

Dans ce code, j'ai codé en dur un nom et un mot de passe dans cet exemple mais, dans la vraie vie, vous voudriez interroger l'utilisateur ou extraire les informations de l'objet d'identité ASP.NET:

 using (var rsc = nouveau ReportServerClient (st))
{
   rsc.Login ("PeterVogel", "milesdavis1");

Je peux maintenant récupérer une liste de tous les rapports disponibles pour l'identifiant de connexion en appelant la méthode GetReportInfos du client. Ce code fait le travail et, en plus, trie les objets par leur CategoryId (ce tri importera plus tard lorsque je récupérerai le nom de la catégorie):

 IEnumerable  reps = rsc.GetReportInfos (). OrderBy (ri => ri .CategoryId);

S'il n'y a aucun rapport accessible par l'utilisateur, GetReportInfos renvoie une collection vide ce qui signifie que je peux utiliser en toute sécurité ma collection ReportInfo dans une boucle – s'il n'y a aucun rapport accessible pour l'utilisateur, la boucle sera ignorée.

Création de la liste

Je suis maintenant presque prêt à commencer à créer ma liste de noms de rapports. J'initialise d'abord une collection pour contenir mes objets ReportName. Je vais (éventuellement) utiliser cette collection dans une liste déroulante dans ma première vue, donc je charge également la collection avec un objet factice pour afficher un message initial dans la liste:

 rNames = new List  ( );
rNames.Add (new ReportName {Name = "Veuillez sélectionner un rapport", Uri = string.Empty});

Maintenant, je vais parcourir ma collection d'objets ReportInfo en créant un objet ReportName pour chacun d'eux. À mesure que les identifiants de catégorie changent, j'utiliserai la méthode getCategory du client pour récupérer le nom de la catégorie du rapport. J'ai défini chaque objet ReportName sur la propriété Name de ReportInfo et la propriété Uri sur la concaténation du nom de la catégorie, du nom du rapport et de son extension:

 reps.ForEach (ri =>
{
   string cIdOld = string.Empty;
   string cName = string.Empty;
   if (ri.CategoryId! = cIdOld)
   {
       cName = rsc.GetCategory (ri.CategoryId) .Name;
   }
   rNames.Add (nouveau ReportName {
                                     Nom = ri.Name,
                                     Uri = cName + "/" + ri.Name + ri.Extension});
   });

Enfin, j'ajoute ma collection d'objets ReportName à l'objet Session pour ne pas avoir à refaire cette opération:

 Session ["ReportNames"] = rNames;

Puisque je vais afficher cette collection dans une liste déroulante, que je la crée ou que je la récupère à partir de la session, je crée une SelectList à partir de ma collection. Lors de la création de la SelectList, je spécifie que la propriété Name doit être affichée à l'utilisateur et que la propriété Uri doit être utilisée comme valeur à renvoyer au serveur lorsque l'utilisateur a effectué sa sélection. Enfin, j'invoque la vue qui inclut ma liste déroulante:

 ViewBag.ReportList = new SelectList (rNames, "Uri", "Name");
return View ("ReportsList");

Affichage de la liste et du rapport

Après tout ce code dans la méthode d'action, la bonne nouvelle est que le code de la vue pour créer la liste déroulante est assez simple. Je viens de passer à la méthode DropDownList de HtmlHelper le nom que je veux appliquer à l'élément HTML et à la SelectList du ViewBag. J'ajoute également du code JavaScript pour déclencher une actualisation de la page et demander la vue qui affichera mon rapport.

J'ai donné à ma liste déroulante le nom Uri afin de pouvoir utiliser la valeur renvoyée sur le serveur avec ma classe ReportName:

  
@ Html.DropDownList ("Uri", (SelectList) ViewBag.ReportList, new {onchange = "form.submit ();" })

Désormais, lorsque l'utilisateur sélectionne un rapport dans la liste déroulante, je publie la valeur de la sélection de l'utilisateur (l'URI du rapport) sur le serveur sous le nom Uri. Dans ma méthode d'action, j'ai choisi de recycler ma classe ReportName en tant que paramètre de la méthode – la liaison de modèle remplira la valeur de ma liste déroulante dans la propriété Uri de l'objet. Après avoir vérifié que j'ai obtenu une valeur du navigateur, je passe cet objet ReportName à ma vue (et si je n'obtiens pas de valeur, je renvoie l'utilisateur à ma vue ReportsList après avoir recréé la SelectList):

 Rapport ActionResult public (ReportName rName)
{
   if (rName.Uri! = null)
   {
       return View (rName);
   }
   Liste  rNames = (Liste ) Session ["ReportNames"];
   ViewBag.ReportList = new SelectList (rNames, "Uri", "Name");
   return View («ReportsList»);
}

Pour afficher le rapport sélectionné dans le contrôle ReportViewer de Telerik, il me suffit de transmettre l’URI du rapport à la propriété Report de l’objet ReportSourceOptions de ReportViewer. Le balisage suivant dans une vue ASP.NET MVC fera l'affaire:

 @ (Html.TelerikReporting (). ReportViewer ()
            .Id ("reportViewer1")
            .ServiceUrl (Url.Content ("http: localhost: 83 / api / reports"))
            .ReportSource (nouveau UriReportSource () {Uri = Model.Uri})
            .ViewMode (ViewMode.Interactive)
            .ScaleMode (ScaleMode.Specific)
            .Échelle (1.0)
            .PersistSession (faux)
            .PrintMode (PrintMode.AutoSelect)
           .EnableAccessibility (false))

Et voilà: deux vues qui montreront à l'utilisateur tous les rapports auxquels il peut accéder et lui afficheront le rapport.

Il existe de nombreuses façons d'améliorer ce code: Il peut être plus judicieux pour vous de conserver la SelectList dans l'objet Session que la collection de base de ReportNames. Sinon, si vous avez beaucoup d'utilisateurs mais un petit nombre d'identifiants de connexion aux rapports, il peut être judicieux de conserver la liste des rapports dans un dictionnaire du MemoryCache, chaque liste étant stockée sous un nom d'utilisateur de rapport. Et il peut également être judicieux de regrouper le code qui génère la collection d'objets ReportName dans une classe car, je parie, vous finirez par l'utiliser dans d'autres applications.





Source link