Kann ein Asp.Net Server Projekt automatisch ohne das ein Benutzer die Webseite besucht in regelmäßigem Abstand einen ApiCall ausführen und die Daten in einem File speichern?

  • C# (ASP)

Es gibt 5 Antworten in diesem Thema. Der letzte Beitrag () ist von nogood.

    Kann ein Asp.Net Server Projekt automatisch ohne das ein Benutzer die Webseite besucht in regelmäßigem Abstand einen ApiCall ausführen und die Daten in einem File speichern?

    Hi,
    die Frage ist mir schon peinlich <X , aber ich weiß es wirklich nicht. In meiner Vorstellung ist eine Webseite etwas "passives" das erst nachdem der User die Adresse in den Browser eintippt "aufwacht".

    Ich entdecke gerade, dass ich Api`s von anderen Servern abfragen kann und die Daten in meinem Webprojekt anzeigen kann ;)
    Fürs erste hab ich diverse Wetter Api Abfragen von (openweathermap. org und climacell.co) verarbeitet. Funktioniert auch alles.

    Meine Frage ist jetzt:
    Im Moment hab ich es so gemacht, dass meine Webseite die Wetterdaten per ApiCall vom Server bei z.B. ClimaCell abfragt und auf meinem eigenen WebServer in ein File speichert inkl. des Datums/Zeit der Abfrage (UTC etc.). Bei jedem Besuch/Aufruf meiner Webseite schaue ich dann, ob das File älter als 15 Min. ist falls ja werden die Daten wieder neu vom ApiServer abgefragt. Hintergrund ist der, dass ich nur die kostenlosen Api Zugriffe nutzen möchte und diese pro Tag zahlenmäßig begrenzt sind.

    Damit die Ladezeiten für den Seitenbesucher noch kürzer werden, wäre es besser, wenn mein Seite automatisch alle 15 Minuten die Daten abruft und das File schreibt (auch wenn die Seite gar nicht "besucht" wird).

    Das würde ja bedeutet, dass meine Webseite sobald sie vollständig hochgeladen ist ohne Unterbrechung alle 15 Min automatisch einen Api Call starten müsste, ohne das die Website theoretisch jemals in einem Browser angezeigt worden wäre. Geht so was ?Wie macht man so was? Wie startet den dann der
    Prozess? Oder bin ich da so was von auf dem Holzweg?

    Ziel ist es, dass immer "frische" Daten (nicht älter als 15) auf meiner Seite in einem File bereitstehen, so das der Seitenbesucher nicht auf die Antwort des ApiCalls warten muss!

    Ich benutze Asp.Net mit Blazer als UI (alles in einer Solution).

    Hoffentlich versteht Ihr was ich meine, Danke für Antworten LG nogood

    *Topic verschoben*
    codewars.com Rank: 4 kyu

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Marcus Gräfe“ ()

    Hi,
    am einfachsten wird es sein, wenn du sogenannte "Hosted Services" / "Background Services" nutzt. Diese erlauben dir, unabhängig vom "Website Code" im Hintergrund Code auszuführen, solange dein Service läuft. Auf MSDN gibt es hierzu eine Einführung: docs.microsoft.com/en-us/aspne…re-3.1&tabs=visual-studio
    Für dich wird der Abschnitt "Timed background tasks" am relevantesten sein - das Beispiel zeigt, wie du per Timer periodisch Code ausführen kannst. Angepasst auf dein Problem kannst du damit leicht die regelmäßigen API Calls implementieren.

    Ich würde mir an deiner Stelle auch überlegen, ob du die Daten nicht in einer Datei, sondern in einem Cache speichern willst (ich denke, dass ASP.NET Cores InMemory Cache ausreichen wird). Das Dateisystem ist für solche Aufgaben nicht die beste Lösung, früher oder später wird Fehler geben, wenn du nicht aufpasst (Race Conditions, gelockte Dateien, etc.). Ein Cache hingegen kommt problemlos mit der Aufgabe klar und ist sehr wahrscheinlich auf performanter.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „shad“ ()

    @EaranMaleasi Ähhmm ich denke IIS ist die richtige Antwort. In VisualStudio wird das Projekt unter IISExpress gestartet und dann auf meinem PC in einem Local Server angezeigt. Wenn ich das dann deploye uploade ich es auf einem "echten" Windows Server bei meinem Webspace Anbieter. Ich hab erst seit Februar den Wechsel von WinForms zu Blazor Asp.net core etc. gemacht. Die Api Responsedaten können dann auf meiner bunten Webseite angezeigt werden (nix Konsole). Bin noch ziemlich unwissend (leider).

    @shad Danke für den Wegweiser, dass sieht so aus als müsste ich mich mal wieder in Sachen rein denken, die ich noch nie gemacht habe (aber das scheint beim Programmieren die Norm zu sein). Mals sehen ob ich da weiter komme.

    Nachfrage dazu:

    Quellcode

    1. public void ConfigureServices(IServiceCollection services)
    2. {
    3. //es gibt eine Klasse in meinem Blazor Project "Startup.cs" wo das hier drin ist
    4. //...
    5. services.AddRazorPages();
    6. services.AddServerSideBlazor();
    7. services.AddScoped<HttpClient>();
    8. //...
    9. }


    Ich hab hier den Service HttpClient eingefügt. Ist diese Stelle schon die halbe Miete und ich könnte hier den Backgroundworker als Singelton initialisieren?
    So ganz verstehe ich nicht wie das mit der lifetime von singleton ist:

    ist die Lebensdauer erster Start der Webseite bis Server die Webseite nicht mehr hostet?
    oder
    Start bei Aufruf der Webseite und Ende sobald der Browser der benutzt wird um die Seite zu besuchen geschlossen wird
    oder
    anders (wenn ja: wann/wie)

    Danke erstmal für Euren Input

    ------------
    P.S.:

    Auf den ersten Blick sieht es so aus als ob es so gehen würde:
    -in Startup.cs
    ​service.AddSingleton<Test>;

    wobei die Class Test so aussieht:

    C#-Quellcode

    1. public class Test
    2. {
    3. public int Nr { get; set; } = 100;
    4. }


    und dann in auf der Webseite:

    Quellcode

    1. ​@inject Test singeltonTest;
    2. <br />
    3. <button class="btn btn-primary" @onclick="@AddCount">Add 1</button>
    4. <br />
    5. <p>@singeltonTest.Nr </p>
    6. ...
    7. @code{
    8. public void AddCount()
    9. {
    10. singeltonTest.Nr += 1;
    11. }
    12. }


    Wenn ich dieses Projekt auf meine Webspace uploade sehe ich egal welches Endgerät immer die aktuelle CounterNr. Ich adde +1 vom Handy und sehe am PC bei refresh der Seite die um +1 erhöhte Zahl.

    Ich muss doch jetzt nur die Test Class mit einer Class ersetzen die meine Wetterdaten hat und ich hätte schon mal das Problem der Zwischenspeicherung in einer Datei beseitigt.

    Ich teste jetzt mal ob ich in die Test class noch eine TimerMethode setzen kann ;)
    codewars.com Rank: 4 kyu

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „nogood“ ()

    nogood schrieb:

    ist die Lebensdauer erster Start der Webseite bis Server die Webseite nicht mehr hostet?


    Genau, das stimmt. :) Die 3 Lifetimes kurz zusammengefasst:
    • Singleton: Die selbe Instanz über die gesamte Laufzeit deines Services.
    • Scoped: Pro Web Request die selbe Instanz. Sprich, wenn du ein Request von User A abarbeitest und mehrfach einen Type Foo injecten lässt, bekommst du innerhalb dieses Requests die selbe Instanz. Wenn ein zweiter User B parallel ein gleiches Request stellt, bekommst du für dieses zweite Request eine andere Instanz injected.
    • Transient: Es wird immer eine neue Instanz beim Injecten erstellt. Entspricht somit quasi immer einem new Foo().
    In den meisten Fällen brauchst du eigentlich nur Singleton und Transient. Transient am besten immer standardmäßig und Singleton für die Spezialfälle, bei denen du über die gesamte Laufzeit eben nur eine Instanz brauchst (z.B. eben um Daten längerfristig zu speichern, wie du geschrieben hast (zumindest vom Konzept her)). Scoped hat auch seine Einsatzzwecke (z.B. Performance/Per-Request State), aber zumindest ich persönlich brauche es seltener.




    Noch ein anderer Einwurf zu dieser Zeile aus deinem Codeausschnitt: services.AddScoped<HttpClient>();
    Der HttpClient sollte in ASP.NET Core am Besten anders verwendet werden. Microsoft hat hierzu auch einen Artikel: docs.microsoft.com/en-us/aspne…uests?view=aspnetcore-3.1
    Kurz zusammengefasst: Anstatt selbst den HttpClient zu registrieren/erstellen, benutzt du eine IHttpClientFactory. Diese kannst du in Startup.cs per services.AddHttpClient(); registrieren. Wenn du einen HttpClient brauchst, lässt du dir die Factory injecten und erstellt über diese deinen HttpClient:


    C#-Quellcode

    1. class Demo {
    2. private readonly IHttpClientFactory _factory;
    3. public Demo(IHttpClientFactory factory) => _factory = factory;
    4. public async Task DoSomething() {
    5. using var httpClient = factory.CreateClient();
    6. // ...
    7. }
    8. }


    Der Grund für das Ganze: Über die Factories vermeidest du HttpClient Exceptions, die auftreten können (und auch werden!), wenn dein Service zu lange läuft. Und bei Web Services kann das schnell passieren, schließlich wirst du den Service ja nicht jeden Tag neu starten. ^^
    Da ich zum selben Projekt noch einen anderen Post gestartet habe. Hier nochmal eine kurze Antwort. Ich habe noch eine Anfrage an meinen Webspace Provider gestellt bezüglich der Lebenszeit meines Singelton Servieces und da wurde mir gesagt, dass mein "Server" nach 5 Min ohne User ausgestellt wird. Also der Service nur eine Lebensdauer von 5 Min. hat (IIS Application Pool -> Idle timeout=5 min.). Sie haben mir jetzt 30 Min. zugestanden ;). Da die Daten ja alle 10 Min. neu auf dem Api-Server sind und dann so oder so neu geladen werden. Sind 30 Min. jetzt ausreichend lang. @shad Danke Dir noch mal
    codewars.com Rank: 4 kyu

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „nogood“ ()