ServerValidateEventArgs and custom validation control in ASP.NET - asp.net

I'm a beginner in ASP.NET, just a question on the custom validation, we know that it works in this way:
protected void customValidation_ServerValidate(Object source, ServerValidateEventArgs e)
{
if(e.Value...)
{
...
} else
{
e.IsValid = false;
}
} //customValidation is the id of the custom validation control
but how the value of e.isValid get transferred to the validation's IsValid property?why we have to use ServerValidateEventArgs instead of coding like;
...
} else
{
customValidation.IsValid = false;
}
isn't this approach more sensible? setting the validation control's isValid to false? why via ServerValidateEventArgs instance?

Lets say you have several controls that use the same custom validation. You only want to indicate those controls which are invalid. This is where ServerValidateEventArgs comes in.
This will then be used to indicate which control(s) have failed validation on the page.
E.G.
ASPX
<asp:TextBox runat="server" ID="txtCustomDate" />
<asp:CustomValidator runat="server" OnServerValidate="cstvDate_ServerValidate"
ControlToValidate="txtCustomDate" ID="ctValDate1" ></asp:CustomValidator>
<asp:TextBox runat="server" ID="txtCustomDate2" />
<!-- Same Logic for validation -->
<asp:CustomValidator runat="server" OnServerValidate="cstvDate_ServerValidate"
ControlToValidate="txtCustomDate2" ID="ctValDate2" ></asp:CustomValidator>
Code behind
protected void customValidation_ServerValidate(Object source, ServerValidateEventArgs e)
{
if(e.Value...)
{
...
} else
{
e.IsValid = false;
}
}
The validation method is identified by the OnServerValidate attribute. The validation control passes information about itself via the source parameter and the validation event via the e parameter.
For more information see:
https://learn.microsoft.com/en-us/dotnet/api/system.web.ui.webcontrols.customvalidator?view=netframework-4.7.2
https://learn.microsoft.com/en-us/dotnet/api/system.web.ui.webcontrols.servervalidateeventargs?view=netframework-4.7.2

Related

Change session variable for all clicks except for one button in a page

I have got 10 button/Links in aspx page. I need to maintain a session variable on only ONE button click and for all other 9 click/action I need to change the value in session variable.
How can I get this in a best way, instead of writing in those 9 click actions.
Please suggest
You can re-use the same event for multiple buttons, and check the 'sender' to see which button was clicked.
Markup:
<asp:Button ID="Button1" runat="server" OnClick="GenericButtonClick" Text="Button" />
<asp:Button ID="Button2" runat="server" OnClick="GenericButtonClick" Text="Button" />
CS:
protected void GenericButtonClick(object sender, EventArgs e)
{
Button button = sender as Button;
switch(button.ID)
{
case "Button1":
//Maintain Session Variable
break;
default:
//Change Value in Session Variable
break;
}
}
You then set all your buttons to use the same event handler
I use mostly the command event handler instead of click, so in aspx side, you would have something like this:
<asp:Button ID="Button1" runat="server" OnCommand="DoSomething" CommandName="SetSession" CommandArgument="true" />
<asp:Button ID="Button2" runat="server" OnCommand="DoSomething" CommandName="SetSession" CommandArgument="false" />
<asp:Button ID="Button3" runat="server" OnCommand="DoSomething" CommandName="SetSession" CommandArgument="false" />
And in the back end cs file, there would be only one event handler like this:
protected void DoSomething(object sender, CommandEventArgs e)
{
if (e.CommandArgument.ToString() == "true")
{
// set session
}
}
The benefit of using CommandEventHandler is that even later on you change the button to ImageButton or LinkButton, you don't need to change the event signature, it works for all.
You can make a property in which you can set the session value and you can also get value from this property. I have made it private because it is used only in that page where you need.
private static string SetGetSession
{
set { HttpContext.Current.Session["Mairaj"] = value; }
get { return HttpContext.Current.Session["Mairaj"].ToString(); }
}
Here is how you can use it
protected void btnOne_Click(object sender, EventArgs e)
{
SetGetSession = "Mairaj";
}
protected void btnTwo_Click(object sender, EventArgs e)
{
SetGetSession = "Ahmad";
}
protected void btnTh_Click(object sender, EventArgs e)
{
SetGetSession = "Minhas";
}
If you want it to be used in other pages as well you can make a class and make this property public you will be able to access it everywhere.

Handling events from dynamic controls NOT added on Page_Load?

I've read a few articles on here and the web that have informed me that I cannot simply add a new control dynamically to the page, wire it to a handler, and expect it to work.
The solution given each time is that the dynamic controls need to be added to the page on Init each time.
My problem is, my controls are NOT added to the page on init, they are added after ANOTHER postback.
the workflow is this:
Page Loads
User fills in a textbox, clicks a button
Page Posts back, creating dynamic link controls in the button_click event based on the input
User clicks one of those link controls to proceed to the next step.
so if this is the behavior I need to support, is there any way to do this? It has to happen in the button_click of step 2, because the dynamic controls are based on the input the user puts in step 2.
have I painted myself into a corner here? how else could I handle such a workflow?
After you dynamically create a link button, set a flag in your page's view state. On postback, re-create the link button if the flag is set in view state. Here's a demo:
Markup:
<asp:Button runat="server" ID="button1" OnClick="button_Click" Text="Create button A" CommandArgument="A" />
<asp:Button runat="server" ID="button2" OnClick="button_Click" Text="Create button B" CommandArgument="B" />
<asp:PlaceHolder runat="server" ID="placeHolder"></asp:PlaceHolder>
Code-behind:
public partial class Default : System.Web.UI.Page
{
private bool LinkButtonCreated
{
get { return ((bool?)this.ViewState["LinkButtonCreated"]).GetValueOrDefault(); }
set { this.ViewState["LinkButtonCreated"] = value; }
}
private string LinkButtonCommandArgument
{
get { return (string)this.ViewState["LinkButtonCommandArgument"]; }
set { this.ViewState["LinkButtonCommandArgument"] = value; }
}
protected override void LoadViewState(object savedState)
{
base.LoadViewState(savedState);
if (this.LinkButtonCreated)
this.CreateLinkButton(this.LinkButtonCommandArgument);
}
protected void button_Click(object sender, EventArgs e)
{
if (!this.LinkButtonCreated)
{
string commandArgument = ((Button)sender).CommandArgument;
this.LinkButtonCreated = true;
this.LinkButtonCommandArgument = commandArgument;
this.CreateLinkButton(commandArgument);
}
}
private void CreateLinkButton(string commandArgument)
{
LinkButton linkButton =
new LinkButton
{
ID = "linkButton",
Text = "Click me",
CommandArgument = commandArgument,
};
linkButton.Click += this.linkButton_Click;
this.placeHolder.Controls.Add(linkButton);
}
private void linkButton_Click(object sender, EventArgs e)
{
LinkButton linkButton = (LinkButton)sender;
linkButton.Text = "I was clicked! Argument: " + linkButton.CommandArgument;
}
}

asp.net editing data

I'm reading data from database and showing it in a page for editing:
<h2>Create new topic:
<asp:Label ID="_lblTopicName" runat="server" Text=""></asp:Label></h2>
<p>
Edit Level:
<br/>
<asp:DropDownList ID="_dtlEditRole" runat="server"></asp:DropDownList>
<br/>
View Level:
<br/>
<asp:DropDownList ID="_dtlViewRole" runat="server"></asp:DropDownList>
<br/>
<asp:TextBox ID="_tbxTopicText" TextMode="MultiLine" runat="server" Height="204px"
Width="885px"></asp:TextBox>
</p>
<asp:Button ID="_btnSaveTopic" runat="server" Text="Save" onclick="_btnSaveTopic_Click" />
I fill the fields in Page_PreRender() like so:
private string _topicString;
private Topic _topic = null;
private Topics_GetTopicByTopicResult _findTopicResults = null;
protected void Page_PreRender(object sender, EventArgs e)
{
// Load the User Roles into checkboxes.
_dtlEditRole.DataSource = Roles.GetAllRoles();
_dtlEditRole.DataBind();
_dtlViewRole.DataSource = Roles.GetAllRoles();
_dtlViewRole.DataBind();
_topicString = Request.QueryString["Topic"];
if (String.IsNullOrEmpty(_topicString))
{
Response.Redirect("~/Default.aspx");
}
else
{
_topic = new Topic();
_findTopicResults = _topic.FindTopic(_topicString);
if (_topic != null)
{
// Check if the user has permission to access
if (RoleHelper.IsEditAllowed(_findTopicResults.ViewRoleName))
{
_lblTopicName.Text = _findTopicResults.Topic;
_tbxTopicText.Text = _findTopicResults.Text;
_dtlEditRole.SelectedValue = _findTopicResults.EditRoleName;
_dtlViewRole.SelectedValue = _findTopicResults.ViewRoleName;
}
else
{
Response.Redirect("~/Error.aspx?ReturnUrl=" + HttpUtility.UrlEncode(Request.RawUrl));
}
}
else
{
Response.Redirect("~/CreateTopic.aspx?Topic=" + _topicString);
}
}
}
But now when i click _btnSaveTopic button the fields:
private string _topicString;
private Topic _topic = null;
private Topics_GetTopicByTopicResult _findTopicResults = null;
They are all NULL and im not able to update aything.
Here's my button click event:
protected void _btnSaveTopic_Click(object sender, EventArgs e)
{
_topic.UpdateTopic(_findTopicResults.ID, _findTopicResults.Topic, _tbxTopicText.Text,
_dtlViewRole.SelectedItem.Text, _dtlEditRole.SelectedItem.Text);
Response.Redirect("~/ViewPage.aspx?Topic=" + _topicString);
}
What would be the right way doing this?
ASP.NET Page Life Cycle states that Page_Init should be used to 'initialize control properties' which looks like what you are doing.
Also, it's usually good practice to breakup such large sections of code into smaller refactored methods. Try to keep the amount of code directly placed in event handlers to a minimum.
You can start by right-clicking a section of highlighted code in visual studio -> refactor -> extract method
Also, if you need more help understanding how to improve your code, you should ask a question pointing to this question on the code review site: here
You are re-binding the drop down list (and therefore wiping out the 'SelectedValue') in your Page_PreRender method. Wrap the method in
protected void Page_PreRender(object sender, EventArgs e)
{
if( !IsPostBack){
//your current code
}
}
and it should work.

Startup Script Not Firing During Partial Refresh

I have a User Control, named MyUpdateControl, that fires a startup script - its HTML is simply:
<div id="updatableArea"></div>
The startup script is added in the User Control's OnLoad():
string doUpdateScript = String.Format(
"DoUpdate('{0}')",
someValue);
this.Parent.Page.ClientScript.RegisterStartupScript(typeof(Page), "DoUpdateScript", doUpdateScript);
The MyUpdateControl User Control is sometimes contained within an Update Panel in another User Control:
<asp:UpdatePanel ID="myUpdatePanel" runat="server" >
<ContentTemplate>
<UC1:MyUpdateControl ID="myUpdaterControl" runat="server" />
</ContentTemplate>
</asp:UpdatePanel>
In those cases, the script is only fired when the page first loads. It never fires during an asynchronous postback. How can I ensure that it's also called during asynchronous postbacks?
You need to use the ScriptManager.RegisterStartupScript when registering a script within an UpdatePanel instead of ClientScript.RegisterStartupScript. There is an overload of this method that expects the control that is registering the client script block as its first parameter.
public class MyUpdateControl : Control
{
public MyUpdateControl()
{
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
//..
string doUpdateScript = String.Format(
"DoUpdate('{0}')", someValue);
ScriptManager.RegisterStartupScript(this, GetType(),
"ServerControlScript", script, true);
//..
}
}
The example above uses a Custom Control, i realize you are using a User Control. The two implementations are very similar but i have included an example of this below for completeness.
public partial class MyUpdateControl : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
//..
string doUpdateScript = String.Format(
"DoUpdate('{0}')", someValue);
ScriptManager.RegisterStartupScript(this, GetType(),
"ServerControlScript", script, true);
//..
}
}

Two text boxes, either one or both are required

I have two textboxes on an asp.net webpage, either one or both are required to be filled in. Both cannot be left blank. How do I create a validator to do this in asp.net?
You'd need a CustomValidator to accomplish that.
Here is some code demonstrating basic usage. The custom validator text will show after IsValid is called in the submit callback and some text will be displayed from the Response.Write call.
ASPX
<asp:TextBox runat="server" ID="tb1" />
<asp:TextBox runat="server" ID="tb2" />
<asp:CustomValidator id="CustomValidator1" runat="server"
OnServerValidate="TextValidate"
Display="Dynamic"
ErrorMessage="One of the text boxes must have valid input.">
</asp:CustomValidator>
<asp:Button runat="server" ID="uxSubmit" Text="Submit" />
Code Behind
protected void Page_Load(object sender, EventArgs e)
{
uxSubmit.Click += new EventHandler(uxSubmit_Click);
}
void uxSubmit_Click(object sender, EventArgs e)
{
Response.Write("Page is " + (Page.IsValid ? "" : "NOT ") + "Valid");
}
protected void TextValidate(object source, ServerValidateEventArgs args)
{
args.IsValid = (tb1.Text.Length > 0 || tb2.Text.Length > 0);
}
Try a CustomValidator.
You'll need to create a method that does the following to handle the ServerValidate event:
void ServerValidation (object source, ServerValidateEventArgs args)
{
args.IsValid = TextBox1.Text.Length > 0 || TextBox2.Text.Length > 0;
}
In addition to creating server-side validation, you can use the ClientValidationFunction property on the CustomValidator to provide client-side validation as well. That might look something like this:
function(sender, args) {
args.IsValid = document.getElementById('<%=TextBox1.ClientID%>').value != ''
|| document.getElementById('<%=TextBox2.ClientID%>').value != '';
}
Onclientclick of your button or whatever submits your page call a javascript function like this
function valtxtbox(){
if (document.getElementById('<%=TextBox1.ClientID%>').value== '' && document.getElementById('<%=TextBox2.ClientID%>').value== '')
{
alert('You must enter in data!');
return false;
}

Resources