0

I'm searching for hours but could not find a solution for my problem. I have made lots of "hobby" projects in c# with WinForms and WPF. Now I want to start a simple website with asp.net.

In VS 2022 I started a new project ASP.NET Core-Web-App

I have a submit-button and in the meantime, I have managed to load an image from an FTP server and display it when I press this button.

However, I would like to periodically load and display a different image from the server without pressing a button. To do this, I have built in a timer that reloads the image over and over again.

I then assign this image to my image in Index.chtml, but unfortunately the page or the image is not updated.

My index.chtml looks like:

@page
    @model IndexModel
    @{
        ViewData["Title"] = "Home page";
    }

    <div class="text-center">
        <h1 class="display-4">Welcome</h1>
        <p>Learn about <a href="https://learn.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
        <p>@Model.Test</p>
        <form method="post">
            <label for="@Model.Test" id="LblTest" runat="server"/>
            <input type="text" id="txtName" name="name" width="300" value="@Model.Test"/>
            <input type="submit" id="btnSubmit" value="Get Current Time" asp-page-handler="Submit"/>
            <br />
            <p><img src="@Model.imageSrc" alt="InfoImage" width="800" border="0" /></p>>
        </form>
    }
    </div>

And my code is:

public class IndexModel : PageModel
{
      System.Timers.Timer ReloadTimer = new System.Timers.Timer(10000);

      public IndexModel(ILogger<IndexModel> logger)
      {
          _logger = logger;
      }

      public void OnGet()
      {
          ReloadTimer.Elapsed += ReloadTimer_Elapsed;
          ReloadTimer.Enabled = true;
      }

      private void ReloadTimer_Elapsed(object? sender, System.Timers.ElapsedEventArgs e)
      {
          ReloadTimer.Interval = 60000;
          Infoanzeige();
      }

      public void OnPostSubmit(string name)
      {
          Infoanzeige();
      }

      public void Infoanzeige()
      {
          //Code to get new image from FTP
      }
}

On pressing the button, the page refresh and shows the the image. But when the timer is elapsed, it runs the same code, but I see only old image. I have read on using StateHasChanged, but this command is not existing in my context. (??)

I would be very grateful for a solution.

Fejlett
  • 3
  • 1
  • 3
  • 1
    A razor page is rendered once and then sent to the client. You cannot simply update the model on the server so that it is updated on the client side: the client should then refresh the whole page, i.e. send a new request. You need something to synchronize a specific element dynamically. Like a websocket... thus look at SignalR... or even better: Blazor , which is the razor integration of SignalR. – JHBonarius May 24 '22 at 13:39
  • 1
    You can use a refresh header to control this from the server https://stackoverflow.com/questions/7879512/what-is-the-meaning-of-response-setheaderrefresh-300 – Rotem May 24 '22 at 14:12
  • It looks like you are using ASP .NET MVC or Razor pages. This type of website uses static pages, once a page is loaded from the server it does not change until the whole page is reloaded. You can get around this problem by using javascript (jQuery) but that is more advance. – fireydude May 24 '22 at 14:20
  • Thank you all for the fast answers. I think I have a little understanding problem about the function of ASP.NET. I was hoping that unlike WinForms or WPF, "only" the programming of the FrontEnd is different, but as I understand now, the code is executed on the server, the FrontEnd/web page is rendered and the result is sent to the client for display. – Fejlett May 24 '22 at 15:23

2 Answers2

1

JHBonarius is right saying you cannot update a page as you want from the server, you need to use technologies like ajax, using javascript

in this case with jQuery

<script type="text/javascript">  

function InvokeAction(param){
    $.ajax({
        type: "GET",
        async: true,
        data: param.data,
        url: param.url,
        success: function(response){
            // replace image with response.image
        },
        error: function (jqXHR, exception) {
            console.log('error')
        }
    })
}

$(function () {  
    setInterval(InvokeAction, 60000)
});  
Leonardo T.
  • 87
  • 10
  • Thanks for your fast answer. I understand it now that the C# code runs exclusively on the server, creates a FrontEnd or web page there, which is then sent to the client to be displayed? So, the solution with timer ist correct, but I have to told the client to get periodically the new rendered web page? – Fejlett May 24 '22 at 15:26
  • if you want, you can use a partial view inwich you place your image and update only the partial view , anyway you have to use ajax – Leonardo T. May 24 '22 at 15:27
  • Thats what I want, I think, cause I want to display several images and every Image has a other timer to refresh. So when I use partial view, it's possible to implement my idea with your JS-snippet? – Fejlett May 24 '22 at 15:35
  • if you need to set a different timer for each image, updating every time only one partial view that contains every image may be expensive and clonky, but you can do it for sure – Leonardo T. May 24 '22 at 15:41
  • I hadn't expressed myself quite correctly, I think. Not every picture has its own timer, I want to display something more like maybe four simultaneous slideshows. The Partial View would be quite suitable for this. But each picture in this slideshow has a different timer. So I need four different timers. After a timer expires, the next image should be loaded in the corresponding slideshow. I will test with partial view an your code, thank you for your help! – Fejlett May 24 '22 at 18:07
0

Thank you very much for your all help. I marked the code of the answer as solution, because it is functional. Nevertheless I found another solution for me. I started a new project as blazor server app. With this I was able to integrate my C#-Code directly into the code of the website without any problems. In my code I have finally call "InvokeAsync(() => StateHasChanged() );", so the changes will render on client-side.

<img src="@ImageSrc" height="650" style="border:1px solid black;"/>

@code
{
    string ImageSrc = "";
    System.Timers.Timer TimerReload = new System.Timers.Timer();

    protected override void OnInitialized()
    {
        TimerReload.Interval = 10000;
        TimerReload.Elapsed += TimerReload_Elapsed;
        TimerReload.Start();

        InfoseiteLaden();
    }

    private void TimerReload_Elapsed(object? sender, System.Timers.ElapsedEventArgs e)
    {
        InfoseiteLaden();
    }

    private void InfoseiteLaden()
    {
        //Code to get new image from FTP

        InvokeAsync(() => StateHasChanged() );
    }
}
´´´
Fejlett
  • 3
  • 1
  • 3