37 messaggi dal 19 settembre 2010
Ho cercato di capirci qualcosa ma sicuramente mi serve una mano.
1) si dovrebbe aggiungere un httpmodule nel webconfig dal nome webtextmodule cosi come la classe? cavolo e come faccio a passarci la connection e la entities? Ma la connection standard rimane?
Ho tradotto in Vb ma........
Grazie


Public Class WebContextModule
Implements IHttpModule
Public Sub Init(context As HttpApplication)
' ad ogni richiesta creiamo un'istanza
context.BeginRequest += Function(sender As Object, e As EventArgs) Do
HttpContext.Current.Items(ConfigurationKeys.ConnectionString) = New NorthwindEntities(Configuration.ConnectionString)
End Function

' alla fine di ogni richiesta, se attiva, la distruggiamo
context.EndRequest += Function(sender As Object, e As EventArgs) Do
Dim ctx = DirectCast(HttpContext.Current.Items(ConfigurationKeys.ConnectionString), ObjectContext)
If ctx IsNot Nothing Then
ctx.Dispose()
End If
End Function
End Sub
End Class


*********************************************************************
Public NotInheritable Class ApplicationContext
Implements IApplicationContext
Private Shared _sync As New Object()
Private Shared _currentInstance As ApplicationContext

Public Shared ReadOnly Property Current() As ApplicationContext
Get
If _currentInstance Is Nothing Then
SyncLock _sync
If _currentInstance Is Nothing Then
_currentInstance = New ApplicationContext()
End If
End SyncLock
End If
Return _currentInstance
End Get
End Property

Public ReadOnly Property Context() As NorthwindEntities
Get
If HttpContext.Current.Items(ConfigurationKeys.ConnectionString) Is Nothing Then
Throw New InvalidOperationException("You must register the HttpModule to use per-Request impelementation.")
End If

Return DirectCast(HttpContext.Current.Items(ConfigurationKeys.ConnectionString), NorthinwEntities)
End Get
End Property
End Class
11.886 messaggi dal 09 febbraio 2002
Contributi
ok, bisogna fare qualche piccola modifica.

pistelli2001 ha scritto:

si dovrebbe aggiungere un httpmodule nel webconfig dal nome webtextmodule cosi come la classe?

sì, dunque, gli HttpModule si registrano in questo modo (se sei su IIS7 o superiore)
<system.webServer>
    <modules>
      <add name="getioneCicloDiVitaDelContesto" type="WebContextModule" />
    </modules>
</system.webServer>


Ora resta il secondo punto

pistelli2001 ha scritto:
come faccio a passarci la connection e la entities

La connection string non devi passargliela, è l'HttpModule che deve andare a leggerla dal web.config mediante la classe ConfigurationManager. Dunque, prova fare così. Nel codice trovi i commenti.
Public Class WebContextModule
    Implements IHttpModule

    Public Sub Init(context As HttpApplication) Implements IHttpModule.Init

        'Gestisco l'evento PostAuthenticateRequest perché mi serve il nome dell'utente
        'e questo lo posso conoscere solo dopo la fase di Autenticazione, che si verifica per ogni richiesta di pagina
        'A patto che tu stia usando la Membership API in una delle sue incarnazioni (es. FormsAuthetication)
        context.PostAuthenticateRequest += Function(sender As Object, e As EventArgs)
                                               'Per prima cosa leggo la connection string "base" dal web.config, grazie alla classe ConfigurationManager
                                               Dim connString = System.Configuration.ConfigurationManager.ConnectionStrings("DatabaseEntities").ConnectionString

                                               'Ora vado a sostituire il nome del database con quello dell'utente, come ti facevo vedere nell'esempio.
                                               '...ma solo se abbiamo un utente autenticato. Potrebbero esserci pagine, come quella di login, che hanno
                                               'bisogno della connection string di base.
                                               If (context.User.Identity.IsAuthenticated) Then
                                                   'Nota che il Replace non cambia in alcun modo la connection string originale, che rimane invariata nel web.config
                                                   'Il Replace cambia solo il valore della variabile connString
                                                   connString = connString.Replace("Database.sdf", context.User.Identity.Name & ".sdf")
                                               End If

                                               'Ora passo la connection string al costruttore che, se non sbaglio, si chiama DatabaseEntities
                                               HttpContext.Current.Items("DatabaseEntities") = New DatabaseEntities(connString)
                                           End Function

        'Al termine della richiesta, distruggo il contesto
        context.EndRequest += Function(sender As Object, e As EventArgs)
                                  Dim ctx = DirectCast(HttpContext.Current.Items("DatabaseEntities"), DatabaseEntities)
                                  If ctx IsNot Nothing Then
                                      'Ecco il dispose, che indicherà al Garbage Collector che l'oggetto può essere rimosso dalla memoria
                                      ctx.Dispose()
                                  End If
                              End Function
    End Sub


    Public Sub Dispose() Implements IHttpModule.Dispose
    End Sub


End Class


Se non dovesse funzionare, posta l'errore dettagliato.

La seconda classe, l'ApplicationContext, per ora lasciamola stare, è solo una facilitazione per accedere al contesto.
Quindi, per ora scrivi questo codice in una tua pagina Asp.Net.

    Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
        Dim contesto = DirectCast(HttpContext.Current.Items("DatabaseEntities"), DatabaseEntities)
        'e qui accedi alle proprietà del contesto
    End Sub


ciao

Enjoy learning and just keep making
37 messaggi dal 19 settembre 2010
Innanzitutto grazie per la disponibilita' sinora dimostrata, in generale credo di aver capito ma.... non funziona.

1) se non uso la autenticazione posso flaggare le righe che non mi ineteressano e cambiare cosi' evidenziandoti che context.User.Identity.Name e possbile cambiarla con una session("nomefile")? Poi all'inizio della classe mi chiede di importare il databasemodel.


Imports Microsoft.VisualBasic
Imports DatabaseModel
***************************************************************************
Public Class WebContextModule
Implements IHttpModule

Public Sub Init(context As HttpApplication) Implements IHttpModule.Init

Dim connString = System.Configuration.ConfigurationManager.ConnectionStrings("DatabaseEntities").ConnectionString



connString = connString.Replace("Database.sdf", context.User.Identity.Name & ".sdf")
'End If

'Ora passo la connection string al costruttore che, se non sbaglio, si chiama DatabaseEntities
HttpContext.Current.Items("DatabaseEntities") = New DatabaseEntities(connString)


'Al termine della richiesta, distruggo il contesto
' context.EndRequest += Function(sender As Object, e As EventArgs)
Dim ctx = DirectCast(HttpContext.Current.Items("DatabaseEntities"), DatabaseEntities)
If ctx IsNot Nothing Then
ctx.Dispose()
End If
End Sub

Public Sub Dispose() Implements IHttpModule.Dispose
End Sub

End Class
****************************************
nella pagina aspx- codice devo reimportare il database model e il databaseentities? cioe':
Imports DatabaseModel
Private dba As New DatabaseEntities
o basta per ogni accesso al database inserire
Dim dba = DirectCast(HttpContext.Current.Items("DatabaseEntities"), DatabaseEntities). Per finire , non mi dire rompi, ho poco chiara

<modules>
<add name="getioneCicloDiVitaDelContesto" type="WebContextModule" />
</modules>

il modulo gestioneciclodivitadelcontesto nel webconfig viene caricato all' inizio ... quello che conta e' il type che si riferisce alla classe?

Se nella classe inserisco un break(f9) ho verificato che non si blocca quindi molto probabilmente non ci passa.

Spero di essermi spiegato bene , grazie
Modificato da pistelli2001 il 07 novembre 2012 16.45 -
37 messaggi dal 19 settembre 2010
Per la seesion mi rispondo da solo, non e' possibile .... e allora help
11.886 messaggi dal 09 febbraio 2002
Contributi
Non disperare... alla Session puoi accedere facendo una modifica.

Nel ciclo di vita di un'applicazione Asp.net si susseguono varie fasi. Noi durante la discussione ne abbiamo incontrate alcune: BeginRequest (l'inizio della richiesta), PostAuthentication (che si verifica subito dopo l'autenticazione) e EndRequest (alla fine). Ce ne sono molte altre e le trovi riassunte in questa immagine.
http://i.msdn.microsoft.com/dynimg/IC142724.png

Come puoi vedere lì, la fase di autenticazione si verifica molto presto, quando ancora non è stata recuperata la sessione dell'utente.
La sessione viene recuperata più tardi durante la fase "Acquire state" ed è in quel momento che dovrai leggere la tua variabile.

Quindi, anziché gestire il PostAuthenticateRequest, gestisci il PostAcquireRequestState.
context.PostAcquireRequestState += Function....

A proposito, segui fedelmente gli esempi altrimenti non funzionano :) Nella Sub Init che hai postato prima manca la gestione del primo evento e poi vedo che il context.EndRequest è stato commentato, probabilmente in seguito a vari test.

Comunque, ora che hai gestito PostAcquireRequestState puoi accedere alla variabile di sessione in questo modo:
Dim nomeFile = HttpContext.Current.Session("nomefile")
'Ora uso nomeFile nel Replace della connection string, ma solo se il valore non è null


pistelli2001 ha scritto:

Poi all'inizio della classe mi chiede di importare il databasemodel.

Sì, va bene come hai fatto tu. Quando usi una classe qualsiasi, come pure DatabaseEntities, è necessario indicare in quale contenitore (namespace) essa si trova. La direttiva Imports serve appunto a questo scopo, quindi va bene.

pistelli2001 ha scritto:

il modulo gestioneciclodivitadelcontesto nel webconfig viene caricato all' inizio ... quello che conta e' il type che si riferisce alla classe?

Sì, esatto. Il name invece può essere una stringa qualsiasi. Di solito negli esempi vedi usare il nome della classe sia nel name che nel type, ma questa è una scelta più che una necessità.

pistelli2001 ha scritto:

Se nella classe inserisco un break(f9) ho verificato che non si blocca quindi molto probabilmente non ci passa.

Ok, cerchiamo di capire come mai.
Se l'esecuzione non si ferma sul breakpoint e se l'applicazione non va in errore, allora probabilmente significa che il nodo <system.webServer> del web.config è stato ignorato.
Questo può capitare quando il tuo webserver è IIS 6.0 (windows server 2003) oppure quando sei su IIS 7.0 in "modalità classica" (windows server 2008 o superiore). Puoi confermarmi che si tratta di uno di questi due casi? Se è così allora gli httpmodules si configurano in altro modo:
<system.web>
<httpModules>
  <add name="gestioneCicloDiVitaDelContesto" type="WebContextModule" />
</httpModules>
</system.web>

Qui trovi un articolo che ti mostra la differenza di configurazione tra IIS 6 e 7.
http://msdn.microsoft.com/en-us/library/ms227673%28v=vs.100%29.aspx#sectionToggle2

Qui invece trovi una guida su come scoprire (e modificare) qual è la modalità di esecuzione, se classica o integrata.
http://technet.microsoft.com/it-it/library/cc725564%28v=ws.10%29.aspx

ciao
Modificato da BrightSoul il 07 novembre 2012 22.57 -

Enjoy learning and just keep making
37 messaggi dal 19 settembre 2010
Ok rimetto tutto a posto , mi da il seguente errore:

Errore di compilazione

Descrizione: Errore durante la compilazione di una risorsa necessaria per soddisfare la richiesta. Rivedere i dettagli relativi all'errore e modificare in modo appropriato il codice sorgente.

Messaggio di errore del compilatore: BC32022: 'Public Event PostAcquireRequestState(sender As Object, e As System.EventArgs)' è un evento e non può essere chiamato direttamente. Utilizzare un'istruzione 'RaiseEvent' per generare un evento.

Errore nel codice sorgente:

context.PostAcquireRequestState += Function(sender As Object, e As EventArgs)

Dim nomeFile = HttpContext.Current.Session("Database")

me lo da sia in questa riga sia nella susseguente function.

Grazie sempre per la tua disponiblita
Modificato da pistelli2001 il 07 novembre 2012 22.49 -
11.886 messaggi dal 09 febbraio 2002
Contributi
Hai ragione, chiedo perdono, sono un po' arrugginito col vb.net.
Ho sbagliato la sintassi per gestire gli eventi. Non si usa l'operatore += come in C# ma la parola chiave AddHandler. Dunque prova così, ho incorporato anche le ultime modifiche che riguardano la variabile Session.

Imports Microsoft.VisualBasic
Imports DatabaseModel

Public Class WebContextModule
    Implements IHttpModule

    Public Sub Init(context As HttpApplication) Implements IHttpModule.Init

        'Gestisco l'evento PostAuthenticateRequest perché mi serve il nome dell'utente
        'e questo lo posso conoscere solo dopo la fase di Autenticazione, che si verifica per ogni richiesta di pagina
        'A patto che tu stia usando la Membership API in una delle sue incarnazioni (es. FormsAuthetication)
        AddHandler context.PostAcquireRequestState, Function(sender As Object, e As EventArgs)
                                                        'Per prima cosa leggo la connection string "base" dal web.config, grazie alla classe ConfigurationManager
                                                        Dim connString = System.Configuration.ConfigurationManager.ConnectionStrings("DatabaseEntities").ConnectionString

                                                        'Ora vado a sostituire il nome del database con quello dell'utente, come ti facevo vedere nell'esempio.
                                                        '...ma solo se la variabile di Sessione esiste. Potrebbero esserci pagine, come quella di login, che hanno
                                                        'bisogno della connection string di base.
                                                        Dim nomefile = HttpContext.Current.Session("Database")
                                                        If (Not nomefile Is Nothing) Then
                                                            'Nota che il Replace non cambia in alcun modo la connection string originale, che rimane invariata nel web.config
                                                            'Il Replace cambia solo il valore della variabile connString
                                                            connString = connString.Replace("Database.sdf", nomefile.ToString() & ".sdf")
                                                        End If

                                                        'Ora passo la connection string al costruttore che, se non sbaglio, si chiama DatabaseEntities
                                                        HttpContext.Current.Items("DatabaseEntities") = New DatabaseEntities(connString)
                                                    End Function

        'Al termine della richiesta, distruggo il contesto
        AddHandler context.EndRequest, Function(sender As Object, e As EventArgs)
                                           Dim ctx = DirectCast(HttpContext.Current.Items("DatabaseEntities"), DatabaseEntities)
                                           If ctx IsNot Nothing Then
                                               'Ecco il dispose, che indicherà al Garbage Collector che l'oggetto può essere rimosso dalla memoria
                                               ctx.Dispose()
                                           End If
                                       End Function
    End Sub


    Public Sub Dispose() Implements IHttpModule.Dispose
    End Sub


End Class


pistelli2001 ha scritto:
nella pagina aspx- codice devo reimportare il database model e il databaseentities? cioe':
Imports DatabaseModel
Private dba As New DatabaseEntities
o basta per ogni accesso al database inserire
Dim dba = DirectCast(HttpContext.Current.Items("DatabaseEntities"), DatabaseEntities).

Non bisogna usare la parola chiave New perché l'istanza di DatabaseEntites l'abbiamo già creata nell'HttpModule, quindi bisogna prendere quella usando questa riga di codice.
Dim dba = DirectCast(HttpContext.Current.Items("DatabaseEntities"), DatabaseEntities)


ciao!
Modificato da BrightSoul il 08 novembre 2012 11.06 -

Enjoy learning and just keep making
37 messaggi dal 19 settembre 2010
Ok , speriamo di arrivare a dama , ti ringrazio per avermi fatto capire molte cose che neanche immaginavo e gia' questo per me e' molto comunque recito il mea culpa in quanto non ti ho detto che la login e password con tutti i campi per gli utenti risiedono su altro database. Una volta loggati la pagina di login indirizza su altro database a secondo dell'accesso e salva il nome del database nella session("database") per cui all'inizio questo valore e' nullo viene riempito di seguito. Ho letto qualcosa sui moduli come da te suggerito e' l'ho spostato adesso il break funziona e mi da il seguente errore
Dim nomefile = HttpContext.Current.Session("Database")

NullreferenceException non e' stata gestita dal codice utente
usare la parola new
determinare se l'oggetto e' null rpima di chiamare il medtodo

Ho provato a gestire la session con dbnull o come hai fatto tu con isnothing ma nulla sempre errore

Mentre se forzo il nome con un archivio esempio
Dim nomefile = "Arc0001"

Funziona

Grazie
Modificato da pistelli2001 il 08 novembre 2012 19.07 -

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.