I am working with ASP.NET doing some client side javascript.
I have the following javascript to handle an XMLHTTPRequest callback. In certain situations, the page will be posted back, using the __doPostBack() function provided by ASP.NET, listed in the code below. However, I would like to be able to set the focus a dropdownlist controls after the post back occurs. Is there a way to set this using Javascript, or do I need to rig that up some other way.
function onCompanyIDSuccess(sender, e) {
if (sender == 0)
document.getElementById(txtCompanyIDTextBox).value = "";
document.getElementById(txtCompanyIDHiddenField).value = sender;
if (bAutoPostBack) {
__doPostBack(txtCompanyIDTextBox, '');
}
}
Since you're doing a full postback, you'd need to use Page.SetFocus on the server side to get the appropriate JavaScript emitted on the next page load.
Otherwise, in a pure AJAX solution - document.getElementById('id').focus() would do the trick.
i have found the solution for this one. In the code behind event handler being called for each particular item, I call the Control.Focus() as the last line. For instance, if a dropdownlist event handler is being triggered, and the next control to get focused is the zipcode text box:
protected void ddl_state_selectedValueChanged(Object sender, EventArgs e)
{
// ... here is all my code for the event handler
txtZipCode.Focus();
}
It was much easier that I what I was trying to do. I keep trying to overcomplicate things by creating Javascript on the fly that does exactly what Microsoft is already doing for me in the Framework.
Related
I would like to know if I can prevent the event bubbling / propagation on the page load based on condition like:
protected override void OnLoad(EventArgs e)
{
// If the user press F5 from the browser
if (IsRefresh)
{
// Here I want to stop propagation/bubbling the events like OnClick of a submit button but without using the button object (I want it generic)
}
else
{
base.OnLoad(e);
}
}
Is this possible?
Prevent the event bubbling has two difficulties - detect the F5 and stop the events - i would simply use the Post/Redirect/Get-pattern:
protected void Button1_Click(object sender, System.EventArgs e)
{
// do what you need to do
// now redirect to the same page,
// then a browser-refresh via F5 won't trigger this event again
Response.Redirect(Request.Url.PathAndQuery);
}
I did once in ASP.NET WebForms project when user press on F5 it'll do something other than refresh, I done this by use jQuery keypress even for the page and call e.preventDefault(); check this
Update:
$(document).ready(){function(){
this.keydown(e){
if (e.which == 116){
e.preventDefault();
window.location.href = "http://foo.com/?IsReferesh=1";
}
};
)};
You can use the QueryString to check if user press F5 and the reflection in Code Behind. If I missed something, then I didn't fully understand your question.
Regarding the specifics of your question, how about inverting it? Maybe add a Load event listener (say, in page Init) only if the condition is not met.
Another option might be doing something like:
this.Load -= MyPageLoadMethod;
You are likely looking at the event itself, not the OnLoad method. Eitherway, I think it is possible, see some options here How to remove all event handlers from a control
There is a big "BUT" though...
Like most people here, I think you are not solving the right problem. I'm sorry the same applies for Emad's solution I think.
Tim nailed it. This answer will try to explain this option more.
The pattern Post-Get-redirect is very popular and very standard. In most of our applications, submitting the same form more than once either by re-clicking the submit button before page loading or refreshing the browser causing another POST call is wrong, so, the practice of redirect after a non-AJAX form submission has become so standard.
Everything else you may try will be no more of a dirty workaround than a proper solution.
--
Now, comes the problem of providing feedback to the user. Ruby On Rails provides a nifty helper for this called Flash helper. It's a message you can set before redirecting (or even in the same page if there is no redirect) and the next time you display it, it'll destroy itself, the next time you call it, you get nothing. so, you display nothing.
ASP.NET MVC has something like this which is TempData. TempData can be stored in many places, by default in the Session, so, if you are redirecting from an MVC action, you can set something like TempData['Message'] , and read it in the next Controller. ASP.NET MVC will handle removing it after the redirect.
So, how about Webforms? There's nothing to prevent you from doing it too. It really isn't rocket science
You can check for URL Referrer whether it is an edit page or not and display message based on that.
You can store a message in Session before redirect, and check for it in every page load, if found, you display it and delete it from Session
If Session is disabled, you can use cookies. You can check the date of the cookie before sending, so that if the redirect never happened (use network dropped or whatever) and use came to the page later in the time he doesn't see an outdated message.
You can also store in Cache (with some key related to user of course, as Cache is application wide), You can then set the Cache expiration to some short period to avoid the problem explained in cookies option
You can also google for Rails Flash-like for ASP.NET Webforms to see what reusable components other people came up with. This result for example came in my search:
http://highoncoding.com/Articles/542_Creating_Rails_Like_Flash_Feature_in__NET_The_Flash_Control.aspx
Check NuGet also maybe there's something there. Again, it's not hard to build your own anyway.
Update:
Another simple approach might be to just redirect to the same URL, this'll cause a GET request and will not run any handler, pretty close to the original implementation of Post-Get-Redirect (yours will be Post-Post-Redirect maybe, kidding), and pretty safe as well.
Something like:
Response.Redirect(Request.RawUrl);
Update 2
Just as mentioned above, if you are running after page init, say in page Load, you can always emove events in a way similar to:
this.SubmitButton.Click -= SubmitButton_Click;
You get the idea...
That's useful if what you want is stop particular events, while the previous bits of the answer were assuming you are trying to stop most of the events.
http://gurustop.net
protected override void OnLoad(EventArgs e)
{
if (!IsPostBack)
{
if (Request.UrlReferrer != null)
if (Request.UrlReferrer.PathAndQuery == Request.RawUrl)
{
// Show Message
}
}
}
protected void Button1_Click(object sender, System.EventArgs e)
{
Response.Redirect(Request.Url.PathAndQuery);
}
Note:
if (Request.UrlReferrer.PathAndQuery == Request.RawUrl) // does not work with chrome
so you can replace it with
if (Request.UrlReferrer.AbsolutePath == Request.Url.AbsolutePath)
static string REFRESH_CHECK_GUID = "REFRESH_CHECK_GUID";
protected void Page_Load(object sender, EventArgs e)
{
if (ViewState[REFRESH_CHECK_GUID] != null && !ViewState[REFRESH_CHECK_GUID].ToString().Equals(Session[REFRESH_CHECK_GUID].ToString()))
{
Response.Redirect("Login.Aspx");
}
Session[REFRESH_CHECK_GUID] = System.Guid.NewGuid().ToString();
ViewState[REFRESH_CHECK_GUID] = Session[REFRESH_CHECK_GUID];
I have an ASP.NET2.0 web page with a Submit button.
When the user clicks, I generate an XML file on the fly and return that as a result.
Here is the code:
protected void submitBtn_Click(object sender, EventArgs e)
{
string result = this.ProduceMyXmlResult();
this.Response.Clear();
this.Response.StatusCode = 200;
this.Response.ContentType = "application/xml";
this.Response.ContentEncoding = System.Text.Encoding.UTF8;
this.Response.Write(result);
this.Response.End();
}
The piece of code does exactly what I want. However, the browser does not recognize the XML file as a new page, so the BACK button does not take me back to my original page. Why and how can I overcome that?
The simplest way to do so, I think, would be to create a separate page that executes this code on Page_Load(), and redirect to it when the button is pressed.
The reason you have no backward navigation is because the browser is unaware the page has changed. Since the Submit button is preforming a postback, and you are returning XML data as the response to that postback, it appears to the browser as though this is just some transformation of the current page (just as though you'd, say, changed the text of a Label control).
The "correct" way to accomplish this would be with some type of HTTP handler, but I haven't the experience to suggest the proper way to do so and you already have working C# code-behind for this method.
Say you have something like an ASP.NET ASP:DetailsView to show and edit a single record in a database.
It's simple to record the error cases... you add validation and a validation summary. When your update form fails validation it naturally makes noise: it shows the validation message and/or the validation summary. Not a single code behind is required.
But then, you pass validation, and it makes your update completely silently. There's no sense that anything happened, and there doesn't seem to be any default settings to make a success message without code-behinds.
But, even code-behinds are confusing. What event should show the success message? onItemUpdate, right? Fine, but then let's say you make another change and get a validation error? Your success message stays. I wasn't able to find an event that would reliably turn off an existing success message if there were a validation error.
This should be web development 101! Why is it so hard?
EDIT:
Someone suggested using the ItemCommand event... I tried this and many other events, but that success message just won't disappear. Here's some code.
My message in ASP.NET
<label id="successMessage" class="successMessage" runat="server"></label>
And my DataView tag (simplified):
<asp:DetailsView
Id="EditClient"
DataKeyNames="LicenseID"
DataSourceID="MySource"
runat="server"
OnItemUpdated="SuccessfulClientUpdate"
OnItemCommand="ClearMessages">
And, my code-behind:
protected void SuccessfulClientUpdate(object sender, DetailsViewUpdatedEventArgs e)
{
successMessage.InnerText = string.Format("Your changes were saved.");
successMessage.Visible = true;
}
protected void ClearMessages(object sender, DetailsViewCommandEventArgs e)
{
successMessage.InnerText = string.Empty;
successMessage.Visible = false;
}
Once I do a successful update, however, nothing seems to make that message disappear, not even failed validation.
2nd EDIT:
Just want to be clear that I did try putting the ClearMessages code in Page_Load. However, nothing seems to make that successMessage label disappear when I hit update a 2nd time WITH a validation error. Can anyone suggest any other troubleshooting tips?
As far as I know, there is no native way of doing this. You may rant about it, maybe Microsoft will hear it :).
Resetting the "success message" on Page_Load, or wherever in your code-behind, won't work. This is because ASP.NET validation is usually done both client and server-side. This means for every validation control you put on the page, ASP.NET generates some client-side Javascript that does the validation and renders the error on the client, without going back to the server. So you're stuck with both the success message and the error message at the same time.
What you can do about it:
place a <div> control on your page, that would show up the success message (as already suggested by others above). Whenever you update something (in server-side code), show up the control and set a meaningful "Successful!" message text.
register a custom Javascript function that would lookup the <div> and hide it on every page submit. Be aware that the function needs to be called before the autogenerated client script that does the validation.
If you look at the client source of an ASP.NET page (with validators on it), here's what you can find:
<form name="aspnetForm" method="post" action="MyPage.aspx" onsubmit="javascript:return WebForm_OnSubmit();id="aspnetForm">
The WebForm_OnSubmit is generated by ASP.NET and calls the javascript that does the validation. Sample:
function WebForm_OnSubmit() {
if (typeof(ValidatorOnSubmit) == "function" && ValidatorOnSubmit() == false)
return false;
return true;
}
To register your custom code that hides the success message, you should place (in your code-behind) something along these lines:
if (!Page.ClientScript.IsOnSubmitStatementRegistered("ClearMessage"))
{
string script = #"document.getElementById('" +
yourDivControl.ClientID + "').style.display='none'";
Page.ClientScript.RegisterOnSubmitStatement(Page.GetType(), "ClearMessage", script);
}
This will turn your page's autogenerated WebForm_OnSubmit into the following:
function WebForm_OnSubmit() {
document.getElementById('ctl00_yourDivControl').style.display='none';
if (typeof(ValidatorOnSubmit) == "function" && ValidatorOnSubmit() == false)
return false;
return true;
}
The effect:
On every postback (e.g. when ItemCommand is triggered, or when some Save button is clicked, or anything else), you will show up the div control with the "success" message. On the next postback, just before submitting the page to the server, this message is cleared. Of course, if this postback also triggers a "success", the message is shown again by the code-behind on the server. And so on and so forth.
I hope the above is helpful. It's not the full-blown solution, but it gives sufficient hints to point you in the right direction.
Use the ItemCommand event and perform reset to clean state for every command that is given. Then if validation fails on update, the validation error will be displayed. If it succeeds, it will show the success message. Subsequent, button clicks will invoke the ItemCommand event and you can reset again to start fresh.
Daniel, I needed something similar so I derived from a Label and bound it directly to the events raised by the various DataSourceControl derivatives (LinqDataSource, ObjectDataSource, SqlDataSource). I also used client-side JavaScript to hide the label during validation and/or form submission (like Dan.C's answer).
The control exposes separate message text properties for successful Deleted, Inserted and Updated events.
I've published the commented source for the solution at http://codehq.net/files/UpdateSuccessMessage.zip
Hope this helps.
Why not turn the validation message off in the Page_Load. I assume that if a post back occurs you'd want to get rid of the message so make sure it's always off. Or disable view state for the control by setting EnableViewState="False" in the markup (aspx page).
So:
protected void ClearMessages(object sender, DetailsViewCommandEventArgs e)
{
successMessage.InnerText = string.Empty;
successMessage.Visible = false;
}
becomes:
protected void Page_Load(object sender, EventArgs e)
{
successMessage.InnerText = string.Empty;
successMessage.Visible = false;
}
Also as a side note if you buiding .net sites you need to get comftorble with code behinds IMHO:-)
I have a search form in an app I'm currently developing, and I would like for it to be the equivalent of method="GET".
Thus, when clicking the search button, the user goes to search.aspx?q=the+query+he+entered
The reason I want this is simply bookmarkable URLs, plus it feels cleaner to do it this way.
I also don't want the viewstate hidden field value appended to the URL either.
The best I could come up with for this is:
Capture the server-side click event of the button and Response.Redirect.
Attach a Javascript onclick handler to the button that fires a window.location.replace.
Both feel quirky and sub-optimal...
Can you think of a better approach?
Use a plain old html form, not a server side form (runat=server), and you should indeed be able to make it work.
This could however be a problem if you have an out of the box visual studio master page which wraps the entire page in a server side form, because you can't nest forms.
Web forms don't have to suck, but the default implementations often do. You don't have to use web forms for everything. Sometimes plain old post/get and process request code will do just fine.
I worked on a web site that had to post to a 3rd party site to do the search on the client's web site. I ended up doing a simple Response.Redirect and passed in the search parameters through the query string like so:
protected void Button1_Click(object sender, EventArgs e)
{
string SearchQueryStringParameters = #"?SearchParameters=";
string SearchURL = "Search.aspx" + SearchQueryStringParameters;
Response.Redirect(SearchURL);
}
And on your Search.aspx page in your pageload...
protected void Page_Load(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(Request.QueryString["SearchParameters"]))
{
// prefill your search textbox
this.txtSearch.Text = Request.QueryString["SearchParameters"];
// run your code that does a search and fill your repeater/datagrid/whatever here
}
else
{
// do nothing but show the search page
}
}
Hope this helps.
This function permits to submit a page using the GET method.
To submit a page using the get method you need to:
add this code Form.Method="get"; in the Page_Load method
Use this code < asp:Button runat="server" ID="btnGenerate" /> as a submit button
add rel="do-not-submit" attribute to all form elements that you don't want to include in your query string
change the codebehind logic of your page using Request.QueryString
disable the page viewstate with EnableViewState="false" (unless it's used for other purposes)
Code
$(document).ready(function(){ enableSubmitFormByGet(); });
function enableSubmitFormByGet(){
if($("form").attr("method") == "get"){
$("form").submit(function() {
$("[name^=" + "ctl00" + "]").each(function(i){
var myName = $(this).attr("name");
var newName = "p" + (i-1);
$(this).attr("name", newName);
});
var qs =$(this).find("input[rel!='do-not-submit'],textarea[rel!='do-not-submit'],select[rel!='do-not-submit'],hidden[rel!='do-not-submit']").not("#__VIEWSTATE,#__EVENTVALIDATION,#__EVENTTARGET,#__EVENTARGUMENT").serialize();
window.document.location.href = "?" + qs;
return false;
});
I would do (b) since (a) would require two round trips for a single query. Alternatively, you could disable viewstate on the page, remove any other hidden fields via javascript, and also use javascript to modify the form method from post to get. I've never done this for real, but my toy page using the included sample worked like a charm. It's arguably easier than encoding the search string and doing the get via javascript.
Actually, it sounds like you would be happier with ASP.NET MVC since this is easily doable there by simply setting the form method to GET in the view.
sample code using jquery
$(document).ready( function() {
$('input[type=hidden]').remove();
$('form').attr('method','get');
});
EDIT: It seems like you ought to be able to do the same thing server-side, too. Maybe in OnPreRenderComplete. Don't have access to Visual Studio right now to check.
I have always used Response.Redirect as it "works".
I don't think there is an optimal method.
Just use this in your .click event before the form submission:
$("#__VIEWSTATE").remove();
$("#__EVENTVALIDATION").remove();
I need to catch the HTML of a ASP.NET just before it is being sent to the client in order to do last minute string manipulations on it, and then send the modified version to the client.
e.g.
The Page is loaded
Every control has been rendered correctly
The Full html of the page is ready to be transferred back to the client
Is there a way to that in ASP.NET?
You can override the Render method of your page. Then call the base implementation and supply your HtmlTextWriter object. Here is an example
protected override void Render(HtmlTextWriter writer)
{
StringWriter output = new StringWriter();
base.Render(new HtmlTextWriter(output));
//This is the rendered HTML of your page. Feel free to manipulate it.
string outputAsString = output.ToString();
writer.Write(outputAsString);
}
You can use a HTTPModule to change the html. Here is a sample.
Using the answer of Atanas Korchev for some days, I discovered that I get JavaScript errors similar to:
"The message received from the server could not be parsed"
When using this in conjunction with an ASP.NET Ajax UpdatePanel control. The reason is described in this blog post.
Basically the UpdatePanel seems to be critical about the exact length of the rendered string being constant. I.e. if you change the string and keep the length, it succeeds, if you change the text so that the string length changes, the above JavaScript error occurs.
My not-perfect-but-working solution was to assume the UpdatePanel always does a POST and filter that away:
protected override void Render(HtmlTextWriter writer)
{
if (IsPostBack || IsCallback)
{
base.Render(writer);
}
else
{
using (var output = new StringWriter())
{
base.Render(new HtmlTextWriter(output));
var outputAsString = output.ToString();
outputAsString = doSomeManipulation(outputAsString);
writer.Write(outputAsString);
}
}
}
This works in my scenario but has some drawbacks that may not work for your scenario:
Upon postbacks, no strings are changed.
The string that the user sees therefore is the unmanipulated one
The UpdatePanel may fire for NON-postbacks, too.
Still, I hope this helps others who discover a similar issue. Also, see this article discussing UpdatePanel and Page.Render in more details.
Take a look at the sequence of events in the ASP.NET page's lifecycle. Here's one page that lists the events. It's possible you could find an event to handle that's late enough in the page's lifecycle to make your changes, but still get those changes rendered.
If not, you could always write an HttpModule that processes the HTTP response after the page itself has finished rendering.
Obviously it will be much more efficient if you can coax the desired markup out of ASP.Net in the first place.
With that in mind, have you considered using Control Adapters? They will allow you to over-ride how each of your controls render in the first place, rather than having to modify the string later.
I don't think there is a specific event from the page that you can hook into; here is the ASP.Net lifecycle: http://msdn.microsoft.com/en-us/library/ms178472.aspx
You may want to consider hooking into the prerender event to 'adjust' the values of the controls, or perform some client side edits/callbacks.