I have a label which I show numbers in and numbers are the count of data from database. Whenever new data is saved in DB, the number in label should increase. It increases when i refresh the page, because I call the method on page_load in codebehind.
What in my mind is that:
I should call the method periodically without refreshing the page.
For this purpose, I know that I should use AJAX, but I couldnt find appropriate usage for me.
Can you direct me to a solution?
This is the label on aspx page:
<div id="panoramCouponBarLittleTalep">
<asp:Label ID="LabelTalepSayisiSag" ClientIDMode="Static" Text="" runat="server" />
</div>
This is the page_load :
protected void Page_Load(object sender, EventArgs e)
{
if (Session["user"] != null)
{
if (!IsPostBack)
{
SonBesGunTalepSayisi();
}
}
}
And the method I use:
private void SonBesGunTalepSayisi()
{
RequestProvider rP = new RequestProvider();
int talepSayisi = rP.LastFiveDaysRequestCount();
if (talepSayisi > 0)
{
LabelTalepSayisiSag.Text = talepSayisi.ToString();
}
else
{
LabelTalepSayisi.Text = "";
}
}
I would use an ASP.NET AJAX Page Method to be the server endpoint that your JavaScript AJAX will call, based upon a timer; like this:
Code-behind:
[WebMethod]
public static string GetRequestCount()
{
RequestProvider rP = new RequestProvider();
int talepSayisi = rP.LastFiveDaysRequestCount();
if (talepSayisi > 0)
{
return talepSayisi.ToString();
}
return "";
}
I would add a CssClass value to your Label control as that will make it easier to use in a jQuery selector, like this:
Markup:
<div id="panoramCouponBarLittleTalep">
<asp:Label ID="LabelTalepSayisiSag" ClientIDMode="Static"
Text="" runat="server" CssClass="TheLabel" />
</div>
$(document).ready(function() {
setInterval(ajaxCall, 5000); // 5000 MS == 5 seconds
});
function ajaxCall() {
$.ajax({
type: "POST",
url: "PageName.aspx/GetRequestCount",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(result) {
// Put result of call into label
$('.TheLabel').text(result);
}
});
}
Note: Obviously you can adjust the timer interval value to be larger or smaller, depending upon your needs and performance. Also, the CssClass value on the Label control avoids the name mangling issue that plagues ASP.NET server controls. Even though you are using the ClientIDMode="Static", I like to avoid using the ID of a server control in jQuery when possible, because a class name will not get mangled by ASP.NET.
You can use ASP Page Methods to do it:
http://www.geekzilla.co.uk/View7B75C93E-C8C9-4576-972B-2C3138DFC671.htm
Related
I've got a WebForm with two drop down lists, where the contents of the second one depend on the first.
So if the user changes the category, the second dropdown needs to be filled with the list of subcategories.
This sounds like a typical job for AutoPostBack.
However, there's a bit of a problem with AutoPostBack: if the list isn't dropped open, and the user uses the keyboard to make the choice, the postback happens right after the first keystroke. This prevents the user from scrolling down the list with the down arrow, or typing the name of the category.
This happens in Chrome and IE and Opera, but not in Firefox. Firefox fires the onchange event only when leaving the control (tabbing to the next control), just like it would when the list was dropped open, and that's what I want the other browsers to do too.
Any solutions how I can achieve this?
I tried to remove the AutoPostBack attribute and use onblur, but apparently the page works differently with AutoPostBack than without, because the browsers start complaining about Javascript errors.
Now since we're all so fond of jsFiddle, here's one. It doesn't actually do anything, but it can demonstrate the problem. Click on the first dropdown, then click again to close the list. (This is what happens when you navigate through the form with the tab key: dropdown lists don't open up.) Now type a letter or the down arrow. Firefox changes the current selection and waits for you to do anything else, but Chrome and IE and Opera all attempt to submit the form immediately, with drastic results.
So how can I avoid that? And note that simply changing the fiddle may not be enough, it must be translatable back to an ASP.NET solution.
Ok here is how I'd do it by using ajax and avoiding the use of AutoPostback all together to populate my sub category.
Create an object that represents the select list json object to send back.
public class SelectItem
{
public string Id { get; set; }
public string Text { get; set; }
}
Then create a PageMethod:
[WebMethod]
public static List<SelectItem> GetSubCategories(string Id)
{
// Returning dummy data for demo purposes
var subCats = new List<SelectItem>();
if (Id == "1")
{
subCats.Add(new SelectItem { Id = "1", Text = "1 Subs"});
}
else if (Id == "2")
{
subCats.Add(new SelectItem { Id = "2", Text = "2 Subs"});
}
return subCats;
}
Add a script manager and EnablePageMethods i.e.
<asp:ScriptManager runat="server" EnablePageMethods="true">
</asp:ScriptManager>
Change your dropdown lists to use ClientIDMode="Static"
<asp:DropDownList Id="ddlCategory" runat="server" ClientIDMode="Static">
<asp:ListItem Value ="1" Text ="One"></asp:ListItem>
<asp:ListItem Value ="2" Text ="Two"></asp:ListItem>
</asp:DropDownList>
<asp:DropDownList Id="ddlSubCategory" runat="server" ClientIDMode="Static">
</asp:DropDownList>
Then use the following jQuery:
<script type="text/javascript">
$(function () {
var $cat = $('#ddlCategory');
$cat.click(function () {
var catId = $cat.val();
$.ajax({
type: "POST",
url: "Default.aspx/GetSubCategories",
data: "{ Id: " + catId + " }",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
var subs = msg.d;
// empty selection
var $ddlSubCategory = $('#ddlSubCategory');
$ddlSubCategory.empty();
$.each(subs, function (index, sub) {
$ddlSubCategory.append($('<option/>', {
value: sub.Id,
text: sub.Text
}));
});
}
});
});
});
</script>
This is a problem I haven't come across before.
I'm working on an MVC4 project. I'm using an asp button control because there isn't a Html Helper that can be used for a button (re: There's no #Html.Button !). My button code is:
<td><asp:Button ID="ButtonUndo" runat="server" Text="Undo"
OnClick="ButtonUndo_Click" AutoPostBack="true"/></td>
I went to the Designer tab and clicked on this button which produced the event handler:
protected void ButtonUndo_Click(object sender, EventArgs e)
{
RRSPSqlEntities db = new RRSPSqlEntities();
int id = (int)ViewData["ClientId"];
var updateAddress = (from a in db.Address
where a.PersonId == id
select a).SingleOrDefault();
updateAddress.Deleted = false;
db.SaveChanges();
}
I should add that this code was added to the same .aspx page wrapped in a script tag. Also within this section is the Page_Load method. The eventhandler is not within Page_Load.
The problem was found when I set a breakpoint and stepped through the code. Clicking my button shows that it doesn't hit my event handler at all. I don't know why this is, particularly as ASP created the event from clicking the button in Design mode.
Clicking my button shows that it doesn't hit my event handler at all.
This isn't all that surprising. ASP.NET MVC uses a completely different event model (i.e. it doesn't have one like web forms). However, what you're trying to do is very straight forward. In your controller build a new method, let's call it Undo:
public ActionResult Undo(int id)
{
RRSPSqlEntities db = new RRSPSqlEntities();
var updateAddress = (from a in db.Address
where a.PersonId == id
select a).SingleOrDefault();
updateAddress.Deleted = false;
db.SaveChanges();
return View("{insert the original action name here}");
}
and then in your markup, simply markup the input like this:
<form method="POST" action="/ControllerName/Undo">
#Html.HiddenFor(Model.Id)
<input type="submit" value="Undo" />
</form>
where the Model for the View you're on contains a property, I've called it Id, that is the id you want passed into Undo.
I usually prefer to make ajax calls. You can try:
<button type="button" class="button" onclick="ButtonUndo();" />
In the form:
<script>
function ButtonUndo() {
$.ajax({
type: 'POST',
url: '/controller/action',
data: 'PersonID=' + ID,
dataType: 'json',
cache: false,
success: function (result) {
//do stuff here
},
error: function () {
//do error stuff here
}
});
}
</script>
Controller:
[HttpPost]
public ActionResult Action(int PersonID)
{
//Do your stuff here
return new JsonResult { result = "something" };
}
(Sorry for any typos or syntax errors...I pulled from existing code that we use in a project.)
I'm trying to create text box dynamically. so I cal it through the AJAX function.
This is my code:
Ajax function
function ChangedAdults(noofAdults) {
alert(noofAdults.value);
$.ajax({
type: 'POST',
dataType: 'json',
url: "/FlightBooking.aspx/Adults",
data: "{noOfAdults:'" + noofAdults.value + "'}",
contentType: "application/json; charset=utf-8",
success: function (result) {
$("#AdultsList").html(result.d);
},
error: function (xhr, ajaxOptions, thrownError) {
alert(xhr.status);
alert(thrownError);
}
});
}
code behind
[WebMethod]
public static string Adults(int noOfAdults)
{
FlightBooking obj = new FlightBooking();
obj.CreateAdultsList(noOfAdults);
string test= "";
return test.ToString();
}
private void CreateAdultsList(int noOfAdults)
{
int n = noOfAdults;
for (int i = 0; i < n; i++)
{
TextBox MyTextBox = new TextBox();
MyTextBox.ID = "tb" + "" + i;
AdultsListPlaceholder.Controls.Add(MyTextBox); //error coming here
AdultsListPlaceholder.Controls.Add(new LiteralControl("<br />"));
}
}
But I receive an error:
Object reference not set to an instance of an object
What could cause this problem?
You can not dynamically add controls to a page using JQuery AJAX. Please get a good understanding of asp.net page lifecycle
In short this is how asp.net pages work.
Browswer sends request to server. i.e. http://localhost/test.aspx
Server creates a object for the page class. In this case the class is Test
The object renders the page. That means it converts the Controls of test.aspx to HTML which browsers can understand.
Server sends the rendered HTML back to Browser and destroys the object.
Browser displays the page.
So the server creates a new object every time it receives a page request.
However when a call to WebMethods is made using AJAX, no page object is created. This is why Webmethods have to be static.
I can see you are trying to create a object yourself and add the dynamic controls to that object. But this object is not related to the content displayed in the browser. So, adding controls to this object won't change anything that's displayed in the browser. For that to happen you have to post the whole page back. And if you return the rendered output of the object you created with Response.Write, that will return the HTML version of the whole page. Which is basically same as a PostBack
However, you can achieve AJAX based dynamic control rendering using UpdatePanel. Below is one way to do it
ASPX page
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
<asp:Button ID="btnCreate" runat="server" Text="Create" OnClick="btnCreate_Click" />
</ContentTemplate>
</asp:UpdatePanel>
<asp:Button ID="btnRead" runat="server" Text="Read" OnClick="btnRead_Click" />
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
</form>
Code Behind
protected int NumberOfControls
{
get { return Convert.ToInt32(Session["noCon"]); }
set { Session["noCon"] = value.ToString(); }
}
private void Page_Init(object sender, System.EventArgs e)
{
if (!Page.IsPostBack)
//Initiate the counter of dynamically added controls
this.NumberOfControls = 0;
else
//Controls must be repeatedly be created on postback
this.createControls();
}
private void Page_Load(object sender, System.EventArgs e)
{
}
protected void btnCreate_Click(object sender, EventArgs e)
{
TextBox tbx = new TextBox();
tbx.ID = "txtData"+NumberOfControls;
NumberOfControls++;
PlaceHolder1.Controls.Add(tbx);
}
protected void btnRead_Click(object sender, EventArgs e)
{
int count = this.NumberOfControls;
for (int i = 0; i < count; i++)
{
TextBox tx = (TextBox)PlaceHolder1.FindControl("txtData" + i.ToString());
//Add the Controls to the container of your choice
Label1.Text += tx.Text + ",";
}
}
private void createControls()
{
int count = this.NumberOfControls;
for (int i = 0; i < count; i++)
{
TextBox tx = new TextBox();
tx.ID = "txtData" + i.ToString();
//Add the Controls to the container of your choice
PlaceHolder1.Controls.Add(tx);
}
}
Hope this helps.
You're mixing your paradigms. What would you expect this code to do? You can render controls in response to an AJAX call, but you must then manually insert the processed HTML into the DOM.
Call server using AJAX
Instantiate a dummy page container
Render server control
Return markup
Insert into DOM
Or, you can add new controls in response to a server event via a full postback or an async postback (e.g. an UpdatePanel).
In asp.net you can not create server control from jQuery or java-script.
Though you can call web-method from jQuery but you can't add any control from web method.
More details
Add new ASP.NEt server controls with jQuery?
One of the idea it to create textbox is to create html textbox
<input type="text" id="text1" ></input>
And post your value through jQuery ajax for manipulation.
Edit 1
Other way is to create all the controls at page load (If you know the maximum number)
Hide them initially
Show one by one on button click
And get the value on the server after postback.
Example:
add text to an asp.net textbox control with jQuery
AdultsListPlaceholder is null, you need to override its onload function to create children of this control.
e.g.
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
CreateAdultsList(5);
}
I have a cascading dropdown (3 of them) Type, Categories and Sub Categories. Type loads first and upon selection of Type, Category load and selection of Category, Sub Category loads.
Also i have 2 buttons, "Add Category" and "Add Sub Category" Upon clicking on these buttons, i call a JQuery Modal Form to add them. I use Webmethod in code behind to add them to database
This works perfectly in ASPX page.
Since I need use this in 3-4 pages, i thought of making the above as User control (ASCX). When i try to use this in a webpage, the webmethods in ASCX don't get called.
Is my approach correct? what should be done for my scenario
lOoking forward for your suggestions.
Thanks in advance
Karthik
i dont think you can have a WebMethod within a ASCX Control.
I solved it for my Problem like this:
AJAXBridge:
namespace Demo{
public partial class AjaxBridge : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
[WebMethod(EnableSession = true)]
public static string Control_GetTest()
{
return Control.GetTest();
}
}}
Control.ascx.cs
namespace Demo{
public partial class Control : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
HttpContext.Current.Session["test"] = DateTime.Now.ToString();
}
// ALMOST A WEB METHOD
public static string GetTest()
{
return " is " + HttpContext.Current.Session["test"];
}
}}
Control.ascx
<script type="text/javascript">
var dataSend = {};
$.ajax({
type: "POST",
url: "AjaxBridge.aspx/Control_GetTest",
data: dataSend,
cache: false,
contentType: "application/json; charset=utf-8",
dataType: "json",
beforeSend: function(data) {
alert("before");
},
success: function(data) {
alert("Page Load Time from Session " + data.d);
},
fail: function() {
alert("fail");
}
}); </script>
So you have one ASPX which acts basically like a Interface for all AJAX Methods in all your Web Controls. There also some advantages like having overview and control of all exposed WebMethods, which makes it a lot easier to handle security matters (eg. with Annotations).
Was your web method was a static method in the code behind that was marked with WebMethod attribute as described in the "Calling Static Methods in an ASP.NET Web Page" section here before you moved it? If so this type of webmethod only works at the page level and cannot be used in a usercontrol. For an alternative read the first two sections of this page.
having a slight problem with an ASP.net page of mine. If a user were to double click on a "submit" button it will write to the database twice (i.e. carry out the 'onclick' method on the imagebutton twice)
How can I make it so that if a user clicks on the imagebutton, just the imagebutton is disabled?
I've tried:
<asp:ImageButton
runat="server"
ID="VerifyStepContinue"
ImageUrl=image src
ToolTip="Go"
TabIndex="98"
CausesValidation="true"
OnClick="methodName"
OnClientClick="this.disabled = true;" />
But this OnClientClick property completely stops the page from being submitted! Any help?
Sorry, yes, I do have Validation controls... hence the icky problem.
Working on this still, up to this point now:
ASP code:
<asp:TextBox ID="hidToken" runat="server" Visible="False" Enabled="False"></asp:TextBox>
...
<asp:ImageButton runat="server" ID="InputStepContinue" Name="InputStepContinue" ImageUrl="imagesrc" ToolTip="Go" TabIndex="98" CausesValidation="true" OnClick="SubmitMethod" OnClientClick="document.getElementById('InputStepContinue').style.visibility='hidden';" />
C# code:
private Random
random = new Random();
protected void Page_Load(object sender, EventArgs e)
{
//Use a Token to make sure it has only been clicked once.
if (Page.IsPostBack)
{
if (double.Parse(hidToken.Text) == ((double)Session["NextToken"]))
{
InputMethod();
}
else
{
// double click
}
}
double next = random.Next();
hidToken.Text = next + "";
Session["NextToken"] = next;
Actually... this nearly works. The double click problem is pretty much fixed (yay!) The image still isn't hidden though.
The general approach is twofold.
Serverside:
On load of the page, generate a token (using System.Random), save it in the session, and write it to a hidden form field
On submit, check that the hidden form field equals the session variable (before setting it again)
Do work
Clientside:
Similar to what you have, but probably just hide the button, and replace it with some text like 'submitting'.
The important thing to note, client side, is that the user may cancel the post by hitting 'escape', so you should consider what to do here (depending on how far along they are the token won't be used, so you'll need to bring the button back from being disabled/hidden).
Complete example follows:
C# (includes code to see it in action):
<html>
<head runat="server">
<title>double-click test</title>
<script language="c#" runat="server">
private Random
random = new Random();
private static int
TEST = 0;
public void Page_Load (object sender, EventArgs ea)
{
SetToken();
}
private void btnTest_Click (object sender, EventArgs ea)
{
if( IsTokenValid() ){
DoWork();
} else {
// double click
ltlResult.Text = "double click!";
}
}
private bool IsTokenValid ()
{
bool result = double.Parse(hidToken.Value) == ((double) Session["NextToken"]);
SetToken();
return result;
}
private void SetToken ()
{
double next = random.Next();
hidToken.Value = next + "";
Session["NextToken"] = next;
}
private void DoWork ()
{
TEST++;
ltlResult.Text = "DoWork(): " + TEST + ".";
}
</script>
</head>
<body>
<script language="javascript">
var last = null;
function f (obj)
{
obj.src = "http://www.gravatar.com/avatar/4659883ec420f39723c3df6ed99971b9?s=32&d=identicon&r=PG";
// Note: Disabling it here produced strange results. More investigation required.
last = obj;
setTimeout("reset()", 1 * 1000);
return true;
}
function reset ()
{
last.src = "http://www.gravatar.com/avatar/495ce8981a5127a9fd24bd72e7e3664a?s=32&d=identicon&r=PG";
last.disabled = "false";
}
</script>
<form id="form1" runat="server">
<asp:HiddenField runat="server" ID="hidToken" />
<asp:ImageButton runat="server" ID="btnTest"
OnClientClick="return f(this);"
ImageUrl="http://www.gravatar.com/avatar/495ce8981a5127a9fd24bd72e7e3664a?s=32&d=identicon&r=PG" OnClick="btnTest_Click" />
<pre>Result: <asp:Literal runat="server" ID="ltlResult" /></pre>
</form>
</body>
</html>
If you have validation on the page, disabling the button client side gets a little tricky. If validation fails, you don't want to disable the button. Here's a snippet that adds the client side event handler:
private void BuildClickOnceButton(WebControl ctl)
{
System.Text.StringBuilder sbValid = new System.Text.StringBuilder();
sbValid.Append("if (typeof(Page_ClientValidate) == 'function') { ");
sbValid.Append("if (Page_ClientValidate() == false) { return false; }} ");
sbValid.Append(ctl.ClientID + ".value = 'Please wait...';");
sbValid.Append(ctl.ClientID + ".disabled = true;");
// GetPostBackEventReference obtains a reference to a client-side script
// function that causes the server to post back to the page.
sbValid.Append(ClientScript.GetPostBackEventReference(ctl, ""));
sbValid.Append(";");
ctl.Attributes.Add("onclick", sbValid.ToString());
}
See this asp.net thread for more info.
Update: the above code would be used to add the OnClientClick handler in code behind. You could also write the javascript in your aspx markup like so:
<script type="text/javascript">
function disableButton(button)
{
// if there are client validators on the page
if (typeof(Page_ClientValidate) == 'function')
{
// if validation failed return false
// this will cancel the click event
if (Page_ClientValidate() == false)
{
return false;
}
}
// change the button text (does not apply to an ImageButton)
//button.value = "Please wait ...";
// disable the button
button.disabled = true;
// fire postback
__doPostBack(button.id, '');
}
</script>
<asp:ImageButton runat="server" ID="VerifyStepContinue" ImageUrl="button.png"
ToolTip="Go" TabIndex="98" CausesValidation="true" OnClick="methodName"
OnClientClick="return disableButton(this);" />
I have solved this by setting a hidden field on the client click before hitting the server.
Then in the server I check the hidden field and if the value is for example something 'FALSE' that might mean I can or cannot of the action.
Similar to Silky's client-side response, I usually make two buttons that look alike except that the second button is disabled and hidden. OnClientClick of the normal button swaps the display styles of the two buttons so that the normal button is hidden and the disabled button is shown.
The double-click feature is a server-side implementation to prevent processing that same request which can be implemented on the client side through JavaScript. The main purpose of the feature is to prevent processing the same request twice. The server-side implementation does this by identifying the repeated request; however, the ideal solution is to prevent this from occurring on the client side.
In the HTML content sent to the client that allows them to submit requests, a small validation JavaScript can be used to check whether the request has already been submitted and if so, prevent the online shopper from submitting the request again. This JavaScript validation function will check the global flag to see if the request has been submitted and, if so; does not resubmit the request. If the double-click feature is disabled on the server, it is highly recommended that the JSP and HTML pages implement this JavaScript prevention.
The following example prevents the form from being submitted more then once by using the onSubmit() action of the form object:
...
<script>
var requestSubmitted = false;
function submitRequest() {
if (!requestSubmitted ) {
requestSubmitted = true;
return true;
}
return false;
}
</script>
...
<FORM method="POST" action="Logon" onSubmit="javascript:submitRequest()">
......
</FORM>
for those who just want to do a quick fix , just hide it and show another button that has no events
<asp:Button ID="RedeemSubmitButton" runat="server" Text="Submit to Redeem" OnClick="RedeemSubmitButton_Click" OnClientClick="hideit();" />
<asp:Button ID="RedeemSubmitButtonDisabled" style="display:none;" runat="server" Text="please wait" OnClientClick="javascript:alert('please wait, processing');" />
<script>
function hideit() {
var btn = $get('<%= this.RedeemSubmitButton.ClientID %>');
var btn2 = $get('<%= this.RedeemSubmitButtonDisabled.ClientID %>');
if (btn != null)
{
btn.style.display = 'none';
btn2.style.display = 'block'
}
}
</script>