Frontend — RequestCenterWeb (shell Default.aspx + UserControl dinamici)
Front-end ASP.NET Web Forms del verticale Service Desk / RequestCenter. Shell unica
Default.aspxche carica dinamicamenteUserControldi azione (fra cuimakeTicket.ascx, la creazione di un ticket). L'apertura di un ticket parte da un.ascx, invoca direttamente il BLDescor.RequestCenter.Ticket.Requestdentro unaRequestCenter.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 inCASSANDRA/CommonWeb/RequestCenter/, namespaceDescor.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")):
- La voce risolve un
AppMenuperidmnu. - Si costruisce uno
SessionObjects.WebObject(0, idworkflow, idactivity)scritto in sessione (WriteOnSession()). - 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 nascostohidUCLoad(script.js:8);actioncontroller(0, idworkflow, idactivity, ...)— popola i campi nascostihidObject/hidWorkflow/hidAction(script.js:35,52-54);mpageloader(mpagename)— impostahidMPFile(master page,script.js:25).
- Al postback successivo,
Default.aspx.vbleggehidUCLoad(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.masterper ruoliUsers/Viewer, o quando è presenteidmnu/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 secondoSettings.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 schedaFILETABmostrata 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):
- Guardie di concorrenza
CheckParentStateChange()/CheckSiblingStateChange()(:83); se lo stato del padre è cambiato, apre una finestra di alert e non crea nulla (:260-262). - Validazione:
errLog.ErrorStrings = Me.DoValidation()(:84) eValidateUpload(uplFilesPanel, errLog)(:85). - Se ci sono errori →
errLog.DataBind()e stop (:257-258). - 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— inCASSANDRA/RequestCenterWeb/WebServices/(SUPPORTED, file presente).RequestsReaderWCF.svceRequestsCacheService.svc— inCASSANDRA/CommonWeb/RequestCenter/WebServices/(SUPPORTED, file presenti; non dentroRequestCenterWeb).
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_PreInitqui descritto è quindi una difesa lato presentazione, non un'autorizzazione applicata al layer di servizio.
Validazione
DoValidation()(override inCreateUserControlBase.vb:222-232): scandisce ricorsivamente iDataUserControlBasefigli (FindMyDataControls) e raccoglieErrorMessagedi quelliVisible AndAlso IsRequired AndAlso Not IsValid. Esiste ancheDoValidationExt()che restituisce un dizionario per-control (:234-252).ValidateUpload(uplFilesPanel, errLog)(:891-896): se il pannello upload è visibile chiamauplFilesPanel.GoValidation()e accoda gli errori aerrLog.ErrorStrings.- La validazione lato server (server-authoritative) gira dentro
btnPost_Clickprima di aprire la transazione; è il gate che decide se procedere allaRequest.Create.
Gestione degli errori
Il Try/Catch/Finally di btnPost_Click (makeTicket.ascx.vb:89-255):
- Catch (
:238-251): rimuoveSession("TargetRequest"),objTransaction.Rollback(),uplFilesPanel.GoRollBack(), invalida le cache condiviseCommonWeb.WebSharedObject.Refresh*, quindi logga conCassandra.Errors.InfocadTraceWrapper.CreateError(...)(chiave app"RequestCenter",:250) e riattiva il pulsante di submit. - Finally (
:252-254):Ticket.Protocol.DeleteTemporaryProtocol(...)eobjTransaction.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) esegueuplFilesPanel.GoUpload(IdRequest, Protocol, appKey)e crea i recordTicket.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
.ascxsottoUserControls/raggiungibile viahidUCLoad/CurrentControl; se è un'azione di creazione, farlo ereditareCreateUserControlBaseper riusare validazione/upload/transazione. callTypeControl+RequestCenter.Constants.CallTypes: i ramiTicket/Anomaly/InfoinbtnPost_Click(:97-157) sono guidati dai GUID dei call type; nuovi tipi si innestano lì.- Master page pluggabile via
hidMPFile(LoadMasterPage). ExtraFlowActionsProxy.svccome 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
- Creare
UserControls/<Area>/<nuovoControl>.ascx(+.ascx.vb). Per un'azione di creazione,Inherits BaseClasses.CreateUserControlBase. - Esporre il control tramite una voce di menu della app
"Requests"conAppData("controlurl") = "UserControls/<Area>/<nuovoControl>.ascx"(vedi guida successiva). Nessuna route da registrare: la shellDefault.aspxlo carica viahidUCLoad/CurrentControl. - Implementare
DoValidation()(override) se servono regole; sfruttareerrLog/uplFilesPaneldalla base. - Racchiudere le scritture DB in
New RequestCenter.Transaction(OpenConnection/Begin/Commit/Rollback/CloseConnection), comebtnPost_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.ascx → Default.aspx carica il control in PHMain → submit actSubmt.ActivityRun → btnPost_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.LoadControl→PHMain;ControlNotFoundException);CurrentControlDefault.aspx.vb:17-67. — VERIFIED - Menu app
"Requests"+AppData(controlurl/idworkflow/idactivity) + startup scriptucontrolloader/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.asaxassente inCASSANDRA/RequestCenterWeb/(glob*.asaxa vuoto). — VERIFIED (bootstrap applicativo → UNKNOWN qui)- Control creazione ticket:
UserControls/FlowActions/makeTicket.ascx:1(Inherits="Descor.RequestCenterWeb.makeTicket"), sotto-control registratimakeTicket.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(newTicket.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); schedaFILETABmakeTicket.ascx.vb:60. — VERIFIED - Gate auth/authz:
CommonWeb/RequestCenter/Classes/Base/RequestCenterPage.vb:74-90(Page_PreInit,RequestCenterEnabled/IsUserSuperAdmin, redirectFormsAuthentication.DefaultUrl); edit mode:56-71;RequestCenterEnableddefinito inCommonWeb/RequestCenter/Classes/HttpContext/WebUser.vb. — VERIFIED - Equivalenti WCF:
CASSANDRA/RequestCenterWeb/WebServices/ExtraFlowActionsProxy.svc;CASSANDRA/CommonWeb/RequestCenter/WebServices/RequestsReaderWCF.svceRequestsCacheService.svc. — SUPPORTED (file presenti) - Package Oracle a valle (via DAL):
GESTREQUEST,GESTREQUEST_T2— vediclass-Ticket-Request.mdeproject-RequestCenter-BL.md. — VERIFIED (cross-ref) - TD-008 (grant valutati solo lato UI):
docs/14-technical-debt/index.md. — SUPPORTED