I use several UpdatePanel in the same page, with UpdateMode = Conditional, and i'm trying to find a clean way to only execute code behind related to the UpdatePanel which will be updated.
So, when i'm calling a __doPostBack from JS, i am able, on the code behind side, to detect the name of the UpdatePanel which is asked to refresh by using Request["__EVENTTARGET"] (which gives me the ClientID of the UpdatePanel).
But when i'm calling the UpdatePanel1.Update() method (from server side), is there a built-in way to know if an Update panel is about to be updated ?
I am posting here to myself my temporary (?) answer.
Because there is apparently no way to detect if a UpdatePanel is being updated (when UpdatePanel is updated by code behind), i've created a class which handle the update, and put some data in session, so, this same class will be able to tell if the UpdatePanel is updating.
So, I doesn't call anymore directly UpdatePanel.Update(), but UpdatePanelManager.RegisterToUpdate().
The method bool isUpdating() is able to tell if an UpdatePanel is updating, and can tell automatically if an updatePanel is Updating though Javascript using HttpContext.Current.Request["__EVENTTARGET"].
Note: isUpdating() need to be used within the OnPreRender Page event.
public static class UpdatePanelManager
{
private const string SessionName = "UpdatePanelRefresh";
public static void RegisterToUpdate(System.Web.UI.UpdatePanel updatePanel)
{
updatePanel.Update();
if (HttpContext.Current.Session[SessionName] == null)
{
HttpContext.Current.Session[SessionName] = new List<string>();
}
((List<string>)HttpContext.Current.Session[SessionName]).Add(updatePanel.ClientID);
}
public static bool IsUpdating(System.Web.UI.UpdatePanel updatePanel)
{
bool output = false;
// check if there is a JavaScript update request
if (HttpContext.Current.Request["__EVENTTARGET"] == updatePanel.ClientID)
output = true;
// check if there is a code behind update request
if (HttpContext.Current.Session[SessionName] != null
&& ((List<string>)HttpContext.Current.Session[SessionName]).Contains(updatePanel.ClientID))
{
output = true;
((List<string>)HttpContext.Current.Session[SessionName]).Remove(updatePanel.ClientID);
}
return output;
}
public static bool IsUpdatingOrPageLoading(System.Web.UI.UpdatePanel updatePanel, System.Web.UI.Page page)
{
bool output = false;
if (!page.IsPostBack || IsUpdating(updatePanel))
output = true;
return output;
}
}
Related
I have a Blazor component named NavBar.razor that displays a Radzen navigation menu with a list of tags. When the user clicks a tag (RadzenPanelMenuItem), the component OrderBrowser.razor is loaded into the page next to the menu. The query string lets OrderBrowser.razor know what tag was selected. (See the OnInitializedAsync method below.) The component loads the associated orders into a grid.
This works fine the first time the user clicks a tag, but when they click a different tag, the OnInitializedAsync method does not execute, even though the uri changes. So I added an event handler to force a reload when the uri changes. This works, but, for some reason, it seems to reload twice, resulting in an undesirable blink when it reloads the 2nd time.
Does anyone know a better way to do this? Thanks.
Code from NavBar.razor:
#foreach (var item in TagsAndCounts)
{
<Radzen.Blazor.RadzenPanelMenuItem
Text="#(item.Tag + " (" + item.Count + ")")"
Path="#("orders/browse?tag=" + item.Tag)" />
}
Order grid from OrderBrowser.razor:
<OrderGrid Data="#orders" AllowPaging="false" />
Code from OrderBrowser.razor:
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
NavManager.LocationChanged += NavManager_LocationChanged;
var uri = NavManager.ToAbsoluteUri(NavManager.Uri);
if (QueryHelpers.ParseQuery(uri.Query).TryGetValue("tag", out var tag))
{
orders = await orderService.GetOrdersForTagAsync(tag);
}
}
private void NavManager_LocationChanged(object sender, LocationChangedEventArgs e)
{
NavManager.NavigateTo(NavManager.Uri, forceLoad: true);
}
Use this event
[Parameter]
[SupplyParameterFromQuery]
public string? Page { get; set; } = "0";
protected override void OnParametersSet()
{
//Fire your Code her
}
When you go from: yourUrl/tag/tagname1 and click to link yourUrl/tag/tagname2 it does not fire OnInitializedAsync, because new page was not created. It is intended and correct behavior. But bit confusing.
You can leverage new, with .net6 introduced, capability of SupplyFromQueryParameter attribute, which will change its value based on query string.
[Parameter, SupplyParameterFromQuery(Name = "tag")] public string Tag { get; set; } = "";
Now you can do the magic inside seeter of the Tag property. Or, if you need to call async method inside setter (which is not a good practice), you can use OnParametersSet method. It is called right after parameters has been changed. So you also need a mechanism to check if tag parameter has been changed (because it is called every time *some* parameter has been changed )
bool tagUpdated = true;
string _tag ="";
[Parameter,SupplyParameterFromQuery] public string Tag { get => _tag; set { if (value != _tag) { _tag = value; tagUpdated = true; } } }
protected override async Task OnParametersSetAsync()
{
if (tagUpdated)
{
tagUpdated = false;
await YourAsyncCallAndOtherMagic();
}
}
Note, that SupplyFromQueryParameter works only on pages (.razor components with #page directive)
(still not the most beautiful solution I guess. Open for suggestions...)
I found a solution. It's still a bit of a hack, but it seems to work. If anybody has any better solutions, please let me know. I just changed the event handler to get the new URL and update the page, instead of forcing a reload.
private async void NavManager_LocationChanged(object sender, LocationChangedEventArgs e)
{
orders = await orderService.GetOrdersForTagAsync(tag);
var index = NavManager.Uri.LastIndexOf("/");
tag = NavManager.Uri.Substring(index + 1);
if (tag != "open_orders")
{
StateHasChanged();
}
}
I'm trying to programmatically login to a site like espn.com. The way the site is setup is once I click on the Log In button located on the homepage, a Log In popup window is displayed in the middle of the screen with the background slightly tinted. My goal is to programmatically obtain that popup box, supply the username and password, and submit it -- hoping that a cookie is returned to me to use as authentication. However, because Javascript is used to display the form, I don't necessarily have easy access to the form's input tags via the main page's HTML.
I've tried researching various solutions such as HttpClient and HttpWebRequest, however it appears that a Webbrowser is best since the login form is displayed using Javascript. Since I don't necessarily have easy access to the form's input tags, a Webbrowser seems the best alternative to capturing the popup's input elements.
class ESPNLoginViewModel
{
private string Url;
private WebBrowser webBrowser1 = new WebBrowser();
private SHDocVw.WebBrowser_V1 Web_V1;
public ESPNLoginViewModel()
{
Initialize();
}
private void Initialize()
{
Url = "http://www.espn.com/";
Login();
}
private void Login()
{
webBrowser1.Navigate(Url);
webBrowser1.DocumentCompleted +=
new WebBrowserDocumentCompletedEventHandler(webpage_DocumentCompleted);
Web_V1 = (SHDocVw.WebBrowser_V1)this.webBrowser1.ActiveXInstance;
Web_V1.NewWindow += new SHDocVw.DWebBrowserEvents_NewWindowEventHandler(Web_V1_NewWindow);
}
//This never gets executed
private void Web_V1_NewWindow(string URL, int Flags, string TargetFrameName, ref object PostData, string Headers, ref bool Processed)
{
//I'll start determing how to code this once I'm able to get this invoked
}
private void webpage_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
HtmlElement loginButton = webBrowser1.Document.GetElementsByTagName("button")[5];
loginButton.InvokeMember("click");
//I've also tried the below InvokeScript method to see if executing the javascript that
//is called when the Log In button is clicked, however Web_V1_NewWindow still wasn't called.
//webBrowser1.Document.InvokeScript("buildOverlay");
}
}
I'm expecting the Web_V1_NewWindow handler to be invoked when the InvokeMember("click") method is called. However, code execution only runs through the webpage_DocumentCompleted handler without any calls to Web_V1_NewWindow. It might be that I need to use a different method than InvokeMember("click") to invoke the Log In button's click event handler. Or I might need to try something completely different altogether. I'm not 100% sure the Web_V1.NewWindow is the correct approach for my needs, but I've seen NewWindow used often when dealing with popups so I figured I should give it a try.
Any help would be greatly appreciated as I've spent a significant amount of time on this.
I know it is the late answer. But it will help someone else.
You can extract the value from FRAME element by following
// Get frame using frame ID
HtmlWindow frameWindow = (from HtmlWindow win
in WbBrowser.Document.Window.Frames select win)
.Where(x => string.Compare(x.WindowFrameElement.Id, "frm1") == 0)
.FirstOrDefault();
// Get first frame textbox with ID
HtmlElement txtElement = (from HtmlElement element
in frameWindow.Document.GetElementsByTagName("input")
select element)
.Where(x => string.Compare(x.Id, "txt") == 0).FirstOrDefault();
// Check txtElement is nul or not
if(txtElement != null)
{
Label1.Text = txtElement.GetAttribute("value");
}
For more details check
this article
I want to set one variable from session to null
Session["my_variable"] = null;
I tried with OnUnload like this
protected override void OnUnload(EventArgs e)
{
base.OnUnload(e);
Session["my_variable"] = null;
}
but it doesn't work right, it sets the variable while the user is on page but I want to set it null whet is leaves page
Your function/event will be fired as soon as page is served to client, because it is a server side event. You might use Viewstate but still it cannot be implemented as navigation does not send any event to server while clientside scripting can help.
This functionality can be implemented by java script on-unload event. You have to send a request to server to remove or put null in particular session value ( as session is key-value object ). Your question is best explained at Asp Forum
But be careful. This event might fire only on navigation by some browser. you might have to do some code-work to implement what you want.
Why dont you are making use of ViewState inplace of Session Variable.
viewstate variable automatically get removed once you leave page
here is example how to use it
protected DataSet MyDataSet
{
get
{
if(ViewState["MyDataSet"] == null)
{
return null;
}
else
{
return (DataSet)ViewState["MyDataSet"];
}
}
set
{
ViewState["MyDataSet"] = value;
}
}
Ok, this is a weird one. I've created a simple sample site to demonstrate the issue. In it, I have a Default.aspx Page that has a button on it:
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
<p><asp:Button OnClick="ButtonClick" Text="Button" runat="server" />
</p>
<asp:Label ID="output" runat="server" />
</asp:Content>
The code behind just sets the label text on the button click:
protected void ButtonClick(object sender, EventArgs e)
{
output.Text = "Button Click!!";
}
I then have an IHttpModule that gets called for every request:
public class SampleModule : IHttpModule
{
public void Dispose()
{
}
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(context_BeginRequest);
}
private void context_BeginRequest(object sender, EventArgs e)
{
HttpApplication application = sender as HttpApplication;
if(application == null)
{
return;
}
HttpContext context = application.Context;
if(context == null)
{
return;
}
string text = "queryStringParam";
var value = context.Request[text];
var boolValue = value == null;
}
}
Again, this is just a demo, but the point here is, I'm accessing the Request, to get the value off the query string. If I run this in Cassini, it all works fine. However when I run this in IIS, this is what happens. When I run the site at:
http://mysamplesite.dev/
and then click on the button, nothing happens. The page just reloads, but my event handler for the button never gets called, and subsequently the label text never gets updated. However if I then run it at:
http://mysamplesite.dev/Default.aspx
and then click the button, it works fine and my event handler does get called!
After digging around some I changed the code in the module to this:
string text = "queryStringParam";
var value = context.Request.QueryString[text];
var boolValue = value == null;
Notice, here I'm accessing the QueryString property directly, and not going to context.Request. When I changed it to this, it works fine regardless of whether or not I had Default.aspx in the url?!
Next step I did was, I looked at Reflector to see what the code of the HttpRequest indexer property actually does:
public string this[string key]
{
get
{
string str = this.QueryString[key];
if (str != null)
{
return str;
}
str = this.Form[key];
if (str != null)
{
return str;
}
HttpCookie cookie = this.Cookies[key];
if (cookie != null)
{
return cookie.Value;
}
str = this.ServerVariables[key];
if (str != null)
{
return str;
}
return null;
}
}
Seems harmless enough, it just checks various collections for me, so I don't need to check each one individually. So then I'm wondering, which one of those calls breaks it. I then changed my module to this:
string text = "queryStringParam";
var value = context.Request.QueryString[text];
var boolValue = value == null;
var value2 = context.Request.Form[text];
var boolValue2 = value2 == null;
And now it's broken again! So to make a long story short, just by accessing the Form collection on the request in the IHttpModule, I somehow screw up the PostBack, and the event never gets fired.
Does anyone have any idea why this is happening? I'm more of an ASP.Net MVC guy, I don't know ASP.Net and all the shtick it pulls behind the scenes well enough to really have a clue as to why this is happening.
give your button an ID (no luck)
try fiddler and see what the traffic looks like - something funny is going on here.
When a request is made to "http://mysamplesite.dev/Default.aspx", the context_BeginRequest event handler is only called once, as you would expect. However, when a request is made to "http://mysamplesite.dev/", for some reason context_BeginRequest is called twice.
For "http://mysamplesite.dev/", the first pass through context_BeginRequest loads the Form values properly when context.Request["queryStringParam"] is executed, but the second pass through does not (I checked the private _form value on context.Request using reflection). During this time, the Page_Load method for the page is only called once.
So, the event is not being handled properly because ASP.NET handles a request for "/" a little bit differently than it handles a request for "/Default.aspx", by firing the BeginRequest for the module twice instead of once. As to why ASP.NET does this, I'm not really sure. You would probably need to profile the ASP.NET request and see what methods are being called on HttpRequest to see why the form values don't get passed properly the second time context_BeginRequest is called (and additionally why this second call is even made in the first place).
Note: this must be an internal ASP.NET thing (maybe a Server.Transfer from "/" to "/Default.aspx" or something like that) because Fiddler2 only shows one request coming from the browser for "http://mysamplesite.dev/".
I was wondering if there was a way to determine when a post-back occured in an update panel. Looking for something similar to (IsPostBack).
I'm using ASP.NET, with C#.
Use ScriptManager.IsInAsyncPostBack:
if (ScriptManager.GetCurrent(this).IsInAsyncPostBack)
{
// In a request from an update panel
}
else {
// Not in a request from an update panel
}
Try IsCallBack - should do the trick.
Are you looking for a way to determine this on the server side or client side? There is a server-side UpdatePanel load event that you can override I think. Client side can be done by following these instructions - http://forums.asp.net/t/1254188.aspx
If any update occured in a page , you can find which updatepanel(s) is caused postback.
It is possible by javascript
Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(PageLoadedHandler);
function PageLoadedHandler(sender, args)
{
//this event is raised after all content on the page is refreshed.
//Whether it was refreshed bacause of a synchronous or asynchronous
if (TargetPanelWasUpdated(args.get_panelsUpdated(), "UpdatePanel1") )
{
//do stuff
}
}
function TargetPanelWasUpdated(panelsUpdated, targetPanelID)
{
// NOTE: Multiple UpdatePanels will be included in the list unless
// you set each panel's UpdateMode property to Conditional.
var matched = false;
for (i = 0 ; i < panelsUpdated.length; i++) {
if (panelsUpdated[i].id == targetPanelID) {
matched = true;
break;
}
}
return matched;
}