Table of Contents

Frontend — RequestCenterWeb (shell Default.aspx + UserControl dinamici)

Front-end ASP.NET Web Forms del verticale Service Desk / RequestCenter. Shell unica Default.aspx che carica dinamicamente UserControl di azione (fra cui makeTicket.ascx, la creazione di un ticket). L'apertura di un ticket parte da un .ascx, invoca direttamente il BL Descor.RequestCenter.Ticket.Request dentro una RequestCenter.Transaction, non passa da una route REST. Classificazione complessiva: VERIFIED per la meccanica di caricamento control + handler di post; SUPPORTED/INFERRED dove segnalato.

Scopo

RequestCenterWeb è l'applicazione Web Forms che espone l'interfaccia operativa del Service Desk: home ticket, apertura/gestione richieste, azioni di workflow. Non è un progetto a sé stante di libreria: è l'app web (una delle famiglie CASSANDRA) che orchestra i UserControl di dominio e delega la logica al BL Descor.RequestCenter (documentato in project-RequestCenter-BL.md) e al DAL Oracle.

  • Repo/percorso: InfocadWeb/WebMachine/CASSANDRA/RequestCenterWeb/.
  • Namespace root delle pagine: Descor.RequestCenterWeb (es. Descor.RequestCenterWeb._Default, Descor.RequestCenterWeb.makeTicket).
  • Le classi base condivise (RequestCenterPage, WebUser) vivono in CASSANDRA/CommonWeb/RequestCenter/, namespace Descor.CommonWeb.RequestCenterWeb.*.

Bootstrap (Global.asax)

UNKNOWN / non presente nel progetto. In CASSANDRA/RequestCenterWeb/ non esiste un file Global.asax (glob *.asax a vuoto). Il bootstrap applicativo (avvio pipeline, Application_Start, cache condivise CommonWeb.WebSharedObject.RequestCenter*) non è definito qui; l'inizializzazione osservabile avviene per-richiesta nel ciclo di vita della pagina (vedi PreInit/Init sotto) e la master page è scelta a runtime (Global.master / Simple.master). Non documento un entry-point di applicazione che non trovo come evidenza in questo progetto.

Routing e navigazione

Non c'è routing MVC/attribute-routing: la navigazione è client-side + querystring verso l'unica shell Default.aspx.

Il menu applicativo è la app "Requests" del ServiceDesk factory: Cassandra.ServiceDeskFactory.UserApplications.FindByKey("Requests") (Default.aspx.vb:139). Ogni voce di menu (AppMenu) trasporta, in AppData, le chiavi controlurl, idworkflow, idactivity (Default.aspx.vb:147,150,152,154).

Flusso di selezione di una voce di menu (Default.aspx.vb:132-171, ramo Request.QueryString("idmnu")):

  1. La voce risolve un AppMenu per idmnu.
  2. Si costruisce uno SessionObjects.WebObject(0, idworkflow, idactivity) scritto in sessione (WriteOnSession()).
  3. Si registra uno startup script che concatena tre funzioni JS di ClientScript/script.js:
    • ucontrolloader(controlurl, hidUCLoad.ClientID) — scrive l'URL del control nel campo nascosto hidUCLoad (script.js:8);
    • actioncontroller(0, idworkflow, idactivity, ...) — popola i campi nascosti hidObject/hidWorkflow/hidAction (script.js:35,52-54);
    • mpageloader(mpagename) — imposta hidMPFile (master page, script.js:25).
  4. Al postback successivo, Default.aspx.vb legge hidUCLoad (proprietà CurrentControl, Default.aspx.vb:17-67) e carica il control corrispondente.

Esistono anche ingressi alternativi alla stessa shell tramite querystring cifrata TAPPAPLOLLI (deep-link a un ticket, Default.aspx.vb:19-53) e IDR (home di una richiesta). Il control di default in assenza di parametri è UserControls/Summary/requestHomePage.ascx (Default.aspx.vb:57-58).

Layout (shell + UserControl dinamici)

Default.aspx (Inherits="Descor.RequestCenterWeb._Default", MasterPageFile="../Global.master", Default.aspx:1) è la shell. La master page effettiva è decisa a runtime in LoadMasterPage() (Default.aspx.vb:219-241):

  • ../Simple.master per ruoli Users/Viewer, o quando è presente idmnu/TAPPAPLOLLI;
  • ../Global.master (o ../{hidMPFile}.master) per gli altri ruoli.

Il corpo variabile è iniettato per composizione: LoadPageControl() fa Page.LoadControl(controlToLoad) e aggiunge il control al placeholder PHMain (Default.aspx.vb:243-257). Il nome del control da caricare arriva dalla proprietà CurrentControl (querystring/campo nascosto). Gli errori di caricamento vengono rilanciati come ControlNotFoundException (Default.aspx.vb:253-255).

SetInterface() (Default.aspx.vb:263-286) popola le zone accessorie (pannello stati PHStates, warningAlert, userStats, quick actions) in funzione del ruolo, caricando dinamicamente più statusView.ascx per ciascun workflow dell'utente.

Gerarchia dei componenti (control makeTicket)

UserControls/FlowActions/makeTicket.ascx (Inherits="Descor.RequestCenterWeb.makeTicket", base BaseClasses.CreateUserControlBase, makeTicket.ascx.vb:4-5) è il control di creazione ticket. È un composito che registra numerosi sotto-control di dominio (makeTicket.ascx:3-17):

  • callTypeControl1 — selezione tipo chiamata (Ticket/Anomaly/Info).
  • UserSelector1 / cntSelHL (contactSelectorHL) — richiedente; visibilità alternata secondo Settings.HeavyLoadMode (makeTicket.ascx.vb:19-29).
  • SpatialSelection1 (spatialSelection) + ObjectSelectionPanel1 (objectSelectionPanel) — localizzazione e oggetto di manutenzione/asset.
  • TextComposer1 (textComposerPro) — descrizione HTML.
  • AlertControl1 (alertControl) — scadenze/alert.
  • categoryControl1, typologyControl1, requestFromType1 — classificazione.
  • uplFilesPanel (uploadPanel) — allegati.
  • actSubmt (activitySubmitControl) — pulsante di invio dell'attività di workflow.
  • errLog (errorsLog) — raccolta/visualizzazione errori di validazione.
  • Layout a schede su RadTabStrip1/RadMultiPage1 (Telerik), con la scheda FILETAB mostrata solo se ci sono file type non-auto (makeTicket.ascx.vb:60, InitializeFiles).

La base CreateUserControlBase (Classes/Base/CreateUserControlBase.vb:13) fornisce lo stato condiviso (_objRequest As Ticket.Request, _objRequestParent, _currentuser, _currentAct As DEM.WorkflowCreatingActivity, ecc.) e le utility di validazione/upload usate dal control.

Gestione eventi (btnPost_Click)

L'invio è gestito da btnPost_Click (makeTicket.ascx.vb:82), agganciato all'evento actSubmt.ActivityRun del control di submit (non è un classico Button.Click; l'handler ha firma (sender, e, runcontinue As Boolean)). Sequenza (VERIFIED — makeTicket.ascx.vb:82-264):

  1. Guardie di concorrenza CheckParentStateChange() / CheckSiblingStateChange() (:83); se lo stato del padre è cambiato, apre una finestra di alert e non crea nulla (:260-262).
  2. Validazione: errLog.ErrorStrings = Me.DoValidation() (:84) e ValidateUpload(uplFilesPanel, errLog) (:85).
  3. Se ci sono errori → errLog.DataBind() e stop (:257-258).
  4. Altrimenti apre la transazione e crea la richiesta (vedi sotto), poi RedirectAction(...) (:256).

Client verso il backend

Il control non chiama un endpoint HTTP: invoca direttamente il BL in-process dentro una RequestCenter.Transaction (pattern del flusso FLOW-REQ-001). Blocco chiave (makeTicket.ascx.vb:88-256):

Dim objTransaction As New RequestCenter.Transaction
...
objTransaction.OpenConnection()
objTransaction.Begin()
idRequest = RequestCenter.Ticket.Request.Create(iduser, _currentuser.CurrentTenantId, ltlProtocol.Text, _
            hidProtocol.Value, CInt(hidSub.Value), CInt(hidProtLevelParent.Value), DateTime.Now)   ' :114
_objRequest = New Ticket.Request(RequestCenter.Configuration.Settings.DALUseReaders, idRequest, ...) ' :115
...
_objRequest.SetSpatialInfo(...)   ' :120
_objRequest.SetManagement(...)    ' :121
_objRequest.SetContract(...)      ' :122
_objRequest.SetCompany(...)       ' :123
_objRequest.WriteDescription()    ' :185
_objRequest.SetCallType(...)      ' :191
_objRequest.SetContactInfo(...)   ' :200
_objRequest.SetType(0)            ' :202
Dim newIdElement As Integer = _currentAct.Run(iduser)   ' :210  (crea l'elemento di workflow DEM)
_objRequest.SetWorkflowInterface(newIdElement)          ' :214
objTransaction.Commit()                                 ' :216

Request.Create / SetSpatialInfo / SetManagement / SetContract / SetCompany / WriteDescription / SetCallType / SetType / SetWorkflowInterface sono i metodi documentati in class-Ticket-Request.md; a valle il DAL RequestDAL invoca i package Oracle GESTREQUEST/GESTREQUEST_T2 (es. ADDREQUEST, ADDDESCRIPTIONTOREQUEST, ADDWORKFLOWINTERFACE). Vedi la CRUD matrix e le procedure in 05-databases/REQUESTCENTER_TEST38.

Equivalenti WCF (letture/servizi, non usati da questo submit). Superficie .svc correlata al verticale — vedi 04-api:

  • ExtraFlowActionsProxy.svc — in CASSANDRA/RequestCenterWeb/WebServices/ (SUPPORTED, file presente).
  • RequestsReaderWCF.svc e RequestsCacheService.svc — in CASSANDRA/CommonWeb/RequestCenter/WebServices/ (SUPPORTED, file presenti; non dentro RequestCenterWeb).

Autenticazione e autorizzazione

Gate a livello di pagina in RequestCenterPage.Page_PreInit (CommonWeb/RequestCenter/Classes/Base/RequestCenterPage.vb:74-90). Tutte le pagine RequestCenter ereditano RequestCenterPage (via Cassandra.InfocadSecurity.CassandraPage). La guardia (VERIFIED):

_currentuser = CommonWeb.RequestCenterWeb.SessionObjects.CurrentWebUser.WebUser(_usereaders)
If Not Page.User.Identity.IsAuthenticated OrElse _currentuser Is Nothing _
   OrElse (Not _currentuser.RequestCenterEnabled AndAlso Not _currentuser.IsUserSuperAdmin) Then
    ' redirect a FormsAuthentication.DefaultUrl (o script redirect se IsCallback)

Condizioni di accesso: identità autenticata e WebUser non nullo e (RequestCenterEnabled oppure IsUserSuperAdmin). RequestCenterEnabled è una proprietà del WebUser (CommonWeb/RequestCenter/Classes/HttpContext/WebUser.vb). In caso negativo → Response.Redirect(FormsAuthentication.DefaultUrl, False).

Livello di privilegio calcolato per ruolo: _lowprivilegeuser è vero per i GUID di ruolo RequestCenter.Constants.Roles.Users/Viewer (RequestCenterPage.vb:86-88); l'edit mode è deciso in Page_Init per ruolo + querystring EMODE (:56-71).

Debito tecnico correlato — TD-008. I grant di sezione sono valutati solo lato UI; i servizi BL raggiunti via .NET Remoting non ri-verificano il grant (vedi 14-technical-debt). Il gate Page_PreInit qui descritto è quindi una difesa lato presentazione, non un'autorizzazione applicata al layer di servizio.

Validazione

  • DoValidation() (override in CreateUserControlBase.vb:222-232): scandisce ricorsivamente i DataUserControlBase figli (FindMyDataControls) e raccoglie ErrorMessage di quelli Visible AndAlso IsRequired AndAlso Not IsValid. Esiste anche DoValidationExt() che restituisce un dizionario per-control (:234-252).
  • ValidateUpload(uplFilesPanel, errLog) (:891-896): se il pannello upload è visibile chiama uplFilesPanel.GoValidation() e accoda gli errori a errLog.ErrorStrings.
  • La validazione lato server (server-authoritative) gira dentro btnPost_Click prima di aprire la transazione; è il gate che decide se procedere alla Request.Create.

Gestione degli errori

Il Try/Catch/Finally di btnPost_Click (makeTicket.ascx.vb:89-255):

  • Catch (:238-251): rimuove Session("TargetRequest"), objTransaction.Rollback(), uplFilesPanel.GoRollBack(), invalida le cache condivise CommonWeb.WebSharedObject.Refresh*, quindi logga con Cassandra.Errors.InfocadTraceWrapper.CreateError(...) (chiave app "RequestCenter", :250) e riattiva il pulsante di submit.
  • Finally (:252-254): Ticket.Protocol.DeleteTemporaryProtocol(...) e objTransaction.CloseConnection().

Gli errori di validazione (non eccezioni) sono mostrati all'utente via il control errLog (errorsLog.ascx).

Upload file

  • InitializeFiles(uplFilesPanel) (CreateUserControlBase.vb:898-919) decide se mostrare la scheda file, in base ai file type non-auto del workflow/attività corrente (makeTicket.ascx.vb:60).
  • Alla submit, SaveFileUpload(uplFilesPanel) (:880-889) esegue uplFilesPanel.GoUpload(IdRequest, Protocol, appKey) e crea i record Ticket.RequestFile.Create(...) per ogni file caricato.
  • In rollback, uplFilesPanel.GoRollBack() annulla gli upload (makeTicket.ascx.vb:242).

Punti di estensione

  • Nuovi control di azione: qualsiasi .ascx sotto UserControls/ raggiungibile via hidUCLoad/CurrentControl; se è un'azione di creazione, farlo ereditare CreateUserControlBase per riusare validazione/upload/transazione.
  • callTypeControl + RequestCenter.Constants.CallTypes: i rami Ticket/Anomaly/Info in btnPost_Click (:97-157) sono guidati dai GUID dei call type; nuovi tipi si innestano lì.
  • Master page pluggabile via hidMPFile (LoadMasterPage).
  • ExtraFlowActionsProxy.svc come punto d'aggancio per azioni di flusso extra (vedi 04-api).

Blocco tracciamento (makeTicket)

Route/ingresso            : Default.aspx?idmnu=<id>  (app menu "Requests")
                            → JS ucontrolloader() scrive hidUCLoad = "UserControls/FlowActions/makeTicket.ascx"
Page/view                 : Default.aspx  (shell, Inherits Descor.RequestCenterWeb._Default)
                            → LoadPageControl() → Page.LoadControl(makeTicket.ascx) in PHMain
Primary component         : UserControls/FlowActions/makeTicket.ascx  (Descor.RequestCenterWeb.makeTicket)
Event handler             : btnPost_Click  (Handles actSubmt.ActivityRun)  makeTicket.ascx.vb:82
API client                : chiamata in-process al BL (nessun HTTP) dentro New RequestCenter.Transaction
                            RequestCenter.Ticket.Request.Create(...)  makeTicket.ascx.vb:114
Backend route             : BL Descor.RequestCenter.Ticket.Request → DAL RequestDAL
                            → Oracle GESTREQUEST_T2.ADDREQUEST / GESTREQUEST.ADDWORKFLOWINTERFACE, ...
Related flow              : FLOW-REQ-001 (apertura ticket)

Guide seed

Aggiungere una nuova pagina/control di azione

  1. Creare UserControls/<Area>/<nuovoControl>.ascx (+ .ascx.vb). Per un'azione di creazione, Inherits BaseClasses.CreateUserControlBase.
  2. Esporre il control tramite una voce di menu della app "Requests" con AppData("controlurl") = "UserControls/<Area>/<nuovoControl>.ascx" (vedi guida successiva). Nessuna route da registrare: la shell Default.aspx lo carica via hidUCLoad/CurrentControl.
  3. Implementare DoValidation() (override) se servono regole; sfruttare errLog/uplFilesPanel dalla base.
  4. Racchiudere le scritture DB in New RequestCenter.Transaction (OpenConnection/Begin/Commit/Rollback/CloseConnection), come btnPost_Click.

Aggiungere una voce di menu

Le voci provengono da Cassandra.ServiceDeskFactory.UserApplications.FindByKey("Requests").Menu (Default.aspx.vb:139-141). Una voce deve portare in AppData le chiavi controlurl, idworkflow, idactivity, così che Default.aspx.vb possa comporre ucontrolloader+actioncontroller+mpageloader (:150-154). Dove/come vengono persistite le voci di menu (tabella/servizio del ServiceDeskFactory) è UNKNOWN da questo progetto — da tracciare nel dominio servicedesk.

Tracciare un'azione UI fino al DB

Menu "Requests"hidUCLoad = makeTicket.ascxDefault.aspx carica il control in PHMain → submit actSubmt.ActivityRunbtnPost_Click (:82) → RequestCenter.Ticket.Request.Create(...) (:114) e i vari Set*RequestDAL → package Oracle GESTREQUEST/GESTREQUEST_T2. Riferimenti procedure e CRUD: 05-databases/REQUESTCENTER_TEST38, crud-matrix.

Flussi correlati

Regole di business correlate

Evidenze

  • Shell Default.aspx: InfocadWeb/WebMachine/CASSANDRA/RequestCenterWeb/Default.aspx:1 (Inherits="Descor.RequestCenterWeb._Default", MasterPageFile="../Global.master"). — VERIFIED
  • Caricamento dinamico dei control: Default.aspx.vb:243-257 (Page.LoadControlPHMain; ControlNotFoundException); CurrentControl Default.aspx.vb:17-67. — VERIFIED
  • Menu app "Requests" + AppData (controlurl/idworkflow/idactivity) + startup script ucontrolloader/actioncontroller/mpageloader: Default.aspx.vb:139-156. — VERIFIED
  • Funzioni JS: CASSANDRA/RequestCenterWeb/ClientScript/script.js:8 (ucontrolloader), :25 (mpageloader), :35 (actioncontroller). — VERIFIED
  • Scelta master page a runtime: Default.aspx.vb:219-241 (Global.master/Simple.master). — VERIFIED
  • Global.asax assente in CASSANDRA/RequestCenterWeb/ (glob *.asax a vuoto). — VERIFIED (bootstrap applicativo → UNKNOWN qui)
  • Control creazione ticket: UserControls/FlowActions/makeTicket.ascx:1 (Inherits="Descor.RequestCenterWeb.makeTicket"), sotto-control registrati makeTicket.ascx:3-17. — VERIFIED
  • Base control: Classes/Base/CreateUserControlBase.vb:13 (MustInherit Class CreateUserControlBase), stato _objRequest/_currentAct :16-26. — VERIFIED
  • Handler submit: makeTicket.ascx.vb:82 (btnPost_Click ... Handles actSubmt.ActivityRun); validazione :84-85; guardie stato :83,260-262. — VERIFIED
  • Chiamata BL in transazione: makeTicket.ascx.vb:88 (New RequestCenter.Transaction), :111-112 (OpenConnection/Begin), :114 (Request.Create), :115 (new Ticket.Request), :120-123,185,191,200,202,214 (Set*/WriteDescription), :210 (_currentAct.Run), :216 (Commit). — VERIFIED
  • Gestione errori/rollback: makeTicket.ascx.vb:238-254 (Rollback, GoRollBack, InfocadTraceWrapper.CreateError, DeleteTemporaryProtocol, CloseConnection). — VERIFIED
  • Validazione: CreateUserControlBase.vb:222-232 (DoValidation), :234-252 (DoValidationExt), :891-896 (ValidateUpload). — VERIFIED
  • Upload: CreateUserControlBase.vb:880-889 (SaveFileUpload/RequestFile.Create), :898-919 (InitializeFiles); scheda FILETAB makeTicket.ascx.vb:60. — VERIFIED
  • Gate auth/authz: CommonWeb/RequestCenter/Classes/Base/RequestCenterPage.vb:74-90 (Page_PreInit, RequestCenterEnabled/IsUserSuperAdmin, redirect FormsAuthentication.DefaultUrl); edit mode :56-71; RequestCenterEnabled definito in CommonWeb/RequestCenter/Classes/HttpContext/WebUser.vb. — VERIFIED
  • Equivalenti WCF: CASSANDRA/RequestCenterWeb/WebServices/ExtraFlowActionsProxy.svc; CASSANDRA/CommonWeb/RequestCenter/WebServices/RequestsReaderWCF.svc e RequestsCacheService.svc. — SUPPORTED (file presenti)
  • Package Oracle a valle (via DAL): GESTREQUEST, GESTREQUEST_T2 — vedi class-Ticket-Request.md e project-RequestCenter-BL.md. — VERIFIED (cross-ref)
  • TD-008 (grant valutati solo lato UI): docs/14-technical-debt/index.md. — SUPPORTED