DotNetOpenAuth - OnLoggedIn not firing on OpenIdButton - c#

I am trying to implement OpenID for a website using only Google as the authentication provider. I am using the OpenIdButton control to send users to their Google Apps login since I always want them to go to the same place.
The button sends them to the right place and returns them to the ReturnToUrl correctly but it doesn't seem that the OnLoggedIn event ever fires. I am checking the event by setting a TextBox value in the method and I am seeing no change in the TextBox value. Here is my code...
<tr>
<td>
<asp:TextBox ID="devMsg" runat="server"/>
</td>
</tr>
<tr>
<td valign="top" align="center">
<font size="-1"><b>Sign in with your</b></font>
<br />
<br />
<rp:OpenIdButton ID="OpenIdButton1" runat="server" Text="Login with your Google account!"
ImageUrl="http://www.google.com/accounts/google_transparent.gif"
Identifier="https://www.google.com/accounts/o8/site-xrds?hd=dev.connexcloud.com"
ReturnToUrl="http://localhost:1587/OpenIdRelyingPartyWebForms/loginGoogleApps.aspx"
OnLoggedIn="OpenIdLogin_LoggedIn" />
<br />
<br />
<font size="-1"><b>Account</b></font>
</td>
</tr>
protected void OpenIdLogin_LoggedIn(object sender, OpenIdEventArgs e)
{
this.devMsg.Text = "no response";
if (e.Response != null)
{
devMsg.Text = "response";
switch (e.Response.Status)
{
case AuthenticationStatus.Authenticated:
this.devMsg.Text = "authenicated";
break;
case AuthenticationStatus.Canceled:
this.devMsg.Text = "canceled";
break;
case AuthenticationStatus.Failed:
this.devMsg.Text = "failed";
break;
}
}
}
The TextBox is never being set to anything so it looks to me like the OpenIdLogin_LoggedIn call is never being made when the response is coming back from Google.

Have you tried setting a breakpoint in your LoggedIn handler? I suspect it's working. After the LoggedIn handler is invoked, the control calls FormsAuthentication.RedirectFromLoginPage with the OpenID claimed identifier, which would scrub the TextBox that you're setting in it before you noticed it.
Another way besides a breakpoint you can test it is by setting e.Cancel = true in your handler, which suppresses the subsequent call to FormsAuthentication.RedirectFromLoginPage.

Related

Changing Text Box to List Drop down gives "Invalid postback or callback argument" error

I have form which was built on Asp.Net platform. This form works as expected whe we enter entry as text for both Country and State and I can submit the data to the database. Now I need to change the code with the logic to have drop down for Country and State. Example: If United States is selected it shows related states and user need to select the entry from drop down and submit the form and it should save it in database. I haven't changed anything in code behind in the working code, just adding the list drop down instead of Text entry for both Country and State. I am getting error "Invalid postback or callback argument" when I click the Submit button for submission. I have included the working code with text box entry and the change I have done by replacing with the list drop down. I have also included the error detail I am getting. Looking at other postings on stackoverflow, I added enableEventValidation="false" in .aspx page, but it didn't solve the issue. Any idea how can I resolve this?
.aspx Code with Text box field: (This is working)
<tr>
<td><div align="right"><span class="style4">*</span> State:</div><asp:RequiredFieldValidator id="reqstate" ControlToValidate="state" ErrorMessage="Required Field!" runat="server" /></td>
<td><asp:TextBox runat="server" name="state" type="text" id="state" size="30" /></td>
</tr>
<tr>
<td><div align="right"><span class="style4">*</span> Country:</div><asp:RequiredFieldValidator id="reqcountry" ControlToValidate="country" ErrorMessage="Required Field!" runat="server" /></td>
<td><asp:TextBox runat="server" name="country" type="text" id="country" size="30" /></td>
</tr>
Changed .aspx Code with List Drop Down: (This is not working)
<tr>
<td><div align="right"><label id="stateLabel" style="display: none"><span class="style4">*</span> State:</label></div><asp:RequiredFieldValidator id="reqstate" ControlToValidate="state" ErrorMessage="Required Field!" runat="server" /></td>
<td><asp:ListBox name="state" id="state" style="display: none" rows="1" runat="server"></asp:ListBox></td>
</tr>
<tr>
<td><div align="right"><span class="style4">*</span> Country:</div><asp:RequiredFieldValidator id="reqcountry" ControlToValidate="country" ErrorMessage="Required Field!" runat="server" /></td>
<td>
<asp:ListBox id="country" onchange="javascript:countryChange()" rows="1" runat="server">
<asp:ListItem selected="false">Select Country</asp:ListItem>
<asp:ListItem>United States</asp:ListItem>
<asp:ListItem>Canada</asp:ListItem>
</asp:ListBox>
</td>
</tr>
<!--Country and State Change Javascript-->
<script>
function countryChange() {
var countryState = [
[
'US', [
['', 'State/Province'],
['AL', 'Alabama'],
['AK', 'Alaska'],
['AZ', 'Arizona'],
['AR', 'Arkansas'],
], ],
[
'CA', [
['', 'State/Province'],
['AB', 'Alberta'],
['BC', 'British Columbia'],
['MB', 'Manitoba'],
['NB', 'New Brunswick'],
]]
];
var countryElement = document.getElementById('countryId');
var stateElement = document.getElementById('stateId');
var stateLabelElement = document.getElementById('stateLabel');
if (countryElement && stateElement) {
var listOfState = [
['XX', 'None']
];
var currentCountry = countryElement.options[countryElement.selectedIndex].value;
for (var i = 0; i < countryState.length; i++) {
if (currentCountry == countryState[i][0]) {
listOfState = countryState[i][1];
}
}
if (listOfstate.length < 2)
{
stateElement.style.display = 'none';
stateLabelElement.style.display = 'none';
}
else
{
stateElement.style.display = 'inline';
stateLabelElement.style.display = 'inline';
}
var selectedState;
for (var i = 0; i < stateElement.length; i++) {
if (stateElement.options[i].selected === true) {
selectedState = stateElement.options[i].value;
}
}
stateElement.options.length = 0;
for (var i = 0; i < listOfState.length; i++) {
stateElement.options[i] = new Option(listOfState[i][1], listOfState[i][0]);
if (listOfState[i][0] == selectedState) {
stateElement.options[i].selected = true;
}
}
}
}
</script>
Error I am getting:
Invalid postback or callback argument. Event validation is enabled
using in configuration or <%#
Page EnableEventValidation="true" %> in a page. For security
purposes, this feature verifies that arguments to postback or callback
events originate from the server control that originally rendered
them. If the data is valid and expected, use the
ClientScriptManager.RegisterForEventValidation method in order to
register the postback or callback data for validation.

Using FindControl to find the contents of an HTML control

I've got this code in the code-behind on my page, which works perfectly fine for a repeater:
protected void AcctAssnRepeater_ItemCommand(object source, RepeaterCommandEventArgs e)
{
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["PBRConnectionString"].ConnectionString);
con.Open();
{
string str10 = ((HtmlInputText)e.Item.FindControl("txtFlgUpdatedOn")).Value;
}
}
I'm trying to do something similar on another page, but it is telling me that "item" isn't valid:
protected void btnSubmit_OnClick(object sender, EventArgs e)
{
string str10 = ((HtmlInputText)e.Item.FindControl("txtDtSentToCIS")).Value;
}
I'm still a C# n00b, can anyone tell me how to reference the value inside this control? Both pages have a runat="server" on the aspx side, so I would expect that there's a way to do it, I'm sure my syntax just needs adjusting.
Thanks!
EDIT: Here's a piece of the aspx. Maybe I should note that it's all inside a Tab Control.
<div style="width:430px;border:1px solid blue;float:left;">
<asp:Panel ID="Panel3" runat="server" Height="220px" style="float:left; margin-left: 19px"
Width="410px">
<table>
<tr>
<td width="210px">BIL Name:</td>
<td width="200px"><asp:textbox id="txtCISName" runat="server"></asp:textbox></td>
</tr>
<tr>
<td width="210px">Date Sent To BIL:</td>
<td width="200px"><input type="text" id="txtDtSentToCIS" class="datepicker" name="txtDtSentToCIS" runat="server" style="height: 14px; width: 70px" /></td>
</tr>
<tr>
<td width="210px">BIL Sign Off Received:</td>
<td width="200px"><asp:DropDownList ID="cboCISSignOff" runat="server" Height="16px"
AutoPostBack="True" onselectedindexchanged="chkCISSignOff_CheckedChanged">
<asp:ListItem>N</asp:ListItem>
<asp:ListItem>Y</asp:ListItem>
</asp:DropDownList></td>
</tr>
<tr>
<td width="210px"><asp:Label runat="server" Text="BIL Response:" ID="CISResp" /></td>
<td width="200px"><asp:textbox id="txtCISResponse" runat="server"
textmode="MultiLine" rows="9" Width="180px"></asp:textbox></td>
</tr>
</table>
</asp:Panel>
</div>
You should be able to use the ID to reach the control. For ex. a textbox:
<asp:TextBox ID="txtDtSentToCIS" runat="server" />
In your code behind you can do something as
SomeMethod(this.txtDtSentToCIS.Text);
or
string enteredByUser = this.txtDtSentToCIS.Text;
If you want to access repeater containing textbox(es) from outside the repeater, you may code like this:
Iterating the RepeaterItemCollection:
foreach (RepeaterItem item in Repeater1.Items)
{
TextBox txtDtSentToCIS = item.FindControl("txtDtSentToCIS") as TextBox;
}
Or simply accessing through indexer:
TextBox txtDtSentToCIS = Repeater1.Items[1].FindControl("txtDtSentToCIS") as TextBox;
Good luck.
If you are using asp I would suggest that you use an asp Text box.
<asp:TextBox ID="textBoxName" runat="server" />
When the button is clicked and you OnClick method is called you can search for the text box by name and assign the text to your string.
string str10 = textBoxName.text;
You don't really need to use the find control unless that control is buried in another control like a grid view or login view.
What could be happening is that the FindControl method only works for the first control collection in this case the only control contained is "Panel3", try this:
var panel = e.Item.FindControl("Panel3") as Panel;
string str10 = ((HtmlInputText)panel.FindControl("txtFlgUpdatedOn")).Value;
Good luck

When exactly does the OnItemUpdated event fire specifically in a FormView in ASP.NET?

I can't for the life of me figure out when OnItemUpdated gets fired. I've been messing around in ASP.NET trying to learn it, so some of the things you see in this code might be purposely done the hard way (so I can better understand whats going on behind the scenes)
Basically, I have a GridView that is the master control that uses a formview as a detail.
Here is the SelectedIndexChanged method for GridView
protected void GridView1_SelectedIndexChanged(object sender, EventArgs e)
{
var context = new DataAccessLayer.SafetyEntities();
var se = (from c in context.Employees
where c.EID == (long)GridView1.SelectedDataKey.Value
select c).ToList();
FormView1.DataSource = se;
FormView1.DataKeyNames = new string[] { "EID" };
FormView1.DataBind();
}
That's working fine, it displays the selected details in the form for editing. This is what the formview looks like:
<asp:FormView ID="FormView1" runat="server" DefaultMode="Edit" OnItemUpdating = "FormView1_ItemUpdating" OnItemUpdated="BLAH">
<ItemTemplate>
Select an employee!
</ItemTemplate>
<EditItemTemplate>
<table>
<tr>
<th>Name:
</th>
<td>
<asp:TextBox runat="server" ID ="NameEdit" Text='<%#Bind("Name") %>' />
</td>
<br />
</tr>
<tr>
<th>Manager:
</th>
<td>
<asp:DropDownList ID = "DDLEdit1" DataSourceID = "ManagerEntitySource" runat="server"
DataTextField = "Option_Value" DataValueField = "Option_Value"
SelectedValue = '<%#Bind("Manager") %>'
AppendDataBoundItems="true">
</asp:DropDownList>
</td>
<br />
</tr>
<tr>
<th>Location:
</th>
<td>
<asp:DropDownList ID="DDLEdit2" DataSourceID = "LocationEntitySource" runat="server"
DataTextField = "Option_Value" DataValueField = "Option_Value"
SelectedValue='<%#Bind("Building") %>'
AppendDataBoundItems="true">
</asp:DropDownList>
</td>
<br />
</table>
<asp:Button ID="Button2" Text="Submit Changes" runat="server" CommandName="Update" />
<!--<asp:LinkButton ID = "LB1" Text="Update" CommandName="Update" runat="server" /> -->
</EditItemTemplate>
</asp:FormView>
This works as well. You can see from the attributes of the FormView that I specify OnItemUpdating and OnItemUpdated.
Here is OnItemUpdating:
protected void FormView1_ItemUpdating(object source, FormViewUpdateEventArgs e)
{
DebugBox.Text = FormView1.DataKey.Value.ToString();
DataAccessLayer.SafetyEntities se = new DataAccessLayer.SafetyEntities();
var key = Convert.ToInt32(FormView1.DataKey.Value.ToString());
DataAccessLayer.Employee employeeToUpdate = se.Employees.Where(emp => emp.EID == key).First();
employeeToUpdate.Name = e.NewValues["Name"].ToString();
employeeToUpdate.Manager = e.NewValues["Manager"].ToString();
employeeToUpdate.Building = e.NewValues["Building"].ToString();
se.SaveChanges();
GridView1.DataBind();
}
This works fine as well. The items are being updated appropriately and the GridView is refreshing.
Here is OnItemUpdated:
protected void BLAH(object source, FormViewUpdatedEventArgs e)
{
DebugBox2.Text = "BLAH!!!!";
}
And here is the problem. This never gets called! Am I missing a step somewhere to get this event to fire? I thought I understood that the button would call Command="Update" which would fire ItemUpdating and then ItemUpdated. Its definitely calling ItemUpdating, but thats it. Do I need something additional to fire ItemUpdated?
Conclusion:
Looking at the source code of the FormView class it seems that the ItemUpdated event is not fired when using DataBinding.
The ItemUpdated event only gets fired when you set the SelectMethod, UpdateMethod, DeleteMethod or InsertMethod properties of the FormView.
The proof
When you're updating an item in your FormView its 'UpdateItem' method is called which internally calls HandleUpdate.
public virtual void UpdateItem(bool causesValidation)
{
this.ResetModelValidationGroup(causesValidation, string.Empty);
this.HandleUpdate(string.Empty, causesValidation);
}
private void HandleUpdate(string commandArg, bool causesValidation)
{
// Lots of work is done here
}
At the bottom of the HandleUpdate method, the OnItemUpdating event is triggered:
this.OnItemUpdating(e);
which is then followed by a rather curious line of code:
if (e.Cancel || !bindingAutomatic)
return;
This in turn is followd by a call to Update on the dataSourceView.
dataSourceView.Update((IDictionary) e.Keys, (IDictionary) e.NewValues,
(IDictionary) e.OldValues,
new DataSourceViewOperationCallback(this.HandleUpdateCallback));
We can see that the last parameter of the Update method takes a callback which in this case is HandleUpdateCallback. HandleUpdateCallback is the place where our OnItemUpdated event is finally triggered.
private bool HandleUpdateCallback(int affectedRows, Exception ex)
{
FormViewUpdatedEventArgs e1 = new FormViewUpdatedEventArgs(
affectedRows, ex);
e1.SetOldValues(this._updateOldValues);
e1.SetNewValues(this._updateNewValues);
e1.SetKeys(this._updateKeys);
this.OnItemUpdated(e1);
// A lot of other stuff goes on here
}
So, that's the map of how we eventually get to the OnItemUpdated method being executed but why isn't it being executed in our case?
Let's skip back a little but to the "curious" part of the HandleUpdate method I mentioned earlier:
if (e.Cancel || !bindingAutomatic)
return;
What's going on here? We're not cancelling our event but what about !bindingAutomatic, what's happening there?
The value is set further up in the HandleUpdate method:
bool bindingAutomatic = this.IsDataBindingAutomatic;
This property, IsDataBindingAutomatic, is an internal property on the BaseDataBound class (a base class bit further up the chain from our FormView class):
protected internal bool IsDataBindingAutomatic
{
get
{
if (!this.IsBoundUsingDataSourceID)
return this.IsUsingModelBinders;
else
return true;
}
}
Since we're not using a DataSourceID we end up returning the value of IsUsingModelBinders. This is a virtual property on the BaseDataBoundControl that is overriden in the CompositeDataBoundControl class, the base class that our FormView directly inherits from.
Now we get to the bit of code that directly determines whether our OnItemUpdating method will be fired:
protected override bool IsUsingModelBinders
{
get
{
if (string.IsNullOrEmpty(this.SelectMethod)
&& string.IsNullOrEmpty(this.UpdateMethod)
&& string.IsNullOrEmpty(this.DeleteMethod))
return !string.IsNullOrEmpty(this.InsertMethod);
else
return true;
}
}
This is basically saying that if we've set a SelectMethod, an UpdateMethod, or a DeleteMethod (these are string properties on the FormView) then return true, otherwise tell us if we've set an InsertMethod. In our case we haven't set any of these properties up and so we get a return value of false.
Because this is false, our curious piece of code from twice earlier simply returns and never reaches the part of the code that triggers the ItemUpdated event.

Finding Captcha control inside createuserwizard

I am integrating a Captcha control inside a CreateUserWizard.
I got the Captcha control sample code from this website here
As I wanted to do a validation for user's input based on the Captcha using an if.. else.. statement.
However an error occured when I trying to get the Captcha control from the createuserwizard.
Here the is error :
The name 'Captcha1' does not exist in the current context
I had tried to get this control as a textbox, image, control but it was not successful.
Here is the code :
<asp:CreateUserWizardStep ID="CreateUserWizardStep1" runat="server">
<ContentTemplate>
<tr>
<td class="style4">Answer:</td>
<td>
<cc1:CaptchaControl ID="Captcha1" runat="server"
CaptchaBackgroundNoise="Medium" CaptchaLength="5"
CaptchaHeight="55" CaptchaWidth="200"
CaptchaLineNoise="None" CaptchaMinTimeout="5"
CaptchaMaxTimeout="240" FontColor = "#FF33CC" CaptchaFontWarping="Medium" />
<asp:TextBox runat="server" ID="txtCaptcha" />
</td>
</tr>
</ContentTemplate>
</asp:CreateUserWizardStep>
Behind code:
protected void CreateUserWizard1_CreatedUser(object sender, EventArgs e)
{
//Control Captcha1 = (Control)CreateUserWizardStep1.ContentTemplateContainer.FindControl("Captcha1");
TextBox txtCaptcha = (TextBox)CreateUserWizardStep1.ContentTemplateContainer.FindControl("txtCaptcha");
Captcha1.ValidateCaptcha(txtCaptcha.Text.Trim());//error occurred here
if (Captcha1.UserValidated)//error occurred here
{
}
}
Try this to find the Controls inside the CreateUserWizard
TextBox txtCaptcha = (TextBox)CreateUserWizardStep1.CreateUserStep.ContentTemplateContainer.FindControl("txtCaptcha");

Multiview - View Clear State

Thanks in advance for your help.
I am using c#.net.
I have two views on my webpage (contained within one multiview), both contain buttons.
view_1
Contains a repeater/datasource and an custom made ‘edit’ button (which holds the ID for each row returned).
view_2
Contain an ‘update’ form and a ‘update’ button. When the user presses the update button the information within the database for that particular row is updated.
The problem I believe lies with my ‘update’ button within view_2
Code behind (‘update’ button), I have an if statement:
protected void Page_Load(object sender, EventArgs e)
{
updateSuccessFailed.Visible = false;
if (!Page.IsPostBack)
{
_multiView1.ActiveViewIndex = 0;
}
}
protected void update_Click(object sender, EventArgs e)
{
var Id = Convert.ToInt32((ID.Value));
notYetUpdated.Visible = true;
updateSuccessFailed.Visible = false;
tblV updateV = new tblV();
updateV.vID = venueId;
updateV.vame = updateName.ToString();
updateV.vPostcode = updatePropPostcode.ToString();
if (vRepos.Update(updateV))
{
notYetUpdated.Visible = false;
updateSuccessFailed.Visible = true;
updateMessage.Text = "Updated.";
}
else
{
notYetUpdated.Visible = false;
updateSuccessFailed.Visible = true;
updateMessage.Text = "An error has occurred, please try again.";
}
}
_view2
<asp:View ID="_view2" runat="server">
<div style="text-align:center" runat="server" id="notYetUpdated">
<table border="0" cellspacing="1">
<tr>
<td style="text-align:left;">Name</td>
<td style="text-align:left;"><asp:TextBox ID="updateName" MaxLength="60" runat="server" /></td>
</tr>
<tr>
<td style="text-align:left;">Postcode</td>
<td style="text-align:left;"><asp:TextBox ID="updatePropPostcode" MaxLength="60" runat="server" /></td>
</tr>
</table><br />
<asp:Button ID="updateVCancel" Text="Cancel" runat="server" onclick="cancel_Click" CssClass="standardButton" />
<asp:Button ID="updateVConfirm" Text="Update" runat="server" onclick="update_Click" CssClass="standardButton" />
<asp:HiddenField ID="vUpdateID" runat="server" />
</div>
<div style="text-align:center" runat="server" id="updateSuccessFailed">
<p><asp:Label ID="updateMessage" runat="server" /></p>
<asp:Button ID="updateBack" Text="Back To Start" runat="server" onclick="backToStart_Click" CssClass="standardButton" />
</div>
</asp:View>
notYetUpdated / updateSuccessFailed are div’s which hold different information.
When the user first ‘updates’ a record it make the right div visible. (notYetUpdated – holds the form information / updateSuccessFailed – holds a message to state whether the record has been updated or not). However when you access the view_2 again it accesses the update_Click event and updateSuccessFailed is visible even though it shouldn’t be.
I thought I could clear all stored information within the viewstates with the code below, however this is not working.
ViewState.Clear();
ClearChildViewState();
Thanks
Clare :-)
The 4th line should be updateSuccessFailed.Visible = false;?
This was an error on my part. I adapted my code, here it is:
var Id = Convert.ToInt32((ID.Value));
tblV updateV = new tblV();
updateV.vID = venueId;
updateV.vame = updateName.ToString();
updateV.vPostcode = updatePropPostcode.ToString();
notYetUpdated.Visible = false;
updateSuccessFailed.Visible = true;
if (vRepos.Update(updateV))
{
updateMessage.Text = "Updated.";
}
else
{
updateMessage.Text = "An error has occurred, please try again.";
}
Hope this helps other people.

Categories