ASP.Net c# - URL Parameter weird behaviour - asp.net

I'm doing some URL changing to add some id values onto the end when certain components are clicked by the user.
So for example, when I'm logged into my AdminCP I have a list of user accounts which can have various things done to them, like modify the information or delete the user accounts.
The ASP.NET page i'm using is designed off a Master Page. That Master Page is also part of the Global Master page. So, like a nested master page.
When the user account is clicked, I record the Username in a Session Variable and then call that on page load with a button postback url. For example;
protected void Page_Load(object sender, EventArgs e)
{
if (Session["QueryString"] != null)
{
AdminHiddenButtonDelete.PostBackUrl = Request.Url.AbsolutePath + Session["QueryString"].ToString();
}
}
I'm setting the Session["QueryString"] when a button event is fired.
private void DeleteUser(string user)
{
admin_user_accounts_wrapper.Style.Add("display", "none");
admin_user_accounts_user_delete.Style.Add("display", "block");
Session["ClickedUserAccount"] = user; // This session is used to hold the username of the clicked useraccount
Session["QueryString"] = "?User = " + user + " ";
admin_user_account_user_delete_heading.InnerText = "Are you sure you wish to delete the user account " + user + "?";
}
This is called when the user clicks the html <button /> on the website.
Where query string houses the user accounts name. The outputted URL should then be url.aspx?User=John for example. Except, it always seems to be one postback behind. So, if I navigate to the John user, and then to the Rick user, the Rick URL will state John, and when I go back to the John user the URL will show Rick.
I hope this makes sense! I'm just not entirely sure on the best way to accomplish this.

To anyone who may of done something similar to me I want to post my answer on how I fixed this in hopes it may help other people out there.
The first thing I did was go back to some sort of basics about dynamic content, and realised I should be using an AJAX Update Panel to decrease the amount of postbacks that was happening.
The next thing I did was go through all my code line by line. I programmatically made a content container that houses for div id's and also some HTML buttons. These HTML buttons when clicked fired a JavaScript function. This function then called two hidden <asp buttons. That is where my mistake started.
The JavaScript function called a click event;
var hiddenButton = $('#<%= AdminHiddenButtonDelete.ClientID %>');
if (hiddenButton != null) {
hiddenButton.click();
This was my first mistake. I had now gotten two buttons, with one button doing a click server command twice, two post backs.
So, after removing the two hidden buttons and all the javascript I then needed to change the way I coded the content.
I swapped to using WebControls.Button and putting the contentResolver in the aspx.cs rather then its own class, then on click using new EventHandler(this.UserDelete_Click);
This tied the eventClick to my own function, allowing me to register the onClick event without postpacking as I'm using update panels.

Related

ASP.NET conditional yes/no messagebox

I have an asp:Button that fires a code behind function on the OnClick event. In that OnClick event several things happen, and among those things I do a check in the database for if I need to ask the user a yes or no question. For that I need a message box. First I did it like this:
protected void MyButton_Onclick(object sender, EventArgs e)
{
// lots of stuff happening
bool iNeedToAskTheUser = INeedToAskTheUser(stuff);
if (iNeedToAskTheUser)
{
DialogResult result = MessageBox.Show("Do you want to fix all objects?", "Fix objects", MessageBoxButtons.YesNo);
if (result == DialogResult.Yes) // do stuff
}
// some other stuff
}
This works fine locally but not when deployed, so I figure I would need to use ScriptManager.RegisterStartupScript instead. I could just add javascript on the ASPX page that fires up a dialog and saves the response in a hidden control that I can then look at, but I don't want to fire up the dialog unless I have to, which I check for before I do the DialogResult in the code above. So I can't do that immediately when the user clicks the button.
Is there any way I can use ScriptManager.RegisterStartupScript in "the middle" of my _OnClick code so that I can choose whether or not to actually show the button, and then also know if the user clicked yes or no, (preferably) without doing a postback?
I've been thinking and testing two different solutions:
Use ScriptManager.RegisterStartupScript in code behind to fire a JavaScript confirm function on the ASPX page. The JavaScript function would set a value in a hidden control depending on if the user answered yes or no and then my code behind stuff would check the value of that hidden field and act upon that. The problem with that is that once ScriptManager.RegisterStartupScript fires it doesn't wait for the JavaScript function to "finish", ie wait for the user to reply to the confirm(). So the value in the hidden control will always be empty because the code behind gets to the check of that control before the user has a chance to respond to the confirm(). So that's a no go.
Use ScriptManager.RegisterStartupScript in code behind to open up a new ASPX page that asks the user the question and then does all the work in response to the user's answer in that page. The problem then is to pass the object that the new ASPX page needs to do work on in response to the user's response.
I'm sure there are great solutions using Ajax or jQuery but this is a fairly simple function that shouldn't take too long to develop, so that is kind of out of scope for this.
Instead I'll go with a solution where I know what the user will respond to the question before they click the button. (While silently muttering under my breath: "It's 2019 and there's no good way to fire up a yes/no dialog from code behind in a .Net web project...". I need to get back to not working with web).

calling alert from code-behind

i have a dropdownlist and a listbox both asp.net controls
i am trying to prevent the user add duplciate items to listbox control
i able to block it but i want to display DIV or Alert box saying,"duplciate names are not allowed"
protected void btn_AddRecipientAction_OnClick(object sender, EventArgs e)
{
if (Convert.ToInt32(this.ddlRecipient.SelectedValue) > 0)
{
if (ddlRecipient.Text.Length > 0)
{
//var items = new System.Collections.ArrayList(this.lstRecipient.Items);
for(var i = lstRecipient.Items.Count - 1; i >= 0; --i)
{
if (lstRecipient.Items[i].Text == ddlRecipient.SelectedItem.Text)
{
lstRecipient.Items.RemoveAt(i);
**//alert("duplicate entry not allowed")
//div display the message and disappears after few seconds?**
}
}
ListItem newList = new ListItem();
newList.Text = ddlRecipient.SelectedItem.Text;
newList.Value = ddlRecipient.SelectedValue;
this.lstRecipient.Items.Add(newList);
}
}
}
alert way:
You could use this line assuming you have a ScriptManager
ScriptManager.RegisterClientScriptBlock(this,this.GetType(),"alert","alert('duplicate entry not allowed');",true);
This, however still does a postback since the script is run when the page is loaded again after the click. A better solution is to validate in client using javascript before submitting the page.
What you want is actually two separate things.
You should be validating on in the code behind, checking for duplicates on the post back. Then, use some javascript to do the same check on the client.
You MUST check for duplicates on the server since the user may not have javascript turned on.
Wow! Please don't inject js in the page to alert the user. You should instead have a notification control that receive a dataset of messages like an array then display the messages to the user. You want to separate your concerns.
You can achieve that in js. At the server you can set the array in json in a hidden field and then at the document ready event in js read that json data, parse it and loop on the array and display you messages. If you must you can use alert to display them but you should avoid it since it's so 1990's.
But I would go beyond that. I you do all the processing and validation in javascript before it gets to the server. So you don't rely on a post back to execute your validation. So as soon as the user adds the item it's told that it's a duplicate. Then, once the list is filled by the user he could save with a ajax call or post the page and at the server you parse the list, validate it and save it. If you have to compare the list to one already persisted at the server you can do that there. SOme thing goes wrong? you add the message to the notification control.
Please think about it. Try using a framework like MVC to separate you concerns. I makes the hole thing much faster to develop and so easier to maintain.
To call some JS from the code behind you can use Page.ClientScript property and call the RegisterStartupScript() method
http://msdn.microsoft.com/en-us/library/asz8zsxy.aspx

How can I reset a asp.net form after postback?

I am trying after the btnCreate_OnClick event to reset the form to it's default value just like the first page_load. The problem is after PostBack, every textbox and other controls, reloads the ViewState value. I cannot deactivate viewstate because of server event on DropDownList selection. The only way I found so far is to Redirect to self after the click event, but this loads the page twice and is therefor a bad solution. I have try ViewState.Clear() and update the UpdatePanel, but was unsuccessful.
I could do a loop for all controls and set the txtXXXXX.Text == "", but I'm quite sure it's not the best idea.
Something like Page.Reset() would have been just perfect but it doesn't exist.
Any thought on this problem of mine?
Thanks
If workable, I usually just use Response.Redirect to reload the same page from scratch.
An initial GET request to a page usually costs less than subsequent POSTs anyway, so there's not much reason to avoid it.
We can reset the ASP.NET Form Page with just 2 lines of code
protected void Button_Reset_Click(object sender, EventArgs e)
{
Session["ViewState"] = null;
Response.Redirect("/Roster/DRAC/Create.aspx");
}
Self redirecting gets tricky because of viewstate.
There is an html input type "reset" for buttons, but I'm not sure what or any integration msft has put into viewstate/asp.net for this. It generally works for simple javascript forms.
ex:
<input type="button" value="Reset" onclick="document.<formId>.reset();">
from google ----^
One way, not necessarily ideal, is to reset the values to their defaults using Javascript. If it is a large form, it can be ugly, but will prevent the need to do a self-redirection.
You also might try Server.Transfer instead of Response.Redirect(/self/)
I dont know if this helps but i change the name of every input on the form that i want to get fresh values by using javascript before submiting the form, since the .net page can no longer match the values from the form to the controls for the page it reloads them as if there was no postback. i also append a new value to the form so i know what button submitted the form and use that logic to decide what to load into all the controls and how to process the form data of course.
$("#Bset").children().click(function() { //all the btns click function
$.each($("form").find("input"), function(e,v) { //could filter this to subset of inputs
$(v).attr("name", "_" + $(v).attr("name")); // ctrl1 becomes _cntrl1
});
$("form").append("<input type='hidden' id='b' name='b' value='" + $(this).text() + "' />").submit();
});
then in the code behind
protected void Page_Init(object sender, EventArgs e)
{
id = int.Parse(Request.QueryString["id"]);
bk = db.dc.getDetailBK(id).Single();
if (Request.Form.Count > 0)
doPostBack();
mrl = (from a in db.dc.getMetricQTD(id, null, null, loadSavedGoals) select a).ToList();
}
i can then do things in dopostback that process the form data, interact with the db etc. that may change the values mrl is loaded with and refresh the data in the inputs tied to mrl regardless of wether they were modified or not on the form.
the other alternative would be to tie some buttons to use a webservice to handle your db interaction then call window.location to refresh the page.
$.ajax({
url: "webservice/dbfunction?"
data: {which btn pressed, some form values etc...}
success: function() {window.location("samepage.aspx?id=xxx");}
...
});
this would also avoid having to response redirect on the server side.
In our case the best performance solution was to set manually for each control the default value in the click event ex:
textbox1.Text = null;
textbox2.Text = null;
This avoid the double page_load and the loop. We don't event have to update the UpdatePanel since it executes before render.
Maybe in a more complex web application we would have to Redirect as most people seem to accept this as a solution.
Setting per control the default value was better suited to our case.
Thank you

How can I do <form method="get"> in ASP.Net for a search form?

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();

Whats the best way to update an ASPX page when its child ASCX controls need to trigger a change?

When I have a child .ASCX control that needs to affect something in the parent page I'm not completely sure how I am supposed to handle the event flow in the case where I need to update something in the parent page.
What I've always ended up doing is putting logic into the 'Pre_Render' event handler.
Since this is processed after any child .ascx controls are processed I can be sure to render the ASPX page correctly before it displays. I just dont think this is a good design and I've always cringed when I've had to do it. But now there is stackoverflow so i can finally ask it!
For instance lets say I have a 'login control' ascx control in a page. The containing page displays a text label in the header bar for 'current logged in user'.
Lets say I click the 'login' button, which will then trigger my authentication and log my user in. The problem is that the text label in the parent page has already been rendered as 'No user logged in'. Thats no good!
By putting the logic into 'PreRender' it will be rendered after the user has logged in. I just dont like this because thats not what PreRender is for.
What is the intended best practice here that I'm missing? I know I could put an event handler on the user control, but that seems clumsy too because there'd be too much coupling.
PS. I'm just using this as an example. I'd had this problem numerous other times so please dont reply telling me how to implement login !
In your ascx.cs:
public delegate void NavigateEventHandler(int PID); // if you want a custom handler
public event NavigateEventHandler onNavigate;
In your page.aspx.cs:
protected void Page_Init(object sender, EventArgs e) {
eSelector1.onNavigate += new PostSelector.NavigateEventHandler(eSelector1_Navigate); }
public void eSelector1_Navigate(int PID) {
eSelector1.PopulateComments(eSelector1.m_PID); }

Resources