I'm developing an blog using ASP.NET, and I want that the user can be able to add comments.
So I want to implement the idea of facebook on adding comments.
The comment will be stored in the database, so I will be able to load it with the page if the user goes to another web page.
You have any idea how can I do this thing ( Ajax, Javascript, jQuery, Ajax Toolkit ) ?
EDIT:
I found this :
<body>
<form id="form1" runat="server">
<p>
<textarea id="textArea"></textarea>
</p>
<input type="submit" value="Commenter"/>
<br />
</form>
<p>Add some Test to the page</p>
</body>
and script.js :
window.onload = initAll;
function initAll() {
document.getElementsByTagName("form")[0].onsubmit = addNode;
}
function addNode() {
var inText = document.getElementById("textArea").value;
var newText = document.createTextNode(inText);
var newGraf = document.createElement("p");
newGraf.appendChild(newText);
var docBody = document.getElementsByTagName("body")[0];
docBody.appendChild(newGraf);
return false;
}
But how can I save the comment in the database, because an input button can't do this !
You don't necessarily need to use JavaScript to do this, although if you wish to do this asynchronously to provide a more responsive user experience then you will need JavaScript.
Using ASP.NET web forms, there are a number of ways this could be set up on the server side. You could use
Page methods
ASMX web services
WCF services
And call them using JavaScript from the client side. Inside of the server side code is where you will connect to the database, perform your CRUD operation and return a response back to the client that made the AJAX call.
A note on security - you'll want to sanitise the comments and mitigate SQL injection, XSS, XSRF and other types of injection attacks. The Anti-XSS library (soon to be superceded by the Web Protection library) is a good tool to leverage to do this and offers a better approach to encoding than the standard encoding in ASP.NET
Generally, if you are using GridView to display those blog post, simply add a template field into the Gridview. Inside the template filed, you put a Textbox and a Button.
When user click on the button, use your code behind to find the postID, and textbox, and save it to database, and then remember to bind the data to the gridview again.
Here is some sample code.
protected void btnBuy_Click(object sender, ImageClickEventArgs e)
{
ImageButton btnBuy = (ImageButton)sender; //Find which button is clicked.
//If that is a button, use Button btnBuy = (Button)Sender;
GridViewRow row = (GridViewRow)btnBuy.NamingContainer; //Find which gridview row //containes the clicked button
Label lblPostID = (Label)row.FindControl("lblPostID"); //Find the post ID
TextBox txtComment = (TextBox)row.FindControl("txtComments"); //Find the textbox
//Save the data to database.
//Put your code here.
//Bind the gridview with the data source which got some new data.
GridView1.DataSource = yourDataSource;
GridView1.DataBind();
}
Related
I am using a jQuery editor and when the user hits the submit button i put the content into asp.net Panel control as html and then when i render this Panel the html i added is not
retrieved.
function MoveData() {
var sHTML = $('#summernote_1').code();
// dvFrontPageHtml is asp.net Panel
$('[id*=dvFrontPageHtml]').html(sHTML);
setTimeout(function () {
javascript: __doPostBack('ctl00$ctl00$ContentPlaceHolderBody$ContentPlaceHolderBody$lnkSave', '');
}, 10000);
return false;
}
System.Text.StringBuilder sb = new System.Text.StringBuilder();
System.IO.StringWriter stWriter = new System.IO.StringWriter(sb);
System.Web.UI.HtmlTextWriter htmlWriter = new System.Web.UI.HtmlTextWriter(stWriter);
dvFrontPageHtml.RenderControl(htmlWriter);
string Message = sb.ToString();
The message does not returning the html added.
I dont want to use jQuery ajax call as of now.
Any suggestions
without seeing all the relevant code its hard to pinpoint the problem.
but im pretty sure you are trying to find an ASP.net control by its serverside ID from clientside.
dvFrontPageHtml is the Controls ID by which asp.net identifies it, and unless you explicitly tell ASP.Net otherwise, it will generate a different ID for the control to be used by scripts at clientside
you need to retrieve the panel's clientside ID thats being generated for it by asp.net
you do it by a preprocessor directive <%=dvFrontPageHtml.ClientID%>:
$('[id*=<%=dvFrontPageHtml.ClientID%>]').html(sHTML);
alternatively, if you want the clientside ID to be same as the serverside ID, you can set the control's attribute ClientIDMode="Static".
UPDATE:
from your comment it seems the problem is elsewhere. what comes to mind, is that RenderControl() takes the control as it was when sent to the client in the Response. but the control is not being submitted to the server in next Request, so you will not be able to retrieve its altered html.
what you can do as a workaround, is hook into ASP.NET's build in postback mechanism, and submit the panel's html as a custom event argument:
for the example, lets assume this is our html:
<asp:Panel ID="dvFrontPageHtml" runat="server" ClientIDMode="Static">test</asp:Panel>
<asp:Button ID="BT_Test" runat="server" Text="Button"></asp:Button>
this will be our javascript:
$(function(){
// add custom event handler for the submit button
$("#<%=BT_Test.ClientID%>").click(function (ev) {
//prevent the default behavior and stop it from submitting the form
ev.preventDefault();
//alter the panels html as you require
var sHTML = $('#summernote_1').code();
$('[id*=dvFrontPageHtml]').html(sHTML);
//cause a postback manually, with target = BTCLICK and argument = panel's html
__doPostBack('BTCLICK', $('[id*=dvFrontPageHtml]').outerHTML());
});
});
and here we capture the postback on serverside:
//we monitor page load
protected void Page_Load(object sender, EventArgs e)
{
string Message;
//check if its a postback
if (IsPostBack)
{
//monitor for our custom target "BTCLICK"
if (Request.Form["__EVENTTARGET"].CompareTo("BTCLICK") == 0)
{
// retrieve the panels html from the event argument
Message = Request.Form["__EVENTARGUMENT"];
}
}
}
I load a piece of html which contains something like:
<em> < input type="text" value="Untitled" name="ViewTitle" id="ViewTitle" runat="server"> </em>
into my control. The html is user defined, do please do not ask me to add them statically on the aspx page.
On my page, I have a placeholder and I can use
LiteralControl target = new LiteralControl ();
// html string contains user-defined controls
target.text = htmlstring
to render it property. My problem is, since its a html piece, even if i know the input box's id, i cannot access it using FindControl("ViewTitle") (it will just return null) because its rendered as a text into a Literal control and all the input controls were not added to the container's control collections. I definitely can use Request.Form["ViewTitle"] to access its value, but how can I set its value?
Jupaol's method is the prefer way of adding dynamic control to a page.
If you want to insert string, you can use ParseControl.
However, it doesn't cause compilation for some controls such as PlaceHolder.
Your process is wrong, you are rendering a control to the client with the attribute: runat="server"
This attribute only works if the control was processed by the server, you are just rendering as is
Since your goal is to add a TextBox (correct me if I'm wrong), then why don't you just add a new TextBox to the form's controls collection???
Something like this:
protected void Page_Init(object sender, EventArgs e)
{
var textbox = new TextBox { ID="myTextBoxID", Text="Some initial value" };
this.myPlaceHolder.Controls.Add(textbox);
}
And to retrieve it:
var myDynamicTextBox = this.FindControl("myTextBoxID") as TextBox;
I have created several working examples and they are online on my GitHub site, feel free to browse the code
I have the following requirement for creating a user profile in my application:
User should be able to enter multiple phone numbers/email addresses in his profile.
The screen looks somewhat like this:
- By default, on page load a single textbox for phone and email are shown.
- User can click a "+" button to add additional numbers/addresses.
- On clicking the "+" button we need to add another textbox just below the first one. User can add as many numbers/addresses as he wants. On submit, the server should collect all numbers/emails and save it in DB.
I tried using the Repeater control to do this. On page_load I bind the repeater to a "new arraylist" object of size 1. So, this renders fine - user sees a single textbox with no value in it.
When he clicks the "+" button, I ideally want to use javascript to create more textboxes with similar mark-up as the first.
My questions are these:
Can I render the new textboxes anyway using js? I notice that the HTML rendered by the repeater control is somewhat complex (names/ids) etc. and it might not be possible to correctly create those controls on client-side.
If there is a way to do #1, will the server understand that these additional inputs are items in the repeater control? Say, I want to get all the phone numbers that the user entered by iterating over Repeater.DataItems.
Conceptually, is my approach correct or is it wrong to use the Repeater for this? Would you suggest any other approach that might handle this requirement?
Coming from a Struts/JSP background, I am still struggling to get a grip on the .NET way of doing things - so any help would be appreciated.
The repeater control may be a bit of overkill for what you're trying to accomplish. It is mainly meant as a databound control for presenting rows of data.
What you can do is to dynamically create the boxes as part of the Page_Load event (C#):
TestInput.aspx :
<form id="form1" runat="server">
<asp:HiddenField ID="hdnAddInput" runat="server" />
<asp:Button ID="btnPlus" OnClientClick="setAdd()" Text="Plus" runat="server" />
<asp:PlaceHolder ID="phInputs" runat="server" />
</form>
<script type="text/javascript">
function setAdd() {
var add = document.getElementById('<%=hdnAddInput.ClientID%>');
add.value = '1';
return true;
}
</script>
TestInput.aspx.cs:
protected void Page_Load(object sender, EventArgs e)
{
if (ViewState["inputs"] == null)
ViewState["inputs"] = 1;
if (hdnAddInput.Value == "1")
{
ViewState["inputs"] = int.Parse(ViewState["inputs"].ToString()) + 1;
hdnAddInput.Value = "";
}
for (int loop = 0; loop < int.Parse(ViewState["inputs"].ToString()); loop++)
phInputs.Controls.Add(new TextBox() { ID = "phone" + loop });
}
I ended up using a PlaceHolder to dynamically add the text boxes and a HiddenField to flag when another TextBox needed to be added. Since the IDs were matching, it maintains the ViewState of the controls during each postback.
Welcome to the hairball that is dynamically-added controls in ASP.NET. It's not pretty but it can be done.
You cannot add new fields dynamically using javascript because the new field would have no representation in the server-side controls collection of the page.
Given that the requirements are that there is no limit to the number of addresses a user can add to the page, your only option is to do "traditional" dynamic ASP.NET controls. This means that you must handle the adding of the control server-side by new-ing a new object to represent the control:
private ArrayList _dynamicControls = new ArrayList();
public void Page_Init()
{
foreach (string c in _dynamicControls)
{
TextBox txtDynamicBox = new TextBox();
txtDynamicBox.ID = c;
Controls.Add(txtDynamicBox);
}
}
public void AddNewTextBox()
{
TextBox txtNewBox = new TextBox();
txtNewBox.ID = [uniqueID] // Give the textbox a unique name
Controls.Add(txtNewBox);
_dynamicControls.Add([uniqueID]);
}
You can see here that the object that backs each dynamically-added field has to be added back to the Controls collection of the Page on each postback. If you don't do this, data POSTed back from the field has nowhere to go.
If you want to user the repeater, I think the easiest way is to put the repeater in a ASP.Net AJAX update panel, add the extra textbox on the sever side.
There are definitely other way to implement this without using repeater, and it maybe much easier to add the textbox using js.
No, but you can create input elements similar to what TextBox controls would render.
No. ASP.NET protects itself from phony data posted to the server. You can't make the server code think that it created a TextBox earlier by just adding data that it would return.
The approach is wrong. You are trying to go a middle way that doesn't work. You have to go all the way in either direction. Either you make a postback and add the TextBox on the server side, or you do it completely on the client side and use the Request.Form collection to receive the data on the server side.
I would like the data that i enter in a text box on pageA to be accessable on pageB
eg: User enters their name in text box on page A
page B says Hello (info they entered in text box)
I heard this can be accomplished by using a session but i don't know how.
can someone please tell me how to setup a session and how to store data in it?
Thank you!
Session["valueName"]=value;
or
Session.Add("valueName",Object);
And You can retrieve the value in label (for Example) By
/*if String value */
Label1.Text=Session["valueName"].ToString();
or
Label1.Text=Session.item["valueName"].ToString();
And also You can remove the session by;
/*This will remove what session name by valueName.*/
Session.Remove( "valueName");
/*All Session will be removed.*/
Session.Clear();
// Page A on Submit or some such
Session["Name"] = TextBoxA.Text;
// Page B on Page Load
LabelB.Text = Session["Name"];
Session is enabled by default.
Yes, you could do something like JohnOpincar said, but you don't need to.
You can use cross page postbacks. In ASP.Net 2.0, cross-page post backs allow posting to a different web page, resulting in more intuitive, structured and maintainable code. In this article, you can explore the various options and settings for the cross page postback mechanism.
You can access the controls in the source page using this code in the target page:
protected void Page_Load(object sender, EventArgs e)
{
...
TextBox txtStartDate = (TextBox) PreviousPage.FindControl("txtStartDate ");
...
}
You can use session to do this, but you can also use Cross Page Postbacks if you are ASP.NET 2.0 or greater
http://msdn.microsoft.com/en-us/library/ms178139.aspx
if (Page.PreviousPage != null) {
TextBox SourceTextBox =
(TextBox)Page.PreviousPage.FindControl("TextBox1");
if (SourceTextBox != null) {
Label1.Text = SourceTextBox.Text;
}
}
There is even a simpler way. Use the query string :
In page A :
<form method="get" action="pageB.aspx">
<input type="text" name="personName" />
<!-- ... -->
</form>
In page B :
Hello <%= Request.QueryString["personName"] %> !
If I have a page with a form (imagine a simple one with just TextBoxes and a submit button) and I want to allow the user to dynamiccally add more TextBoxes to the form via javascript, what is the best way to handle the request server side?
Example: I have a page rendered like the following :
<input type = "text" id = "control1" name = "control1" />
<input type = "text" id = "control2" name = "control2" />
<input type = "text" id = "control3" name = "control3" />
<input type = "submit" />
The user trigger some Javascript and the page turns out like:
<input type = "text" id = "control1" name = "control1" />
<input type = "text" id = "control2" name = "control2" />
<input type = "text" id = "control3" name = "control3" />
<input type = "text" id = "control4" name = "control4" />
<input type = "text" id = "control5" name = "control5" />
<input type = "submit" />
What is the best way to handle this kind of situation, or, more generally, working with dynamically generated input both client and server side (eg, how to generate them server side starting from, say, some data taken from a database)?
If you want to be able to access them in the code behind using the FindControl method, the AJAX UpdatePanel is probably your best bet. Just remember that every time you update the UpdatePanel, your going through the entire page life cycle but only getting the pieces that render in the update panel back from the server, so be weary of the overhead.
If you create them dynamically with Javascript you will not be able to use FindControl to get access to them in the code behind because they won't be re-created during the page event life cycle. Also, be careful because if you're creating a lot of them at the same time with some kind of loop it can slow things down, especially in Internet Explorer.
You may also consider using AJAX and WebServices with WebMethods for submitting the data instead of a post-back if you're creating the controls dynamically with Javascript.
I have done similiar things to this numerous times. My preferred approach is usually to use a Repeater and a Button (labelled Add) inside an UpdatePanel.
For the Button_OnClick event in your code behind do something similiar to this;
Loop through the Items collection of the Repeater
Use item.FindControl("txtUserInput") to get the TextBox for that item
Save the text of each input to List<string>
Add an empty string to the the list
Databind the repeater to this new list
Here's some example code;
<asp:Repeater runat="server" ID="rptAttendees">
<ItemTemplate>
<asp:TextBox runat="server" ID="txtAttendeeEmail" Text='<%# Container.DataItem %>'></asp:TextBox>
</ItemTemplate>
</asp:Repeater>
protected void btnAddAttendee_Click(object sender, EventArgs e)
{
var attendees = new List<string>();
foreach (RepeaterItem item in rptAttendees.Items)
{
TextBox txtAttendeeEmail = (TextBox)item.FindControl("txtAttendeeEmail");
attendees.Add(txtAttendeeEmail.Text);
}
SaveAttendees();
attendees.Add("");
rptAttendees.DataSource = attendees;
rptAttendees.DataBind();
}
On client side, make a JS function for creating the inputs, for example:
var numCtrl = 1; // depends on how many you have rendered on server side
var addCtrl = function() {
var in = document.createElement('input');
in.name = "control" + ++i;
in.type = "text";
in.id = "control" + i;
document.getElementById("yourcontainer").appendChild(in);
}
..on the server side just lookup your HTTP params collection, iterate through it, and select only those matching /control\d*/
On the server side look into Request.Form["controlN"] where you will find your old and new fields.
On the server side you can add controls dynamically like:
foreach (Type object in MyDBCollection)
{
Controls.Add (new TextBox ());
}
In webforms you won't have a lot of choices if you expect the values to postback and be able to access them in typical fashion. What I would suggest is that you use an Ajax UpdatePanel to allow the controls to be registered at the appropriate point of the page lifecycle (before onLoad), this will also make a difference on whether or not you need the boxes to persist across postbacks. The JS methods involved in the other 2 answers will not persist the textboxes through a postback.
MVC gives you more leeway, since there isn't that crazy page lifecycle, control registration, viewstate, etc to get in your way.
So the big question is, which model/framework for ASP.Net are you using?
Since you are indeed using webforms, I really strongly suggest you go with updatepanels if they'll work for you. it will permit you to add controls in such a way that wont get in the way of eventvalidation, etc.
I've begun using jquery in a lot of my webforms applications and have found the combination of dynamic controls and using JSON to communicate with the page's WebMethods give me much more control over how the page is presented and eliminate needless postbacks.
When I want to trigger a postback, I use javascript to populate server controls on the page that are hidden by jquery and then click a server control button. This allows the page to degrade gracefully if the user cannot use javascript.