Login Login
MORE

WIDGETS

Widgets

Wanted articles
Who is online?
Article tools

CSharp:WebAPI Esempi

From Aino Wiki

Jump to: navigation, search

Tutorial Microsoft
Video corsi Microsoft

Partenza

Prima di iniziare diciamo che Visual Studio consente di creare una prima versione in base ad un template standard.

Creare una solution

Creare una nuova solution

C sharp Progetto Web API 01.png

Quindi scegliere il nome della solution, la versione del framework etc, quindi:

C sharp Progetto Web API 02.png

Una solution potrebbe esser strutturata come segue:

Web API Solution 01.png

Nel template è inclusa una pagina di partenza come è possibile vedere sotto:
.\Views\Home, pagina "index.cshtml" che supporta un menu con una pagina elenco delle API esportate ed una pagina di help stessa.
I primi steps saranno aggiungere una classe modello (ovvero una entità quel che sul database potrà corrispondere ad una tabella), ed un controller ovvero una classe con i metodi\azioni che agiranno sul modello.
Esempio di aggiunta di un controller.

C sharp Progetto Web API 04.png
C sharp Progetto Web API 05.png

Nel esempio ho aggiunto una cartella, DAL, con le classi di accesso al DB (MS SQL Server) *DAOed una classe Helper per automatizzare il binding da query verso SQL server.
Nella cartella Controllers ho aggiunto una classe base cui per comodità si potranno far ereditere da tutti i nuovi controller.
Notare il Web.config che a sua volta è composto in una versione Debug ed una Release a seconda della compilazione\pubblicazione in debug o release con configurazioni specifiche. Questa soluzione consente di definire una stringa di connessione al DB per il debug ed una per la Release.

Aggiungere librerie

Conviene da subito integrare la solution con funzionalità tipiche provenienti da librerie esterne.
Ad esempio per il debug si può integrare NLog per il logging, Swagger per debuggare\testare i metodi della Web API. Allo scopo basta lanciare il manager dei package di NuGet:

C sharp Progetto Web API 033.png

Per accedere alla pagina di test di Swagger dei metodi della Web API basta aggiungere \Swagger all'URL di default, es.:
https://localhost:44368/swagger/ui/index

Web.Config

Per gestire in automatico la versione della stringa di connessione al DB segue un esempio:
web.config
E' necessario comunque definire la sezione di configurazione delle stringa di connessione

<configuration>
  <appSettings>
    ...
  </appSettings>
 
    <connectionStrings>
        <add name="Digitalk_DB"
             connectionString="Data Source=localhost;Initial Catalog=Digitalk;Integrated Security=True;MultipleActiveResultSets=True"
             providerName="System.Data.SqlClient" />
    </connectionStrings>
<configuration>


web.Debug.config
Notare il riferimento a "XML-Document-Transform" che indica che si adotterà un motore di sostituzione dell'XML della configurazione affinché si applichi l'automatismo di sostituzione della stringa di connessione come voluto.
l'attributo xdt:Transform="SetAttributes" xdt:Locator="Match(name)" serve a fare la sostituzione automatica dell'attributo name del TAG connectionStrings

<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
    <connectionStrings>
        <add name="Digitalk_DB" 
             connectionString="Data Source=NomeServerDebug;Initial Catalog=NomeDB;;User ID=utenteApplicativoDB;Password=passwordUtente;MultipleActiveResultSets=True"
             providerName="System.Data.SqlClient"
             xdt:Transform="SetAttributes" xdt:Locator="Match(name)" />
    </connectionStrings>
 
  <system.web>
...
  </system.web>
</configuration>


web.Release.config

<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
    <connectionStrings>
        <add name="Digitalk_DB" 
             connectionString="Data Source=NomeServerProduzione;Initial Catalog=NomeDB;;User ID=utenteApplicativoDB;Password=passwordUtente;MultipleActiveResultSets=True"
             providerName="System.Data.SqlClient"
             xdt:Transform="SetAttributes" xdt:Locator="Match(name)" />
    </connectionStrings>
 
  <system.web>
...
  </system.web>
</configuration>


HTTP o HTTPS

IIS Express

Quando si crea un progetto WebAPI al più si aggiungerà l'uso del SSL, in questo caso però anche la connessione HTTP funzionerà. Nella situazione di default IIS Express predisporrà due URL che risponderanno su porte differenti ma con protocolli diversi, notare la seguente immagine la cui proprietà del progetto WebAPI selezionato è visualizzato nella colonna di sx.

WebAPI HTTP e HTTPS.png

IIS

Se il sito web è sotto IIS occorrerà impostare il binding affinché si possa lavorare in doppia modalità.
Supponendo di aver posto il proprio sito sotto il "Default Web Site":

  • selezionare il nodo Default Web Site,
  • nel pannello di estrema sinistra intitolato "Actions", selezionare bindings
  • se non già predisposto l'HTTP cliccare sul pulsante "Add..." ed aggiungere l'ulteriore protocollo non impostato precedentemente
IIS HTTP HTTPS.png

Aggiungere il bindigs all'HTTP

IIS HTTP HTTPS2.png

Risultato finale:

IIS HTTP HTTPS3.png

Debug

Ora per fare debug del sito sotto IIS occorrerà agganciare Visual Studio al processo dell'IIS come segue:

Debug on IIS.png

Quindi, fate attenzione che sia checcato "Show process from all users" !!!

Debug on IIS2.png

Esempio semplice

Modificato e adattato da tutorial Microsoft

Model

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
 
namespace WebAPI_ToTestMultiUpdater.Models
{
    public class ShipPackage
    {
        public string ShipFullCode { get; set; }
 
        public string ShipCode { get; set; }
 
        public string CompanyCode { get; set; }
 
        public string CompanyName { get; set; }
 
        public string PackageFileName { get; set; }
    }
}

Controller

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using WebAPI_ToTestMultiUpdater.Models;
 
namespace WebAPI_ToTestMultiUpdater.Controllers
{
    public class ShipPackagesController : ApiController
    {
        ShipPackage[] shipPackages = new ShipPackage[]
        {
            new ShipPackage { ShipFullCode = "C_DI", ShipCode = "DI", CompanyCode = "C", CompanyName = "Costa", PackageFileName = "K:\\zighinè\\C_DI_20160518_1619" },
            new ShipPackage { ShipFullCode = "C_PA", ShipCode = "PA", CompanyCode = "C", CompanyName = "Costa", PackageFileName = "C:\\KT\\C_PA_20160518_1620" },
            new ShipPackage { ShipFullCode = "C_FA", ShipCode = "FA", CompanyCode = "C", CompanyName = "Costa", PackageFileName = "d:\\KT\\C_FA_20160518_1621" },
            new ShipPackage { ShipFullCode = "A_ST", ShipCode = "ST", CompanyCode = "A", CompanyName = "Aida", PackageFileName = "A_ST_20160518_1622" }
        };
 
        public IEnumerable<ShipPackage> GetAllShipPackages()
        {
            return shipPackages;
        }
 
        public IHttpActionResult GetShipPackage(string id) // ATTENZIONE il nome della variabile si DEVE chiamare id
        {
            var shipPackage = shipPackages.FirstOrDefault((p) => p.ShipFullCode == id);
            if (shipPackage == null)
            {
                return NotFound();
            }
            return Ok(shipPackage);
        }
    }
}

Client

Supponendo una applicazione client che usi la WebAPI occorre installare e referenziare nella solution del client il pacchetto "Microsoft.AspNet.WebApi.SelfHost", a tal scopo si può usare NuGet. EsempioSegue un pezzo di codice di una mia Windows Form application (molti using non servono):

using NLog;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;
using System.Xml;
using System.Threading;
using Microsoft.Win32;
using System.Text.RegularExpressions;
using System.Net.Http;
using System.Net;
using System.Net.Http.Headers;
 
namespace MultiPrepareKTUpdater
{
// Classe contenitore....
        private void BtnMultiCopy_Export_Click(object sender, EventArgs e)
        {
            string exportDestinationRootPath = string.Empty;
            string strOutput = string.Empty;
 
            try
            {
                Cursor.Current = Cursors.WaitCursor;
                exportDestinationRootPath = TxtExportDestinationRootPath.Text.Trim();
                if (!string.IsNullOrWhiteSpace(exportDestinationRootPath))
                {
                    // http://localhost:60098/api/ShipPackage
 
                    var handler = new HttpClientHandler();
                    handler.UseDefaultCredentials = true;
                    handler.PreAuthenticate = true;
                    handler.ClientCertificateOptions = ClientCertificateOption.Automatic;
                    //handler.Credentials = new NetworkCredential("test01", "test01");
 
                    m_HTTPClient = new HttpClient(handler);
                    m_HTTPClient.BaseAddress = new Uri("http://localhost:60098");
 
                    //var resp = m_HTTPClient.GetAsync(string.Format("api/books/{0}", id)).Result;
                    var resp = m_HTTPClient.GetAsync(string.Format("api/ShipPackages")).Result;
                    resp.EnsureSuccessStatusCode();
 
                    var shipPackages = resp.Content.ReadAsAsync<IEnumerable<ShipPackage>>().Result;
                    foreach (var p in shipPackages)
                    {
                        //Console.WriteLine("{0} {1} {2} ({3})", p.Id, p.Name, p.Author, p.Rating);
                        strOutput += string.Format("ShipCode = '{0}'\tCompanyCode = '{1}'\tCompanyName = '{2}'\tPackageFileName = '{3}'\r\n", 
                                        p.ShipCode, p.CompanyCode, p.CompanyName, p.PackageFileName);
                    }
                    MessageBox.Show(string.Format("From Web API:\r\n\r\n{0}", strOutput), string.Format("BtnMultiCopy_Export_Click"),
                                MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                else
                {
                    Cursor.Current = Cursors.Default;
                    MessageBox.Show(string.Format("Type the root path where copy the configuration files."), string.Format("BtnMultiCopy_Export_Click"),
                                MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            catch (Exception ex)
            {
                Cursor.Current = Cursors.Default;
                m_loggerForm.Error("Ex.: '{0}'\r\n\r\n{1}", ex.Message, ex.StackTrace);
                MessageBox.Show(string.Format("{0}", ex.Message), string.Format("BtnMultiCopy_Export_Click"),
                                MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                Cursor.Current = Cursors.Default;
                Application.DoEvents();
            }
        }
 
}
//..... Oggetto da aggiungere da qualche parte. Nota che è ugale all'oggetto inserito nella solution della Web API
    public class ShipPackage
    {
        public string ShipFullCode { get; set; }
 
        public string ShipCode { get; set; }
 
        public string CompanyCode { get; set; }
 
        public string CompanyName { get; set; }
 
        public string PackageFileName { get; set; }
    }

Un altro modo con cui si può chiamare la web API è quello di specificare puntualmente quel che si vuole come id dell'oggetto. Segue URL:

http://localhost:65342/api/ShipPackages/C_FA

Restituirà solo il seguente item XML (è quel che si vedrebbe in un browser):

<ShipPackage xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/WebAPI_ToTestMultiUpdater.Models">
	<CompanyCode>C</CompanyCode>
	<CompanyName>Costa</CompanyName>
	<PackageFileName>d:\KT\C_FA_20160518_1621</PackageFileName>
	<ShipCode>FA</ShipCode>
	<ShipFullCode>C_FA</ShipFullCode>
</ShipPackage>

Esempio POST realistico

E' un metodo POST che genera au file system un file PDF usando la libreria PDFSharp e MiraDoc

using efabbisognoweb.common;
using efabbisognoweb.DAL;
using efabbisognoweb.Interfaces;
using log4net;
 
using MigraDoc.DocumentObjectModel;
using MigraDoc.DocumentObjectModel.Shapes;
using MigraDoc.DocumentObjectModel.Tables;
using MigraDoc.Rendering;
using PdfSharp;
using PdfSharp.Pdf;
 
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Web.Http;
using System.Web.UI;
using TheArtOfDev.HtmlRenderer.PdfSharp;
 
namespace efabbisognoweb.api
{
    public class StampeController : ApiController
    {
        #region Costanti
        private static readonly ILog log = LogManager.GetLogger(typeof(StampeController));
        private static readonly string c_logo_RelativePath = "\\content\\xxx_logo.jpg";
        private static readonly string c_PDF_RelativeOutputPath = "\\DocRepository\\";
 
        // RGB colors
        Color c_TableBorder = new Color(81, 125, 192);
        Color c_TableBlue = new Color(235, 240, 249);   // Colore dell'intestazione
        Color c_TableGray = new Color(242, 242, 242);   // Colore delle righe pari
        #endregion
 
        string m_logoFullPath = string.Empty;
 
        #region Stampa Anteprima Ordini Fornitori
        /// <summary>
        /// Dato un JSON in input costruisce un report PDF ponendolo in una cartella convenzionata (dove il clinet si aspetta che ci sia). 
        /// Se tutto va bene in output fornisce il percorso relativo, comprensivo del nome file generato, 
        /// altrimenti fornisce l'errore generato
        /// </summary>
        /// <param name="aof">JSON in input</param>
        /// <returns>percorso relativo, comprensivo del nome file, dove è collocato il file generato</returns>
        [ActionName("stampa-menu-anteprimaordini")]
        [Route("stampa-menu-anteprimaordini")]
        [HttpPost]
        public HttpResponseMessage Post_Stampa_menu_anteprimaordini_HttpResponse(AnteprimaOrdiniFornitoriIN aof)
        {
            log4net.Config.XmlConfigurator.Configure();
            HttpResponseMessage cResponse;
            string fileNameRelativePath = string.Empty;
            string pdfFileNameFullPath = string.Empty;
 
            try
            {
                if (aof == null)
                {
                    throw new Exception("Il JSON di Input risulta vuoto.");
                }
                log.InfoFormat("Impianto {0}, dal {1}, al {2}, Nr fornitori {3}, Totale Ordini {4}, User account '{5}'.",
                               aof.codice_impianto, aof.data_dal, aof.data_al, aof.numero_fornitori, aof.totale_ordini, aof.account);
 
                // Pulizia fiels vecchi di precedenti elaborazioni
                int maxMinutesOld = 10;
                string pathPDF = System.Web.HttpRuntime.AppDomainAppPath + c_PDF_RelativeOutputPath;
                FileSystemHelper fsh = new FileSystemHelper(log);
                fsh.PuliziaVecchiFile(pathPDF, "PDF", maxMinutesOld);
 
                #region Verifica informazioni propedeutiche
                if (string.IsNullOrWhiteSpace(aof.codice_impianto))
                {
                    throw new Exception("Non è stato indicato in input il codcie impianto.");
                }
                if (aof.ordini == null
                    || aof.ordini.Length == 0)
                {
                    throw new Exception("Non risultano ordini di cui produrre anteprima.");
                }
                #endregion
 
                CostruisciPDF_AnteprimaOrdini(aof, ref pdfFileNameFullPath); // <-- !
 
                fileNameRelativePath = string.Format("{0}{1}", 
                                                c_PDF_RelativeOutputPath, Path.GetFileName(pdfFileNameFullPath));
                cResponse = new HttpResponseMessage(HttpStatusCode.OK);
                cResponse.Content = new StringContent(fileNameRelativePath, System.Text.Encoding.Unicode, "text/html");
            }
            catch (Exception e)
            {
                string errorMessage = string.Format("Path relativo PDF: '{0}'. Errore generico {1}, {2}", 
                                                    pdfFileNameFullPath, e.HResult, e.Message);
                log.ErrorFormat(errorMessage);
                cResponse = new HttpResponseMessage(HttpStatusCode.InternalServerError);
                cResponse.Content = new StringContent(errorMessage, System.Text.Encoding.Unicode, "text/html");
            }
            return cResponse;
        }
 
        private MemoryStream CostruisciPDF_AnteprimaOrdini(AnteprimaOrdiniFornitoriIN aof, ref string pdfFileNameFullPath, 
                                                            bool pdfStreamOut = false)
        {
            MemoryStream stream = new MemoryStream();
            try
            {
                InfoColonna[] infoTabColonne;
                #region Definizione array delle colonne delle tabelle di dati
                infoTabColonne = new InfoColonna[]
                {
                    new InfoColonna
                    {
                        Label = "Cod.Art.",
                        Ampiezza = "2.2cm",
                        AllineamentoOrizzontale = ParagraphAlignment.Center,
                        AllineamentoVerticale = VerticalAlignment.Center
                    },
                    new InfoColonna
                    {
                        Label = "Articolo",
                        Ampiezza = "7.3cm",
                        AllineamentoOrizzontale = ParagraphAlignment.Left,
                        AllineamentoVerticale = VerticalAlignment.Center
                    },
                    new InfoColonna
                    {
                        Label = "U.M.",
                        Ampiezza = "1.2cm",
                        AllineamentoOrizzontale = ParagraphAlignment.Center,
                        AllineamentoVerticale = VerticalAlignment.Center
                    },
                    new InfoColonna
                    {
                        Label = "M.Imb.",
                        Ampiezza = "2cm",
                        AllineamentoOrizzontale = ParagraphAlignment.Right,
                        AllineamentoVerticale = VerticalAlignment.Center
                    },
                    new InfoColonna
                    {
                        Label = "Prezzo",
                        Ampiezza = "2.3cm",
                        AllineamentoOrizzontale = ParagraphAlignment.Right,
                        AllineamentoVerticale = VerticalAlignment.Center
                    },
                    new InfoColonna
                    {
                        Label = "Q.tà",
                        Ampiezza = "1.7cm",
                        AllineamentoOrizzontale = ParagraphAlignment.Right,
                        AllineamentoVerticale = VerticalAlignment.Center
                    },
                    new InfoColonna
                    {
                        Label = "Costo",
                        Ampiezza = "2.7cm",
                        AllineamentoOrizzontale = ParagraphAlignment.Right,
                        AllineamentoVerticale = VerticalAlignment.Center
                    }
                };
                #endregion
 
                var currentApp = System.Web.HttpRuntime.AppDomainAppPath;
                m_logoFullPath = currentApp + c_logo_RelativePath;
 
                Document pdfDocument = new Document();
                pdfDocument.Info.Title = "Anteprima Ordini";
                pdfDocument.Info.Subject = string.Format("Anteprima ordini del {0}. Utente '{1}'", 
                                                    DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss.fff"), 
                                                    aof.account);
                pdfDocument.Info.Author = "yyy";
 
                string codiceImpianto = aof.codice_impianto;
 
                Section section = new Section();
                //-----------------------------------------------------------------------
                DefineStyles(ref pdfDocument);
                CreatePage(ref pdfDocument, ref section, infoTabColonne, codiceImpianto);
                FillContent(aof, ref section, infoTabColonne);
                //-----------------------------------------------------------------------
 
                // Create a renderer for PDF that uses Unicode font encoding
                PdfDocumentRenderer pdfRenderer = new PdfDocumentRenderer(true);
                // Set the MigraDoc document
                pdfRenderer.Document = pdfDocument;
                // Create the PDF document
                pdfRenderer.RenderDocument();
 
                string nomeFilePDF = string.Format("AnteprimaOrdini_{0}.pdf", Guid.NewGuid());
                pdfFileNameFullPath = string.Format("{0}{1}{2}", currentApp, c_PDF_RelativeOutputPath, nomeFilePDF);
 
                #region Salva il PDF
                if (pdfStreamOut)
                {
                    // Salva nel memory stream
                    pdfRenderer.Save(stream, false);
 
                    // Salva su FileSystem
                    using (var fileStream = new FileStream(pdfFileNameFullPath, FileMode.CreateNew))
                    {
                        // write to just created file
                        stream.WriteTo(fileStream);
                    }
                }
                else
                {
                    pdfRenderer.Save(pdfFileNameFullPath);
                }
                #endregion
            }
            catch (Exception e)
            {
                log.ErrorFormat("Errore generico {0}, {1}", e.HResult, e.Message);
                throw;
            }
            return stream;
        }
 
        #region PDF Anteprima Ordini
        private void DefineStyles(ref Document pdfDocument)
        {
            // Si allargano i margini utili
            pdfDocument.DefaultPageSetup.LeftMargin = 20;
            pdfDocument.DefaultPageSetup.RightMargin = 20;
            //pdfDocument.DefaultPageSetup.HeaderDistance = "6.3cm"; // 1.3 Distance between header and pageTop of the pages
            //pdfDocument.DefaultPageSetup.PageHeight = "10cm"; // E' l'altezza complessiva della pagina
 
            // Get the predefined style Normal.
            Style style = pdfDocument.Styles["Normal"];
            // Because all styles are derived from Normal, the next line changes the 
            // font of the whole document. Or, more exactly, it changes the font of
            // all styles and paragraphs that do not redefine the font.
            style.Font.Name = "Verdana";
 
            style = pdfDocument.Styles[StyleNames.Header];
            style.ParagraphFormat.AddTabStop("16cm", TabAlignment.Right); // Cos'è un TabStop ??????????????????
 
            style = pdfDocument.Styles[StyleNames.Footer];
            style.ParagraphFormat.AddTabStop("8cm", TabAlignment.Center);
 
            // Create a new style called Table based on style Normal
            style = pdfDocument.Styles.AddStyle("Table", "Normal");
            style.Font.Name = "Verdana";
            style.Font.Size = 9;
 
            // Create a new style called Reference based on style Normal
            style = pdfDocument.Styles.AddStyle("Reference", "Normal");
            style.ParagraphFormat.SpaceBefore = "5mm";
            style.ParagraphFormat.SpaceAfter = "5mm";
            style.ParagraphFormat.TabStops.AddTabStop("16cm", TabAlignment.Right);
        }
 
        private void CreatePage(ref Document pdfDocument, ref Section section, 
                                InfoColonna[] infoTabColonne, string codiceImpianto)
        {
            #region doc
            /*  Document
             *     L-> Section
             *          |
             *          Headers.Primary
             *                  +--> Image                  (LOGO)
             *                  +--> TextFrame
             *                          +--> Paragraph      (TITOLO)
             *                                  +--> Text
             *                  +--> Table                  (Tabella di inizioPagina)
             *          |
             *          +--> Table (Prima tabella nel corpo della prima pagina)
             *          |
             *          Footers.Primary
             *                  +--> Paragraph
             *                          +--> Text           (PIEDE PAGINA)
             */
            #endregion
            try
            {
                // Each MigraDoc document needs at least one SECTION !!!
                section = pdfDocument.AddSection();
                // You have to set the TopMargin of the PageSetup to reserve space for the header.
                section.PageSetup.TopMargin = Unit.FromCentimeter(3.97); // http://forum.pdfsharp.net/viewtopic.php?p=3077
                // [Section].PageSetup.BottomMargin = Unit.FromCentimeter(x)
 
                #region Intestazione
                #region LOGO
                // Put a logo in the header
                Image imageLogo = section.Headers.Primary.AddImage(m_logoFullPath); // Ex.: "../../PowerBooks.png");
                imageLogo.Height = "1.7cm"; // Ex 2.5cm                
                imageLogo.LockAspectRatio = true; // Proprorzioni dell'immagine
                imageLogo.RelativeVertical = RelativeVertical.Line;
                imageLogo.RelativeHorizontal = RelativeHorizontal.Margin;
                imageLogo.Top = ShapePosition.Top;
                imageLogo.Left = ShapePosition.Left; // Ex. ShapePosition.Right;
                imageLogo.WrapFormat.Style = WrapStyle.TopBottom; // ex. WrapStyle.Through;                
                #endregion
 
                #region Aggiunta TITOLO: Nome doc + Intestazione tabella
                TextFrame titoloFrame = section.Headers.Primary.AddTextFrame();
                titoloFrame.WrapFormat.Style = WrapStyle.Through;// <--- tentativo per evitare la sovrascrittura in seconda pagina
 
                titoloFrame.Height = "5.0cm"; // Ex.: 3.0cm
                titoloFrame.Width = "19.6cm"; //Ex. 7.0cm
                titoloFrame.Left = ShapePosition.Center; // Ex.: ShapePosition.Left;
                titoloFrame.RelativeHorizontal = RelativeHorizontal.Margin;
                titoloFrame.Top = "2.3cm";  // Distanza dal TOP  // Ex.: "5.0cm" OK 2.6cm
                titoloFrame.RelativeVertical = RelativeVertical.Page; 
 
                // Riempimento del Titolo text frame
                Paragraph paragraphTitolo = titoloFrame.AddParagraph();
                paragraphTitolo.Format.Font.Bold = true;
                paragraphTitolo.Format.Font.Size = 12;
                paragraphTitolo.Format.Alignment = ParagraphAlignment.Center;
                paragraphTitolo.AddText("Anteprima Ordini");
 
                paragraphTitolo.AddLineBreak();
                Font fontCodImpiantolABEL = new Font(); // ToDo Togliere da qui e mettere nel metodo DefineStyles
                fontCodImpiantolABEL.Bold = true;
                fontCodImpiantolABEL.Size = 9;
                paragraphTitolo.AddFormattedText("Impianto: ", fontCodImpiantolABEL);
                Font fontCodImpianto = new Font();      // ToDo Togliere da qui e mettere nel metodo DefineStyles
                fontCodImpianto.Bold = false;
                fontCodImpianto.Size = 10;
                paragraphTitolo.AddFormattedText(codiceImpianto, fontCodImpianto); // objAnteprimaOrdini.codice_impianto, fontCodImpianto);
                #endregion
 
                //-----------------------
                //ex Table tabellaHeader = section.Headers.Primary.AddTable();
                Table tabellaHeader = titoloFrame.AddTable();
 
                DefinizioneIntestazioneTabella(ref tabellaHeader, infoTabColonne);
                double topPadding = 3.8;
                RiempieIntestazioneTabellaHeader(ref tabellaHeader, infoTabColonne, topPadding);
                #endregion
 
                #region Pie' di pagina: Data e nr Pagina
                // Create footer
                Paragraph paragraph = section.Footers.Primary.AddParagraph();
                paragraph.Format.Alignment = ParagraphAlignment.Left;
                paragraph.AddText(string.Format("{0}", DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss"))); // Ex.: "PowerBooks Inc · Sample Street 42 · 56789 Cologne · Germany");
                paragraph.AddTab(); paragraph.AddTab(); paragraph.AddTab(); paragraph.AddTab(); paragraph.AddTab(); paragraph.AddTab(); paragraph.AddTab(); paragraph.AddTab();
                paragraph.AddText("Pagina "); paragraph.AddPageField(); paragraph.AddText(" di "); paragraph.AddNumPagesField();
                paragraph.Format.Font.Size = 9;
                #endregion                               
            }
            catch (Exception e)
            {
                log.ErrorFormat("Errore {0}, {1}", e.HResult, e.Message);
                throw;
            }
        }
 
        private void FillContent(AnteprimaOrdiniFornitoriIN aof, ref Section section, 
                                InfoColonna[] infoTabColonne)
        {
            string codiceFornitore = string.Empty;
            string dataConsegna = string.Empty;
            try
            {
                IFormatProvider culture = new System.Globalization.CultureInfo("it-IT", true);
                int numero_fornitori = aof.numero_fornitori;
                decimal totale_ordini= aof.totale_ordini;
                Table table = new Table();
                Paragraph paragrafoRighaVuota = new Paragraph();
 
                // Per ogni ordine a fornitore (ci posson essere +ordini per stesso fornitore, l'ordinamento è per data)
                foreach (OrdineFornitore of in aof.ordini.OrderBy(x => 
                         DateTime.Parse(x.data_consegna, culture, System.Globalization.DateTimeStyles.AssumeLocal)))
                {
                    table = section.AddTable();
 
                    DefinizioneIntestazioneTabella(ref table, infoTabColonne);                    
                    RiempieIntestazioneTabellaDati(ref table, of);
 
                    codiceFornitore = of.codice_fornitore;
                    dataConsegna = of.data_consegna;
 
                    RiempieTabellaDati(ref table, codiceFornitore, dataConsegna, of);
 
                    paragrafoRighaVuota = table.Section.AddParagraph(" ");
                }
 
                #region Tabella RIEPILOGO
                table = section.AddTable();
                DefinizioneIntestazioneTabella(ref table, infoTabColonne);
 
                Row row = table.AddRow();
                row.Format.Font.Bold = true;
                row.Shading.Color = c_TableBlue; // Colore di sfondo della intestazione
 
                row.Cells[0].AddParagraph(string.Format("Nr Fornitori: {0}", aof.numero_fornitori));
                row.Cells[0].MergeRight = 3; // Unisce sino alla colonna 3 ovvero del M.Imb
                row.Cells[0].Format.Alignment = ParagraphAlignment.Left;
                row.Cells[0].Format.Borders.Right.Visible = false; // Non funziona
 
                row.Cells[4].AddParagraph(string.Format("Totale Ordini"));
                row.Cells[4].MergeRight = 1; // Unisce sino alla colonna 5 ovvero del Q.tà
                row.Cells[4].Format.Alignment = ParagraphAlignment.Right;
                row.Cells[4].Format.Borders.Left.Visible = false; // Non funziona
 
                row.Cells[6].AddParagraph(aof.totale_ordini.ToString("0.0000"));
                row.Cells[6].Format.Alignment = ParagraphAlignment.Right;
                row.Cells[6].Format.Borders.Left.Visible = false; // Non funziona
                #endregion
            }
            catch (Exception e)
            {
                log.ErrorFormat("Codice Fornitore {0}, DataConsegna {1}. Errore {0}, {1}", codiceFornitore, dataConsegna, e.HResult, e.Message);
                throw;
            }
        }
 
        #region Metodi di servizio
        /// <summary>
        /// Assegna lo stile generale della tabella e poi definisce le colonne in base a "infoTabColonne", 
        /// per ciascuna colonna si definisce l'ampiezza e l'allineamento.
        /// La tabella occuperà l'intero rigo utile della pagina che si presume sia 19.5 centimetri
        /// </summary>
        /// <param name="table"></param>
        /// <param name="infoTabColonne"></param>
        private void DefinizioneIntestazioneTabella(ref Table table, InfoColonna[] infoTabColonne)
        {
            try
            {
                // ATTENZIONE la posizione della seguuente tabella dipende dal fatto 
                // che nelle istruzioni che precedono si sia aggiuto un PARAGRAFO
                // Create the item table
                table.Style = "Table";
                table.Borders.Color = c_TableBorder;
                table.Borders.Width = 0.25;
                table.Borders.Left.Width = 0.5;
                table.Borders.Right.Width = 0.5;
                table.Rows.LeftIndent = 0;
 
                // Before you can add a row, you must define the columns
                // ATTENZIONE attualmente l'ampiezza della pagina è di 19.5cm
                #region Aggiunta delle colonne alla tabella
                Column column;
                for (int i = 0; i < infoTabColonne.Length; i++)
                {
                    column = table.AddColumn(infoTabColonne[i].Ampiezza);
                    column.Format.Alignment = infoTabColonne[i].AllineamentoOrizzontale;
                }
                #endregion
            }
            catch (Exception e)
            {
                log.ErrorFormat("Errore {0}, {1}", e.HResult, e.Message);
                throw;
            }
        }
 
        private void RiempieIntestazioneTabellaHeader(ref Table table, InfoColonna[] infoTabColonne, double padding = 1.5)
        {
            try
            {
                // Create the header of the table
                #region Riga INTESTAZIONE Tabella
                //  PRIMO RIGO rigo di intestazione
                Row row = table.AddRow();
                row.HeadingFormat = true; // <-- if you set this, for the first n rows of your table, you mark this rows as header rows !!!
                row.Format.Alignment = ParagraphAlignment.Center;
                row.Format.Font.Bold = true;
                row.Shading.Color = c_TableBlue; // Colore di sfondo della intestazione
                if (padding != 1.5)
                {
                    row.TopPadding = padding;
                    row.BottomPadding = padding;
                }
 
                for (int i = 0; i < infoTabColonne.Length; i++)
                {
                    row.Cells[i].AddParagraph(infoTabColonne[i].Label);  // Testo intestazione
                    row.Cells[i].Format.Alignment = infoTabColonne[i].AllineamentoOrizzontale;
                    row.Cells[i].VerticalAlignment = infoTabColonne[i].AllineamentoVerticale;
                }
                #endregion
 
                // Impostazione del bordo
                table.SetEdge(0, 0, infoTabColonne.Length, 1, Edge.Box, BorderStyle.Single, 0.75, Color.Empty);
            }
            catch (Exception e)
            {
                log.ErrorFormat("Errore {0}, {1}", e.HResult, e.Message);
            }
        }
 
        private void RiempieIntestazioneTabellaDati(ref Table table, OrdineFornitore of)
        {
            try
            {
                // Create the header of the table
                #region Riga INTESTAZIONE Tabella
                //  PRIMO RIGO rigo di intestazione
                Row row = table.AddRow();
                row.HeadingFormat = true; // <-- if you set this, for the first n rows of your table, you mark this rows as header rows !!!
                row.Format.Alignment = ParagraphAlignment.Center;
                row.Format.Font.Bold = true;
                row.Shading.Color = c_TableBlue; // Colore di sfondo della intestazione
 
                row.Cells[0].AddParagraph(string.Format("{0} - {1}", of.codice_fornitore, of.descrizione_fornitore));
                row.Cells[0].MergeRight = 5; // Unisce sino alla colonna 5 ovvero del Costo
                row.Cells[0].Format.Alignment = ParagraphAlignment.Left;
                row.Cells[0].Format.Borders.Right.Visible = false; // Non funziona
 
                row.Cells[6].AddParagraph(string.Format("{0}", of.data_consegna));
                row.Cells[6].Format.Alignment = ParagraphAlignment.Right;
                row.Cells[6].Format.Borders.Left.Visible = false; // Non funziona
                #endregion
 
                // Impostazione del bordo
                table.SetEdge(0, 0, 7, 1, Edge.Box, BorderStyle.Single, 0.75, Color.Empty);
            }
            catch (Exception e)
            {
                log.ErrorFormat("Errore {0}, {1}", e.HResult, e.Message);
                //throw;
            }
        }
 
        private void RiempieTabellaDati(ref Table table, string codiceFornitore, string dataConsegna, OrdineFornitore of)
        {
            string ultimoCodiceArticolo = string.Empty;
            int rigo = 0;
            try
            {
                foreach (ArticoloFornitore a in of.articoli)
                {
                    rigo++;
                    Row row = table.AddRow();
                    ultimoCodiceArticolo = a.codice_articolo;
 
                    // Le pagine pari avranno lo sfondo in grigio per facilitare la lettura
                    if (rigo % 2 == 0)
                    {
                        row.Shading.Color = c_TableGray; // Colore di sfondo
                    }
 
                    row.Cells[0].AddParagraph(a.codice_articolo); // Codice Articolo
                    row.Cells[0].Format.Alignment = ParagraphAlignment.Center;
 
                    row.Cells[1].AddParagraph(a.descrizione_articolo); // Descrizione articolo
                    row.Cells[1].Format.Alignment = ParagraphAlignment.Left;
 
                    row.Cells[2].AddParagraph(a.unita_misura); // UM
                    row.Cells[2].Format.Alignment = ParagraphAlignment.Center;
 
                    row.Cells[3].AddParagraph(a.imballo_minimo.ToString("0.00")); // M.Imb.
                    row.Cells[3].Format.Alignment = ParagraphAlignment.Right;
 
                    row.Cells[4].AddParagraph(a.prezzo.ToString("0.00")); // Prezzo
                    row.Cells[4].Format.Alignment = ParagraphAlignment.Right;
 
                    row.Cells[5].AddParagraph(a.quantita_ordine.ToString("0.00")); // Quantità
                    row.Cells[5].Format.Alignment = ParagraphAlignment.Right;
 
                    row.Cells[6].AddParagraph(a.costo_totale.ToString("0.0000")); // Costo
                    row.Cells[6].Format.Alignment = ParagraphAlignment.Right;
 
                    // Impostazione del bordo
                    //table.SetEdge(0, table.Rows.Count - 1, 7, 2, Edge.Box, BorderStyle.Single, 0.75);
                }
 
                // Ultima riga con il totale
                Row rowRecap = table.AddRow();
                rowRecap.Cells[0].AddParagraph(string.Format("Totale ordine Fornitore:"));
                rowRecap.Cells[0].MergeRight = 5; // Unisce sino alla colonna 5 ovvero del Costo
                rowRecap.Cells[0].Format.Alignment = ParagraphAlignment.Right;
                rowRecap.Cells[0].Format.Borders.Right.Visible = false; // Non funziona
 
                rowRecap.Cells[6].AddParagraph(string.Format("{0}", of.totale_ordine_fornitore.ToString("0.0000")));
                rowRecap.Cells[6].Format.Alignment = ParagraphAlignment.Right;
                rowRecap.Cells[6].Format.Borders.Left.Visible = false; // Non funziona
 
                // Impostazione del bordo
                table.SetEdge(0, table.Rows.Count - 1, 7, 1, Edge.Box, BorderStyle.Single, 0.75, Color.Empty);
            }
            catch (Exception e)
            {
                log.ErrorFormat("Fornitore {0}, DataConsegna {1}, Ultimo Articolo {2}. Errore {3}, {4}", 
                                codiceFornitore, dataConsegna, ultimoCodiceArticolo, e.HResult, e.Message);
            }
        }
        #endregion
        #endregion
        #endregion
 
        #region Oggetti per le tabelle PDF MigraDoc
        private class InfoColonna
        {
            public string Label
            {
                get; set;
            }
 
            /// <summary>
            /// With della colonna, es.: "1.7cm"
            /// </summary>
            public string Ampiezza
            {
                get; set;
            }
            public ParagraphAlignment AllineamentoOrizzontale
            {
                get; set;
            }
 
            public VerticalAlignment AllineamentoVerticale
            {
                get; set;
            }
        }
        #endregion
    }
}

Post o Get

Un metodo di default è interpretato come POST, se lo si vuole invece come GET occorrerà usare l'attributo di direttiva [GET]. Segue esempio di POST:

using System;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.ServiceModel.Channels;
using System.Web;
using System.Web.Http;
using VF_Digitalk_Model;
 
namespace WebAPISrv_455_Simulator.Controllers
{
    public class DonationController : ApiController
    {
 
        [System.Web.Http.Route("ivr_donate")]        
        public HttpResponseMessage Donate(string msisdn, string user_check_id, string amount_id, string short_numner)
        {
            //Es: https://localhost:44356/ivr_donate?msisdn=12345&user_check_id=666&amount_id=5&short_numner=45566
            HttpResponseMessage response = new HttpResponseMessage();
            DateTime startExec = DateTime.Now;
            DonationResponseOutput objOut = new DonationResponseOutput();
 
            try
            {
                m_logger.Info("Controller - ivr_donate - Ver. {0}\t\tClient IP {1}"
                    , System.Reflection.Assembly.GetExecutingAssembly().GetName().Version
                    , GetClientIp());
 
 
                objOut.ResultCode = "0";
                objOut.TransactionID = GenerateTransactionId();
                response = Request.CreateResponse(HttpStatusCode.OK, objOut);
            }
            catch (Exception ex)
            {
                m_logger.Error(ex);
                objOut.ResultCode = "1";
                response = Request.CreateResponse(HttpStatusCode.InternalServerError, objOut); //? ok ?
            }
            response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
            m_logger.Debug("Execution duration: {0}\"\r\n\r\n\r\n"
                            , DateTime.Now.Subtract(startExec).TotalSeconds);
            return response;
        }
 
        #region Private methods
        private string GenerateTransactionId()
        { 
            string transactionId = "000000";
            int range = 999999;
 
            Random r = new Random();
            double rDouble = r.NextDouble() * range; //for doubles
 
            transactionId = (rDouble.ToString() + transactionId).Substring(0, 6);
            return transactionId;
        }
 
        private string GetClientIp(HttpRequestMessage request = null)
        {
            try
            {
                request = request ?? Request;
 
                if (request.Properties.ContainsKey("MS_HttpContext"))
                {
                    return ((HttpContextWrapper)request.Properties["MS_HttpContext"]).Request.UserHostAddress;
                }
                else if (request.Properties.ContainsKey(RemoteEndpointMessageProperty.Name))
                {
                    RemoteEndpointMessageProperty prop = (RemoteEndpointMessageProperty)request.Properties[RemoteEndpointMessageProperty.Name];
                    return prop.Address;
                }
                else if (HttpContext.Current != null)
                {
                    return HttpContext.Current.Request.UserHostAddress;
                }
            }
            catch (Exception ex)
            {
                m_logger.Error(ex);
            }
            return string.Empty;
        }
        #endregion
    }
}

ATTENZIONE stesso ed identico codice ma con metodo che sarà interpretato come GET

//...
 
public class DonationController : ApiController
{
	[HttpGet]
	[System.Web.Http.Route("ivr_donate")]        
	public HttpResponseMessage Donate(string msisdn, string user_check_id, string amount_id, string short_numner)
	{
		//Es: https://localhost:44356/ivr_donate?msisdn=12345&user_check_id=666&amount_id=5&short_numner=45566
		HttpResponseMessage response = new HttpResponseMessage();
		DateTime startExec = DateTime.Now;
		DonationResponseOutput objOut = new DonationResponseOutput();
 
		try
		{
			m_logger.Info("Controller - ivr_donate - Ver. {0}\t\tClient IP {1}"
				, System.Reflection.Assembly.GetExecutingAssembly().GetName().Version
				, GetClientIp());
 
 
			objOut.ResultCode = "0";
			objOut.TransactionID = GenerateTransactionId();
			response = Request.CreateResponse(HttpStatusCode.OK, objOut);
		}
		catch (Exception ex)
		{
			m_logger.Error(ex);
			objOut.ResultCode = "1";
			response = Request.CreateResponse(HttpStatusCode.InternalServerError, objOut); //? ok ?
		}
		response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
		m_logger.Debug("Execution duration: {0}\"\r\n\r\n\r\n"
						, DateTime.Now.Subtract(startExec).TotalSeconds);
		return response;
	}
//...etc
}

Sarà richiamabile come segue:

https://localhost:56544/ivr_donate?msisdn=12345&user_check_id=666&amount_id=5&short_numner=45566

Notare la query string! In effetti usare la GET è più comoda perché non si dovrà comporre un JSON per inviare i 5 parametri invece passati via query string.

Mappa e Link


WEB API | WebAPI Esempi | C# | Teoria


Soluzioni varie | Visual Studio

Author