[ASP.NET] Client timezone offset gebruiken in Page_Load

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • NickThissen
  • Registratie: November 2007
  • Laatst online: 09-09 10:50
Hoi,

Ik werk aan een website met een pagina die data uit een database leest en die daarna toont in een Repeater control. De data bevat twee tijd velden (start en eindtijd) die in UTC zijn opgeslagen. In de Repeater toon ik momenteel de start, eind en totale tijd via deze code:
ASP:
1
2
3
4
5
6
7
<asp:Repeater runat="server" ID="repeater">
    <ItemTemplate>
        <div>
            Time: <%# GetTimeDisplay(Container.DataItem) %>
        </div>
    </ItemTemplate>
</asp:Repeater>

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
public class TestPage : ChildPage
{
    private readonly List<Session> sessions;

    protected void Page_Load(object sender, EventArgs e)
    {
        sessions = Database.LoadSessions();
        
        if (!this.IsPostBack)
        {
            repeater.DataSource = sessions;
            repeater.DataBind();
        }
    }
    
    protected string GetTimeDisplay(object sessionObject)
    {
        Session session = (Session) sessionObject;
        int minutes = (int)(session.EndTime - session.StartTime).TotalMinutes;
        
        return string.Format("{0} - {1} ({2} min)",
            session.StartTime.ToString(@"hh\:mm"),
            session.EndTime.ToString(@"hh\:mm"),
            minutes.ToString());
    }
}


Wat hier relevant is is dat de data dus in de Repeater geladen wordt in het Page_Load event, zodat de data meteen getoond wordt bij het openen van de pagina.


Nu wil ik graag deze tijden omrekenen naar de lokale tijd van de gebruiker, zodat ik (naast UTC) ook de lokale tijd kan laten zien (ik ga er dan maar even vanuit dat de PC op de lokale tijd ingesteld staat, meer kan ik niet doen natuurlijk). Nu weet ik dat ik via Javascript het aantal minuten kan opvragen die de gebruiker verschilt met UTC, via Date.getTimezoneOffset(). Het probleem is dat dit dus met Javascript is, en ik dat niet meteen aan de server kant krijg.

De oplossing die ik overal vind is om de timezone offset op te vragen bij de document.load / window.load in Javascript, en die waarde toe te kennen aan een HiddenField op de pagina. Dan zou ik aan de serverkant de waarde weer kunnen uitlezen en gebruiken. Deze methode ben ik bekend mee, echter werkt het in dit geval niet. Het probleem is misschien al duidelijk: de data wordt in de Repeater gezet tijdens het renderen van de pagina, dus nog voordat de pagina naar de client gaat. De HiddenField waarde wordt dus pas gezet als de pagina bij de client is, en op dat moment is het al te laat, de data had ik al moeten hebben. De HiddenField blijft dan natuurlijk ook leeg totdat de pagina geladen is.


Hoe kan ik de timezone offset opvragen zodat ik die in de Page_Load beschikbaar heb? Volgens mij is dat onmogelijk, niet? De timezone kan ik alleen van de client krijgen, echter heeft de pagina nog niks met de client te doen in de Page_Load, die komt natuurlijk voordat de pagina naar de client gaat... Klopt dat, of mis ik hier iets?


Een soort van oplossing die ik kan zien is door een postback te genereren in de Javascript code nadat de HiddenField waarde gezet is. De data wordt dan enkel geladen en in de Repeater gezet als de HiddenField waarde niet leeg is. Het resultaat zou dan zijn (denk ik) dat de pagina laadt zonder data, dan wordt de HiddenField gezet, en daarna laadt de pagina opnieuw en kan ik de HiddenField waarde gebruiken in de Page_Load. Op dat moment is het dus een postback, daar zou ik dan rekening mee moeten houden (momenteel laadt ik de data niet meer opnieuw in de Repeater bij een postback).

Maar dit vind ik een bijzonder nare oplossing, vooral omdat het voor de gebruiker zichtbaar is dat de pagina twee keer laadt.

Is er geen betere oplossing om de timezone offset te krijgen en die meteen te kunnen gebruiken bij het laden van de pagina?

Bedankt!

Mijn iRacing profiel


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
En als je de timezone al eens bij, zeg, een logon opslaat in je sessie?

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • NickThissen
  • Registratie: November 2007
  • Laatst online: 09-09 10:50
Een deel van de pagina (inclusief de tijden) is altijd zichtbaar ook voor gebruikers die niet ingelogd zijn, dus dat werkt niet helemaal. Het is wel een goed idee, ik zou natuurlijk de lokale tijd alleen kunnen laten zien als de gebruiker ingelogd is, maar dat is (voor de gebruiker) misschien wel wat vreemd...

Mijn iRacing profiel


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Als de "eerste de beste" pagina al die repeater bevat dan ontkom je er vrees ik niet aan een postback te doen (so what overigens...) maar ander zou je met een Ajax-requestje, wanneer de timezone niet bekend is, alsnog die timezone "alvast" kunnen versturen en die in je sessie knallen (dus ook voor niet-ingelogde gebruikers).

En anders hield ik 't lekker op client-side formatting van dat veld / die kolom.

[edit]
Je zou natuurlijk op basis van andere beschikbare data zoals IP van 't request in ieder geval een "best guess / best effort" timezone kunnen guesstimaten.

[ Voor 39% gewijzigd door RobIII op 24-07-2012 18:22 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • NickThissen
  • Registratie: November 2007
  • Laatst online: 09-09 10:50
RobIII schreef op dinsdag 24 juli 2012 @ 18:03:
Als de "eerste de beste" pagina al die repeater bevat dan ontkom je er vrees ik niet aan een postback te doen (so what overigens...) maar ander zou je met een Ajax-requestje, wanneer de timezone niet bekend is, alsnog die timezone "alvast" kunnen versturen en die in je sessie knallen (dus ook voor niet-ingelogde gebruikers).
Ik heb de postback methode geprobeerd, en hoewel dat lijkt te werken gaat er nu vanalles mis, de Repeater vuurt bijvoorbeeld zijn ItemCommand event niet meer als ik op een knop klik, terwijl dat voorheen prima werkte.

Ik zal wel iets fout doen. Dit is mijn javascript:
JavaScript:
1
2
3
4
5
6
7
8
9
        $(window).load(function () {
            var d = new Date();
            var n = d.getTimezoneOffset();
            var field = document.getElementById('<%= hiddenTimeOffset.ClientID %>');
            if (field.value == '') { // als de waarde al gezet is natuurlijk niet nog eens submitten
                field.value = n;
                masterform.submit();
            }
        });


C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private int? timezoneOffset = null;

protected void Page_Load(object sender, EventArgs e)
{
    if (string.IsNullOrEmpty(hiddenTimeOffset.Value)) return;

    timezoneOffset = int.Parse(hiddenTimeOffset.Value);

    sessions = Database.LoadSessions(); 
 
    if (????)
    { 
        repeater.DataSource = sessions; 
        repeater.DataBind(); 
    } 
}


De logica is als volgt:
- Pagina laadt voor de eerste keer. De HiddenField wordt gezet en de form wordt gesubmit (postback).
- In de codebehind wordt de eerste keer gezien dat de HiddenField leeg is, dus gebeurt er verder niks.
- Na de postback wordt de HiddenField gelezen zodat ik de waarde kan gebruiken.

Er is nu een probleem: wanneer zet ik de DataSource van de Repeater? Als ik de standaard check doe zoals voorheen (alleen als IsPostBack false is) dan wordt hij nooit gezet; het is namelijk wel een postback wanneer de data geladen moet worden. Maar ik wil ook niet elke keer als er een postback plaats vind alle data in de Repeater laden, dat is niet nodig toch? Dat gebeurt nu dus wel, en (ik denk) daardoor vuurt de Repeater bijvoorbeeld geen ItemCommand event meer... Wat zie ik over het hoofd?
RobIII schreef op dinsdag 24 juli 2012 @ 18:03:
En anders hield ik 't lekker op client-side formatting van dat veld / die kolom.
Bedoel je hiermee na het laden van de data alle items in de repeater nalopen en de tijd velden met javascript veranderen? Daar had ik aan gedacht, ik zou natuurlijk alle tijden in een Label kunnen zetten die ik een bepaalde naam geef, daarna met jQuery al die labels nalopen, tijd inlezen en omrekenen naar lokale tijd, en weer terugschrijven. Dat is optie 2 die ik in ieder geval ga proberen, maar aangezien ik niet zo'n javascript held ben hou ik het liever aan de server kant.

Mijn iRacing profiel


Acties:
  • 0 Henk 'm!

  • D-Raven
  • Registratie: November 2001
  • Laatst online: 10-09 20:32
Zo lastig is javascript niet, gewoon ff googlen en je vind genoeg manieren om een datum te formatteren.

Acties:
  • 0 Henk 'm!

  • Haan
  • Registratie: Februari 2004
  • Laatst online: 23:11

Haan

dotnetter

Kan je niet gewoon de DateTime.ToLocalTime() method gebruiken hiervoor?

Kater? Eerst water, de rest komt later


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Haan schreef op dinsdag 24 juli 2012 @ 20:27:
Kan je niet gewoon de DateTime.ToLocalTime() method gebruiken hiervoor?
En hoe gaat die ToLocalTime() weten wat "Local" precies is voor iemand in tijdzone X? ;) Je zult toch op één of andere manier uit de client moeten halen wat de timezone voor die gebruiker is. Dat was nou net de crux hier ;)

Los daarvan vind ik overigens wel dat de gebruiker alsnog de timezone moet kunnen overrulen als die niet overeenkomt met wat z'n browser ervan vindt; dus ergens een setting neerzetten is wel zo netjes IMHO.

[ Voor 7% gewijzigd door RobIII op 24-07-2012 20:45 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • NickThissen
  • Registratie: November 2007
  • Laatst online: 09-09 10:50
RobIII schreef op dinsdag 24 juli 2012 @ 20:45:
[...]

Los daarvan vind ik overigens wel dat de gebruiker alsnog de timezone moet kunnen overrulen als die niet overeenkomt met wat z'n browser ervan vindt; dus ergens een setting neerzetten is wel zo netjes IMHO.
Het idee is dat de lokale tijd naast de tijd in GMT gegeven wordt. Ik zou per user account kunnen opslaan welke tijdzone ze willen, maar dan maak ik het mezelf weer lastiger met het aanpassen van de tijden in javascript; hoe kom ik daar aan de settings van de user..? Tenzij ik het in een cookie ga opslaan... Teveel opties met allemaal voor/nadelen :+

Mijn iRacing profiel


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
NickThissen schreef op dinsdag 24 juli 2012 @ 22:28:
[...]

Het idee is dat de lokale tijd naast de tijd in GMT gegeven wordt. Ik zou per user account kunnen opslaan welke tijdzone ze willen, maar dan maak ik het mezelf weer lastiger met het aanpassen van de tijden in javascript; hoe kom ik daar aan de settings van de user..? Tenzij ik het in een cookie ga opslaan... Teveel opties met allemaal voor/nadelen :+
code:
1
2
3
4
5
6
<!doctype html>
...
...
<script>
  var timezoneoffset = <%= session("timezoneoffset") %> || new Date().getTimezoneOffset();
</script>


Maar als je 't allemaal te veel moeite vindt zou ik juist de timezone detectie aan de client-kant achterwege laten (minder betrouwbaar en lastig voor de gebruiker om aan te passen) en juist een optie maken voor de gebruiker om de timezone naar zijn/haar voorkeur aan te passen. Daar heb je geen cookies voor nodig.

[ Voor 20% gewijzigd door RobIII op 24-07-2012 23:01 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • NickThissen
  • Registratie: November 2007
  • Laatst online: 09-09 10:50
Het viel toch wel mee in Javascript inderdaad... Ik heb het werkend gekregen. Ik kan nog altijd later een user preference toevoegen voor een tijdzone zonder al te veel moeite, maar ik denk niet dat het nodig is.


In ieder geval bedankt voor de hulp!

Mijn iRacing profiel


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
NickThissen schreef op dinsdag 24 juli 2012 @ 23:31:
maar ik denk niet dat het nodig is.
Ik wel ;)

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij

Pagina: 1