[ASP.NET] Webdev tips

Pagina: 1
Acties:
  • 844 views sinds 30-01-2008
  • Reageer

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 19:05
De bedoeling van dit topic is om een aantal tips en best practises over ASP.NET met elkaar te sharen.
Vul dit topic gerust aan en lever gerust (onderbouwde) kritiek op de items die hier geplaatst zijn.

Laad en bewaar sessie-variabelen op een gecentraliseerde plaats

Aangezien sessie-variabeles case-sensitive zijn, kunnen er wel eens problemen opduiken als je niet nauwgezet bezig bent. Stel bv, dat je een sessie-variabele maakt met de naam "MySessionVar".
code:
1
Session["MySessionVar"] = 1;

Op een later ogenblik wil je die variabele opnieuw uitlezen, maar je typed het volgende:
code:
1
int i = (int)Session["MySessionvar"];

Hier zit je dus met een probleem. MySessionVar en MySessionvar zijn nl. niet hetzelfde. De compiler gaat hier ook niet over klagen.
Om dit probleem binnen de perken te houden, ga je dus best je sessie-variabelen op een centrale plaats gaan ophalen en opnieuw bewaren.
Je kunt je sessie-variabelen dus het best ophalen in je Page.OnLoad event omdat dit event altijd getriggered wordt als er een pagina geladen wordt.
De sessie-variabelen opnieuw bewaren kan je best doen in de Page.OnUnLoad event. Deze event wordt nl. getriggered als andere events uitgevoerd zijn.

Maak gebruik van Stored Procedures

Gebruik zoveel mogelijk gebruik van stored procedures om data op te halen en te bewerken.
Aangezien het DBMS het beste execution plan voor die procedure bewaart (en dus niet steeds opnieuw hoeft na te gaan wat het beste execution plan voor die query is), is dat dus een zeer snelle manier om queries uit te voeren.
Je kan ook verschillende bij elkaar horende queries groeperen in 1 procedure. Op die manier spaar je een aantal roundtrips naar de DB server uit, wat de performance ook zeker ten goede komt.
Naast de performance winst, kunnen Stored Procedures ook de veiligheid ten goede komen. Door gebruik te maken van parameters kan je nl. al SQL injection attacks voorkomen, en hoef je de waarden die je aan je query meegeeft niet meer te controleren op illegal characters.

bv:
code:
1
2
3
4
5
6
7
8
9
10
11
SqlCommand cmdAddRecord = new SqlCommand ();

cmdAddRecord.Connection = conn;
cmdAddRecord.CommandType = CommandType.StoredProcedure;
cmdAddRecord.CommandText = "INSERT_PERSON";

cmdAddRecord.Parameters.Add ("@p_Name", SqlDbType.VarChar);

cmdAddRecord.Parameters["@p_Name"].Value = "1;delete from tblPersons;";

cmdAddRecord.ExecuteNonQuery();

Zal geen problemen opleveren, en zal gewoon een nieuw record maken met een Naam "1;delete from tblPersons;".

Maak gebruik van caching

Er zijn verschillende manier om caching te implementeren:
Page Output Caching
Fragment Caching
Caching van variabelen/objecten

Als je een aspx pagina hebt waarvan je weet dat de inhoud niet erg onderhevig is aan verandering, dan kan je die pagina cachen. Het cachen van de pagina zorgt ervoor dat bij een volgende request de webserver geen diskaccess of processing meer moet doen om de pagina naar de client te sturen. Hij wordt gewoon vanuit z'n geheugen aan de client geserveerd.

Page Caching implementeren doe je door volgende directive aan je page toe te voegen:

code:
1
<%@ OutputCache Duration="5" VaryByParam="none" %>


Bovenstaande regel zorgt ervoor dat de pagina gedurende 5 seconden gecached wordt.

Je kan ook variabelen en objecten cachen. Dit doe je door gebruik te maken van het Cache object.
Aan zo'n gecachede variabele kan je ook een dependency toekennen. Stel bv dat je een configuratie file hebt die je inleest en die je graag in je cache zou willen hebben om zo snel bepaalde instellingen te kunnen uitlezen.
Als je iets aan die configuratie-file veranderd, dan is je gecachede object natuurlijk waardeloos. Je kan dit oplossen door van die config-file een dependency te maken van je gecachede object. Als er dan iets aan die config-file veranderd, dan wordt het gecachete object weggegooid.

Je kan ook data uit een databank gaan cachen. Echter, je kan niet zomaar een dependency maken op een tabel in je databank. Als de data in je databank dan veranderd, dan is de gecachete data eigenlijk waardeloos.
Je kan dit echter oplossen door gebruik te maken van triggers en extended stored procedures. Jeff Prosise heeft er een interessant artikel over geschreven dat je hier vindt.

Connection pooling

Het maken van een connectie naar een databank is een expensive cost die op de performance van je site kan wegen.
Je kan echter gebruik maken van connection pooling om deze kost tot een minimum te herleiden.
.NET kan automatisch voor connection pooling zorgen. Er moet dan wel aan een tweetal voorwaarden voldaan worden:
Connecties kunnen pas in eenzelfde connection-pool ondergebracht worden als ze identieke connectionstrings hebben. Zelfs een klein verschil kan er al toe leiden dat een connection niet gepooled kan worden. Om dit dus te voorkomen ga je het best je connectionstring in een centrale plaats gaan opslaan.
De web.config is daar ideaal voor.

Je kan een sectie <appSettings> in je web.config maken waar je een aantal keys in kwijt kunt:
code:
1
2
3
<appSettings>
  <add key="connectionString"   value="initial catalog=....."/>
</appSettings>

Als je nu een nieuwe connectie moet aanmaken, kan je dat eenvoudig doen:
code:
1
2
3
SqlConnection conn = new SqlConnection (System.Configuration.
                                        ConfigurationSettings.
                                        AppSettings["connectionString"]);

Een bijkomend voordeel van deze aanpak is, dat je je connectionstring slechts op 1 plaats hoeft te wijzigen mocht dat nodig zijn.

Een andere vereiste om gebruik te kunnen maken van connection pooling is, dat je je connectie sluit van zodra je ze niet meer nodig hebt. Op die manier kan ze aan een connection-pool toegevoegd worden.
Een bijkomend voordeel van deze 'disconnected' aanpak is dat je code veel schaalbaarder zal zijn.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 07-07 07:46

gorgi_19

Kruimeltjes zijn weer op :9

In omgekeerde wil ik nog wat dingen noemen..
De connectionstring vindt ik zelf nog te foutgevoelig; ik heb er zelf nog een tussenlaagje in gezet.

Het wordt bij mij dus:
Visual Basic .NET:
1
2
3
4
5
6
7
8
9
10
11
12
13
Public Class Globals
        Public Shared ReadOnly Property ConnectionString() As String
            Get
                Dim strConnectionString As String = ConfigurationSettings.AppSettings("connectionString")
                If Not strConnectionString = "" Then
                    Return strConnectionString
                Else
                    Throw New Exception("Globals::ConnectionString::Error occured.")
                End If

            End Get
        End Property
End class

Mijn aanroep wordt dan vervolgens:
Visual Basic .NET:
1
Dim conn as SQLConnection = new SqlConnection(Globals.GetConnectionString)


Zelfde methodiek kan je ook gebruiken met Session vars. Het gevaar van tikfouten vind ik te groot, zodat ik een class maakt, welke of een de Usercontrol of Page class erft. Vervolgens ga ik dan van deze class uit werken (Dus ipv dat ik System.Web.Page inherit, inherit MyCustomPage)

Een andere methodiek blijft om het te centraliseren in een Globals class. Nadeel is dan wel dat alles shared is, maar veel zware berekeningen worden er niet mee gedaan.

Met caching kan je trouwens nog een stuk verder gaan... Je kan ook datatables of datasets cachen.
Visual Basic .NET:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Public Class Pressmessage

     Public Function SelectAll() as DataTable

            Dim siteSettingsCacheKey As String = "PressMessageCache"

            If HttpContext.Current.Cache(siteSettingsCacheKey) Is Nothing Then

                ' Create Instance of the IDataProvider
                Dim dp As IDataProvider = New DataProvider().Instance
                HttpContext.Current.Cache.Insert(siteSettingsCacheKey, dp.LoadPressmessages())

            End If
            Return CType(HttpContext.Current.Cache(siteSettingsCacheKey), DataTable)

     End Function

End class

En bij een update zet je vervolgens je cache op Nothing; waarna de data de volgende keer weer opgehaald wordt.

Je kan trouwens niet alleen objecten cachen, ook volledige assemblies.. :P
Dit maakt het imho mogelijk om echt n-tier te gaan werken, met een volledig losse datalaag.

[ Voor 34% gewijzigd door gorgi_19 op 18-06-2003 20:26 ]

Digitaal onderwijsmateriaal, leermateriaal voor hbo


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 19:05
gorgi_19 schreef op 18 juni 2003 @ 20:17:
In omgekeerde wil ik nog wat dingen noemen..
De connectionstring vindt ik zelf nog te foutgevoelig; ik heb er zelf nog een tussenlaagje in gezet.
Mijn aanroep wordt dan vervolgens:
Visual Basic .NET:
1
Dim conn as SQLConnection = new SqlConnection(Globals.GetConnectionString)
Inderdaad, goed idee. :Y)
Zelfde methodiek kan je ook gebruiken met Session vars. Het gevaar van tikfouten vind ik te groot, zodat ik een class maakt, welke of een de Usercontrol of Page class erft. Vervolgens ga ik dan van deze class uit werken (Dus ipv dat ik System.Web.Page inherit, inherit MyCustomPage)

Een andere methodiek blijft om het te centraliseren in een Globals class. Nadeel is dan wel dat alles shared is, maar veel zware berekeningen worden er niet mee gedaan.
Hier kan je er eigenlijk ook voor kiezen om constanten te maken die de namen van je session-variabelen bevatten. Op die manier kan je ook tikfouten gaan voorkomen.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 19:05
gorgi_19 schreef op 18 juni 2003 @ 20:17:
Met caching kan je trouwens nog een stuk verder gaan... Je kan ook datatables of datasets cachen.
Idd, en je kan er ook dependencies op leggen. Zie die link naar dat artikel van Jeff Prosise in m'n openingspost. ;)
Ik zal het hier ook nog maar ff neerzetten:

Supporting Database cache dependencies

edit:
ff de link gefixed

[ Voor 46% gewijzigd door whoami op 19-06-2003 08:15 ]

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 07-07 07:46

gorgi_19

Kruimeltjes zijn weer op :9

whoami schreef op 18 June 2003 @ 20:26:
[...]


Idd, en je kan er ook dependencies op leggen. Zie die link naar dat artikel van Jeff Prosise in m'n openingspost. ;)
Ik zal het hier ook nog maar ff neerzetten:

Supporting Database cache dependencies
Hmmmm.. Interesting.. In ieder geval gebookmarked..
whoami schreef op 18 June 2003 @ 20:20:
Hier kan je er eigenlijk ook voor kiezen om constanten te maken die de namen van je session-variabelen bevatten. Op die manier kan je ook tikfouten gaan voorkomen.
Hoe had je dit dan in gedachten?
Visual Basic .NET:
1
2
3
4
Public Enum SessionNames
     Name
     Address
End Enum

En dan aanroepen met
Visual Basic .NET:
1
2
Session(SessionNames.Name) = "melp"
Session(SessionNames.Address) = "Orbb"

?

Daarnaast nog een tip voor mensen die met validatie aan de gang gaan.. Waarom stopt iedereen z'n UserID in een Session variabele? ASP.Net heeft een prachtige FormsAuthentication methode, inclusief controle voor MD5. :?

Een andere bijzonder interessante mogelijkheid vindt ik ook tracing. Zo kan je een stuk effectiever debuggen; je kan zelf tracelines in je code zetten en deze achteraf bekijken. Een normale gebruiker ziet hier helemaal niets van.

[ Voor 81% gewijzigd door gorgi_19 op 18-06-2003 20:38 ]

Digitaal onderwijsmateriaal, leermateriaal voor hbo


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 19:05
gorgi_19 schreef op 18 June 2003 @ 20:29:
[...]

Hoe had je dit dan in gedachten?
Visual Basic .NET:
1
2
3
4
Public Enum SessionNames
     Name
     Address
End Enum

En dan aanroepen met
Visual Basic .NET:
1
2
Session(SessionNames.Name) = "melp"
Session(SessionNames.Address) = "Orbb"
Nee, gewoon:

code:
1
2
3
public const  SessionName = "Naam";

Session[SessionName] = "whoami";

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 07-07 07:46

gorgi_19

Kruimeltjes zijn weer op :9

whoami schreef op 18 June 2003 @ 20:38:
[...]

Nee, gewoon:

code:
1
2
3
public const  SessionName = "Naam";

Session[SessionName] = "whoami";
Maar hoe gebruik je deze dan als je die in meerdere classes wil gebruiken, of op meerdere pagina's?

Visual Basic .NET:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Public Class Page1

    Public Const m_iAantalTeams as integer = 5

    Public Function GetAantal() as integer

        return m_iAantalTeams 

    End Function

End Class

Public Class Page2

    Public Function GetAantal() as integer

        return m_iAantalTeams 

    End Function

End Class

Gaat niet werken..

[ Voor 40% gewijzigd door gorgi_19 op 18-06-2003 20:42 ]

Digitaal onderwijsmateriaal, leermateriaal voor hbo


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 19:05
gorgi_19 schreef op 18 June 2003 @ 20:29:
[...]
Daarnaast nog een tip voor mensen die met validatie aan de gang gaan.. Waarom stopt iedereen z'n UserID in een Session variabele? ASP.Net heeft een prachtige FormsAuthentication methode, inclusief controle voor MD5. :?
Inderdaad, dat was ook iets dat ik in eerste instantie nog wou opnemen in m'n openingspost, maar ik had er geen zin meer in. :P

Als je een 'secure' site ofzo wilt maken, pas dan de juiste authentication methode toe en maak dus gebruik van de mogelijkheden die ASP.NET al biedt en ga niet zelf gaan briedelen met een eigen custom authentication stuff ofzo.
Een andere bijzonder interessante mogelijkheid vindt ik ook tracing. Zo kan je een stuk effectiever debuggen; je kan zelf tracelines in je code zetten en deze achteraf bekijken. Een normale gebruiker ziet hier helemaal niets van.
Hoe bedoel je, een normale gebruiker ziet hier niets van? Je moet dan wel je applicatie in release-mode opleveren.
Is het ook niet zo dat, als je de customErrors in je web.config op True zet, dat alle trace-informatie naar een centrale page weggeschreven wordt?

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 07-07 07:46

gorgi_19

Kruimeltjes zijn weer op :9

whoami schreef op 18 June 2003 @ 20:42:
Hoe bedoel je, een normale gebruiker ziet hier niets van? Je moet dan wel je applicatie in release-mode opleveren.
Is het ook niet zo dat, als je de customErrors in je web.config op True zet, dat alle trace-informatie naar een centrale page weggeschreven wordt?
ff twee quotes uit m'n config.web.

XML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
    <!--  CUSTOM ERROR MESSAGES
          Set customErrors mode="On" or "RemoteOnly" to enable custom error messages, "Off" to disable. 
          Add <error> tags for each of the errors you want to handle.
    -->
    <customErrors mode="Off" />

      <!--  DYNAMIC DEBUG COMPILATION
          Set compilation debug="true" to insert debugging symbols (.pdb information)
          into the compiled page. Because this creates a larger file that executes
          more slowly, you should set this value to true only when debugging and to
          false at all other times. For more information, refer to the documentation about
          debugging ASP.NET files.
    -->
    <compilation defaultLanguage="vb" debug="true" />

    <!--  APPLICATION-LEVEL TRACE LOGGING
          Application-level tracing enables trace log output for every page within an application. 
          Set trace enabled="true" to enable application trace logging.  If pageOutput="true", the
          trace information will be displayed at the bottom of each page.  Otherwise, you can view the 
          application trace log by browsing the "trace.axd" page from your web application
          root. 
    -->
    <trace enabled="true" requestLimit="40" pageOutput="false" traceMode="SortByTime" localOnly="true" />

Ze zijn dus onafhankelijk van elkaar in te stellen. Wat jij bedoeld is de bedoeld is de debuginformatie, welke weg is als je het in release mode aflevert. Tracing blijft beschikbaar (mits je deze aanzet, en afhankelijk van de rechten die je instelt) in release modus.

Het wordt ook op een aparte pagina weergegeven,

http://webadres/applicationnaam/trace.axd
Inderdaad, dat was ook iets dat ik in eerste instantie nog wou opnemen in m'n openingspost, maar ik had er geen zin meer in.

Als je een 'secure' site ofzo wilt maken, pas dan de juiste authentication methode toe en maak dus gebruik van de mogelijkheden die ASP.NET al biedt en ga niet zelf gaan briedelen met een eigen custom authentication stuff ofzo.
Custom authentication is op zich ook wel leuk om te maken.. :P Is iig iets waar ik me nog wel verder in wil verdiepen, puur uit principe. Het enige wat ik weet is dat in dan iig met IPrincipal aan de gang moet. Nog geen idee wat het is; misschien dat ik zo niet alleen het UserID kan opslaan, maar nog wat meer informatie. Kortom, een uitbouw van de User class..

In aanvulling op de FormsAuthentication; Role-Based Security is natuurlijk ook erg handig. :)

[ Voor 58% gewijzigd door gorgi_19 op 18-06-2003 20:48 ]

Digitaal onderwijsmateriaal, leermateriaal voor hbo


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 19:05
gorgi_19 schreef op 18 June 2003 @ 20:45:
[...]

In aanvulling op de FormsAuthentication; Role-Based Security is natuurlijk ook erg handig. :)
Role-based security kan je makkelijk implementeren ism Forms Authentication.

Stel dat je je users wilt authenticaten dmv de user-informatie in de databank en dat een user ook tot meerdere groepen kan behoren.

Om dan de groepen waartot de user behoort ook aan die user toe te wijzen, kan je gebruik maken van volgende code:

global.asax
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
  // Get User-Role information.
  if( m_UserInfo != null )
  {
    HttpApplication app = (HttpApplication)sender;
                
    if( app.Request.IsAuthenticated && app.User.Identity is FormsIdentity )
    {
            
         FormsIdentity ident = (FormsIdentity)app.User.Identity;
                
         string[] roles = mtDataLayer.UserData.GetRolesInfo(m_UserInfo.UserId,  
         ConfigurationSettings.AppSettings["dsnLibrary"]);
                                                  
         app.Context.User = new GenericPrincipal( ident, roles);    
     }
  }
}

Deze code gaat gewoon (als de user geauthenticeerd is, en er gebruik gemaakt wordt van formsauth), de groepen gaan ophalen tot welke de current user behoord.
Die method GetRolesInfo returned gewoon een string array met daarin de groepen waartoe de user behoord.
Er wordt dan een nieuw GenericPrincipal object gemaakt met de gegevens van de geauthenticeerde user en zijn groepen.

Nu kan je dus ook in je web.config gebruik gaan maken van 'deny roles' etc...

[ Voor 5% gewijzigd door whoami op 18-06-2003 21:03 ]

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 07-07 07:46

gorgi_19

Kruimeltjes zijn weer op :9

Waarbij je ook nog met cookies kan werken, om de boel iets te besparen.. :P

Visual Basic .NET:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
             If HttpContext.Current.Request.Cookies("ProSimRoles") Is Nothing Then

                        Dim clsUser As User = New User
                        clsUser.UserID = HttpContext.Current.User.Identity.Name
                        Dim arrRoles As ArrayList = clsUser.GetRoles

                        Dim strRoles As String = ""
                        ' Create a string to persist the roles

                        For Each role In arrRoles

                            userRoles.Add(role)
                            strRoles &= role & ";"
                        Next role

                        ' Create a cookie authentication ticket.
                        '   version
                        '   user name
                        '   issue time
                        '   expires every hour
                        '   don't persist cookie
                        '   roles
                        Dim ticket As New FormsAuthenticationTicket(1, _
                            HttpContext.Current.User.Identity.Name, _
                            DateTime.Now, _
                            DateTime.Now.AddHours(1), _
                            False, _
                            strRoles)

                        ' Encrypt the ticket
                        Dim cookieStr As String = FormsAuthentication.Encrypt(ticket)

                        ' Send the cookie to the client
                        HttpContext.Current.Response.Cookies("ProSimRoles").Value = cookieStr
                        HttpContext.Current.Response.Cookies("ProSimRoles").Path = "/"
                        HttpContext.Current.Response.Cookies("ProSimRoles").Expires = DateTime.Now.AddMinutes(3)

                    Else

                        ' Get roles from roles cookie
                        Dim ticket As FormsAuthenticationTicket = FormsAuthentication.Decrypt(HttpContext.Current.Request.Cookies("ProSimRoles").Value)

                        'convert the string representation of the role data into a string array
                        For Each role In ticket.UserData.Split(New Char() {";"c})
                            userRoles.Add(role)
                        Next role

                    End If

                    roles = CType(userRoles.ToArray(GetType(String)), String())
                    ' Add our own custom principal to the request containing the roles in the auth ticket
                    HttpContext.Current.User = New GenericPrincipal(HttpContext.Current.User.Identity, roles)
                End If

Deze code controleert of er een cookie bestaat, met de rollen er in. Zo niet, dan wordt het cookie aangemaakt en worden de rollen uit de database gehaald. Scheelt iig weer 1 request. :)

Over de roles:
Ook in je code kan je vervolgens valideren...
Visual Basic .NET:
1
2
3
If Not HttpContext.Current.User.IsInrole("melp") Then
     CType(Me.Findcontrol("panel1"),Panel).Visible = False
End if

En kan je je code afhankelijk maken van je rol. In een pagina kan je zo stukken coden verbergen of toevoegen. De tijd staat nu op 3 minuten, maar deze kan verlegd c.q. verkort worden, naar gelang nodig is.

[ Voor 23% gewijzigd door gorgi_19 op 18-06-2003 21:07 ]

Digitaal onderwijsmateriaal, leermateriaal voor hbo


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 19:05
Nog een tip:

Schakel de ViewState uit voor controls die dat in je applicatie niet nodig hebben. Dit kan de performance positief beinvloeden, er moet dan namelijk minder informatie naar de client gestuurd worden waardoor de pagina sneller zal laden.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 07-07 07:46

gorgi_19

Kruimeltjes zijn weer op :9

whoami schreef op 19 June 2003 @ 08:18:
Nog een tip:

Schakel de ViewState uit voor controls die dat in je applicatie niet nodig hebben. Dit kan de performance positief beinvloeden, er moet dan namelijk minder informatie naar de client gestuurd worden waardoor de pagina sneller zal laden.
Hoewel ik dit wel een van de engste tips vindt als je net begint met ASP.Net. Bepaalde acties, zoals linkbuttons, sorting mogelijkheden van een datagrid, etc. kunnen dan uitgeschakeld worden.

Verder moet je ook je datagrid iedere keer rebinden, als ik me goed herinner. Idd dus als je alleen informatie stuurt, en er vervolgens geen enkele actie meer mee gedaan hoeft te worden.

Ook is het van belang wat je in de viewstate stopt. Als je een dataset serialized en in de viewstate stopt, wordt je viewstate stukken groter dan als je een simpele arraylist er in stopt.

Een van de vage acties van Microsoft vindt ik trouwens wel dat ValidateRequest vanaf .Net 1.1 standaard op true staat. Dit houdt in dat je data, die je verstuurt via tekstboxen, etc., gecontroleerd wordt op HTML. Zo ja, dan wordt er een error gegenereerd.

Echter, ik kan deze fout niet afvangen anders dan door middel van een errorpage. Liever had ik gehad dat het een property was van een textbox, zodat je zoiets had als:

Visual Basic .NET:
1
2
3
4
If textbox1.HasHTML Then
    req_Validator1.ErrorMessage = "Geen HTML Toegestaan"
    Page.IsValid = False
End if

Op deze wijze zijn de fouten wat makkelijker af te vangen, of iig wat netter. 't is wat veiliger voor je code, maar imho niet praktisch. Een andere optie zou zijn dat er een aparte property wordt gemaakt van een textbox, EncodedText oid, waar automatisch Server.HtmlEncode / Server.HTMLDecode overheen wordt gegooid.

Persoonlijk gebruik ik dan ook ValidateRequest="false".

Verder over veiligheid gesproken.. Ik kwam net een artikel boekwerk tegen op MSDN over security, genaamd Improving Web Application Security: Threats and Countermeasures . 't is een boekwerkje van 833(!) pagina's geworden. Op zich zeker interessant, hoewel ik denk dat grote stukken voor beginners redelijk ongegrijpelijk zijn.

Ik gok trouwens dat bovenstaande niet alleen voor ASP.Net'ers interessant is. Gezien het algemene karakter van een aantal hoofdstukken kan het ook interessant zijn voor PHP'ers.

[ Voor 62% gewijzigd door gorgi_19 op 19-06-2003 08:48 ]

Digitaal onderwijsmateriaal, leermateriaal voor hbo


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 19:05
Ik heb het net ff uitgetest (heb nog maar net .NET v1.1), en inderdaad.
Zoals je zegt zorgt het er wel voor wat extra veiligheid, maar boet je wel aan flexibiliteit in als die property op true staat.

Misschien hadden ze beter een NoHtmlValidator ofzo gemaakt die je -net zoals de bekende requiredfieldvalidators etc- aan een control kunt hangen.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 07-07 07:46

gorgi_19

Kruimeltjes zijn weer op :9

whoami schreef op 19 juni 2003 @ 08:48:
Ik heb het net ff uitgetest (heb nog maar net .NET v1.1), en inderdaad.
Zoals je zegt zorgt het er wel voor wat extra veiligheid, maar boet je wel aan flexibiliteit in als die property op true staat.

Misschien hadden ze beter een NoHtmlValidator ofzo gemaakt die je -net zoals de bekende requiredfieldvalidators etc- aan een control kunt hangen.
Op zich is die trouwens wel eenvoudig te maken. Gewoon de basevalidatorcontrol inheriten (ff de naam kwijt) en daar vervolgens een paar regular expressions overheen gooien. Of nog eenvoudiger: RegularExpressionValidator inheriten en standaard een reg ex inzetten.

Digitaal onderwijsmateriaal, leermateriaal voor hbo


Acties:
  • 0 Henk 'm!

  • TeeDee
  • Registratie: Februari 2001
  • Laatst online: 21:37

TeeDee

CQB 241

Heren, bedankt :) Heb deze in mijn bookmarks staan.

Ik zal niks kunnen aandragen, maar goed. Zulk volk moet je ook hebben :)

Heart..pumps blood.Has nothing to do with emotion! Bored


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
whoami schreef op 19 June 2003 @ 08:48:
Ik heb het net ff uitgetest (heb nog maar net .NET v1.1), en inderdaad.
Zoals je zegt zorgt het er wel voor wat extra veiligheid, maar boet je wel aan flexibiliteit in als die property op true staat.

Misschien hadden ze beter een NoHtmlValidator ofzo gemaakt die je -net zoals de bekende requiredfieldvalidators etc- aan een control kunt hangen.
En een van de belangrijkste dingen die eigenlijk natuurlijk niks met ASP.NET te maken heeft. Controleer altijd de input van de gebruikers. Voor de database is het door gebruik van parameters al niet meer zo'n probleem maar als je de gegevens die door de gebruiker ergens ingevoerd zijn ook weer ergens anders toont moet je altijd HTMLEncoden. Omdat dit door een hoop mensen nog wel eens vergeten wordt staat die property natuurlijk altijd op true. Ikzelf had er eerst ook problemen mee bij een applicatie die van een 1.0 server naar een 1.1 server ging :) best lastig als opeens een hoop pagina's niet meer werken waar gewoon best html ingevoerd mag worden.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 07-07 07:46

gorgi_19

Kruimeltjes zijn weer op :9

rwb schreef op 19 juni 2003 @ 09:18:
[...]


En een van de belangrijkste dingen die eigenlijk natuurlijk niks met ASP.NET te maken heeft. Controleer altijd de input van de gebruikers. Voor de database is het door gebruik van parameters al niet meer zo'n probleem maar als je de gegevens die door de gebruiker ergens ingevoerd zijn ook weer ergens anders toont moet je altijd HTMLEncoden. Omdat dit door een hoop mensen nog wel eens vergeten wordt staat die property natuurlijk altijd op true. Ikzelf had er eerst ook problemen mee bij een applicatie die van een 1.0 server naar een 1.1 server ging :) best lastig als opeens een hoop pagina's niet meer werken waar gewoon best html ingevoerd mag worden.
Klopt, maar om dan gelijk een exception te gooien als iemand <kiekeboe> er in zet, en dan wel op een moment zodat je deze nog helemaal niet kan afvangen, lijkt me ook niet echt de bedoeling.

Veiligheid is een goed argument, maar op deze wijze bevordert het de gebruiktsvriendelijkheid niet echt...

Digitaal onderwijsmateriaal, leermateriaal voor hbo


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
gorgi_19 schreef op 19 June 2003 @ 09:22:
[...]

Klopt, maar om dan gelijk een exception te gooien als iemand <kiekeboe> er in zet, en dan wel op een moment zodat je deze nog helemaal niet kan afvangen, lijkt me ook niet echt de bedoeling.

Veiligheid is een goed argument, maar op deze wijze bevordert het de gebruiktsvriendelijkheid niet echt...
Dat probeerde ik inderdaad ook te zeggen. Ik begrijp best dat ze het er in hebben gezet maar de manier vindt ik echt heel beroerd. Ik heb bijvoorbeeld ergens een gastenboek staan. Op deze pagina kunnen de gebruikers geen html gebruiken en ik HTMLEncode alles wat ingevoerd wordt dan ook. Maar het kan natuurlijk best voorkomen dat een gebruiker bijvoorbeeld "dsafadfdsaf < blaat >:)" en dat is best geldig want er mogen smilies gebruikt worden.

[ Voor 8% gewijzigd door Woy op 19-06-2003 09:28 . Reden: ff kromme zin wat rechter gemaakt :) ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 19:05
gorgi_19 schreef op 19 juni 2003 @ 08:29:

Persoonlijk gebruik ik dan ook ValidateRequest="false".
Dit kan je ook in je web.config kwijt. Op die manier hoef je niet in elke page die attribute in de directive gaan zetten:

code:
1
<pages validateRequest="false"/>

[ Voor 3% gewijzigd door whoami op 19-06-2003 09:28 ]

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 19:05
rwb schreef op 19 juni 2003 @ 09:18:
[...]


En een van de belangrijkste dingen die eigenlijk natuurlijk niks met ASP.NET te maken heeft. Controleer altijd de input van de gebruikers. Voor de database is het door gebruik van parameters al niet meer zo'n probleem maar als je de gegevens die door de gebruiker ergens ingevoerd zijn ook weer ergens anders toont moet je altijd HTMLEncoden. Omdat dit door een hoop mensen nog wel eens vergeten wordt staat die property natuurlijk altijd op true. Ikzelf had er eerst ook problemen mee bij een applicatie die van een 1.0 server naar een 1.1 server ging :) best lastig als opeens een hoop pagina's niet meer werken waar gewoon best html ingevoerd mag worden.
Ik encode de gegevens liever niet op het moment dat ze naar m'n database gepost worden.
Stel nl. dat die gegevens zowel door een webapplicatie en door een windows-applicatie gebruikt worden, dan zit je met die ge-encode HTML tekens op je windows-form.
Wat ik wel doe is ze HtmlEncoden op het moment dat ik ze wil tonen. Het HtmlEncoden zet ik dus in m'n presentatie-laag en op die manier heb ik ook de gegevens in de databank zitten zoals de user ze ingegeven heeft.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
whoami schreef op 19 June 2003 @ 09:30:
[...]


Ik encode de gegevens liever niet op het moment dat ze naar m'n database gepost worden.
Stel nl. dat die gegevens zowel door een webapplicatie en door een windows-applicatie gebruikt worden, dan zit je met die ge-encode HTML tekens op je windows-form.
Wat ik wel doe is ze HtmlEncoden op het moment dat ik ze wil tonen. Het HtmlEncoden zet ik dus in m'n presentatie-laag en op die manier heb ik ook de gegevens in de databank zitten zoals de user ze ingegeven heeft.
Hier heb je gelijk in. Ik heb een klein parsertje geschreven die op het moment dat de text eerst HTML encode en dan een klein aantal UBB tags parst zodat smilies werken en dikke letters enzo.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 19:05

Ik zit nu wel ff uit te zoeken hoe je het best data die je in een DataGrid toont kunt HtmlEncoden.
Data die ik in een DataList toon, encode ik als volgt:
code:
1
2
3
<asp:Label id=Label24 runat="server" 
  Text='<%# Server.HtmlEncode((string)DataBinder.Eval(Container.DataItem, "Familienaam") 
                              + " " + DataBinder.Eval(Container.DataItem, "Voornaam")) %>'>



Echter, als ik een DataGrid gebruik, dan weet ik nog niet zo goed hoe ik de data kan encoden. Ik bouw m'n dataGrids nl. als volgt op:
bv:
code:
1
2
3
4
5
6
7
DataGrid1.AutoGenerateColumns = false;
DataGrid1.DataKeyField = "ContactId";

BoundColumn bc = new BoundColumn();
bc.DataField = "Naam";

DataGrid1.Columns.Add(bc);


Hoe kan ik in bovenstaand stukje code mijn gegevens gaan encoden? :?

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 07-07 07:46

gorgi_19

Kruimeltjes zijn weer op :9

Visual Basic .NET:
1
2
3
4
5
Dim tc As New TemplateColumn()
tc.HeaderText = ""
tc.ItemTemplate = New HtlmEncodedColumn("companyname")
tc.HeaderStyle.Width = Unit.Pixel(40)
tc.ItemStyle.Width = Unit.Pixel(40)

Visual Basic .NET:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
    Public Class HtlmEncodedColumn
        Implements ITemplate
        Private _column As String
        Private _datafield As String = ""

        Public Event DataBinding As EventHandler

        Public Sub New(ByVal column As String)
            _column = column
        End Sub

        Public Sub InstantiateIn(ByVal container As Control) Implements ITemplate.InstantiateIn
            Dim l As Label = New Label()
            AddHandler l.DataBinding, AddressOf BindData
            container.Controls.Add(l)
        End Sub

        Public Sub BindData(ByVal sender As Object, ByVal e As EventArgs)

            Dim l As Label = CType(sender, Label)
            Dim container As DataGridItem = CType(l.NamingContainer, DataGridItem)
            Dim data As String = CType(container.DataItem, DataRowView)(_column).ToString()
            l.Text = HttpContext.Current.Server.HtmlEncode(data)

        End Sub

    End Class 'checkboxColumn

Zo bijvoorbeeld? Ik denk dat de code op zich wel voor zichzelf spreekt. :) In principe maak je een custom column aan. Oftewel je maakt een eigen class, welke ITemplate implementeert. Vervolgens kan je deze gebruiken als TemplateColumn

[ Voor 33% gewijzigd door gorgi_19 op 19-06-2003 10:40 ]

Digitaal onderwijsmateriaal, leermateriaal voor hbo


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 19:05
Ik heb net een oplossing gevonden:

In de ItemDataBound event van m'n DataGrid kan ik de text gaan encoden. Die event wordt nl. voor iedere keer getriggered als er een Item 'gebinded' wordt:
code:
1
2
3
4
5
private void DataGrid1_ItemDataBound(object sender, 
                                     System.Web.UI.WebControls.DataGridItemEventArgs e)
{           
  e.Item.Cells[0].Text = Server.HtmlEncode(Convert.ToString(e.Item.Cells[0].Text));
}


Mja, die oplossing van jou gorgi_19 is natuurlijk ook wel mooi. 'k Ga er es ff mee spelen...

[ Voor 10% gewijzigd door whoami op 19-06-2003 10:45 ]

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • Rhapsody
  • Registratie: Oktober 2002
  • Laatst online: 00:32

Rhapsody

In Metal We Trust

ik denk dat whoami de viewstate van controls zelf bedoeld.
Dus dat je per control aangeeft of de viewstate wel of niet aanmoet staan.

Dat kan erg veel schelen ja (zeker als ik in de bron kijk van de output)

🇪🇺 pro Europa! | Puinhoop Veroorzaken en Vertrekken (PVV)


Acties:
  • 0 Henk 'm!

  • EfBe
  • Registratie: Januari 2000
  • Niet online
"Gebruik stored procedures".

Nou, gebruik parametrized queries. Op sqlserver en elke andere database met een goede optimizer, zijn parametrized queries even snel als stored procedures. Soms zijn dynamische parametrized queries zelfs te prefereren, want je kunt flexibel omgaan met wat je wilt doen, ipv een hele serie stored procs te maken.

MS heeft een aantal application blocks gereleased die helpen bij bv caching, exception handling etc. Hier een link naar een lijstje met alle blocks:
http://weblogs.asp.net/sbchatterjee/posts/8883.aspx

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


Acties:
  • 0 Henk 'm!

  • Scharnout
  • Registratie: November 2000
  • Laatst online: 10-04-2024

Scharnout

Meuk

Mijn nederige bijdrage:

Omdat ik in Mozilla werk en mijn pagina' s ook daarin bekijk en test, vond ik het nogal irri dat hij de html niet goed renderde. En idd MS zou MS niet zijn als de default niet proMS stond (NOFI). Dus met onderstaand in je web.config ben je wat vriendelijker voor de gebruiker:

code:
1
2
3
4
5
<configuration>
  <system.web>
    <browserCaps>tagwriter=System.Web.UI.HtmlTextWriter</browserCaps>
  </system.web>
</configuration>


Geen idee wat het verder met je performance of veiligheid zou doen, maar mozilla werkt een stuk lekkerder :)

[ Voor 8% gewijzigd door Scharnout op 19-06-2003 12:53 ]

And Bob's your uncle ...


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 19:05
EfBe schreef op 19 juni 2003 @ 12:49:
"Gebruik stored procedures".

Nou, gebruik parametrized queries. Op sqlserver en elke andere database met een goede optimizer, zijn parametrized queries even snel als stored procedures. Soms zijn dynamische parametrized queries zelfs te prefereren, want je kunt flexibel omgaan met wat je wilt doen, ipv een hele serie stored procs te maken.
Een query zal toch iedere keer weer opnieuw moeten geprepared en geparsed worden, terwijl dat bij een SP toch het geval niet is?
Verder kan je ook "dynamische" queries in je SP kwijt:

code:
1
2
3
4
5
6
7
8
9
10
CREATE PROCEDURE myProc ( @p_naam   VARCHAR(50),
                          @p_Voornaam    VARCHAR(50))
AS
BEGIN

  SELECT * FROM tblPersons
  WHERE tblPersons.Naam = ISNULL(@p_naam, tblPersons.Naam)
  AND  tblPersons.Voornaam = ISNULL(@p_Voornaam, tblPersons.Voornaam)

END;


Ik zie dat je op je blog daar ook een stukje over staan hebt. 'k Moet dat ook nog es lezen.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • EfBe
  • Registratie: Januari 2000
  • Niet online
Nee de execution plans worden gecached. Doe maar eens een benchmark, je krijgt dezelfde executiontimes eruit :)

Die dynamische query die jij weergeeft is traag. (kan beter met COALESCE() btw). Zie:
http://weblogs.asp.net/fbouma/posts/7008.aspx en voor de testcode: http://weblogs.asp.net/fbouma/story/7049.aspx .

Maar ik snap je gedachtengang erachter: t.a.t. vermijdt sql string concatenaties en probeer ook zoveel mogelijk sql statements te vermijden in ASP.NET (i.e. gui code).

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


Acties:
  • 0 Henk 'm!

  • EfBe
  • Registratie: Januari 2000
  • Niet online
Nog een tip over validation controls en een common trap waar je in kunt vallen (engels) : http://weblogs.asp.net/sibrahim/posts/8723.aspx

Microsoft's gratis ASP.NET editor, web matrix heeft een nieuwe versie sinds afgelopen maandag: http://asp.net/WebMatrix/

Er waren een maand geleden wat blogs over wat meer advanced ASP.NET technieken zoals custom HttpHandlers en andere leuke dingen, die kan ik zo 1 2 3 niet terugvinden.

[ Voor 26% gewijzigd door EfBe op 19-06-2003 13:23 ]

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 19:05
EfBe schreef op 19 June 2003 @ 13:10:
Die dynamische query die jij weergeeft is traag. (kan beter met COALESCE() btw). Zie:
http://weblogs.asp.net/fbouma/posts/7008.aspx en voor de testcode: http://weblogs.asp.net/fbouma/story/7049.aspx .

Maar ik snap je gedachtengang erachter: t.a.t. vermijdt sql string concatenaties en probeer ook zoveel mogelijk sql statements te vermijden in ASP.NET (i.e. gui code).
Zeer interessant, en eigenlijk ben ik wel verwonderd over de resultaten.

Het beste -op performance gebied dan- zou eigenlijk zijn dat je zowel gebruik maakt van dynamic queries en stored procedures.
Als je queries hebt die op geen enkel moment 'dynamisch' moeten zijn, en INSERT/UPDATE/DELETE statements kan je in Stored Procedures kwijt.
Het opbouwen van dynamische queries kan je dan op de client kwijt. (In je DAL layer).

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 19:05
Nog iets over die dynamic queries.

Die query met die ISNULL of COALESCE is gewoon traag omdat die functie in de WHERE clause staat vermoed ik.
Je kan je query toch ook dynamisch opbouwen in je stored procedure? Ik ben benieuwd wat het verschil in performance dan zal zijn ivgl met een dynamisch opgebouwde query in je C# code.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • EfBe
  • Registratie: Januari 2000
  • Niet online
Dynamisch opbouwen in je stored procedure vernaggeld je execution plan, plus string concatenation is niet de sterkste kant van sql :)

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


Acties:
  • 0 Henk 'm!

Anoniem: 58296

En nog een simpele: Zet errors uit :)
Ik vind het beste dat je gewoon een database of een xml bestand maakt en daar alle urls die errors geven (met indien mogelijk extra info) opslaat en de gebruiker enkel een simpel errortje geeft (bv Fout opgetreden, klik hier om naar startpagina te gaan...).

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 19:05
Anoniem: 58296 schreef op 19 juni 2003 @ 21:12:
En nog een simpele: Zet errors uit :)
Ik vind het beste dat je gewoon een database of een xml bestand maakt en daar alle urls die errors geven (met indien mogelijk extra info) opslaat en de gebruiker enkel een simpel errortje geeft (bv Fout opgetreden, klik hier om naar startpagina te gaan...).
Echt gebruiksvriendelijk is dat niet he.
Als jij gewoon zegt: er is een fout opgetreden, dan staat de user mooi voor jan lul.

Als je nu nog eens zou zeggen wat er gebeurd is, hoe hij het kan voorkomen, of het aan hem ligt of niet, etc.... Dat zou al heel wat beter zijn.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 07-07 07:46

gorgi_19

Kruimeltjes zijn weer op :9

whoami schreef op 19 juni 2003 @ 21:20:
[...]


Echt gebruiksvriendelijk is dat niet he.
Als jij gewoon zegt: er is een fout opgetreden, dan staat de user mooi voor jan lul.

Als je nu nog eens zou zeggen wat er gebeurd is, hoe hij het kan voorkomen, of het aan hem ligt of niet, etc.... Dat zou al heel wat beter zijn.
Exceptions mogen imho wel zo opgevangen worden, met de melding van:
"Er is iets fout gegaan, probeer het later nog eens".

Standaard foutmeldingen, by default, kunnen opgevangen worden, bijvoorbeeld door validator controls.

Digitaal onderwijsmateriaal, leermateriaal voor hbo


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 19:05
Ik zeg niet dat je standaard foutmeldingen moet tonen, of dat je geen exceptions mag opvangen.
Ik zeg gewoon dat je wel met een wat uitgebreidere foutmelding mag komen ipv 'er is iets fout gegaan'.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 07-07 07:46

gorgi_19

Kruimeltjes zijn weer op :9

whoami schreef op 19 juni 2003 @ 21:30:
Ik zeg niet dat je standaard foutmeldingen moet tonen, of dat je geen exceptions mag opvangen.
Ik zeg gewoon dat je wel met een wat uitgebreidere foutmelding mag komen ipv 'er is iets fout gegaan'.
Unhandled exceptions mogen niet getoond worden (imho). Dan is er iets goed fout gegaan en mag een standaard foutmelding (welke normaliter toch niet hoort voor te komen) getoond worden.

De ontwikkelaar heeft dan een fout achtergelaten; hij moet deze wel kunnen terugvinden in de errorlog. Verder heeft de gebruiker niets met de exception te maken. Hiermee is dan ook voldoende informatie voor de bezoeker: "Er is iets fout gegaan"

Handled exceptions / andere foutmeldingen horen wel gewoon een net iets aan de user weer te geven....

(als verduidelijking op m'n vorige post.. ;))

Digitaal onderwijsmateriaal, leermateriaal voor hbo


Acties:
  • 0 Henk 'm!

  • Rhapsody
  • Registratie: Oktober 2002
  • Laatst online: 00:32

Rhapsody

In Metal We Trust

nog een tippie:

gebruik ook zo min mogelijk postbacks, soms kunnen handelingen ook met javascript afgehandeld worden, en dat scheelt weer tijd voor de gebruiker.

🇪🇺 pro Europa! | Puinhoop Veroorzaken en Vertrekken (PVV)


Acties:
  • 0 Henk 'm!

  • simon
  • Registratie: Maart 2002
  • Laatst online: 23:16
Rhapsody schreef op 19 June 2003 @ 21:45:
nog een tippie:

gebruik ook zo min mogelijk postbacks, soms kunnen handelingen ook met javascript afgehandeld worden, en dat scheelt weer tijd voor de gebruiker.
Dat lijkt me niet zo slim, want dat is client sided, en ik zelf vind: zo min mogelijk client sided..

|>


Acties:
  • 0 Henk 'm!

  • Rhapsody
  • Registratie: Oktober 2002
  • Laatst online: 00:32

Rhapsody

In Metal We Trust

maar elke keer een postback uitvoeren is langzamer, en als het gaat om gebruiksvriendelijkheid......

Bijvoorbeeld controls verbergen, dat kan makkelijk met javascript.


maar waarom zo min mogelijk clientside?

🇪🇺 pro Europa! | Puinhoop Veroorzaken en Vertrekken (PVV)


Acties:
  • 0 Henk 'm!

  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 07-07 07:46

gorgi_19

Kruimeltjes zijn weer op :9

Simon schreef op 19 June 2003 @ 21:47:
[...]

Dat lijkt me niet zo slim, want dat is client sided, en ik zelf vind: zo min mogelijk client sided..
Erhm.. Want? Als je zaken toch uiteindelijk als batch gaat updaten, kan je net zo goed zaken clientside oplossen. Om voor alles een postback te doen, wordt je ook niet vrolijk van.

Zo kan je bij OnChange van een textbox in een aantal gevallen net zo goed client side javascript gebruiken ipv een postback.
Rhapsody schreef op 19 June 2003 @ 21:50:
maar elke keer een postback uitvoeren is langzamer, en als het gaat om gebruiksvriendelijkheid......

Bijvoorbeeld controls verbergen, dat kan makkelijk met javascript.
UserControls en Panels zijn nu net zaken welke ik niet clientside wil verbergen.. ;)

[ Voor 26% gewijzigd door gorgi_19 op 19-06-2003 21:54 ]

Digitaal onderwijsmateriaal, leermateriaal voor hbo


Acties:
  • 0 Henk 'm!

  • Rhapsody
  • Registratie: Oktober 2002
  • Laatst online: 00:32

Rhapsody

In Metal We Trust

ik ga maar een voorbeeldje he.
voorbeeld wat jij noemt gebruik ik ook.

🇪🇺 pro Europa! | Puinhoop Veroorzaken en Vertrekken (PVV)


Acties:
  • 0 Henk 'm!

  • Ramon
  • Registratie: Juli 2000
  • Laatst online: 22:03
Scharnout schreef op 19 June 2003 @ 12:52:
Mijn nederige bijdrage:

Omdat ik in Mozilla werk en mijn pagina' s ook daarin bekijk en test, vond ik het nogal irri dat hij de html niet goed renderde. En idd MS zou MS niet zijn als de default niet proMS stond (NOFI). Dus met onderstaand in je web.config ben je wat vriendelijker voor de gebruiker:

code:
1
2
3
4
5
<configuration>
  <system.web>
    <browserCaps>tagwriter=System.Web.UI.HtmlTextWriter</browserCaps>
  </system.web>
</configuration>


Geen idee wat het verder met je performance of veiligheid zou doen, maar mozilla werkt een stuk lekkerder :)
wat is het effect hiervan dan?

Check mijn V&A ads: https://tweakers.net/aanbod/user/9258/


Acties:
  • 0 Henk 'm!

  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 07-07 07:46

gorgi_19

Kruimeltjes zijn weer op :9

Tampie schreef op 19 juni 2003 @ 22:10:
[...]

wat is het effect hiervan dan?
We're using ASP.NET and targetting HTML 4.01 and CSS. The browser detection code in ASP.NET detects recent versions of Netscape as being down-level browsers, so the controls will render HTML 3.2 with all the nasty inline stuff like <font> tags.

ASP.NET:
1
2
3
4
5
6
<browserCaps>
  <result type="System.Web.HttpBrowserCapabilities, System.Web, 
Version=1.0.3102.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
  <use var="HTTP_USER_AGENT" />
  TagWriter=System.Web.UI.HtmlTextWriter
</browserCaps>


That forces ASP.NET to render HTML 4.0 always, regardless of the browser. This was the right choice for us, but might not be for everybody; if you want to be selective about it, you could write a more elaborate browserCaps section which detects only Netscape 6.x or 7 or Mozilla 1.0 or whatever you're after, and tell it just to use HTML 4.0 for that.

I haven't run across any of the built-in controls that are IE specific. Some are more annoying than others (I can't find a way to make the Calendar control render without adding tons of "style=" onto everything, for example), but everything works fine. What you'll want to be careful about is the Microsoft add-on controls, some of which DO specifically target IE.

[ Voor 58% gewijzigd door gorgi_19 op 19-06-2003 22:13 ]

Digitaal onderwijsmateriaal, leermateriaal voor hbo


Acties:
  • 0 Henk 'm!

  • Scharnout
  • Registratie: November 2000
  • Laatst online: 10-04-2024

Scharnout

Meuk

Ik was, dacht ik, bezig met wat buttons dynamisch toe te voegen met een cssClass. Stomme alleen was dat die dingen in Mozilla niet te voorschijn kwamen. Toen ik heb diep verborgen in Google dit gevonden en hiermee geeft hij alles weer in html4.01 anders doet hij in mozilla html3.2 proberen. En die versie werkt niet zo lekker met css :)

edit:

ik lees net dat ik het goed onthouden hebt :)

[ Voor 9% gewijzigd door Scharnout op 19-06-2003 22:15 ]

And Bob's your uncle ...


Acties:
  • 0 Henk 'm!

  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 07-07 07:46

gorgi_19

Kruimeltjes zijn weer op :9

Scharnout schreef op 19 June 2003 @ 22:13:
Ik was, dacht ik, bezig met wat buttons dynamisch toe te voegen met een cssClass. Stomme alleen was dat die dingen in Mozilla niet te voorschijn kwamen. Toen ik heb diep verborgen in Google dit gevonden en hiermee geeft hij alles weer in html4.01 anders doet hij in mozilla html3.2 proberen. En die versie werkt niet zo lekker met css :)

edit:

ik lees net dat ik het goed onthouden hebt :)
Wat achtergrondinformatie is trouwens te vinden in:
http://www.asp.net/Forums...x?tabindex=1&PostID=86795

Voor wat oplossingen, met uitleg er bij...
http://www.asp.net/Forums...?tabindex=1&PostID=192882
http://www.asp.net/Forums...x?tabindex=1&PostID=89874

Digitaal onderwijsmateriaal, leermateriaal voor hbo


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 19:05
* whoami schopt en kijk rond en dacht dat er hier wel meerdere mensen zaten die met ASP.NET bezig zijn...

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

Anoniem: 72194

Maak er anders een sticky van.
Kunne we is iets toevoegen nadat we dagen hebben zitten sukkelen op een probleem en dan de oplossing hebben gevonden!

Acties:
  • 0 Henk 'm!

Anoniem: 58296

gorgi_19 schreef op 19 June 2003 @ 21:36:
[...]

Unhandled exceptions mogen niet getoond worden (imho). Dan is er iets goed fout gegaan en mag een standaard foutmelding (welke normaliter toch niet hoort voor te komen) getoond worden.

De ontwikkelaar heeft dan een fout achtergelaten; hij moet deze wel kunnen terugvinden in de errorlog. Verder heeft de gebruiker niets met de exception te maken. Hiermee is dan ook voldoende informatie voor de bezoeker: "Er is iets fout gegaan"

Handled exceptions / andere foutmeldingen horen wel gewoon een net iets aan de user weer te geven....

(als verduidelijking op m'n vorige post.. ;))
Gorgi is right :)

Stel dat er ergens een unhandled exception is in je sql en je zou de error tonen aan de gebruiker dan zou die wel eens security holes kunnen ontdekken en dan ben je de pineut :o
Errors mogen alleen meegegeven worden bij unhandled exceptions anderzijds...
Stel dat je de gebruiker zou kunnen zeggen wat hij moet doen dan wil dat zeggen dat jij opzettelijk een fout in je code hebt staan EN dat je weet hoe je ze oplost... afgang dus :D
Een 404, 403, enzo zijn natuurlijk andere dingen

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 19:05
Tuurlijk mogen unhandled exceptions niet zo getoond worden etc.
Ik zeg alleen dat je -als het kan- wel wat meer info mag geven ipv gewoon 'er is iets fout gegaan.'.

En nu misschien verder ontopic. ;)

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 07-07 07:46

gorgi_19

Kruimeltjes zijn weer op :9

Aangezien we toch bij de datalaag waren aangekomen.. ;)

Bij het bestuderen van een aantal applicaties ben ik onder andere een hele flexibele methodiek tegen gekomen om een datalaag te creeeren. Je kan op deze manier heel makkelijk switchen tussen bijvoorbeeld MySQL, Access of SQL Server als back-end. Je hoeft alleen de SP's / SQL statements te vervangen.

In je web.config geef je de assembly aan waarin alle SQL Statements zich bevinden. Per Assembly staat dit voor 1 database. Je hebt dus bijvoorbeeld ProSim.SqlDataProvider.dll, ProSim.MySQLDataprovider, etc.

In deze dll staat steeds 1 class, met hierin alle SQL Statements. De overeenkomst tussen al deze assemblies is dat ze allemaal dezelfde Interface implementeren.

Voor zover de voorbereiding. Nu is er nog 1 class welke de juiste assembly ophaalt, aan de hand van de gegevens uit de web.config, en vervolgens als returnwaarde de interface heeft. Iedere class heeft deze immers geimplementeerd.

Hierdoor kan je heel snel en eenvoudiger meerdere databases ondersteunen, zonder ook maar een regel code te wijzigen in de rest van je applicatie.

Is het niet trager, om steeds de boel op te halen? Ja, maar daarvoor kan je het caching object misbruiken en hier de data in op slaan. Tuurlijk zal er wel enig performance verlies zijn, maar deze is niet groot aanwezig.

Om het eea wat minder abstract te maken (voor de volledigheid: onderstaande code is een vertaling en aanpassing van de aspnetForums, van oa. Rob Howard en Justin Rogers)
ASP.NET:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
   Public Class DataProvider

        '/ <summary>
        '/ Returns an instance of the user-specified data provider class.
        '/ </summary>
        '/ <returns>An instance of the user-specified data provider class.  This class must inherit the
        '/ IDataProvider interface.</returns>
        Public Shared Function Instance() As IDataProvider

            'use the cache because the reflection used later is expensive
            Dim cache As System.Web.Caching.Cache = System.Web.HttpContext.Current.Cache
            If cache("IDataProvider") Is Nothing Then
                'get the assembly path and class name from web.config
                Dim prefix As String = ""
                Dim _context As NameValueCollection = CType(ConfigurationSettings.GetConfig("ProSimSettings"), NameValueCollection)
                If _context Is Nothing Then
                    ' get the appSettings context
                    prefix = "ProSimSettings."
                    _context = CType(ConfigurationSettings.GetConfig("appSettings"), NameValueCollection)
                End If

                Dim assemblyPath As String = _context((prefix + "DataProviderAssemblyPath"))
                Dim className As String = _context((prefix + "DataProviderClassName"))

                assemblyPath = HttpContext.Current.Server.MapPath((HttpContext.Current.Request.ApplicationPath & _
 "/bin/" + assemblyPath))

                Try
                    cache.Insert("IDataProvider", [Assembly].LoadFrom(assemblyPath).GetType(className).GetConstructor(Type.EmptyTypes), New CacheDependency(assemblyPath))
                Catch
                    HttpContext.Current.Response.Write("<b>ERROR:</b> Could not " &_ 
"locate file: <code>" + assemblyPath + "</code> or could not locate class <code>" + className + "</code> in file.")
                    HttpContext.Current.Response.End()
                End Try
            End If ' could not locate DLL file

            Return CType(CType(cache("IDataProvider"), ConstructorInfo).Invoke(Nothing), IDataProvider)
        End Function 'Instance

    End Class 'DataProvider


Vervolgens heb je de interface
Visual Basic .NET:
1
2
3
4
5
  Public Interface IDataProvider

        Function GetGameID(ByVal UserID As Integer) As Integer

  End interface


En als laatste een, in dit geval, SQLDataProvider class

ASP:
1
2
3
4
5
...
Public Function GetGameID(ByVal userid As Integer) As Integer Implements IDataProvider.GetGameID
    return 1

End Function


Persoonlijk vind ik dit wel een redelijke flexibele manier van werken. Het is wat meer werk, zeker in het begin, maar het biedt imho ook wel duidelijk voordelen.

[ Voor 22% gewijzigd door gorgi_19 op 22-06-2003 22:38 ]

Digitaal onderwijsmateriaal, leermateriaal voor hbo


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 19:05
Is het dan niet mooier als je een aantal 'DbHelper' classes maakt, die allen dezelfde interface implementeren of van dezelfde base-class inheriten?

In je code schrijf je dan een functie die bv in de web.config een key gaat gaan ophalen waarin het type database staat dat dit project gebruikt. Adhv die waarde maak je creeër je een bepaalde factory, en die factory gebruik je dan telkens om het juiste DbHelper object te creeëren.

(Klinkt misschien vaag, als ik ff tijd heb dan illustreer ik dit wel ff met een voorbeeldje).

Op MSDN heb ik ook nog een artikel gevonden waarin je een flexibele DAL zou kunnen mee bouwen. Ik heb het al eens vluchtig gelezen, maar zou het toch nog ff van dichter moeten bekijken:
Dynamically Bind Your Data Layer to Stored Procedures and SQL Commands Using .NET Metadata and Reflection

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 07-07 07:46

gorgi_19

Kruimeltjes zijn weer op :9

whoami schreef op 22 June 2003 @ 22:42:
Is het dan niet mooier als je een aantal 'DbHelper' classes maakt, die allen dezelfde interface implementeren of van dezelfde base-class inheriten?

In je code schrijf je dan een functie die bv in de web.config een key gaat gaan ophalen waarin het type database staat dat dit project gebruikt. Adhv die waarde maak je creeër je een bepaalde factory, en die factory gebruik je dan telkens om het juiste DbHelper object te creeëren.

(Klinkt misschien vaag, als ik ff tijd heb dan illustreer ik dit wel ff met een voorbeeldje).

Op MSDN heb ik ook nog een artikel gevonden waarin je een flexibele DAL zou kunnen mee bouwen. Ik heb het al eens vluchtig gelezen, maar zou het toch nog ff van dichter moeten bekijken:
Dynamically Bind Your Data Layer to Stored Procedures and SQL Commands Using .NET Metadata and Reflection
Ik heb zo een vaag vermoeden dat deze het code hetzelfde doet.....

In mijn web.config geef ik nu namelijk aan:
XML:
1
2
3
4
<ProSimSettings>
<add key="DataProviderClassName" value="ProSim.Data.SqlDataProvider" />
<add key="DataProviderAssemblyPath" value="ProSim.Data.SqlDataProvider.dll" />
</ProSimSettings>

Waardoor je dus ongeveer hetzelfde effect bereikt...
De SQL Dataprovider implementeert ook de interface, zet zoals eventuele andere dataprovider classes.

* gorgi_19 gaat iig het artikel nog even doorlezen...

[ Voor 21% gewijzigd door gorgi_19 op 22-06-2003 22:48 ]

Digitaal onderwijsmateriaal, leermateriaal voor hbo


Acties:
  • 0 Henk 'm!

  • MrHighStone
  • Registratie: November 2001
  • Laatst online: 03-02-2023
Tipje voor een ieder die met een ASP.NET app wil beginnen, of zelf een site'je wil opzetten. Kijk een naar de IBuySpy Poral site, bekijk de architectuur eens en zie hoe eenvoudig het is om met user controls te werken.
IBuySpy is opgezet door MS als showcase. Voor iemand die begint met een ASP.NET web app denk ik dat deze architectuur leerzaam kan zijn (hoewel ie verre van perfect is).

Ook het gebruik van user controls spreekt mij persoonlijk erg aan, heel eenvoudig om controls die je vaker gebruikt te kunnen maken en onderhouden op een plek. Werkt handiger dan het gebruik van includes in bv PHP of ColdFusion.

Ik kom zelf meer uit de webapp hoek, dan uit de winapp hoek, dus wat mij opvalt aan ASP.NET zijn de zaken die volgens mij voor winapps al lang gebruikelijk waren. Onder andere het gebruik van panels om bepaalde (samenhangende) controls zichtbaar/onzichtbaar te maken.
Gevaar hierbij is denk ik wel dat je te veel functionaliteit in de user controls gaat stoppen door enkel panel visibility te beinvloeden...

Een file op de A12 is nooit grappig...


Acties:
  • 0 Henk 'm!

  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 07-07 07:46

gorgi_19

Kruimeltjes zijn weer op :9

MrHighStone schreef op 23 June 2003 @ 10:44:
Tipje voor een ieder die met een ASP.NET app wil beginnen, of zelf een site'je wil opzetten. Kijk een naar de IBuySpy Poral site, bekijk de architectuur eens en zie hoe eenvoudig het is om met user controls te werken.
IBuySpy is opgezet door MS als showcase. Voor iemand die begint met een ASP.NET web app denk ik dat deze architectuur leerzaam kan zijn (hoewel ie verre van perfect is).
Om heel eerlijk te zijn vindt ik dat IBuySpy ontzettend ranzig is gebouwd. De methodiek om zo met usercontrols te werken vindt ik dat je nu vrij gebonden zit; beter lijkt het mij om met templates te werken, zoals het gaan is met ASPNetForums.

Ook de datalaag vind ik vrij slecht opgezet; deze is imho wel stukken efficienter te bouwen. Als voorbeeldapplicatie wat je met ASP.Net, kijken hoe alles een beetje werkt, is het leuk. Als echt voorbeeld voor een goede structuur is het volstrekt ongeschikt, imho.
Daar kan natuurlijk bijkomen dat ik niet zo een fan ben van usercontrols icm de bijbehorende codebehind. Ik ben meer fan van een dynamische control, welke een template laadt, waarbij deze template geen code-behind heeft.

Verder geef je aan van panels en dynamisch controls. Dit vind ik een van de zwakkere zaken in ASP.Net. Als je een control verwijderd, en vervolgens in dezelfde context eentje toevoegd, krijgt deze bijvoorbeeld als nummer 3. Echter, bij een postback en het herbouwen van de pagina, vindt deze verwijdering niet plaats en krijg je dus de nummer 2. Hierdoor komt de viewstate van de controls niet meer overeen (de UniqueID is immers verschillend) en kan je hele vreemde effecten krijgen.

De reden is dat de controlcollection een control bij nummering wel met eentje toevoegd, maar niet met eentje verminderd bij het verwijderen. Ik ben hier een hele tijd mee bezig geweest; de enige oplossing voor mij was de UniqueKey property te overriden en zelf een ID te genereren.
Tip: Voeg dus, tenzij je weet waar je mee bezig bent, niet dynamisch controls toe en verwijder ze later.

Digitaal onderwijsmateriaal, leermateriaal voor hbo


Acties:
  • 0 Henk 'm!

  • MrHighStone
  • Registratie: November 2001
  • Laatst online: 03-02-2023
Zoals ik zei, verre van perfect, maar goed genoeg om een idee op te doen van de mogelijkheden.
In de categorie dynamische usercontrols en dynamsche webcontrols, begrijp ik dat jij een dynamisch persoon bent ;)

Ik ken de code achter ASPNetForums niet goed genoeg om het principe van dynamische controls te begrijpen. Kan me in jouw geval voorstellen dat eea met de viewstate niet helemaal lekker loopt, goed om te onthouden.
Waarschijnlijk doordat ik meer uit de webapp hoek komt, heb ik er nooit bij stilgestaan om dynamisch controls toe te voegen (het leek mij in eerste instantie dat je dan minder controle hebt over de plaatsing/layout van de app), maar ik wijzigde dan gewoon de visibility properties van de controls of panels.

Btw, het praat lekker verwarrend over verschillende controls he! :?

Misschien een leuke waar ik vanochtend aan dacht. Stel dat:
Men wil een overzicht (datalist) op het scherm van producten, daarbij een view knop waarmee men productgegevens kan inzien en wijzigen, maar niet inline (dus mbv een selectedItemTemplate). In plaats daarvan wil men een 'leeg en overzichtelijk' scherm met enkel de productdetails die je dan kunt inzien, wijzigen, en vervolgens opslaan.

Nou leek mij het handig om voor deze productdetails page toch een datalist te gebruiken, met een ItemTemplate (om de productdetails in te zien) en een EditItemTemplate (om productdetails te wijzigen), ondanks dat je slechts telkens een record aan het inzien/bijwerken bent.
Het voordeel hierbij is dan dat je niet zelf de view/edit state steeds hoeft bij te houden en de bijbehorende controls te wijzigen e.d.

En nu ik dit allemaal heb opgetypt zie ik geloof ik het voordeel van de dynamische control, zoals jij hierboven bedoelde... 8)

Een file op de A12 is nooit grappig...


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 19:05
MrHighStone schreef op 24 June 2003 @ 11:50:
Misschien een leuke waar ik vanochtend aan dacht. Stel dat:
Men wil een overzicht (datalist) op het scherm van producten, daarbij een view knop waarmee men productgegevens kan inzien en wijzigen, maar niet inline (dus mbv een selectedItemTemplate). In plaats daarvan wil men een 'leeg en overzichtelijk' scherm met enkel de productdetails die je dan kunt inzien, wijzigen, en vervolgens opslaan.

Nou leek mij het handig om voor deze productdetails page toch een datalist te gebruiken, met een ItemTemplate (om de productdetails in te zien) en een EditItemTemplate (om productdetails te wijzigen), ondanks dat je slechts telkens een record aan het inzien/bijwerken bent.
Het voordeel hierbij is dan dat je niet zelf de view/edit state steeds hoeft bij te houden en de bijbehorende controls te wijzigen e.d.
Waarom toon je die productdetails dan niet op een andere page als je toch maar de details van 1 product wilt tonen?

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 07-07 07:46

gorgi_19

Kruimeltjes zijn weer op :9

MrHighStone schreef op 24 June 2003 @ 11:50:
Zoals ik zei, verre van perfect, maar goed genoeg om een idee op te doen van de mogelijkheden.
In de categorie dynamische usercontrols en dynamsche webcontrols, begrijp ik dat jij een dynamisch persoon bent ;)
In tegendeel.. Ik heb een schurfthekel aan .ascx bestanden met codebehind, omdat ze me juiste niet dynamisch genoeg zijn.. ;) Ik maak zelf vrij intensief gebruik van custom controls, welke afgeleid zijn van Usercontrol class.
.ascx bestanden zijn nuttig als template, echter moet je er imho geen code-behind bij gebruiken, tenzij je snel 'drag&drop' wilt doen.
Waarschijnlijk doordat ik meer uit de webapp hoek komt, heb ik er nooit bij stilgestaan om dynamisch controls toe te voegen (het leek mij in eerste instantie dat je dan minder controle hebt over de plaatsing/layout van de app), maar ik wijzigde dan gewoon de visibility properties van de controls of panels.
Jups, eerst ook gedaan. Via een observer, netjes alles toevoegen en op invisible zetten. Echter, ik moet wel steeds alle objecten aanmaken, terwijl ik ze helemaal niet nodig heb. Door alleen de objecten aan te maken welke ik nodig heb, heb ik dat probleem niet.
Misschien een leuke waar ik vanochtend aan dacht. Stel dat:
Men wil een overzicht (datalist) op het scherm van producten, daarbij een view knop waarmee men productgegevens kan inzien en wijzigen, maar niet inline (dus mbv een selectedItemTemplate). In plaats daarvan wil men een 'leeg en overzichtelijk' scherm met enkel de productdetails die je dan kunt inzien, wijzigen, en vervolgens opslaan.
Zoek eens op Master/Detail grid. Dingen bestaan al, zijn al een aantal tutorials over geschreven.. ;)
Nou leek mij het handig om voor deze productdetails page toch een datalist te gebruiken, met een ItemTemplate (om de productdetails in te zien) en een EditItemTemplate (om productdetails te wijzigen), ondanks dat je slechts telkens een record aan het inzien/bijwerken bent.
Het voordeel hierbij is dan dat je niet zelf de view/edit state steeds hoeft bij te houden en de bijbehorende controls te wijzigen e.d.
Mja.. In dit geval kan je net zo goed ook een nieuwe pagina gebruiken.. ;)

[ Voor 4% gewijzigd door gorgi_19 op 24-06-2003 12:11 ]

Digitaal onderwijsmateriaal, leermateriaal voor hbo


Acties:
  • 0 Henk 'm!

  • MrHighStone
  • Registratie: November 2001
  • Laatst online: 03-02-2023
Was ook het plan, maar ben ik vergeten te vermelden (mijn hoofd was aan het multitasken: bovenstaand verhaal intypen en nadenken over een dynamisch verhaal)...
Lees dus voor een 'leeg overzichtelijk scherm' een nieuwe page.
Maar dan nog blijft de vraag staan, is het dan handig om voor de view/edit wisselwerking gebruik te maken van de datalist mogelijkheden?
Het voordeel hiervan is dan dat je enkel de ItemTemplate en EditItemTemplates hoeft aan te passen, en de buttons hun werk te laten doen, zonder dat je je verder druk hoeft te maken overde de (on)zichtbaarheid van de view/edit controls, afhankelijk van het feit of je de details wilt bekijken, dan wel bewerken.

Een file op de A12 is nooit grappig...


Acties:
  • 0 Henk 'm!

  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 07-07 07:46

gorgi_19

Kruimeltjes zijn weer op :9

MrHighStone schreef op 24 juni 2003 @ 14:02:
Was ook het plan, maar ben ik vergeten te vermelden (mijn hoofd was aan het multitasken: bovenstaand verhaal intypen en nadenken over een dynamisch verhaal)...
Lees dus voor een 'leeg overzichtelijk scherm' een nieuwe page.
Maar dan nog blijft de vraag staan, is het dan handig om voor de view/edit wisselwerking gebruik te maken van de datalist mogelijkheden?
Het voordeel hiervan is dan dat je enkel de ItemTemplate en EditItemTemplates hoeft aan te passen, en de buttons hun werk te laten doen, zonder dat je je verder druk hoeft te maken overde de (on)zichtbaarheid van de view/edit controls, afhankelijk van het feit of je de details wilt bekijken, dan wel bewerken.
Dat is per situatie verschillend, is geen eenduidig antwoord op te geven. Soms is het beter om het in een aparte pagina te doen, soms inline.

Digitaal onderwijsmateriaal, leermateriaal voor hbo


Acties:
  • 0 Henk 'm!

  • MrHighStone
  • Registratie: November 2001
  • Laatst online: 03-02-2023
Heb het idee dat mijn vraag niet helemaal duidelijk over komt.
Probeer het nog een keer:
De insteek is een datalist te gebruiken om de details van een record te inzien/bewerken, ook al is het altijd maar een record dat je inziet/bewerkt.
Dit om eenvoudig gebruik te kunnen maken van de itemtemplate en edititemtemplates van de datalist componenten, inplaats van twee verschillende 'states' bij te houden waarin de controls worden geenabeld/gedisabled ivm datainvoer...

Een file op de A12 is nooit grappig...


Acties:
  • 0 Henk 'm!

  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 07-07 07:46

gorgi_19

Kruimeltjes zijn weer op :9

MrHighStone schreef op 25 juni 2003 @ 13:11:
Heb het idee dat mijn vraag niet helemaal duidelijk over komt.
Probeer het nog een keer:
De insteek is een datalist te gebruiken om de details van een record te inzien/bewerken, ook al is het altijd maar een record dat je inziet/bewerkt.
Dit om eenvoudig gebruik te kunnen maken van de itemtemplate en edititemtemplates van de datalist componenten, inplaats van twee verschillende 'states' bij te houden waarin de controls worden geenabeld/gedisabled ivm datainvoer...
* gorgi_19 blijft hetzelfde antwoord geven...

't is afhankelijk van de situatie. Soms is het makkelijker om itemtemplate te gebruiken, soms niet.
Een nieuwe pagina is sowieso wel sneller, dus dat kan ook meespelen.

Digitaal onderwijsmateriaal, leermateriaal voor hbo


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 19:05
MrHighStone schreef op 25 June 2003 @ 13:11:
Heb het idee dat mijn vraag niet helemaal duidelijk over komt.
Probeer het nog een keer:
De insteek is een datalist te gebruiken om de details van een record te inzien/bewerken, ook al is het altijd maar een record dat je inziet/bewerkt.
Dit om eenvoudig gebruik te kunnen maken van de itemtemplate en edititemtemplates van de datalist componenten, inplaats van twee verschillende 'states' bij te houden waarin de controls worden geenabeld/gedisabled ivm datainvoer...
Ik zie hierin geen vraag....

Trouwens, dit topic is bedoeld om tips en best practices neer te zetten, niet echt om problemen op te lossen

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • MrHighStone
  • Registratie: November 2001
  • Laatst online: 03-02-2023
Klopt, was ook mijn insteek. Denk dat ik de vraag niet duidelijk genoeg geformuleerd heb. 8)7
Op naar de volgende dan maar...

Een file op de A12 is nooit grappig...


Acties:
  • 0 Henk 'm!

  • PhoneTech
  • Registratie: Mei 2000
  • Laatst online: 07-07 12:06
Eindelijk heb ik de tijd gevonden om deze lijst met allemaal handige tips aan te vullen. Ik ga hier een aantal stukken code plaatsen die handig zijn voor .NET devvers.

Session objecten
Het eerste wat ik ga behandelen is een toevoeging op de eerste post van whoami

Om de session variabelen die je vaak gebruikt op te slaan, heb ik een aparte namespace gemaakt. Je zult dus wel voor elke session var een lapje code moeten toevoegen. Je kan ook nog checks er in zetten of iets ook wel er in mag enzo...

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
namespace JouwApp.Session
{
    public class SessionVars
    {
        public Session()
        {
        }

        public static int NewsID
        {
            get
            {
                if(HttpContext.Current.Session["NewsID"] == null)
                {                   
                    return 0;
                }
                else
                {
                    return (int)HttpContext.Current.Session["NewsID"];
                }
            }
            set
            {
                HttpContext.Current.Session["NewsID"] = value;
            }
        }
    }
}


Cachen is leuk. Maar cachen op een gebruiker of rol is nog leuker!
Stop deze code in je global.asax.cs
C#:
1
2
3
4
public override string GetVaryByCustomString(HttpContext context, string arg)
{
    return HttpContext.Current.User.Identity.Name;          
}

en deze code in de header van je form of usercontrol
ASP.NET:
1
<%@ OutputCache Duration="30" VaryByParam="none" VaryByCustom="RoleID" %>

Ok..Dit was simpel....
Nu komt er iets ingewikkelder...op het gebied van Active Directory Service Interfaces (ADSI)

Virtual Directory toevoegen
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public void CreateVirtualDirectory(string PhysicalPath, string VirDirName)
        {
            //Controleer eerst of het fysieke pad wel bestaat
            DirectoryInfo di = new DirectoryInfo(PhysicalPath);
            if(!di.Exists)
                throw new Exception("Directory does not exists.");
            
            //Maak de benodigde objecten aan
            System.DirectoryServices.DirectoryEntry oDE;
            System.DirectoryServices.DirectoryEntries oDC;
            System.DirectoryServices.DirectoryEntry oVirDir;
            string sIISPath;
            try
            {               
                /* Opbouw
                 * IIS://       <- Internet Information Server
                 * Localhost    <- Local bak...Kan niet anders
                 * 1            <- Dit is het nummer van de website. 
                 *                 zie ander script om dit te kiezen
                 * Root         <- Dit is dus het pad naar de homedir, 
                 *                 hier kan je nog een virtual dir aanplakken
                 */
                sIISPath = "IIS://localhost/W3SVC/1/Root";
                oDE = new DirectoryEntry(sIISPath);
                oDC = oDE.Children;                 
                oVirDir = oDC.Add(VirDirName,oDE.SchemaClassName.ToString()); 
                oVirDir.CommitChanges(); 
                //Beschikbare instellingen van het IIS object
                oVirDir.Properties["Path"].Value            = PhysicalPath; 
                oVirDir.Properties["AccessRead"][0]         = true;
                oVirDir.Properties["AccessWrite"][0]        = false;
                oVirDir.Properties["AccessExecute"][0]      = false;
                oVirDir.Properties["AuthAnonymous"][0]      = true;
                oVirDir.Properties["AuthBasic"][0]          = false;
                oVirDir.Properties["AuthNTLM"][0]           = true;
                oVirDir.Properties["ContentIndexed"][0]     = false;
                oVirDir.Properties["EnableDirBrowsing"][0]  = false;
                oVirDir.Invoke("AppCreate",true); 
                oVirDir.Properties["AppFriendlyName"][0]    = VirDirName;
                oVirDir.CommitChanges();            
            }
            catch (Exception exc) 
            {
                throw new Exception(exc.Message); 
            }
        }


Virtual Directory verwijderen

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public void DeleteVirtualDirectory(string sIISPath, string VirDir)
        {           
            Object[] oParams = {"IISWebVirtualDir", VirDir};
            try
            {
                System.DirectoryServices.DirectoryEntry oDE;
                oDE = new DirectoryEntry(sIISPath);
                oDE.Invoke("Delete", oParams);
                oDE.CommitChanges();                
            }
            catch (Exception exc) 
            {
                throw new Exception(exc.Message); 
            }           
        }


Alle websites opsommen die op de webserver geinstalleerd zijn

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public static DataTable getAllWebsites()
        {
            DataTable dt = new DataTable();
            dt.Columns.Add(new DataColumn("IISPATH", typeof(string)));
            dt.Columns.Add(new DataColumn("Name", typeof(string)));
            dt.Columns.Add(new DataColumn("DisplayName", typeof(string)));
            dt.Columns.Add(new DataColumn("Path", typeof(string)));         

            DataRow dr;
            string MachineName = "localhost";
            string IIsObjectPath = "IIS://" + MachineName + "/w3svc";
            const string WebServerSchema = "IIsWebServer"; // Case Sensitive        


            DirectoryEntry IIsObject = new DirectoryEntry(IIsObjectPath);           
            
            DirectoryEntry SiteRoot;
            foreach (DirectoryEntry Site in IIsObject.Children) 
            {
                if (Site.SchemaClassName == WebServerSchema)
                {
                    SiteRoot = new DirectoryEntry(Site.Path + "/Root");
                    
                    dr = dt.NewRow();
                    dr["IIsPath"] = Site.Path;
                    dr["Name"] = Site.Properties["ServerComment"].Value.ToString(); 
                    dr["Path"] = SiteRoot.Properties["Path"].Value.ToString();
                    dr["DisplayName"] = SiteRoot.Path + "-" + Site.Properties["ServerComment"].Value.ToString(); 

                    dt.Rows.Add(dr);
                }
            }           
            return dt;
        }


In de toekomst, zal ik nog veel meer handige tips geven op mijn website. Deze is nog niet af...maar dit was dus alvast een voorproefje ;)

Have phun!

Acties:
  • 0 Henk 'm!

Anoniem: 115240

whoami schreef op woensdag 18 juni 2003 @ 20:38:
[...]

Nee, gewoon:

code:
1
2
3
public const  SessionName = "Naam";

Session[SessionName] = "whoami";
Met enum werken zoals Gorgi voostelt werkt niet omdat sessies met integers en met strings overweg kunnen. Enums werken niet met strings. Als je dan iets oproept met enum zal het een integer zijn en in de sessie dus met een index gaan werken. je zal vervolgens deze fout krijgen ArgumentOutOfRangeException in bepaalde gevallen.

Een andere mogelijke klasse is om een utility klasse te maken met voor elke key een shared function
Pagina: 1