Wpadłem na pomysł rozwiązania pewnego dręczącego mnie problemu (o którym pewnie wkrótce) w aplikacji webowej. Pomysł ten polega na wstrzyknięciu informacji o aktualnym użytkowniku w postaci JSON do HTMLa zwracanego do przeglądarki. Ot, po prostu żeby strona kliencka wiedziała z kim ma do czynienia.
Aplikacja ta powstaje w Nancy – bardzo eleganckim frameworku, o którym chyba kiedyś wspomniałem, ale też którego nigdy w technicznym poście nie poruszyłem.
W Nancy rozwiązanie problemu jest całkiem proste. Cała konfiguracja aplikacji znajduje się w klasie Bootstraper. Nancy dostarcza nam kilka standardowych bootstraperów, a żeby osiągnąć pożądaną funkcjonalność – wystarczy nadpisać “najbardziej standardowy” z nich, czyli DefaultNancyBootstrapper.
O tak:
public class CustomBootstrapper : DefaultNancyBootstrapper { protected override void ApplicationStartup(TinyIoCContainer container, IPipelines pipelines) { pipelines.AfterRequest.AddItemToEndOfPipeline(new PipelineItem<Action<NancyContext>>( "Injecting user info into a non-ajax, authenticated response", ctx => { if (ctx.CurrentUser == null || ctx.IsAjaxRequest()) { return; } var str = new MemoryStream(); ctx.Response.Contents.Invoke(str); string originalOutput = Encoding.UTF8.GetString(str.GetBuffer()); int endOfBody = originalOutput.LastIndexOf("</body>"); if (endOfBody > 0) { var userInfo = ctx.CurrentUser.DumpClientSideInfo(); string json = new JavaScriptSerializer().Serialize(userInfo); ctx.Response.Contents = s => { string modifiedOutput = originalOutput.Insert(endOfBody, @"<script> var currentUser = ({0}) </script>".FormatWith(json)); var writer = new StreamWriter(s, Encoding.UTF8) {AutoFlush = true}; writer.Write(modifiedOutput); }; } })); } }
Da się to rozwiązać jakoś bardziej elegancko, obiektowo, i w ogóle, ale…
Ja podobną rzecz napisałem do MVC żeby wstrzykiwać dane do Angulara. Sporo o Nancy słyszę i chyba następny mój projekt w tym powstanie :)
Wstrzykiwanie informacji do HTML w Nancy | Maciej Aniserowicz o programowaniu…
Dziękujemy za dodanie artykułu – Trackback z dotnetomaniak.pl…
Hej,
zmieniłbym dwie rzeczy: pierwsza to serializator (JSON.NET is good). Druga to to, że aby dokleić na koniec fragment tekstu, cała odpowiedź jest wczytywana do pamięci, potem LastIndexOf… trochę to cięzkie. Zastanawiałeś się nad sekcją i dorzuceniem tego w Layoutcie (Razor)?
Scooletz,
U mnie tutaj dowolny serializer się sprawdzi, chociaż faktycznie gdyby nie wiedział co tam będzie wysyłane to bym z json.net skorzystał (inne miejsca w systemie z niego korzystają). W tym przypadku nie ma to znaczenia.
Co do sekcji w razor to faktycznie dobry pomysł, thx! Wcześniej w tym miejscu było doklejanie ciasteczka zamiast wrzucania jsona do htmla i miejsce operacji zostało stare, tyle że z nowym mechanizmem :).
Jako niedoświadczony w aplikacjach webpowych zastanawiam się nad wykorzystaniem tego pomysłu i tak na szybko przyszło mi na myśl dostosowywanie aplikacji web po stronie klienta w zależności od użytkownika, np. z wykorzystaniem KnockoutJS lub Angulara. Mam rację?
Bartek,
Tak, dokładnie, robie single-page application gdzie nawet logowanie jest robione ajaxem, bez przeładowania strony. Jednak trzeba być gotowym na to że user kliknie F5 (co swoją drogą przy pierwszych testach klient zrobił ze 20x w ciągu kilku minut:) ) i jakoś dostarczyć te informacje do przeglądarki.
ogólnie takie wstrzykiwanie informacji do html’a jest bardzo wartościowe! np. bootstrapData w google docs. często widzę aplikacje, które na onload zaczynają bombardować serwer po jakieś informacje. a zwykle można je “wkleić” do htmla.