Using Nemiro OAuth library for Google authentication in Webforms - asp.net

I am trying to use Nemiro library to authenticate against Google in a Webforms asp.net project. This library documentation is at Nemiro GoogleClient Documenation
I have a simple aspx page called ExternalLogin.aspx, whose markup and code-behind are as given below.
Question
With code that I have, when Login using Google button is clicked, then user does not get directed to Google's authorization page. What is missing in my code that is causing this?
Markup
<%# Page Language="C#" AutoEventWireup="true" CodeFile="ExternalLogin.aspx.cs" Inherits="ExternalLogin" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Button ID="btnGoogle" runat="server" Text="Login using Google" OnClick="btnGoogle_Click" />
</div>
</form>
</body>
</html>
Code-behind
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Nemiro;
using Nemiro.OAuth.Clients;
using Nemiro.OAuth;
public partial class ExternalLogin : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void btnGoogle_Click(object sender, EventArgs e)
{
var result = OAuthWeb.VerifyAuthorization();
if (result.IsSuccessfully)
{
var user = result.UserInfo;
Response.Write(String.Format("User ID: {0}<br />", user.UserId));
Response.Write(String.Format("Name: {0}<br />", user.DisplayName));
Response.Write(String.Format("Email: {0}", user.Email));
}
}
}
I have also defined the keys for Google OAuth in Application_Start event as below.
void Application_Start(object sender, EventArgs e)
{
Nemiro.OAuth.OAuthManager.RegisterClient(
new Nemiro.OAuth.Clients.GoogleClient(
"some-value-1",
"some-value-2"
));
}

I think you should be looking at OAuthWeb.RedirectToAuthorization method. Here's the API doc for your reference. So just call this method in your btnGoogle_Click, and then verify your authorization in Page_Load event handler.
Here's the sample code:
protected void btnGoogle_Click(object sender, EventArgs e)
{
OAuthWeb.RedirectToAuthorization("Google", new Uri(Request.Url, "ExternalLogin.aspx").AbsoluteUri);
}
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostback)
{
var result = OAuthWeb.VerifyAuthorization();
if (result.IsSuccessfully)
{
var user = result.UserInfo;
Response.Write(String.Format("User ID: {0}<br />", user.UserId));
Response.Write(String.Format("Name: {0}<br />", user.DisplayName));
Response.Write(String.Format("Email: {0}", user.Email));
}
}
}
Also, if you'd like to verify the authorization results on a different page, just change the page name in the URI constructor, and put verification code in the Page_Load event of your new page.
Hope it helps.

Related

asp.net Web Forms - async await Exception

All,
I am using asp.net web forms, asp.net 4.7.2.
NOTE: The page is marked as
Async="true"
I have created a user control that has an event (in my example: ProcessOrder event). When the user control tries to raise the event
this.ProcessOrder?.Invoke(this, args);
I immediately get this exception:
System.InvalidOperationException: 'An asynchronous operation cannot be started at this time. Asynchronous operations may only be started within an asynchronous handler or module or during certain events in the Page lifecycle. If this exception occurred while executing a Page, ensure that the Page is marked <%# Page Async="true" %>. This exception may also indicate an attempt to call an "async void" method, which is generally unsupported within ASP.NET request processing. Instead, the asynchronous method should return a Task, and the caller should await it.'
The event handler method signature on the page is:
protected async void PaymentOptions_ProcessOrder(object sender, PaymentOptions.ProcessOrderEventArgs e)
and executes this line:
await _SubmitOrderAsync(e.PaymentToken, e.PaymentTokenDescriptor);
which in turn executes my send async email method
await this.CheckoutServices.TrySendOrderConfirmationEmailAsync(receipt);
Like I mentioned, I marked the page Async and I did follow the protocol for async methods, not sure what the problem is.
UPDATE:
I made slight change to the code, I removed async keyword from PaymentOptions_ProcessOrder event handler and therefore I am NOT awaiting _SubmitOrderAync() method anymore (which is fine since there's no code after it). But, in the SubmitOrderAsync() method
private async void _SubmitOrderAsync(string paymentToken, string paymentTokenDescriptor)
I am awaiting TrySendOrderConfirmationEmailAsync()
await this.CheckoutServices.TrySendOrderConfirmationEmailAsync(receipt);
Now, when I run this code, it blows up with the same exception when _SubmitOrderAsync() is invoked (it basically errors out on the first method decorated with async keyword). Not sure now, I have all my methods that are awaitable return a task with the exception of _SubmitOrderAsync() which I am not awaiting anymore.
UPDATE 2
OK, to troubleshoot this problem further, I created a dummy button on the very same page and created an async onclick event handler for it
protected async void btnGO_Click(object sender, EventArgs e)
I placed my async method TrySendOrderConfirmationEmailAsync() that I am trying to run in there and it works!
What is the difference between how the button click event handler is invoked vs my user control's event handler???? Again, I am using this line to invoke my event handler in the User Control:
this.ProcessOrder?.Invoke(this, args);
Should I be using different line??
According to the documentation, the only way to execute asynchronous code is using page asynchronous tasks.
Here's a working example:
Default.aspx:
<%# Page Language="C#" AutoEventWireup="True" CodeBehind="Default.aspx.cs" Inherits="WebApplication1.Default" Async="True" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<p>
<asp:Label ID="IsPostBackLabel" runat="server" Text=""></asp:Label>
</p>
<p>
<asp:Button ID="Button1" runat="server" Text="Button 1" OnClick="Button1_Click" /><asp:Label ID="IsButton1Label" runat="server" Text="Clicked!"></asp:Label>
</p>
<p>
<asp:Button ID="Button2" runat="server" Text="Button 2" OnClick="Button2_Click" /><asp:Label ID="IsButton2Label" runat="server" Text="Clicked!"></asp:Label>
</p>
<p>
<asp:Button ID="Button3" runat="server" Text="Button 3" OnClick="Button3_Click" /><asp:Label ID="IsButton3Label" runat="server" Text="Clicked!"></asp:Label>
</p>
</div>
</form>
</body>
</html>
Default.aspx.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebApplication1
{
public partial class Default : System.Web.UI.Page
{
private bool isPostBack;
private int buttonclicked;
protected override void OnLoad(EventArgs e)
{
this.RegisterAsyncTask(
new PageAsyncTask(
this.IsPostBack
? new Func<Task>(OnPostBackAsync)
: new Func<Task>(OnNotPostBackAsync)));
}
protected override void OnPreRenderComplete(EventArgs e)
{
base.OnPreRender(e);
this.IsPostBackLabel.Text = this.isPostBack
? "This was a post back!"
: "This was not a post back!";
this.IsButton1Label.Visible = this.buttonclicked == 1;
this.IsButton2Label.Visible = this.buttonclicked == 2;
this.IsButton3Label.Visible = this.buttonclicked == 3;
}
protected void Button1_Click(object sender, EventArgs e)
{
this.RegisterAsyncTask(
new PageAsyncTask(
() => OnButtonClickedAsync(1)));
}
protected void Button2_Click(object sender, EventArgs e)
{
this.RegisterAsyncTask(
new PageAsyncTask(
() => OnButtonClickedAsync(2)));
}
protected void Button3_Click(object sender, EventArgs e)
{
this.RegisterAsyncTask(
new PageAsyncTask(
() => OnButtonClickedAsync(3)));
}
private async Task OnPostBackAsync()
{
await Task.Delay(1).ConfigureAwait(false);
this.isPostBack = true;
}
private async Task OnNotPostBackAsync()
{
await Task.Delay(1).ConfigureAwait(false);
this.isPostBack = false;
}
private async Task OnButtonClickedAsync(int button)
{
await Task.Delay(1).ConfigureAwait(false);
this.buttonclicked = button;
}
}
}

Asp.net form links

How can I use a link in asp.net as a button. What's the right way to do this? For example with a label I'm doing it like this:
<a class="navbar-brand" href="#">Welkom<asp:Label ID="txtWelkom" runat="server" Text=""></asp:Label></a>
And then I set the label to a value that I received from the server for example:
txt.Welkom = name;
So how can I do this with a link (without seeing the button).
Is this the right way to do it (in asp.net forms)?
You want the LinkButton Control:
On .aspx side
<asp:LinkButton ID="lnkWelkom" runat="server" OnClick="lnkWelkom_OnClick" />
Code behind (aspx.cs)
using System;
using System.Web.Security.AntiXss;
using System.Web.UI;
namespace StackOverflowExamples.WebForms
{
public partial class _Default : Page
{
protected void Page_Load(object sender, EventArgs e)
{
var name = "";
lnkWelkom.Text = AntiXssEncoder.HtmlEncode(name, true);
}
protected void lnkWelkom_OnClick(object sender, EventArgs e)
{
//Do stuff
}
}
}

How do I have a usercontrol add a Html String to Head of a MasterPage

I know this is easy when you know what you are adding. For example, with a UI control its
Page.Header.Controls.Add([control])
However, I am pulling HTML code from a CMS database. In other words, I need to add a string to the Head section of the master page.
You can add a Literal control to the Header by using code similar to the one you show in your question:
public partial class MyUserControl : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
var lit = new LiteralControl();
lit.Text = "<link href=\"test.css\" rel=\"stylesheet\" />";
Page.Header.Controls.Add(lit);
}
}
If you're using a master page, you could:
Master page markup:
<html>
<head runat="server">
<asp:ContentPlaceHolder ID="MyHeadContentPlaceHolder" runat="server"></asp:ContentPlaceHolder>
</head>
</html>
Content page markup:
<asp:Content ID="MyContent" ContentPlaceHolderID="MyHeadContentPlaceHolder" runat="server">
<asp:Literal ID="MyLiteralForCmsContent" runat="server"></asp:Literal>
</asp:Content>
Content page code-behind:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
//Load the literal with content from the CMS.
this.MyLiteralForCmsContent.Text = ""; //Hook up the call to the CMS here.
}
}

Event Bubbling From Web User Controls in ASP.NET

I have two UserControls - UserControl1.ascx and UserControl2.ascx in PageDefault.aspx:
How I can call the method (GetLabelText() in UserControl1.ascx) from UserControl2.ascx using event bubbling?
This is my example code - When I click on the button (UserControl2Button1 in UserControl1.ascx) - I want to call the method GetLabelText() from UserControl2.ascx - using event bubbling.
PageDefault.aspx:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="PageDefault.aspx.cs" Inherits="TelerikAjaxEvents.PageDefault" %>
<%# Register TagPrefix="uc" TagName="UserControl1" Src="~/UserControl1.ascx" %>
<%# Register TagPrefix="uc" TagName="UserControl2" Src="~/UserControl2.ascx" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Page Default</title>
</head>
<body>
<form id="form1" runat="server">
UserControl1:
<uc:UserControl1 ID="UserControl1" runat="server" />
UserControl2:
<uc:UserControl2 ID="UserControl2" runat="server" />
</form>
</body>
</html>
UserControl1.ascx
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="UserControl1.ascx.cs" Inherits="TelerikAjaxEvents.UserControl1" %>
<asp:Label ID="UserControl1Label1" runat="server"></asp:Label>
UserControl1.ascx.cs
public partial class UserControl1 : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
}
public void GetLabelText()
{
UserControl1Label1.Text = "Text is Visible";
}
}
UserControl2.ascx
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="UserControl2.ascx.cs" Inherits="TelerikAjaxEvents.UserControl2" %>
<asp:Button ID="UserControl2Button1" runat="server" Text="Send"
onclick="UserControl2Button1_Click" />
UserControl2.ascx.cs
public partial class UserControl2 : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void UserControl2Button1_Click(object sender, EventArgs e)
{
//Call method from UserControl1 (GetLabelText()) - Show Label text - USING BUBBLE EVENT
}
}
There are many ways to go about this. Mark's answer hints at what was classically known as event bubbling using a built in functionality part of System.Web.UI.Control base control. However, it's a simple exercise to expose your own event, bind to it, and bubble up events through a control hierarchy. For more details on using BubbleEvent in ASP.NET read the following. Please keep in mind that both of these MSDN articles were written for .NET 1.1
Bubbling an Event
Event Bubbling Control Sample
K. Scott Allen does a good job at demonstrating exactly what an "event bubbling" implementation looks like in his post: Event Bubbling From Web User Controls in ASP.NET (C#) . See the following modification to your example for inspiration.
UserControl1 with GetLabelText()
public partial class UserControl1 : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
}
public void GetLabelText()
{
UserControl1Label1.Text = "Text is Visible";
}
}
UserControl2 with exposed BubbleClick event handler that callers can subscribe to.
public partial class UserControl2 : System.Web.UI.UserControl
{
protected Button UserControl2Button1;
protected void Page_Load(object sender, EventArgs e)
{
}
public event EventHandler BubbleClick;
protected void OnBubbleClick(EventArgs e)
{
if(BubbleClick != null)
{
BubbleClick(this, e);
}
}
protected void UserControl2Button1_Click(object sender, EventArgs e)
{
// do some stuff
OnBubbleClick(e);
}
}
PageDefault subscribes to UserControl2's BubbleClick event handler and executes UserControl1.GetLabelText()
public partial class PageDefault : WebPage
{
UserControl1 userControl1;
UserControl2 userControl2;
protected void Page_Load(object sender, EventArgs e)
{
UserControl2.BubbleClick += RootBubbleClickHandler;
}
protected void RootBubbleClickHandler(object sender, EventArgs e)
{
if (sender is UserControl2)
{
// subscribe UserControl1 to UserControl2 click event and do something
userControl1.GetLabelText();
}
// check for other controls with "BubbleClicks"
}
}
Event Bubbling is a poorly understood concept in ASP.NET WebForms. It does exist (and is used by most of the databound controls), but is often mistaken for the simpler concept of "implement an event in a user control" (as K Scott Allen does).
The core of event bubbling is that the event travels up through the control hierarchy until it is handled or hits the root. This allows some centralization of handler code. It is implemented using the Control.RaiseBubbleEvent and Control.OnBubbleEvent methods. The main use case is controls with a lot of child controls (think Repeaters, ListViews, etc.). Instead of subscribing to each individual control, the Repeater catches them all in it's OnBubbleEvent and raises a single ItemCommandEvent for them.
If you really wanted to use event bubbling (as opposed to K. Scott's example), it'd look something like:
class Page {
override bool OnBubbleEvent(object sender, EventArgs e) {
var btn = sender as Button;
if (btn == null) return false;
// You may want to do further checking that the source is what you want
// You could use CommandEventArgs to do this
this.uc1.GetLabelText();
return true;
}
}
The sequence of events goes like this:
- Button Clicked
- Button RaiseBubbleEvent
- UserControl OnBubbleEvent returns false (default, since you didn't override)
- Page OnBubbleEvent
Can you try declaring the UserControl1 as public property(e.g. "UserControl1") on the PageDefault.aspx and then in the UserControl2, use Parent.Page.UserControl1.GetLabelText()?

ASP.NET refer a control from .aspx file

I have the following code :
<html xmlns="http://www.w3.org/1999/xhtml">
<body style="height: 1336px">
<input type="hidden" id="loadingtime"/>
.
.
.
.
</body>
</html>
and the Code.cs file is :
using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Diagnostics;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button1_Click(object sender, EventArgs e)
{
string s = "";
HiddenField t = (HiddenField)Page.FindControl("loadingtime");
s = t.Value;
Response.Write("<script language='javascript'>alert('It took : " + s + "')</script>");
}
}
I get error
Any idea?
EDIT :
The above problem is successfully solved by
Now when I retrieve the value of loading time, the value is empty string. Can anyone please solve this one?
Your input should have runat="server" enabling it to be parsed by the ASP.NET runtime i.e.
<input type="hidden" runat="server" id="loadingtime"/>
You can then refer to the control as you would normally in code behind using:
HiddenField t = (HiddenField)loadingtime;
AS LONG AS it is not wrapped in another server control such as an asp:repeater in which case you would need to use alternative method of traversing the control hierarchy

Resources