[C#] Gegevens asynchroon updaten via ICallBackEventHandler

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Mastermind
  • Registratie: Februari 2000
  • Laatst online: 13-09 21:30
Ik heb een kleine tutorial geschreven hoe verschillende acties in de browser asynchroon verschillende acties uitvoeren op de server, en op de client weer de juiste result eruitgehaald wordt waar een actie op uitgevoerd wordt. Ik zou graag feedback willen of onderstaande methode de juiste methode is, of dat het anders of beter kan.

Gegevens asynchroon updaten via ICallBackEventHandler

In deze tutorial beschrijf ik hoe je asynchroon de browser een berichtje kunt laten sturen naar de server, de server een proces laat uitvoeren, en daarna een berichtje terugstuurt naar de browser. Dit berichtje kan dan gebruikt worden voor verdere actie van de browser, bijvoorbeeld de innerHTML van een DIV aan de laten passen. Op die manier is er geen postback vereist voor verversen van de data.

Een extra aanpassing die ik heb gemaakt, is dat het mogelijk wordt verschillende controls op je pagina verschillende dingen asynchroon te kunnen laten doen.

Laten we stellen dat je class MyClass heet.
Dan moet je deze ook de ICallBackEventHandler interface laten implementeren. In onderstaand voorbeeld wordt deze naast UserControl of Page gezet.
public class MyClass : System.Web.UI.UserControl, System.Web.UI.ICallBackEventHandler

Voeg using System.Web.UI; toe aan de using-statements.
Zet in de Page_Load event van de class de volgende code, want deze injecteert een stuk javascript in de aspx/ascx-pagina:

C#:
1
2
3
string cbReference = cm.GetCallbackEventReference(this, "arg", "ReceiveServerData", "");
string callbackScript = "function CallServer(arg, context) {" + cbReference + "; }";
cm.RegisterClientScriptBlock(this.GetType(), "CallServer", callbackScript, true);


Dit betekent dat als de CallServer functie in je browser aangeroepen wordt, de RaiseCallBackEvent methode op de server wordt aangeroepen.

Maak dan ook een methode:
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
47
    public void RaiseCallbackEvent(String eventArgument)
    {
        string[] eventArgs = eventArgument.Split(':'); // Split in de aanroeper en de argumenten
        switch (eventArgs[0])
        {
            case "DoProcessA":
                this.DoProcessA(eventArgs[1]); // Roep methode A aan
                break;
            case "DoProcessB":
                this.DoProcessB(eventArgs[1]); // Roep methode B aan
                break;
            // vul aan met hoeveel je wilt. Maak ook de methods.
        }
    }
    
    private void DoProcessA(string arg)
    {
        // Process het argument. Dit is de string die vanaf de browser gestuurd werd.
        string result = "Resultaat van proces A";
        Session["ResultProcessA"] = result; // Zet het in de session
        // GetCallBackResult wordt aangeroepen als het proces klaar is.
    }
    
    private void DoProcessB(string arg)
    {
        string result = "Resultaat van proces B";
        Session["ResultProcessB"] = result;

    }
    
// Deze method wordt aageroepen als DoProcess klaar is. Het resultaat wordt uit de sessionvariabele gehaald. De return van deze method stuurt het resultaat in een string door naar de browser en komt daar in de javascriptfunctie ReceiveServerData binnen.
    public string GetCallbackResult()
    {
        if (Session["ResultProcessA"] != null)
        {
            string callBackResult = Session["ResultProcessA"].ToString();
            Session["ResultProcessA"] = null; // Weer null maken
            return "ProcessA:" + callBackResult; // "ProcessA:" moet mee. Dit wordt eraf gesplit in de browser voor verdere processing.
        }
        if (Session["ResultProcessB"] != null)
        {
            string callBackResult = Session["ResultProcessB"].ToString();
            Session["ResultProcessB"] = null;
            return "ProcessB:" + callBackResult;
        }
        return "";
    }


Wat er gebeurt is, omdat er maar één lange string meegegeven wordt moeten we kunnen bepalen welke browseraanroep de callback veroorzaakt heeft, maar ook de callbackResult terug naar de browser moet zo'n identificatie bevatten. Vandaar de "ProcessA:" voor de returnstring, omdat we dat met de split functie er weer af kunnen strippen.

Laten we nu naar de javascript gaan. We hebben 2 functies die door bijv. een onclick="callBackProcessA()" aangeroepen kunnen worden.
Zet onderstaande code in je javascript sectie van de aspx/ascx pagina. Heb je die niet zet het dan tussen een <script type="text/javascript"> </script> tag.
JavaScript:
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
function callBackProcessA() 
{
    // voer een javascript proces uit.
    var myProcessResult = "Resultaat van process";
    CallServer("DoProcessA:" + myProcessResult, "ProcessA");
}

function callBackProcessB() 
{
    // idem voor Process B. (verander de A's in een B), enz.  voor meerdere processen
}
    
// Hier komt het resultaat van het proces weer de browser binnen, asynchroon!
function ReceiveServerData(arg, context) // context wordt helaas niks bruikbaars mee gedaan door .Net, maar moet er wel in.
{
    var args = arg.split(":", 2); // Splitten zodat we kunnen achterhalen welk process feedback geeft.
    var caller = args[0]; // De caller van de server dus
    var argParams = args[1]; // De argumenten
    switch (caller) 
    {
        case "ProcessA":
            var resultaatVanServer = argParams;
            // Doe iets met die var, bijvoorbeeld de innerHTML van een div wijzigen. 
            // Er bestaat bijvoorbeeld een <div id="infoDiv"></div>, dan doe je:
            var infoDiv = document.getElementById("infoDiv");
            infoDiv.innerHTML = resultaatVanServer;
            // en de tekst wijzigt zonder dat de pagina ververst is.
        break;
        case "ProcessB":
            var resultaatVanServer = argParams; 
            // doe iets ermee
        break;

}


Je kunt naar believen processen toevoegen door gewoon te copy/pasten en de procesnamen de juiste naam te geven.

Is dit de juiste manier of kan dit beter/anders? (8>

Acties:
  • 0 Henk 'm!

  • boe2
  • Registratie: November 2002
  • Niet online

boe2

'-')/

Het lijkt me eerlijk gezegd wel een vrij omslachtige manier om dit klaargespeeld te krijgen. Persoonlijk zou ik voor Webmethods gaan ;)

'Multiple exclamation marks,' he went on, shaking his head, 'are a sure sign of a diseased mind.' - Pratchett.


Acties:
  • 0 Henk 'm!

  • Russel88
  • Registratie: Juli 2009
  • Laatst online: 20-09 09:36
Is een UpdatePanel niet wat makkelijker?

Acties:
  • 0 Henk 'm!

  • Mastermind
  • Registratie: Februari 2000
  • Laatst online: 13-09 21:30
Boeboe, dat is een hele goeie tip! Bedankt! (8>
UpdatePanels heb ik ook gebruikt, alleen dat is in ons geval niet toepaspaar.

Acties:
  • 0 Henk 'm!

  • PressPlayOnTape
  • Registratie: Augustus 2012
  • Laatst online: 22:31

PressPlayOnTape

Loading.. Ready... Run!

Let wel op dat Webmethods (voor zover ik weet) altijd static moeten zijn en je dus geen toegang hebt tot in de pagina gedeclareerde variabelen en methodes (tenzij deze ook static zijn).

Overigens werken Webmethods naar mijn weten niet in usercontrols. Daarvoor is de methode die je beschrijft wel geschikt.

You know, I rather like this God fellow. He’s very theatrical. A little pestilence here, a plague there... Omnipotence...got to get me some of that.


Acties:
  • 0 Henk 'm!

  • Sebazzz
  • Registratie: September 2006
  • Laatst online: 19:58

Sebazzz

3dp

Russel88 schreef op woensdag 31 oktober 2012 @ 11:04:
Is een UpdatePanel niet wat makkelijker?
Gemakkelijk maar gewoon bar slecht als het om zulke use-cases gaat ;)

Of altijd slecht? :P

[Te koop: 3D printers] [Website] Agile tools: [Return: retrospectives] [Pokertime: planning poker]

Pagina: 1