I have seen a couple of other posts on here regarding the use of Recaptcha with ASP.net UpdatePanels but have not yet found an answer that solves my problem.
Here is my ASPX code :
<asp:UpdatePanel ID="updRecaptcha" runat="server" UpdateMode="Always">
<ContentTemplate>
<recaptcha:RecaptchaControl ID="btnrecaptcha" runat="server" Theme="clean" PrivateKey"<%$ Resources: General, CaptchaPrivateKey %>" PublicKey="<%$ Resources: General, CaptchaPublicKey %>" />
<asp:Label ID="recaptchaerror" runat="server" style="color: Red;"/>
</ContentTemplate>
</asp:UpdatePanel>
So the Recaptcha control lives within a user control that uses several .Net validation controls (e.g. RequiredFieldValidator). I need to valdiate the Recaptcha and the ASP.net controls before allowing the process to continue.
If any of the validation fails (Recaptcha or .Net) then the Recaptcha control disappears. Looking at the HTML source, the control isn't loading at all after the Postback - eventhough I am telling the UpdatePanel to update.
I can't reload the page completely as this all appears as an overlay on top of the page and there are other form fields on the page behind.
Please help!
Edit:
From C# when the Recaptcha fails I am calling this code :
ScriptManager.RegisterClientScriptBlock(Page, Page.GetType(), "InvalidRecaptcha", "alert('Recaptcha Failed');Recaptcha.reload();alert('Recaptcha Reloaded');", true);
Both of the alert statements fire but the Recaptcha still does not load.
The accepted solution did not work for me. Here is the answer that I have tried and is working:
ASP.Net, disappearing Recaptcha, UpdatePanels and Partial PostBacks: Fixed once and for all
Basically it involves creating a hidden div and using jquery to re-render the html. Also the blog post gives a nice little breakdown of the typical solutions (e.g., using RegisterClientScriptBlock with a simple reload) and why they fail.
<div runat="server" id="pbTarget" visible="false"></div>
<recaptcha:RecaptchaControl ID="recaptcha" runat="server" Theme="clean" />
code behind:
protected void btnSubmit_Click(object sender, EventArgs e)
{
recaptcha.Validate();
if (!Page.IsValid || !recaptcha.IsValid)
{
pbTarget.Visible = true;
ScriptManager.RegisterClientScriptBlock(
recaptcha,
recaptcha.GetType(),
"recaptcha",
"Recaptcha._init_options(RecaptchaOptions);"
+ "if ( RecaptchaOptions && \"custom\" == RecaptchaOptions.theme )"
+ "{"
+ " if ( RecaptchaOptions.custom_theme_widget )"
+ " {"
+ " Recaptcha.widget = Recaptcha.$(RecaptchaOptions.custom_theme_widget);"
+ " Recaptcha.challenge_callback();"
+ " }"
+ "} else {"
+ " if ( Recaptcha.widget == null || !document.getElementById(\"recaptcha_widget_div\") )"
+ " {"
+ " jQuery(\"#" + pbTarget.ClientID + "\").html('<div id=\"recaptcha_widget_div\" style=\"display:none\"></div>');"
+ " Recaptcha.widget = Recaptcha.$(\"recaptcha_widget_div\");"
+ " }"
+ " Recaptcha.reload();"
+ " Recaptcha.challenge_callback();"
+ "}",
true
);
return;
}
else
{
//normal page processing here...
If you are using Recaptcha 2.0 this is your Javascript
<script type="text/javascript">
function CaptchaReload() {
Recaptcha.create("yourpublicKey", 'yourRecaptchadiv', {
theme: 'white',
callback: grecaptcha.reset()
});
}
This is your recaptcha Div
<div class="g-recaptcha" data-sitekey="yourPublicKey"></div>
Then at end of postback event call the Javascript
protected void txtEmail_TextChanged(object sender, EventArgs e)
{
if (txtEmail.Text != string.Empty)
{
ValidateEmail();
ScriptManager.RegisterStartupScript(this, this.GetType(), "CaptchaReload", "$.getScript(\"https://www.google.com/recaptcha/api.js\", function () {});", true);
}
}
Forget the ScriptManager. All you need is this script in the page. Change accordingly for your identifiers:
<script type="text/javascript">
// RECAPTURE CODE FOR RELOADING AFTER INCORRECT ENTRY
if (typeof Sys != 'undefined') {
var requestManager = Sys.WebForms.PageRequestManager.getInstance();
requestManager.add_endRequest(function(sender, args) {
$('<div id="recaptcha_widget_div"/>').appendTo('#recaptcha_widget_div2');
if (typeof Recaptcha != 'undefined') {
Recaptcha.create(recaptcha_key, "recaptcha_widget_div",
{
theme: "red",
callback: Recaptcha.focus_response_field
});
}
});
}
Surprisingly, I didn't need to apply the RegisterClientScriptBlock call to make it work.
I just use:
UpdateMode="Always"
for the updatepanel and on the server side I call:
updatePanel.Update();
This also prevents the captcha from displaying a new challenge.
My answer is basically the same as "User" (that worked !), but to help anyone using VB.
I would have commented there, but I have zippo rep...
(hope this isn't too much of an infraction, and that it helps someone out)
I ported the meat of this to VB.NET:
pbTarget.Visible = True
Dim _sb As New StringBuilder
With _sb
.Append("Recaptcha._init_options(RecaptchaOptions);")
.Append("if ( RecaptchaOptions && ""custom"" == RecaptchaOptions.theme )")
.Append("{")
.Append(" if ( RecaptchaOptions.custom_theme_widget )")
.Append(" {")
.Append(" Recaptcha.widget = Recaptcha.$(RecaptchaOptions.custom_theme_widget);")
.Append(" Recaptcha.challenge_callback();")
.Append(" }")
.Append("} else {")
.Append(" if ( Recaptcha.widget == null || !document.getElementById(""recaptcha_widget_div"") )")
.Append(" {")
.Append(" jQuery(""#")
.Append(pbTarget.ClientID)
.Append(""").html('<div id=""recaptcha_widget_div"" style=""display:none""></div>');")
.Append(" Recaptcha.widget = Recaptcha.$(""recaptcha_widget_div"");")
.Append(" }")
.Append(" Recaptcha.reload();")
.Append(" Recaptcha.challenge_callback();")
.Append("}")
End With
ScriptManager.RegisterClientScriptBlock(recaptcha, recaptcha.[GetType](), "recaptcha", _sb.ToString, True)
I was able to make it work using version 2.1.0.0 of the reCAPTCHA library for .NET with webforms, script manager and inside an update panel.
First, in the .aspx page outside of the update panel I'm loading the Google reCAPTCHA library:
<script src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit"
async defer></script>
Second, in the .aspx page inside the update panel I added a div that will work as the target panel to load the reCAPTCHA:
<div runat="server" id="pbTarget" visible="false"></div>
<cc1:Recaptcha ID="recaptcha" runat="server" Theme="Clean" />
Third, in the code behind at the end of my postback event I registered a startup script to render the reCAPTCHA in my target panel
Private Sub cmdSubmit_Click(sender As Object, e As EventArgs) Handles cmdSubmit.Click
pbTarget.Visible = True
ScriptManager.RegisterStartupScript(
UpdatePanel1,
UpdatePanel1.GetType(),
"loadCaptcha",
"grecaptcha.render('" & pbTarget.ClientID & "', {'sitekey': 'YourKey' });",
End Sub
You need to reload reCaptcha control with javascript, try this:
protected void Button1_Click(object sender, EventArgs e)
{
btnrecaptcha.Validate();
if(IsValid && updRecaptcha.IsValid}
{
//Some logic here
}
ScriptManager.RegisterClientScriptBlock(Page, Page.GetType(), "CaptchaReload", "Recaptcha.reload();", true);
}
Related
I've read a few different examples of this, and it seems to be a clear newbie question for those that don't fully understand the asp.net page life cycle, sorry still learning. None of my attempts to fix have panned out.
aspx:
...
<%
for( int j = 0; j < 11; j++)
{
ChildWeightPounds.Items.Add( new ListItem(j.ToString(),j.ToString()));
}
%>
<asp:DropDownList ID="ChildWeightPounds" runat="server" OnSelectedIndexChanged="DropDownListSelected">
<asp:ListItem Value="">-Select-</asp:ListItem>
</asp:DropDownList>
...
<asp:Button ID="InsertButton" runat="server" Text="Submit" OnClick="InsertButton_Click" />
aspx.cs:
protected void InsertButton_Click(object sender, EventArgs e)
{
foreach (Control c in NewPatientForm.Controls)
{
....
if (c is TextBox)
{
TextBox tb = (TextBox)c;
//Expected response:
Response.Write( "field: " + tb.ID + " = " + tb.Text + "<br />");
}
if (c is DropDownList)
{
DropDownList ddl = (DropDownList)c;
//Unexpected response:
//this is not giving me my selected value, but only the top item ("--select--")
Response.Write("field: " + ddl.ID + ", selectedItem: " + ddl.SelectedItem.Value + "<br />");
}
}
}
It's pretty clear this is a IsPostBack, DataBind(), problem with my lack of understanding of the page life cycle. But what doesn't make sense, is i'm iterating through all controls, and textboxes, checkboxes, checkboxlists all work fine, and give me the value in the field, for some reason the dropdownlist doesn't give me the value.
I've tried using the OnSelectedIndexChanged event, I've tried using the DataBind() function, but playing with these, still hasn't gotten me the value.
The biggest issue with your example is you are using inline C# within your page with <% %>. This isn't advised for asp.net. That's more of a legacy/classic ASP approach which won't play well with .NET for many reasons.
Try moving your code that adds the items to the dropdownlist from the markup file into the .cs file, and be sure to hook into a page event that happens at or before OnPreRender. That is the last point you can alter the page controls and have viewstate/lifecycle work correctly.
protected void Page_Load(object sender, EventArgs e)
{
for( int j = 0; j < 11; j++)
{
ChildWeightPounds.Items.Add( new ListItem(j.ToString(),j.ToString()));
}
}
It's likely without running your example that the values are being inserted into the dropdownlist at the incorrect time in the lifecycle, and because of that when you try to access the selected value in the code behind it doesn't work.
Consider the following article on asp.net lifecycle which may assist you.
You can adjust AutoPostBack="true" on your DropDownList, and define OnSelecIndexChanged event
<asp:DropDownList ID="ChildWeightPounds" runat="server"
OnSelectedIndexChanged="DropDownListSelected" AutoPostBack="true>
<asp:ListItem Value="">-Select-</asp:ListItem>
</asp:DropDownList>
Code Behind
void DropDownListSelected(Object sender, EventArgs e)
{
var value = ChildWeightPounds.SelectedValue;
}
When using a MultiLine TextBox (which generates a TextArea) setting the MaxLength property has no effect. What is the best workaround? I'd like to get basic, intended functionality with minimum of ugly javascript etc. Just prevent user from entering more than max number of characters.
If you don't care about older browsers (see supported browsers here),
you can set MaxLength normally like this
<asp:TextBox ID="txt1" runat="server" TextMode="MultiLine" MaxLength="100" />
and force it to be printed out to the HTML
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
txt1.Attributes.Add("maxlength", txt1.MaxLength.ToString());
}
If you want to let the user know if he exceeded the amount of characters as he writes, you could use a javascript function attached to keypress event. This function would test the length of the input and cancel the character rendering if the maxlenght was reached.
Another option is to use RegularExpressionValidator control to validate the input on submit.
In my opinion, the first option is much more better.
I'm not adding any code since google is full of examples for all tastes, this is a very common task.
Here you have a sample search that might help.
Hey pukipuki you can do as follows:
<asp:TextBox ID="txtValue" runat="server"TextMode="MultiLine" Rows="10"Columns="50"></asp:TextBox>
$(document).ready(function(){
var MaxLength = 250;
$('#txtValue').keypress(function(e)
{
if ($(this).val().length >= MaxLength)
{
e.preventDefault();
}
});});
You can see more in this following link:
http://jquerybyexample.blogspot.in/2010/10/set-max-length-for-aspnet-multiline.html
Here's a cross browser solution :
<asp:TextBox TextMode="MultiLine" runat="server" ID="txtPurpose" Columns="50" Rows="2" onkeypress="return isokmaxlength(event,this,255);" ClientIDMode="static"></asp:TextBox>
Javascript :
function isokmaxlength(e,val,maxlengt) {
var charCode = (typeof e.which == "number") ? e.which : e.keyCode
if (!(charCode == 44 || charCode == 46 || charCode == 0 || charCode == 8 || (val.value.length < maxlengt))) {
return false;
}
}
You have to think about the Copy and Paste. This is a little bit tricky, I simply disable it with Jquery. But you can create your own function to do more complex verification. But in my case, copy and paste is not allowed.
Jquery to disable copy and paste :
jQuery(function ($) {
$("#txtPurpose").bind({
paste: function (e) {
e.preventDefault();
}
});
});
If you are using a model object bind to that textbox you can use DataAnnotations attributes to set the maxlength of that property. I'm based on MVC about that but it should work for ASP.NET too!
This way you don't mess with any Javascript or setting anything in the markup.
Try this..
Dim script As String = ""
script = script + " <script type='text/javascript'> function CheckLength(obj) {"
script = script + " var object = document.getElementById(obj);"
script = script + " if (object.value.length > 5) {"
script = script + " object.focus();"
script = script + " object.value = object.value.substring(0, 5); "
script = script + " object.scrollTop = object.scrollHeight; "
script = script + " return false;"
script = script + " }"
script = script + " return true;"
script = script + " }</script>"
Dim b As New TextBox()
b.ID = "btnSomeButton"
b.TextMode = TextBoxMode.MultiLine
Mypanel.Controls.Add(b)
b.Attributes.Add("onkeyup", "return CheckLength('" & b.ClientID & "');")
Page.ClientScript.RegisterStartupScript(Page.GetType(), "key", script, False)
To force asp.net to send the maxlength attribute for all multiline textboxes on a page or a whole site,
building on Aximili's answer above:
Create a function to get all the controls on the page:
I use the control extension method from David Findley
https://weblogs.asp.net/dfindley/linq-the-uber-findcontrol
and referenced in this SO post
Loop through all controls on asp.net webpage
namespace xyz.Extensions
{
public static class PageExtensions
{
public static IEnumerable<Control> All(this ControlCollection controls)
{
foreach (Control control in controls)
{
foreach (Control grandChild in control.Controls.All())
yield return grandChild;
yield return control;
}
}
}
}
In the page or master page
Make sure to reference the namespace for the extension method in step 1.
Put the following code in the Page_Load function:
if (!IsPostBack){
//force textareas to display maxlength attribute
Page.Controls.All().OfType<TextBox>().ToList()
.Where(x => x.TextMode == TextBoxMode.MultiLine && x.MaxLength > 0)
.ToList().ForEach(t => t.Attributes.Add("maxlength", t.MaxLength.ToString()));
}
I am trying to create a logout button through dynamically generated HTML (string).
htmlGen = "<div class=\"issue\" style=\"float:right; width:70%;\">";
htmlGen += "Welcome, " + Page.User.Identity.Name.ToString() + " ( logout )";
As you can see, the logout method is in the server code:
public void LogOut_OnClick(object sender, EventArgs args) {
FormsAuthentication.SignOut();
string htmlGen = "<div class=\"issue\" style=\"float:right; width:45%;\">";
htmlGen += "<a style=\"color:White;\" href=\"/Login.aspx\">Login</a>";
htmlGen += " | <a style=\"color:White;\" href=\"/Accounts/SignUp.aspx\">Register</a>";
this.Literal1.Text = htmlGen + "</div>";
FormsAuthentication.RedirectToLoginPage();
}
No matter what i do, this doesn't seem to work (won't fire, won't log out, etc). Is there something about doing this as an HTML string to a literal that is causing this?
Would somebody mind telling me how to do this?
Thanks!
First, you are trying to do a post back using a javascript client side event (onlick="..."). Also, using ASP.net directive <%= %> in the code behind won't work. In fact, if you check right now in your rendered HTML on your browser, you probably have something along these lines:
onclick="<%=LogOut_OnClick%>"
Anyway, if you can't generate this code in your aspx file, you should consider replacing this by the __dopostback javascript function (http://stackoverflow.com/questions/3591634/how-to-use-dopostback):
[...] htmlGen += "onclick=\"__dopostback('" + LogOutButton.ID + "')\""; [...]
However, you should really consider putting all this code inside your aspx file in a way or another. Here's how I would do it:
Welcome, <%= UserName %> (<asp:LinkButton ID="LogoutButton" Text="Logout" runat="server"/>)
iam using calender control in asp.net 2.0
as it is using master pages.. iam opening a window form content pages..
on window.close it is giving me null object as its not getting form name
you help will be appreciated
code on content page:
<a onclick="openwindow();" ahref="#">
<img src="Images/calendar.gif" style="width: 20px; height: 20px" border=0/></a>
<input ID="Text1" runat="server" readonly="readOnly" type="text" />
function openwindow() {
window.open('/Calender.aspx', 'calendar_window','width=154,height=188');
}
code on opened window from content page
protected void Calender1_SelectionChanged(object sender, EventArgs e)
{
string strjscript = "<script language='javascript'>";
strjscript += "window.opener." + HttpContext.Current.Request.QueryString["formname"];
strjscript += ".value = '" + Calender1.SelectedDate.ToString("yyyy-MM-dd") + "'; window.close();";
strjscript += "</script" + ">";
Literal1.Text = strjscript;
}
protected void Calendar1_dayrender(object sender, DayRenderEventArgs e)
{
if(e.Day.Date==DateTime.Now)
{
e.Cell.BackColor = System.Drawing.Color.LightGray;
}
}
Looks like you are not following this tutorial but not exactly what it is doing.
Points to note:
1: Make sure you are naming your form
2: Pass textbox reference via querystring i.e. Calender.aspx?formname=frmCalendar.txtDate
3: Path to your calender.aspx is correct.
You are close to solution but may be you need to share your main page code as well for us.
Edit 1
Ok I see now what you are saying. Add this script block to your content page:
<script type="text/javascript">
function openwindow() {
var txtid = '<%=txtDate.ClientID %>';
var frmid = '<%=Page.Form.ClientID %>';
var qs = "formname=" + frmid + "." + txtid;
window.open('/Calendar.aspx?' + qs,'calendar_window', 'width=154,height=188');
}
</script>
Although if possible try using jquery datepicker and you can post your code and issue if you want to go that route.
I am writing a javascript in asp.net server side (with in a button click event), this script is called if the user id and password matches and it supposed to close current window and open welcome page, but it is not happening. Below is my code, can anyone help me figure out what is the problem?
protected void okbtn_Click(object sender, EventArgs e)
{
account.txtuser = txtuid.Text;
account.txtpwd = txtupwd.Text;
account.login();
if (account.data == true)
{
string script = "<script language='javascript' type='text/javascript'>function f11(){window.close();var strLocation ;var strProfileID ;if (top.opener == null){strLocation = 'YourAccount.aspx';window.location = strLocation;}else{strLocation = 'http://' + top.opener.location.hostname+':'+ window.location.port + '/SendMail/' + 'YourAccount.aspx';top.opener.location = strLocation;top.opener.focus();}}</script>";
ClientScript.RegisterStartupScript(GetType(),"abc", script, true);
}
else
{
Label1.Text = "Invalid user name or password";
}
}
Add a OnClientClick event instead. For example:
<asp:Button id="okbtn" runat="server" text="OK" OnClientClick="window.close();" />
As for registering the startup script, you'd probably want to do this on Page_Load.
ClientScript.RegisterStartupScript(GetType(), "abc", script, true);
if you pass true argument at the end of the function parameters you don't need to add tags in your javascript codes because true means " tags will automatically wrap your javascript code"
Try in this way. If it doesn't help, please let us know.
Don't include <script></script> tag.
string script = "setTimeout(f11,10); function f11(){ window.close();}";
ClientScript.RegisterStartupScript(GetType(), "abc", script, true);