One of my forms has a captcha.
I am forced to use this captcha since there's a lot of code already written before me.
This way is simple:
There is an ashx file. An image will be created using that file. At the same time, that file will create a session with the same value from the image.
Upon submission, the code will check whether they are the same. If so, continue. if not, return.
Upon page refresh, the captcha will update.
Then I need to add in ajax update panel as the requirement.
Then the captcha is still working fine in chrome and safari but it is not refreshing when the page loads again in IE and firefox.
I created a simple page just for captcha
aspx
<%# Page Language="C#" AutoEventWireup="true" CodeFile="Default7.aspx.cs" Inherits="Default7" %>
<!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></title>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<img height="30" alt="" src="Handler.ashx" width="80"><br>
<asp:Button ID="btnSubmit" runat="server" Text="Submit"
onclick="btnSubmit_Click"/>
</ContentTemplate>
</asp:UpdatePanel>
<div>
</div>
</form>
</body>
</html>
aspx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class Default7 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void btnSubmit_Click(object sender, EventArgs e)
{
}
}
handler.ashx
<%# WebHandler Language="C#" Class="Handler" %>
using System;
using System.Web;
using System.Web.SessionState;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Text;
public class Handler : IHttpHandler,System.Web.SessionState.IRequiresSessionState {
public void ProcessRequest(HttpContext context)
{
Bitmap objBMP = new System.Drawing.Bitmap(60, 20);
Graphics objGraphics = System.Drawing.Graphics.FromImage(objBMP);
//objGraphics.Clear(Color.Blue);
objGraphics.TextRenderingHint = TextRenderingHint.AntiAlias;
//' Configure font to use for text
Font objFont = new Font("Arial", 8, FontStyle.Bold);
string randomStr = "";
int[] myIntArray = new int[5];
int x;
//That is to create the random # and add it to our string
Random autoRand = new Random();
for (x = 0; x < 5; x++)
{
myIntArray[x] = System.Convert.ToInt32(autoRand.Next(0, 9));
randomStr += (myIntArray[x].ToString());
}
randomStr = GetRandomString();
//This is to add the string to session cookie, to be compared later
context.Session.Add("randomStr", randomStr);
//' Write out the text
objGraphics.DrawString(randomStr, objFont, Brushes.White, 3, 3);
//' Set the content type and return the image
context.Response.ContentType = "image/GIF";
objBMP.Save(context.Response.OutputStream, ImageFormat.Gif);
objFont.Dispose();
objGraphics.Dispose();
objBMP.Dispose();
}
public bool IsReusable
{
get
{
return false;
}
}
private string GetRandomString()
{
string[] arrStr = "A,B,C,D,1,2,3,4,5,6,7,8,9,0".Split(",".ToCharArray());
string strDraw = string.Empty;
Random r = new Random();
for (int i = 0; i < 5; i++)
{
strDraw += arrStr[r.Next(0, arrStr.Length - 1)];
}
return strDraw;
}
}
Any idea?
I got the answer now.
change image control to server control.
and in code behind change the image source with current date time
<img height="30" alt="" src="/Handler.ashx" width="80" runat="server" id="imgCaptcha">
imgCaptcha.Src = "Handler.ashx?dt=" + DateTime.Now.ToString();
change image control to server control.
and in code behind change the image source with current date time
<img height="30" alt="" src="/Handler.ashx" width="80" runat="server" id="imgCaptcha">
imgCaptcha.Src = "Handler.ashx?dt=" + DateTime.Now.ToString();
Related
I'm writing an admin page where I have a textbox for user name and a refresh button which shows user details when clicked. Among other controls, I have a 'remove user' button to delete the user. I have javascript code to get confirmation before attempting this.
Because I do not want this Remove User button to have submit behavior, I have set UseSubmitBehavior=False. However, this caused the server side event to not get fired. So I wrote a small client side function to explicitly call __doPostBack.
The final code works, but only on pages that are not based off of a master page or nested master pages. Sadly all my web pages are based off of master pages.
Wondering if I'm missing something or if there is a way around? I've just started asp.net so please excuse any obvious mistakes.
Many thanks in advance.
Code Sample:
Following code works (webform with no master page)
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm_with_NoMasterPage.aspx.cs" Inherits="WebApplication1.WebForm_with_NoMasterPage" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<script type="text/javascript">
function GetConfirmation(btn, msg) {
if (confirm(msg)) {
__doPostBack(btn.id, '');
return true;
}
else {
return false;
}
}
</script>
<asp:Button ID="btnRemoveUser" runat="server" Text="Remove User" OnClick="btnRemoveUser_Click"
OnClientClick="return GetConfirmation(btnRemoveUser, 'Really remove?');"
UseSubmitBehavior="false"
Height="37px" Width="230px" />
</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;
namespace WebApplication1
{
public partial class WebForm_with_NoMasterPage : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void btnRemoveUser_Click(object sender, EventArgs e)
{
// put a breakpoint here and see if it is hit.
int x = 0;
}
}
}
Following does not work (same fragment but in a Webform based on masterpage):
<%# Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="WebForm_WITH_MasterPage.aspx.cs" Inherits="WebApplication1.WebForm_WITH_MasterPage" %>
<asp:Content ID="Content1" ContentPlaceHolderID="HeadContent" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="FeaturedContent" runat="server">
</asp:Content>
<asp:Content ID="Content3" ContentPlaceHolderID="MainContent" runat="server">
<script type="text/javascript">
function GetConfirmation(btn, msg) {
if (confirm(msg)) {
__doPostBack(btn.id, '');
return true;
}
else {
return false;
}
}
</script>
<asp:Button ID="btnRemoveUser" runat="server" Text="Remove User" OnClick="btnRemoveUser_Click"
OnClientClick="return GetConfirmation(btnRemoveUser, 'Really remove?');"
UseSubmitBehavior="false"
Height="37px" Width="230px" />
</asp:Content>
Code behind:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebApplication1
{
public partial class WebForm_WITH_MasterPage : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void btnRemoveUser_Click(object sender, EventArgs e)
{
// put a breakpoint here and see if it is hit
int z = 0;
}
}
}
I have now working updatable news using xml, but whenever i refresh the 1st Page which is the Inserting/Updating Page it's still posting even if i emptied the textboxes.
Code of 1st HTML/ASPX File:
(
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml;
public partial class Main : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button1_Click(object sender, EventArgs e)
{
XmlDocument xmlfile = new XmlDocument();
xmlfile.Load(Server.MapPath("~/TestXML.xml"));
//create element
XmlElement theNewsTag = xmlfile.CreateElement("news");
XmlElement theTitleTag = xmlfile.CreateElement("title");
XmlElement theContentsTag = xmlfile.CreateElement("contents");
//create text node
XmlText theTitleText = xmlfile.CreateTextNode(xmlTitle.Text);
XmlText theContentsText = xmlfile.CreateTextNode(xmlContent.Text);
//append
theTitleTag.AppendChild(theTitleText);
theContentsTag.AppendChild(theContentsText);
theNewsTag.AppendChild(theTitleTag);
theNewsTag.AppendChild(theContentsTag);
//save
xmlfile.DocumentElement.AppendChild(theNewsTag);
xmlfile.Save(Server.MapPath("~/TestXML.xml"));
xmlTitle.Text = "";
xmlContent.Text = "";
Response.Redirect(Server.MapPath("~/Main.aspx"));
}
}
My 1st HTML/ASPX File (For inserting/Updating)
<h2>Title</h2>
<asp:TextBox ID="xmlTitle" runat="server"/>
<h2>Content</h2>
<asp:TextBox ID="xmlContent" runat="server"/>
<h2>Insert XML</h2>
<asp:Button ID="Button1" runat="server" Text="Post News"
onclick="Button1_Click" />
My 2nd HTML/ASPX File (For Viewing the XML File)
<%# Page Language="C#" AutoEventWireup="true" CodeFile="xmlpath.aspx.cs" Inherits="xmlpath" %>
<!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></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ListView ID="ListView1" runat="server" DataSourceID="newDS">
<LayoutTemplate>
<div id="ItemPlaceHolderContainer"></div>
<span id="ItemPlaceHolder" runat="server"></span>
</LayoutTemplate>
<ItemTemplate>
<h2><%#XPath("title") %></h2>
<p><%#XPath("contents") %></p>
</ItemTemplate>
</asp:ListView>
<asp:XmlDataSource ID="newDS" runat="server" DataFile="~/TestXML.xml">
</asp:XmlDataSource>
</div>
</form>
</body>
</html>
When you refresh your page it reposts the data, It also show you a dialog box
Confirm Form Resubmission so actually you are pressing the button again.
In your page load create this
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
Session["Key"] = "1";
}
}
and check the session before button click
protected void button_Click(object sender, EventArgs e)
{
if (Session["Key"].ToString() == "1")
{
XmlDocument xmlfile = new XmlDocument();
xmlfile.Load(Server.MapPath("~/TestXML.xml"));
//create element
XmlElement theNewsTag = xmlfile.CreateElement("news");
XmlElement theTitleTag = xmlfile.CreateElement("title");
XmlElement theContentsTag = xmlfile.CreateElement("contents");
//create text node
XmlText theTitleText = xmlfile.CreateTextNode(xmlTitle.Text);
XmlText theContentsText = xmlfile.CreateTextNode(xmlContent.Text);
//append
theTitleTag.AppendChild(theTitleText);
theContentsTag.AppendChild(theContentsText);
theNewsTag.AppendChild(theTitleTag);
theNewsTag.AppendChild(theContentsTag);
//save
xmlfile.DocumentElement.AppendChild(theNewsTag);
xmlfile.Save(Server.MapPath("~/TestXML.xml"));
xmlTitle.Text = "";
xmlContent.Text = "";
Response.Redirect(Server.MapPath("~/Main.aspx"));
Session["Key"] = "0"; // set key = 0
}
}
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I'm an C# ASP.NET beginner, so please excuse anything that's... not quite right!
In short, I want to create a really basic login system: one which runs through a database and uses sessions so that only logged in users can access certain pages. I know how to do most of that, but I'm stuck with querying data with LINQ on the login page.
On the login page, I have a DropDownList to select a username, a Textbox to type in a password and a button to login (I also have a literal for errors). The DropDownList is databound to a datatable called DT_Test. DT_Test contains three columns: UsernameID (int), Username (nchar(30)) and Password (nchar(30)). UsernameID is the primary key.
I want to make the button's click event query data from the database with the DropDownList and Textbox, in order to check if the username and password match. But I don't know how to do this...
Current Code (not a lot!):
Front End:
<%# Page Language="C#" AutoEventWireup="true" CodeFile="Login_Test.aspx.cs" Inherits="Login_Login_Test" %>
<!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>Login Test</title>
</head>
<body>
<form id="LoginTest" runat="server">
<div>
<asp:DropDownList ID="DDL_Username" runat="server" Height="20px"
DataTextField="txt">
</asp:DropDownList>
<br />
<asp:TextBox ID="TB_Password" runat="server" TextMode="Password"></asp:TextBox>
<br />
<asp:Button ID="B_Login" runat="server" onclick="B_Login_Click" Text="Login" />
<br />
<asp:Literal ID="LI_Result" runat="server"></asp:Literal>
</div>
</form>
</body>
</html>
Back End:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class Login_Login_Test : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
Binder();
}
}
private void Binder()
{
using (DataClassesDataContext db = new DataClassesDataContext())
{
DDL_Username.DataSource = from x in db.DT_Honeys select new { x.UsernameID, txt = x.Username };
DDL_Username.DataBind();
}
}
protected void B_Login_Click(object sender, EventArgs e)
{
if (TB_Password.Text != "")
{
using (DataClassesDataContext db = new DataClassesDataContext())
{
}
}
}
}
I have spent hours searching and trying different code, but none of it seems to fit in for this context.
Anyway, help and tips appreciated, thank you very much!
I am aware of security risks etc. but this is not a live website or anything, it is simply for testing purposes as a beginner. *
Updated code:
Back End:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class Login_Page_Test : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
Tester();
}
}
private void Tester()
{
using (DataClassesDataContext db = new DataClassesDataContext())
{
DDL_Username.DataSource = from x in db.DT_Honeys select new { id = x.UsernameID, txt = x.Username };
DDL_Username.DataValueField = "id";
DDL_Username.DataTextField = "txt";
DDL_Username.DataBind();
}
}
protected void B_Login_Click(object sender, EventArgs e)
{
if (TB_Password.Text != "")
{
using (DataClassesDataContext db = new DataClassesDataContext())
{
DT_Honey blah = new DT_Honey();
blah = db.DT_Honeys.SingleOrDefault(x => x.UsernameID == int.Parse(DDL_Username.SelectedValue.ToString()));
if (blah != null)
{
if (TB_Password.Text.ToString().Trim() == blah.Password.ToString())
{
LI_Result.Text = "Credentials correct.";
}
else
{
LI_Result.Text = "Error: credentials are incorrect.";
}
}
else
{
LI_Result.Text = "Error: null value.";
}
}
}
}
}
Front End:
<%# Page Language="C#" AutoEventWireup="true" CodeFile="Login_Page_Test.aspx.cs" Inherits="Login_Page_Test" %>
<!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>Logi Page Test</title>
</head>
<body>
<form id="LoginPageTest" runat="server">
<div>
</div>
<asp:DropDownList ID="DDL_Username" runat="server">
</asp:DropDownList>
<br />
<asp:TextBox ID="TB_Password" runat="server"></asp:TextBox>
<br />
<asp:Button ID="B_Login" runat="server" onclick="B_Login_Click" Text="Login" />
<br />
<asp:Literal ID="LI_Result" runat="server"></asp:Literal>
</form>
</body>
</html>
I have checked the database aspects, and it is all fine in terms of primary key, columns, actual data, and dataclasses.
Same with textbox:
Back End:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class Login_Login_Page_2 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void B_Login_Click(object sender, EventArgs e)
{
if (TB_Username.Text.ToString().Trim() != "" && TB_Password.Text.ToString().Trim() != "")
{
using (DataClassesDataContext db = new DataClassesDataContext())
{
DT_Honey Login = new DT_Honey();
Login = db.DT_Honeys.SingleOrDefault(y => y.UsernameID == int.Parse(TB_Username.Text.ToString().Trim()));
if (Login != null)
{
if (TB_Password.Text.Trim() == Login.Password.ToString().Trim())
{
LI_Result.Text = "Yeah! The credentials you entered were correct!";
}
}
else
{
LI_Result.Text = "Oops! There was an error with the credentials you entered; please try again.";
}
}
}
else
{
LI_Result.Text = "Wow! Please fill out <b>both</b> the Username and Password text fields to login; thank you.";
}
}
}
Front End:
<%# Page Language="C#" AutoEventWireup="true" CodeFile="Login_Page_2.aspx.cs" Inherits="Login_Login_Page_2" %>
<!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>Login Page 2</title>
</head>
<body>
<form id="LoginPage2" runat="server">
<div>
<asp:TextBox ID="TB_Username" runat="server"></asp:TextBox>
<br />
<asp:TextBox ID="TB_Password" runat="server"></asp:TextBox>
<br />
<asp:Button ID="B_Login" runat="server" onclick="B_Login_Click" Text="Login" />
<br />
<asp:Literal ID="LI_Result" runat="server"></asp:Literal>
</div>
</form>
</body>
</html>
Since you're a self-described beginner, I'd really recommend using the native asp.net login controls. It's very likely that your code is less secure than the login control that 100's of engineers have spent years working on. Is there really a compelling reason for you to build your own custom login?? To begin with, doing what you're doing relies on storing unencrypted passwords....
You're introducing potentially serious security vulnerabilities in your application by redoing the login control yourself!!
Maybe this will help you?:
protected void B_Login_Click(object sender, EventArgs e)
{
if (TB_Password.Text != "")
{
using (DataClassesDataContext db = new DataClassesDataContext())
{
var user = db.DT_Test.SingleOrDefault(x => x.Username == DDL_Username.SelectedText);
if (user == null)
{
// whoops something's wrong (no matching username in db)
}
if (user.Password == TB_Password.Text)
{
// do something (correct password)
}
else
{
// something else (incorrect password)
}
}
}
}
However, best practice would be to use a standard membership provider for ASP.NET. Then you don't have to be in the business of setting up your own membership schema in a database. (It looks as though you're storing passwords in clear text, but a membership provider will fix that and handle the details for you.)
MSDN Introduction to Membership
Edit You'll probably want to change the Binder code so that your drop down items' IDs match up with the database ID numbers:
private void Binder()
{
using (DataClassesDataContext db = new DataClassesDataContext())
{
DDL_Username.DataSource = from x in db.DT_Honeys select new { id = x.UsernameID, txt = x.Username };
DDL_Username.DataValueField = "id";
DDL_Username.DataTextField = "txt";
DDL_Username.DataBind();
}
}
On the OnPreRender of my custom server control, I am registering an alert to popup everytime the page is loaded after a partial postback (add_pageLoaded(function() { alert('Hi')})). I only want this to be called once, but its gets called as many times as there has been partial postbacks. For example, in the code below, if you open the page and click "Click me" you get one alert, click again and you will get two alerts, three --> three alerts and so forth. My understanding was that ScriptManager.RegisterClientScriptBlock, using the scriptKey parameter was suppose to check if the script has already been registered, and if so, dont register it again.
I cannot register this script on !IsPostBack because my custom control will be inserted during Postbacks into pages, so using !IsPostBack will not include my script.
Here is a simple example of this problem:
ASPX:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="RegisterClientScriptExperimentation._Default" %>
<%# Register Assembly="RegisterClientScriptExperimentation" Namespace="RegisterClientScriptExperimentation" TagPrefix="cc" %>
<!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></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ScriptManager ID="ScriptManager1" runat="server"/>
<asp:UpdatePanel runat="server">
<ContentTemplate>
<asp:Panel ID="panel" runat="server"/>
</ContentTemplate>
</asp:UpdatePanel>
</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 System.Text;
namespace RegisterClientScriptExperimentation
{
public partial class _Default : System.Web.UI.Page
{
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
panel.Controls.Add(new CustomControl());
}
}
public class CustomControl : CompositeControl
{
private Button button;
public CustomControl()
{
button = new Button();
button.Text = "Click me";
}
protected override void CreateChildControls()
{
Controls.Clear();
Controls.Add(button);
}
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
StringBuilder _text = new StringBuilder();
_text.Append("var prm = Sys.WebForms.PageRequestManager.getInstance();");
_text.Append("prm.add_pageLoaded(function() { alert('Page Loaded'); });");
if (null != System.Web.UI.ScriptManager.GetCurrent(Page) && System.Web.UI.ScriptManager.GetCurrent(Page).IsInAsyncPostBack)
System.Web.UI.ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "customControlScript", _text.ToString(), true);
else
Page.ClientScript.RegisterStartupScript(this.GetType(), "customControlScript", _text.ToString(), true);
}
}
}
if(!Page.ClientScript.IsClientScriptBlockRegistered("customControlScript") && !Page.IsPostBack)
{
if (null != System.Web.UI.ScriptManager.GetCurrent(Page) && System.Web.UI.ScriptManager.GetCurrent(Page).IsInAsyncPostBack)
System.Web.UI.ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "customControlScript", _text.ToString(), true);
else
Page.ClientScript.RegisterStartupScript(this.GetType(), "customControlScript", _text.ToString(), true);
}
I found the solution to this.
In your page events, after you execute whatever you need to do, you need to remove the function from the event which you hooked into.
For example:
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_pageLoaded(DoSomething);
function DoSomething() {
alert('Hello');
Sys.WebForms.PageRequestManager.getInstance().remove_pageLoaded(DoSomething);
}
I've got an angry boss that will beat me down if I waste another day on this :-P Many karma points to the ajax guru who can solve my dilemma.
But more detail: I want to have an AccordionPane that grabs a bunch of links from an XML source and populate itself from said source.
There might be a sexier way, but this works. Populate your data source however you wish. This was just for demo purposes. Ditto for PrettyTitle() Key is to remember there are two item types in the accordion.
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Accordion Binding</title>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="AjaxScriptManager" runat="server">
</asp:ScriptManager>
<div>
<cc1:Accordion ID="AccordionControl" runat="server"
onitemdatabound="AccordionControl_ItemDataBound">
<Panes></Panes>
<HeaderTemplate>
<asp:Label ID="HeaderLabel" runat="server" />
</HeaderTemplate>
<ContentTemplate>
<asp:Literal ID="ContentLiteral" runat="server" />
<asp:HyperLink ID="ContentLink" runat="server" />
</ContentTemplate>
</cc1:Accordion><asp:xmldatasource runat="server" ID="RockNUGTwitter" ></asp:xmldatasource>
</div>
</form>
</body>
</html>
And codebehind is :
Using System;
using System.Web.UI.WebControls;
using System.Xml;
namespace Ajaxy
{
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Fill();
}
private void Fill()
{
PopulateDataSource();
AccordionControl.DataSource = RockNUGTwitter.GetXmlDocument().SelectNodes("//item");
AccordionControl.DataBind();
}
private void PopulateDataSource()
{
XmlDocument RockNugTwitterRSSDocument = new XmlDocument();
RockNugTwitterRSSDocument.Load("http://twitter.com/statuses/user_timeline/15912811.rss");
RockNUGTwitter.Data = RockNugTwitterRSSDocument.OuterXml;
}
protected void AccordionControl_ItemDataBound(object sender, AjaxControlToolkit.AccordionItemEventArgs e)
{
XmlNode ItemNode = (XmlNode)e.AccordionItem.DataItem;
if(e.AccordionItem.ItemType == AjaxControlToolkit.AccordionItemType.Content)
{
HyperLink ContentLink = (HyperLink)e.AccordionItem.FindControl("ContentLink");
ContentLink.NavigateUrl = ItemNode.SelectSingleNode("link").InnerText;
Literal ContentLiteral = (Literal)e.AccordionItem.FindControl("ContentLiteral");
ContentLiteral.Text = ItemNode.SelectSingleNode("title").InnerText;
ContentLink.Text = "Link";
}
else if(e.AccordionItem.ItemType == AjaxControlToolkit.AccordionItemType.Header)
{
Label HeaderLabel = (Label) e.AccordionItem.FindControl("HeaderLabel");
HeaderLabel.Text = PrettyTitle(ItemNode.SelectSingleNode("title").InnerText);
}
}
private string PrettyTitle(string FullItem)
{
string PrettyString = FullItem.Replace("RockNUG: ", "");
string[] Words = PrettyString.Split(' ');
const int MAX_WORDS_TOSHOW = 4;
int WordsToShow = MAX_WORDS_TOSHOW;
if(Words.Length < MAX_WORDS_TOSHOW)
{
WordsToShow = Words.Length;
}
PrettyString = String.Join(" ", Words, 0, WordsToShow);
if (Words.Length > WordsToShow)
{
PrettyString += "...";
}
return PrettyString;
}
}
}