Blazor web assembly: cannot stop img streaming when leaving page - c#

I'm having a problem with the disposing of a Blazor Web Assembly page containing an img tag having as src the path of a camera stream. In short, when I leave the page, the stream is not interrupted and remains active, wasting bandwitdh and resources.
I've the following Blazor page:
#page "/counter"
#implements IDisposable
<img src="#imgSrc" />
<br />
<button #onclick="OnBtnClicked">Hide/Show Image</button>
#code {
private string imgSrc;
private string imgPath = "http://192.168.x.x/axis-cgi/mjpg/video.cgi";
protected override async void OnInitialized() {
imgsrc=imgPath;
}
private void OnBtnClicked() {
imgsrc=(imgSrc.Equals("") ? imgPath : "");
StateHasChanged();
}
public void Dispose() {
Console.WriteLine("Disposing!");
}
}
When I enter counter page the streaming starts, and I can see badwitdh increasing from 0Mbps to about 4Mbps from Task Manager; if I click the button to "hide" the image, the bandwitdh goes back to 0Mbps.
However, if while the live stream is being shown I navigate e.g. to Home page, the bandwitdh remains to 4Mbps. At this point, even if I go back to the counter page and click the button to hide the image, even if the image correctly hides, the bandwitdh remains 4Mbps.
It's like an underlying connection remains active and Blazor has no means to stop it, and disposing the page does not stop it either.
Do you know if there is a clean way to stop this stream?
please note calling OnBtnClicked from inside Dispose() yield no result, as if once entered in Dispose(), user interface is no more updated and thus the instructions have no effect
There actually is a very dirty way to solve this, managing manually all the navigation related stuff from the main layout page and performing some cleaning before disposing the page... but the use of this workaround force me to setup a complex structure just to fix this problem.
Tests have been performed on
Mozilla Firefox 94.0.2 64-bit
Microsoft Edge 96.0.1054.41 64-bit
Google Chrome 96.0.4664.45 64-bit
I've tried with Blazor Server as well (same .razor page code) and the problem is still there.
Thank you very much!
EDIT: I've added browser used for testing and I have to remove the username and password from the Url since otherwise Chrome and Edge would block the request. I've also added Blazor Server test result.

Related

Blazor Server Dll loading progress [duplicate]

I have a Blazor server-side application that could be viewed by users from remote regions with slower internet connections to the server. After typing the URL in the browser, it displays a blank screen for a few seconds and then my loading animation shows up, and then content loads.
Loading animation is what I have on the page while waiting for the API call to return data. Nothing special. However, what about the blank screen? Is that when the browser is attempting to establish SignalR connection to the server?
I am OK with the slow speed, but is there a way to also use a loading animation while this connection is established? A blank screen is not ideal at all.
Thanks for any advice.
How about change the loading indicator to be visible from start and if you have a bool field it will be true initially. That way as soon as page is displayed you would see the loading screen and after the API data is fetched you can mark it as hidden.
Some example code for a razor below:
#if (IsLoading)
{
<div class="loader">Loading...</div>
}
#code {
public bool IsLoading { get; set; } = true;
protected override async Task OnInitializedAsync()
{
await _apiClient.Get(...);
IsLoading = false;
}
}

PuppeteerSharp - Access a background page, that opens in a new tab, as a regular page

I'm having issues with a program that generates reddit apps with refresh tokens from a discord command.
I've managed to get to a point, where I can generate the application, get all the relevant information, head over to https://not-an-aardvark.github.io/reddit-oauth-helper/ and from there generate the token, which opens a reddit confirmation page in a new window.
I've tried accessing it in various ways and have gone through multiple different methods, until I landed on using Target.PageAsync() to get the page.
For some reason, Puppeteer only sees the page as an iFrame and only gives this link when getting the Url property - https://www.redditmedia.com/gtm/jail?cb=8CqR7FcToPI - which doesn't lead to anywhere but seems to be related to the very first iFrame from what I've gathered in the HTML.
I've ran out of ideas on how to access the page to press quite literally one button and would appreciate any ideas or solutions on how to solve this or how to generate the refresh token without the use of an external website.
Another two hours later and I managed to figure out a solution.
Since PuppeteerSharp was unwilling to recognize the page, I just subscribed to Browser.TargetCreated at the correct moment with a handler that, after immediately unsubscribing, will log the most recent target (in this case, a javascript calling window.open()) and take the sender as the Browser, will then try to get the pages into an array and with a bit of code to ensure that it doesn't break itself, I finally managed a solution, I feel kinda dumb after three days and 12+ hours of work.
For anyone who might run into a similar situation, here's the snippet of code that made it finally work:
// Bla bla bla code to crawl or do whatever on the main page.
// Immediately subscribe to the target created event with the event handler
// that will handle the background page once it has
// been triggered by a button, link, etc.
browser.TargetCreated += TargetCreatedEventHandler;
}
static async void TargetCreatedEventHandler(object sender, TargetChangedArgs e)
{
// Unsubscribe from the event to
// make sure there are no duplicate unnecessary calls that might break the code.
browser.TargetCreated -= TargetCreatedEventHandler;
// Since I know the sender is the Browser object,
// I cast it it to another Browser used inside the event handler.
Browser eventBrowser = (Browser) sender;
// Get all the pages from the event browser
// and assume the first page is background one (for now)
Page[] pages = await eventBrowser.PagesAsync();
Page page = pages[0];
int counter = 0;
// Iterate through the pages, check if they're the page you were just on,
// use an int to help you keep track of of indexes.
// If it isn't the page you were on, assign the Page object the page
// with the current counter index from pages.
// (basically make sure it doesn't break itself with the wrong order).
foreach (var item in pages)
{
if (item.Url != "Main Page URL HERE")
{
page = pages[counter];
break;
}
counter++;
}
// Do whatever you need to do on your background page here
}

How do I fully refresh an ASP.NET page so that Page_Load is run again?

I have an ASP.NET page where an iframe src is being dynamically set:
<iframe id="specialframe" src="<%= IframeSrc %>"></iframe>
And the codebehind:
internal string IframeSrc { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
IframeSrc = SpecialService.GetNewUrl();
}
SpecialService is a third-party service that, when called, returns a one-time use URL that looks something like:
http://www.specialservice.com/oneTimeUseId=fh8396123lkjufgh49
For security purposes, this ID can only be used once before expiring. However, this leads to a problem.
The first time I display the page in a browser, it loads the iframe correctly. However, if I hit refresh, I will receive an error message in the iframe because it's trying to use the same one-time use ID. It works properly if I Ctrl+F5 refresh to force a cache clear, but I can't tell my users to do that every time.
My question is, is it possible to force the browser to never use the cache and always request a fresh copy from the server?
You need to set expiration and caching one your page correctly so browser always will have to request page from the server.
This question maybe a good start http://msdn.microsoft.com/en-us/library/y18he7cw.aspx.
You need cacheability to none (and maybe to set expiration in the past, maybe SetMaxAge too):
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Cache.SetExpires(DateTime.Now.AddMinutes(-30));

Response.Redirect causes download of the swf

I have a flash image slider with a button below each image.
When i press that button, the user is redirected to a new page
where i add that image product to my cart.
The problem is that after doing the adding, i want to redirect the user back to the initial page.
The code:
protected void Page_Load(object sender, EventArgs e)
{
addProductToBasket(getCategoryIdFromUrl(), getProductIdFromUrl());
Response.Redirect(Request.UrlReferrer.ToString());
}
Please note that in Firefox is working fine but in IE or Chrome it is DOWNLOADING the swf...If i comment Response.Redict(...) the user remains on this page so the click button is working well, only the redirect seems to be the problem.
Any suggestions please?
Edit: The problem seems to be that Request.UrlReferrer keeps as link not the initial page containing the swf but the swf itself....
So, instead of doing redirect to:
http://localhost:1336/Site/Index.aspx
if does redirect to the swf contained on the Index.aspx page
http://localhost:1336/carousel/carouse.swf
Solved: with a session variable where i keep the initial page's url
It seems to me that it's a function of the flash player setting the referrer header differently in different browsers.
If that is the case, then you might want to have the flash player get the url of the page it is hosted on, and pass that as a parameter to your page, and then redirect to the contents of the parameter.
What I think you really should be doing though is registering an HttpHandler (IHttpHandler implementation) for the URL which performs the processing and creating a response which returns JSON or XML, which flash can easily parse.
This way, you don't have a page reload and you have a seamless experience.

Updating ASP.NET label while processing

I have a method thats run on a button click, with 4 labels. What I need to do is update a label after each block of code executes. I've tried threading, updatepanels, etc and can't seem to get anything to work. I thought the timer would work, but it only ticks when you're not inside a method. The code looks something like this:
private void SomeMethod()
{
label1.text = "Processing...";
AnotherMethod();
label1.text = "Done.";
label2.text = "Processing...";
AnotherAnotherMethod();
label2.text = "Done.";
//etc...
}
You have a misunderstanding of how asp.net works. Your server code runs in response to a request from a browser for a complete html page. This is true even when all you really want to do is run some button click code. The entire page must be rebuilt from scratch anyway, even on postbacks. It's just the way web forms are designed.
As soon as the page is rendered to the browser, that instance of your page class is destroyed. On the next postback you'll start from scratch again, with the notable exceptions of the session, viewstate, and the application cache. Even the page's previous DOM instance in the browser is replaced.
So when you set the text property of the label you aren't directly updating anything visually in the browser. All you are doing is updating some temporary storage in your page class. As the last stage of executing your server code, all those temporary variables are used to render the completed html and the response is finally sent to the browser and shown to the user.
That should be enough information to give you an understanding of why your code doesn't behave as expected. It's running all of the code in the method before any of your property changes make their way to the browser. Therefore, the only thing the user sees is the final state of the operation.
Now ajax can complicate things a bit. When using an ajax control you might not be updating the entire page anymore, but the concept still applies: one request is made, and one response is received and used to update the entire context of the request. You can further muddle things if you have a lot of javascript in place to handle the result of the ajax request.
Unfortunately, there's no quick fix for the code you posted. You'll need to think about how this really works and decide how you want your page to flow.
Can you expose the 3 methods to client script and then call them sequentially from your client side code, when method1 finishes the client script would update the ui then call method2, and so on...

Categories

Resources