I've spent 4 days trying to make an ajax call to my .aspx.cs. In the best case, I got answer in html format. I don't understand why that happened, maybe I have to add some lib from NuGet or write something in web.config?
What I tried:
[HttpPost] [HttpGet]
[WebMethod]
jQuery ajax call
change url
my first app was a sample from VS with razor pages, I thought the problem was in using razor, so I created new project - a empty web application, but I still got the same answer from server in html format.
What I want to get:
My app imitates a vending machine. A user click on buttons with coins and coins have to increase on server side. (BtnAddCoin()) Also user's coins are always showing on a panel. (ShowInsertedCoins())
ClientSide.aspx
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="ClientSide.aspx.cs" Inherits="VendingMachine.ClientSide" Async="true" AsyncTimeout="60" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<link rel="stylesheet" href="StyleSheet.css" />
<title></title>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
function AddCoin(coin) {
alert(coin);
var val1 = coin;
$.ajax({
type: "POST",
url: "/ClientSide.aspx/BtnAddCoin",
data: '{coin: "' + coin + '" }',
dataType: "text",
success: function (data) {
alert("AddCoin" + data);
},
error: function (req, status, error) {
alert(error + status);
}
}).done(function (result) { ShowInsertedCoin(); });
}
function ShowInsertedCoin() {
var insertedCoins = document.getElementById('InsertedCoins');
alert('ShowInsertedCoin');
$.ajax({
type: "GET",
url: "/ClientSide.aspx/ShowInsertedCoins",
dataType: "text",
data: {},
success: function (data) {
alert("ShowInsertedCoin " + data);
insertedCoins.textContent = data;
}
});
}
</script>
</head>
<body>
<form id="form1" runat="server">
</form>
<div>
<h1>Coffee machine</h1>
</div>
<div>
<div>
<p> Add coins: </p>
<div>
<div>
<a id ="coin1" onclick="AddCoin(1)"> 1 </a>
<a> 2 </a>
<a> 5 </a>
<a> 10 </a>
</div>
</div>
<div>
<p id="InsertedCoins" ><%=ShowInsertedCoins()%> </p>
</div>
</div>
</div>
</body>
</html>
ClientSide.aspx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace VendingMachine
{
public partial class ClientSide : System.Web.UI.Page
{
static int coins = 10;
protected void Page_Load(object sender, EventArgs e)
{
}
[WebMethod]
public static string ShowInsertedCoins()
{
return "You inserted: " + coins.ToString();
}
[WebMethod]
public void BtnAddCoin(int coin)
{
coins = +coin;
//ShowInsertedCoins();
}
}
}
So, how I can do an ajax call to .aspx.cs with jQuery or js?
Why do I get html format when my function has to return a string?
Thanks for your attention and help.
Lots of issues here.
First issue?
You have this static value for the page class:
static int coins = 10;
You can't really control, or use or have static values in a class. The MAIN reason is such values will apply to all users of the site - not just the one user.
You can as a general rule call, use, consume static classes. In fact in vb.net, we OFTEN create a Module, and inside we have our boatload of helper routines, and routines that we freely call that library of code. While each of the routines can freely use local values, you can NOT use variables global to that module, since no instance of the class is being created, and as a result, multiple users will/would be able to set such values - and overwrite values used by other users. Worse yet, how long does the server persist such static values?
Answer: it is a total Las Vegas gamble.
this means to persist that coin count, we can choose one of MANY possible ways to persist that value.
We can have a global JavaScript variable hold the value.
We can use a control like text box to hold the value (and hide it)
We can use a hidden control (so ViewState will hold the value).
We can use ViewState directly to the hold the value (client side persisting), but is managed by server side code.
We can use session() to hold the value (server side persisting)
Over the years, we see "many" attempts to pass, share, persist data vales in a static class. It sometimes works, and often during development it "seems" to work, but the instant you deploy to a real working site, it blows up in a huge ball of flames.
So, using a static class to hold a Hodge podge of code? Sure, no problem, and that's quite much what we do in c# to obtain general "code module" of routines that we need throughout the applcation. But, be a vb.net module, or in c# a static class? Any concept of global values to that static class MUST be taken off the table and NOT used!!
Ok, so let's cook up a working example. We first have to choose a place/spot to hold and persist our coin count.
Hum, we have many choices. However, since this example code involves server side code. Then let's use session.
I mean, it would kind of defeat this whole example if we write the code 100% client-side JavaScript (which is not all that bad of a idea). However, since we attempting to learn, and use a web method?
Then let's wire this up using a web method. (as noted, we really don't need to use any server-side code here).
So, if we going to use session() to persist the value, then on first page load, we setup our coin count with a starting value of 10.
Also, WHEN you use/call/consume a web method of the page? There is NOT a instance of the page class. As a result, ANY AND ALL web methods must be static. In fact, it means really don't care if we placed the web method in the current page, is some ascx file, or wherever. Since the web page is NOT being posted back to the server, then all of the controls, values and things on that web page are STILL sitting on your desktop, and there is no copy of the web page in existence on the server side.
Next up:
data: '{coin: "' + coin + '" }',
dataType: "text",
So, you have some jason data, yet on the next line you saying we going to use text? Nope!!! If you going to pass json data the method, it going to return such json data back. Same goes if you choose xml, or whatever.
So, you can't pass json data, but then on the next line state we going to use text!!!!!
Ok, so our server side code now becomes this:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
// setup starting coin count
Session["CoinCount"] = (int)0;
}
}
[WebMethod(enableSession: true)]
public static void BtnAddCoin(int coin)
{
int MyCoins = (int)HttpContext.Current.Session["CoinCount"];
MyCoins += coin;
HttpContext.Current.Session["CoinCount"] = MyCoins;
Debug.Print("coins = " + MyCoins.ToString());
}
[WebMethod(enableSession: true)]
public static string ShowInsertedCoins()
{
int MyCoins = (int)HttpContext.Current.Session["CoinCount"];
return "You inserted: " + MyCoins.ToString();
}
Now, for client side, DO NOTE that when you use json format, then the return value/results are of the ".d" property of the web method. This is a asp.net thing, and it just the way it works.
So, now our client side code;
<div>
<div>
<p>Add coins: </p>
<div>
<div>
<a id="coin1" onclick="AddCoin(1)">1 </a>
<a>2 </a>
<a>5 </a>
<a>10 </a>
</div>
</div>
<div>
<p id="InsertedCoins"></p>
</div>
</div>
</div>
<script>
function AddCoin(coin) {
$.ajax({
type: "POST",
url: "/CoinCount.aspx/BtnAddCoin",
data: JSON.stringify({ coin: coin }),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function () {
// alert("AddCoin" + data);
ShowInsertedCoin();
},
error: function (req, status, error) {
alert("x" + error + status);
}
}).done(function (result) { ShowInsertedCoin(); });
}
function ShowInsertedCoin() {
var insertedCoins = $('#InsertedCoins');
$.ajax({
type: "POST",
url: "CoinCount.aspx/ShowInsertedCoins",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: {},
success: function (data) {
insertedCoins.text(data.d);
}
});
}
</script>
Next up?
How did "form2" get inserted into this page?
If you create a new aspx page, (web forms), then the last gazillion pages will have by default form1, and BIG flag that you have form2 here.
Anyway, the above should work. Note that you not only are sending json data, but you as a general rule need to add the content type, and you had this missing:
contentType: "application/json; charset=utf-8",
Also, so far we only added a click event for the "1", and you have to do the same for the other 3 values you have.
As other people already commented, it's recommended to use newer technologies, other than Webforms, but if you want to continue using it or it's an project of your work or something related, here's how I normally do in Javascript:
$.ajax({
method: "POST",
url: "ClientSide.aspx/BtnAddCoin",
contentType: 'application/json',
dataType: 'json',
data: JSON.stringify({
obj: JSON.stringify(data)
}),
success: function (response) {
let return = JSON.stringify(response.d);
// something
},
error: function (ex) {
// something
console.log(ex.Message)
},
beforeSend: function () {
// something
},
complete: function () {
// somethin
}
});
And for the C# file, every time you want to make an webmethod, that method need to be public and static, just like that (at least I learned that every time needs to be static):
[WebMethod]
public static string BtnAddCoin(int newCoin)
{
return newCoin;
}
Try and see if that helps
Related
Im doing a Maintenance Page where people can store the description of what it will say in a Resource file, at this point in the requirement they dont even know if the text will be pure text or will have tags like <a></a>. So at this point I have to assume it will be the case.
This proyect have been made in Webforms framework 3.5 in VS2010.
For simplicity sake I'll reveal the relevant parts:
<article>
<img alt="an image" src="Images/logo.jpg"/>
<h2>Site under Maintenance</h2>
<div>
<p id="Description"></p>
</div>
</article>
<script src="Includes/jquery-1.12.3.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function () {
$.ajax({
type: "GET",
url: "MaintenanceSite.aspx/GetMaintenanceDescription",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
$("#Description").text(msg.d);
}
});
});
</script>
Backend:
[WebMethod]
[ScriptMethod(UseHttpGet = true)]
public static string GetMaintenanceDescription()
{
string mensaje = HttpUtility.HtmlEncode(Resources.MaintenanceDescription);
return mensaje;
}
The problem is, Im receiving this on my paragraph:
<To href="">Contact Us</a>
(without the spaces as stack overflow is parsing the html correctly).
What am I missing?
There's two issues here. Firstly you need to remove the call to HtmlEncode() in the C# logic to return a plain HTML string. Secondly you need to use jQuery's html() method to display it instead of text(), as the latter will again encode the HTML.
string mensaje = Resources.MaintenanceDescription;
$("#Description").html(msg.d);
I have to bind nearly 50k records to my asp.net dropdownlist and it has to be searchable. What is the best way to do implement it . Are there any caching techniques so that the list loads as we scroll?Appreciate the suggestions.
Please advise.
I'd recommend taking advantage of jQuery's autocomplete plugin:
https://jqueryui.com/autocomplete/
It's configurable and has autocomplete search out of the box. It can also consume your remote data source (though you might consider a paginated API response):
http://api.jqueryui.com/autocomplete/#option-source
You can achieve this by use of web service.
first of all add following code in your aspx page.
<div>
<input type="text" value="" id="tbCountries" />
</div>
Now, Create your Web service using following code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Data.SqlClient;
[System.Web.Script.Services.ScriptService]
public class WebService : System.Web.Services.>WebService {
[WebMethod]
public List<string> ShowCountryList(string sLookUP)
{
List<string> lstCountries = new List<string>();
string sConnString = "Data Source=DNA;Persist Security Info=False;" +
"Initial Catalog=DNA_CLASSIFIED;User Id=sa;Password=;Connect Timeout=30;";
SqlConnection myConn = new SqlConnection(sConnString);
SqlCommand objComm = new SqlCommand("SELECT CountryName FROM Country " +
"WHERE CountryName LIKE '%'+#LookUP+'%' ORDER BY CountryName", myConn);
myConn.Open();
objComm.Parameters.AddWithValue("#LookUP", sLookUP);
SqlDataReader reader = objComm.ExecuteReader();
while (reader.Read()) {
lstCountries.Add(reader["CountryName"].ToString());
}
myConn.Close(); return lstCountries;
}
}
Finally, Create jquery Method for bind Textbox with webservice,
<script>
$(document).ready(function() {
BindControls();
});
function BindControls() {
$("#tbListOfCountries").autocomplete({
source: function(request, response) {
$.ajax({
url: "WebService.asmx/ShowCountryList",
data: "{ 'sLookUP': '" + request.term + "' }",
dataType: "json",
type: "POST",
contentType: "application/json; charset=utf-8",
dataFilter: function(data) { return data; },
success: function(data) {
response($.map(data.d, function(item) {
return { value: item }
}))
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
alert(textStatus);
}
});
},
minLength: 1 // MINIMUM 1 CHARACTER TO START WITH.
});
}
</script>
In the backend, create a controller action (if you are using ASP.NET MVC) or a page method (if you're using ASP.NET Web Forms) that receives a searchTerm parameter and returns an array of the top (say, 100) results.
In the frontend, use a typeahead / autocomplete plugin such as this one. When the user sets the search term, perform an Ajax request against the backend and display the results. When performing the Ajax request, you can also enable and configure caching. No more optimization shall be needed.
Use AutoComplete textbox and set datasource from remote API especially when working with huge dataset. This will avoid your application UI getting hanged on every character search.
Ref the Link: https://github.com/ghiden/angucomplete-alt
depends on where the list items are coming from.
if they are coming from a list or database just append them then use javascript to search the list.
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css" />
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
</head>
<body>
<form id="form1" runat="server">
<div class="ui-widget">
<asp:TextBox ID="txtDepartment" runat="server" ClientIDMode="Static" />
</div>
</form>
<script>
$(function () {
$("[id$=txtDepartment]").autocomplete({
source: function (request, response) {
$.ajax({
url: "FetchDropdownList.aspx/GetDepartment",
data: "{'departmentName':'" + document.getElementById('txtDepartment').value + "'}",
dataType: "json",
type: "POST",
contentType: "application/json; charset=utf-8",
dataFilter: function (data) { return data; },
success: function (data) {
response($.map(data.d, function (item) {
return {
value: item.Name
}
}))
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert(textStatus);
}
});
},
minLength: 1
});
});
</script>
</body>
</html>
public class Department
{
public int Id { get; set; }
public string Name { get; set; }
}
private static List<Department> GetDepartment()
{
List<Department> departments = new List<Department>();
for (int i = 0; i < 10000; i++)
{
Department department = new Department();
department.Id = i;
department.Name = "Department " + i.ToString();
departments.Add(department);
}
return departments;
}
[WebMethod]
public static List<Department> GetDepartment(string departmentName)
{
int totalDepartments = GetDepartment().Count;
List<Department> departments = GetDepartment().Where(d => d.Name.ToLower().StartsWith(departmentName.ToLower())).Take(20).ToList();
return departments;
}
I had same problem like you and I used RadAutoCompleteBox. It has many
client-side and server-side events that help you to handle various situations. It's very comfortable for ASP.NET projects.
I see two immediate solution for this.
As other has suggested usign ajax to search related item as user types and show them.
On page load get all your data and store them in javascript variable then you can perform search on that variable as user types and bind search result to dropdown list.
Similar to this one:
Definitely any Autocomplete implementation will work in your scenario.
Solution 1: Use Autocomplete select box
If you don’t want to waste bandwidth or want to support devices with
low specification, you should go for AutoComplete with server side
data fetching.
If you want high usability and don’t care about the bandwidth,
you can use autocomplete with local data (Fetch 50k records one time
and bind to the autocomplete). But to make sure that you don’t paint
all these into DOM at a single time. You need to limit the records
being shown at a particular time.
Solution 2 : Use select with virtualization
But if you want to give the best of the usability to your
clients, you should go with a solution where your select box is
virtualized and the data loaded into DOM on scrolling of the select box. By virtualization you are making sure that only those
items are getting pushed to DOM which are being shown in the
screen at that point of time.
You can find a jQuery based virtual select here
Similar implementation in React here
I am not quite sure what I am doing wrong here, I have a page in my webforms project which uses jQuery accordion. When the page is loaded for the first time, the server side code fetches some data to populate a user control which is then added to my page as shown below. This works fine and I have no problem with this.
The problem is, I am trying to generate a similar thing on my client, using jQuery by simply creating the controls in jQuery ajax response function and then add to dvProjects
ASPX markup:
<asp:Content ID="Content2" ContentPlaceHolderID="Content" runat="server">
<div runat="server" id="dvProjects" class="dvAccordion">
</div>
</asp:Content>
jQuery AJAX code:
function AddUserProject() {
var projectDialog = $('.dvEditExhibition');
var projectName = projectDialog.find('.txtProjectName').val();
var projectDescription = projectDialog.find('.txtProjectDescription').val();
var project= JSON.stringify({
'projectId': "00000000-0000-0000-0000-000000000000",
'projectName': projectName,
'projectDescription': projectDescription
});
$.ajax({
type: "POST",
url: "PresentationService.asmx/AddUserProject",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: project,
success: function(response) {
var data = response.d;
console.log(data);
var h3Title = $('<h3/>', {
id: "h3ProjectTitle",
text:data.Name
});
var divWrapper = $('<div/>', {
});
var dvProjectImages = $('<div/>', {
class: "dvProjectImages"
});
var imgProjectImage = $('<img/>', {
id: "imgProjectImage",
class: "imgProjectImage"
});
var dvProjectDetails = $('<div/>', {
id: "dvProjectDetails",
});
var pProjectDescription = $('<p/>', {
id: "pProjectDescription",
class: "pProjectDescription",
text: data.Description
});
dvProjectImages.append(imgProjectImage);
dvProjectDetails.append(pProjectDescription);
divWrapper.append(dvProjectImages, dvProjectDetails);
var dvProjects = $('#dvProjects');
dvProjects.append(h3Title);
},
error: function(response) {
}
});
}
My problem is these controls are not added to dvProjects.
Update: you had a bug in your javscript too, refer to my comments.
That's because when you set a div to runat="server" every html element in it, becomes a Literal Control server side and they are persisted to view state.
When you post the page, the server side control rebuilds the runat="server" div with information in the postdata (view state).
When you add controls with jQuery they are not in the postData/ViewState, so when the server side code revuilds the div, it doesn't see the ones you added with jQuery.
To fix that, you would need to create a custom WebControl and implement IPostBackEventHandler. So instead of...
<div runat="server" id="dvProjects" class="dvAccordion">
You would have something like this,
<xyz:ProjectsControl runat="server" cssclass="dvAccordion" id="theProjects" />
Then to add a control to it, you would do something like
__doPostBack('<%= theProjects.UniqueID %>, 'someJsonStringHere');
Then in your IPostBackEventHandler implementation, you serialize the json string coming in and use that to determine what server side controls to add to the ProjectsControl.
WebControl has methods you can override, WriteBeginTag, WriteEndTag, and there you could write an opening div and closing div, so your web control would render as a div.
By adding a string property calledd "CssClass" to your webcontrol, you can use that to set the class. So in WriteBeginTag you would also write out the class attribute to the div using CssClass as the value.
I want to send data using ajax from jQuery to c# (note: I'm sending request to the same page).
I am following this tutorial http://encosia.com/using-jquery-to-directly-call-aspnet-ajax-page-methods/.
NOTE: This is a asp.net 3.5 on SharePoint 2010 webpart solution.
This is my jquery code:
$.ajax({
type: "POST",
url: getURLWithoutQuery() + "/saveOrder",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
alert(msg.d);
}
});
// return the url of the current page without any query parameters
function getURLWithoutQuery() {
return location.protocol + '//' + location.host + location.pathname;
}
and in c#, the main file is PDFLibraryUserControl.ascx.cs. This is the one that has the Page_Load function.
However I have another class file called SaveStructure.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI;
using System.Web.Services;
namespace PDFLibrary.PDFLibrary
{
public partial class SaveStructure : Page
{
[WebMethod]
public static int saveOrder()
{
return 1234;
}
}
}
I expect to get an alert saying 1234, but instead I get this:
Does it have something to do with the function saveOrder being on another file than the main one? Or maybe my URL is not correct? I don't want to hardcode the URL in it, because the current page is the aspx page and also contains the jQuery code to send the POST (to the same page).
Does anyone know what's wrong and can fix this?
Putting page methods inside of a user control is a bad idea, because the biggest problem is that user controls are not directly accessible via script (read: jQuery) like .aspx pages are. If you are constrained to only putting this logic in a user control, then my recommendation is create a web service (.asmx) that will perform the logic the page method was going to do. A web service is directly accessible via the jQuery .ajax() method, like this:
Code from myService.asmx:
[WebMethod]
public static int saveOrder()
{
return 1234;
}
Code in SharePoint .aspx page:
<script type="text/javascript">
$(document).ready(function() {
$.ajax({
type: "POST",
url: "myService.asmx/saveOrder",
contentType: "application/json; charset=utf-8",
data: "{}",
dataType: "json",
success: handleSuccess,
error: handleError
});
});
function handleSuccess(data, status) {
// Do something with successful data retrieval
}
function handleError(xmlRequest) {
// Do something with error
}
</script>
I have a public in my code behind page that takes a string.
I would like to call this method from javascript.
The parameter that I want to pass down is variable that changes from a ddl.
So I have something like this:
var value = document.getElementById('ddlContact').value;
<%=PopulateContactFields("value") %>
This passes down the word 'value' and not the data in value.
I can't figure out the proper syntax to pass down the data in value.
Thanks
As mentioned by others, trying to access C# code behind directly from javascript is impossible.
However, you can communicate with it indirectly.
I think your best shot is to use a combination of jQuery and the [WebMethod] attribute.
javascript function using jQuery to do an AJAX call:
function Search() {
var search = $('#<%= ddlContact.ClientId %>').val();
var options = {
type: "POST",
url: "Default.aspx/Hello",
data: "{'name' :'" + search + "'}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg) {
alert(msg);
}
};
$.ajax(options);
}
Code behind:
public partial class _Default : System.Web.UI.Page
{
[WebMethod]
public void Hello(string name)
{
return "Hi " + name;
}
}
The code you are showing is executed server side when the HTML is generated. In other words it is executed BEFORE it hits the browser and your user had a chance to do anything with the page.
No matter what syntax you would use here the information you want cannot be accessed at this time - it does not exist yet.
The right approach here is to sent this information to the server either by posting the page or using AJAX and then, on the tail end of request/response cycle do your processing
Another option would be to do the processing client side using Javascript