Let's say I've got a table in a SQL Server database that looks like
StateName notes
alabama 'notes about alabama'
alaska 'notes about alaska'
..... .........
EDIT: This question will be divided into two parts, one for the initial problem and why it didn't work and my reformed, hopefully more accurate second solution.
In the web form, the name of the state are represented as link button inside of a table. I'm trying to use jQuery to make an Ajax database call when a user clicks on a state name, the text value of the link button will be send to a stored procedure in the database.
That stored procedure is something like
create proc spGetStateData
#stateName varchar(50)
as
begin
select notes from
states
where statename = #stateName
end
For testing purposes, I added a a text box and a button so that when the user types the name of the state into the text box, the Notes column from the States database table is displayed.
[WebMethod]
public static string GetStateData(string stateName)
{
string stateNotes = string.Empty;
string cs = ConfigurationManager.ConnectionStrings["dbcs"].ConnectionString;
using (SqlConnection con = new SqlConnection(cs))
{
using (SqlCommand cmd = new SqlCommand("spGetStateData", con))
{
con.Open();
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#stateName", stateName);
stateNotes = cmd.ExecuteScalar().ToString();
}
}
return stateNotes;
}
protected void btnSubmit_Click(object sender, EventArgs e)
{
lblStateNotes.Text = GetStateData(txtStateName.Text);
hiddenDiv.Visible = true;
}
This part works, so I know it's not my WebMethod or a database connection that's failing. When I try to do this same thing with jQuery, it fails.
<script type="text/javascript" language="javascript">
$(document).ready(function () {
$("#states a").click(function () {
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "WebForm1.aspx/GetStateData",
data: $(this).text(),
dataType: "json",
success: function (data) {
response(data.d);
},
error: function (x) {
alert('error');
}
});
});
});
</script>
Okay, I pulled open developer tools for Chrome and found out what the reason for the AJAX failing was that I was getting a 'couldn't load resource HTTP 500 error'. It was telling me that the method name and parameter couldn't be found (even though by all rights they were there). So then I tried a second way, which seems like a better way (if I can get it to work!)
So then I thought 'let's use a WebService'. And here is my rendition of that:
<!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>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$("a").click(function () {
var stateName = JSON.stringify({ "stateName": $(this).text() });
$.ajax({
type: "POST",
url: "GetStateData.asmx/GetData",
contentType: "application/json; charset=utf-8",
data: stateName,
dataType: "json",
success: function (data) {
$("#lblNotes").text(data);
},
error: function (x) {
alert('message');
}
});
});
});
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
Alabama
Alaska
<asp:Label runat="server" ID="lblNotes"></asp:Label>
</div>
</form>
</body>
</html>
web service:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Web.Script.Services;
namespace jQueryAjaxWebservice
{
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
[System.Web.Script.Services.ScriptService]
public class GetStateData : System.Web.Services.WebService
{
[WebMethod]
[ScriptMethod]
public string GetData(string stateName)
{
string cs = ConfigurationManager.ConnectionStrings["dbcs"].ConnectionString;
string stateNotes ="test" ;
using (SqlConnection con = new SqlConnection(cs))
{
using (SqlCommand cmd = new SqlCommand("spGetStateData",con))
{
con.Open();
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#stateName", stateName);
stateNotes = cmd.ExecuteScalar().ToString();
}
}
return stateNotes;
}
}
}
I've tested the WebService, and it works. However, when I try to call the web service code from default.aspx, I get [Object object] as the lblNotes text. If I change (data) to "test" then I get the correct output of "test" to the screen. So the faulty part is in the success portion of the Ajax call. I put a breakpoint on the GetData function and stateNotes is receiving the proper text value, so the only place left for the problem to be is in the success line of the ajax call.
I think the way you format your data option in ajax might be wrong. It always works in key-value pairs. In the current form you are only sending the value, no key. You might have to change it to this format :
var stateName = { "stateName" : $(this).text()}
or
var stateName = JSON.stringify({ "stateName" : $(this).text()})
But mostly, I've seen only the second one to work, partly because jQuery doesn't pre-process the data option for it be readable in C#. So it's always recommended to use stringify on ajax requests with type set to "POST".
Then, in your ajax call,
$.ajax({
//ajax options
data : stateName
//some more ajax options
});
Also, you might want to make your error option more descriptive, like this :
$.ajax({
//ajax options
error: function (xhr, ajaxOptions, thrownError) {
alert(xhr.status);
alert(thrownError);
}
});
This will tell you where you're going wrong and you could debug it as well.
EDIT:
In the success function, try looking for data.d instead of data. You'll find that your data lies inside it. Also, as mentioned before (and i cant stress this enough), please use error handler with xhr options. It'll be easier to debug then. Read this if you want to know why the result returns data.d and not just data.
$.ajax({
//some ajax options
success: function (data) {
//data.d will contain your data
console.log(data.d);
$("#lblNotes").text(data.d);
},
error: function (xhr, ajaxOptions, thrownError) {
console.log(xhr);
alert(xhr.status);
alert(thrownError);
}
});
Hope this helps!
Related
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
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
Ok, I know this is embarassing since I've been working as a web developer with ASP.NET for months, but I used to starting with a largely prepackaged ASP.NET MVC site with routing, controllers, etc., and extending it from there. All I need to do right now is creating a single-page ASP.NET page that submits a form to the database.
I already have my table in the database
CREATE TABLE stuff ( field1 VARCHAR (100), field2 VARCHAR (100) );
and I have a form in my HTML
<form id="myform">
<input type="text" name="field1"/>
<input type="text" name="field2"/>
<input type="submit"/>
</form>
and I have a function
$('#myform input[type="submit"]').click(function(){
var that = this;
$.ajax({
url: '????',
method: 'POST',
data: new FormData($(that).closest('form')[0]),
success: function() { alert("Well, at least this succeeded"); }
});
I started in Visual Studio with a "ASP.NET Empty Web Application Visual C#" but I seriously don't know what type of file I need to right-click-Add to the project to handle this. All I'm trying to do is a simple insertion of the inputs field1 and field2 into their corresponding columns in the database. I can't find any resources of how to build an ASP.NET page from scratch and all the books I've ever read start with a template that has everything hooked up, so ...
Can someone give me a hint of how to connect the dots here?
Here is the Code
web method must be public and static
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.8.0.js"></script>
<script src="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.22/jquery-ui.js"></script>
<link rel="Stylesheet" href="StyleSheet.css" />
<script type="text/javascript">
$(document).ready(function () {
$('#Button1').click(function (e) {
alert('Data Saved')
var commentsCorrespondence;
var ddlST = $('#ddlStatus option:selected').val();// get dropdown selected value in ddlST variable
var chkbox = $('#ChkValue').val();// get checkbox value in chkbox
var Date = $('#txtDate').val();//get textbox value in date variable
$.ajax({
type: "POST",
url: "AutoCompleteCity.aspx/SaveData", //this is the url from which you call your web method ! in my case its /Default.aspx and method name is SaveData
data: "{'status': '" + ddlST + "','chkBoxValue': '" + chkbox + "','DueDate': '" + Date + "'}",// These are the method parameters in my case 'status' , 'chkBoxValue' and 'DueDate' are parameters
contentType: "application/json; charset=utf-8",
dataType: "json",
success: alert('Data Saved'),
failure: function (response) {
Message = response.d;
}
});
return false;
});
});
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:TextBox ID="txtDate" runat="server"></asp:TextBox>
<asp:DropDownList ID="ddlStatus" runat="server"></asp:DropDownList>
<asp:CheckBox ID="ChkValue" runat="server" />
<asp:Button ID="Button1" runat="server" Text="Button" />
<br />
<br />
<br />
</div>
</form>
</body>
</html>
Code Behind
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class AutoCompleteCity : System.Web.UI.Page
{
[WebMethod]
public static void SaveData(string status, string chkBoxValue, string DueDate)
{
List<string> Emp = new List<string>();
string query = string.Format("Insert Into [Table] Values ({0},{1},{2})", status, chkBoxValue, DueDate);
using (SqlConnection con = new SqlConnection("your Connection string"))
{
using (SqlCommand cmd = new SqlCommand(query, con))
{
con.Open();
cmd.ExecuteNonQuery();
}
}
}
protected void Page_Load(object sender, EventArgs e)
{
}
}
Create a WebMethod in cs file of the same page
[WebMethod]
Public static bool FxName(string field1, string field2){
// Do the code here for saving
}
in ajax
$('#myform input[type="submit"]').click(function(){
var that = this;
$.ajax({
url: 'pagename.aspx/FxName',
method: 'POST',
contentType: 'application/json; charset=utf-8',
dataType: 'json',
data: {"field1": valueoftextbox,"field2":valueoftextbox},
success: function() { alert("Well, at least this succeeded"); }
});
Given the template you're using, I think a controller from ASP.NET Web API will be more appropriate than WebMethods (which were introduced in .NET 3.5 and haven't changed since...).
Add an ApiController to your project:
public class FooController : ApiController
{
[HttpPost]
public IHttpActionResult PostForm(FormInput input)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
// You'll have to create the repository class as well as inject it
// into your controller. If you don't know what I'm talking about,
// google "dependency injection asp.net webapi" for more info.
_repository.SaveFormDataToDb(input.Field1, input.Field2);
return Ok();
}
}
You'll also need to create the input model:
[DataContract]
public class FormInput
{
[DataMember]
[Required]
public string Field1 { get; set; }
[DataMember]
[Required]
public string Field1 { get; set; }
}
The [DataContract] and [DataMember] attributes are from System.Runtime.Serialization. [Required] is from System.ComponentModel.DataAnnotations, and will work in conjunction with ModelState.IsValid() to validate input - you can add a bunch of other attributes too (or write your own!) to specify other rules than just required fields.
Depending on how you're planning to host this (in IIS or not) the way you hook up the dependency injection, routing etc is a little different, but the tutorials on asp.net are legio.
Good luck! :)
We're migrating to ASP.NET from PHP, and I'm a little new to jQuery. So, I'm having a little bit of an issue with this function:
[System.Web.Services.WebMethod]
internal static string[] GetSearchSuggestions(string SearchQuery)
{
string ConnectionString = "Data Source=<omitted>;Initial Catalog=<omitted>;Integrated Security=True";
string TSQL_Query = String.Format("SELECT DISTINCT TOP 5 [colum-name] from [table] WHERE [column-name] LIKE '{0}%' AND len([column-name]) > 0", SearchQuery);
List<string> SearchSuggestions = new List<string>();
using (System.Data.SqlClient.SqlConnection connection = new System.Data.SqlClient.SqlConnection(ConnectionString))
{
using (System.Data.SqlClient.SqlCommand command = new System.Data.SqlClient.SqlCommand(TSQL_Query, connection))
{
connection.Open();
System.Data.SqlClient.SqlDataReader r = command.ExecuteReader();
while (r.Read())
{
SearchSuggestions.Add(r.GetString(0));
}
}
}
return SearchSuggestions.ToArray();
}
And this is my jquery:
<script type="text/javascript">
$(document).ready(function () {
$("#SearchQueryBox").autocomplete({
source: function (request, response)
{
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: GetSearchSuggestions,
data: "{'term':'" + $("#SearchQueryBox").val() + "'}",
dataType: "json",
success: function (data) {
response(data.d);
},
error: function (result) {
alert("error");
}
});
}
});
});
</script>
Now, if I were to turn this into a simple post that loads the next page, the above ASP.NET C# code works. However, I can't seem to get a jQuery response under any of my test circumstances.
This page is called Default.cshtml, and is using the ASP.NET Razor syntax. The function is located on the same page like this:
#functions
{
// GetSearchSuggestions() code here
}
How do I appropriately post to an ASP.NET function on the same page, and receive a response?
Thanks in advance!
I am assuming you are using ASP.NET MVC. If that's the case:
You would need to move your function (that is in Default.cshtml) to a new ActionMethod with HttpPost in your Controller.
So, let's say your Default.cshtml is loaded by HomeController.cs. In HomeController.cs, you would create new ActionMethod:
[HttpPost]
public void ActionResult GetSearchSuggestions() {
// GetSearchSuggestions() code here
}
Also, in your jQuery, the option url of .ajax will need to be the URL of your site. Again, with the example I gave above, the URL would be http://www.example.com/Home/GetSearchSuggestions
You can't call C# or ASP.NET function from jQuery like that, you must specify the URL of that ActionMethod.
UPDATE
On the second look, I am not sure if where your internal static string[] GetSearchSuggestions(string SearchQuery) located. But you can move that to HomeController.cs I was talking about. Just remove the [System.Web.Services.WebMethod] and changed to [HttpPost]
Me and ASMX web services do not get on. We argue. She brings up arguments we had in the past. It's a pain. Our relationship is on the rocks!
I have an ASMX web service, which I haven't serialised with the Newtonsoft library (as explained why here: http://encosia.com/2011/04/13/asp-net-web-services-mistake-manual-json-serialization/). It looks like this:
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public string[] GetCitiesWithState(string isoalpha2, string prefixText)
{
var dict = AtomicCore.CityObject.GetCitiesInCountryWithStateAutocomplete(isoalpha2, prefixText);
string[] cities = dict.Values.ToArray();
return cities;
}
Simple enough right? It return this when searching for new:
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://tempuri.org/">
<string>New Orleans, Louisiana</string>
<string>New York, New York</string>
</ArrayOfString>
I was expecting JSON, but after a bit of reading, it seems I shouldn't try and serialise the output - it should just happen right? Anyway, so I have the following JQuery on the frontend:
$('#<%=txtCity.ClientID%>').autocomplete('<%=ResolveUrl("~/AtomicService/Assets.asmx/GetCitiesWithState")%>', {
dataType: 'json',
httpMethod: 'POST',
contentType: 'application/json; charset=utf-8',
parse: function (data) {
var rows = new Array();
for (var i = 0; i < data.d.length; i++) {
rows[i] = { data: data.d[i], value: data.d[i].Value, result: data.d[i].Value };
}
return rows;
},
formatItem: function (row, i, n) {
return row.Value;
},
extraParams: {
minChars: 2,
isoalpha2: '<%=Session["BusinessCountry"].ToString()%>',
maxRows: 20,
prefixText: function () {
return $('#<%=txtCity.ClientID%>').val()
}
},
max: 20
}).result(function (event, data, formatted) {
if (data) {
alert(data['Key']);
}
});
I can see the calls using Chrome:
And yet stuff all happens! There is no Jquery errors, no fireworks, no anything. She is ignoring me.
At first I was blaming the webservice, but I think this may have more to do with how I'm parsing and formatting the data in jquery.
So, my question is, what am I doing wrong and how can I make the autocomplete work correctly?
Help appreciated :)
EDIT: It may not be helpful, but this is what I see in Fiddler:
The jQuery UI autocomplete does not anymore use the formatItem method. That and many other such methods were present in autocomplete's earlier version that was a plugin here
I have rewritten your code using the jQuery UI's autocomplete and it works for me with the below htm and asmx files.
Refer to the demos on the jQueryUI autocomplete for more methods you could use.
I have used the json2.min.js from www.json.org
Also I have added the [System.Web.Script.Services.ScriptService] attribute to the Service1 class so that it could directly be invoked from jQuery as a json web service.
These articles helped me:
ASMX and JSON – Common mistakes and misconceptions
Using jQuery to Consume ASP.NET JSON Web Services
3 mistakes to avoid when using jQuery with ASP.NET AJAX
The htm file
<!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>
<title>jQuery to ASMX</title>
<link rel="Stylesheet" type="text/css"
href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.11/themes/cupertino/jquery-ui.css"/>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script>
<script type="text/javascript"
src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.11/jquery-ui.min.js"></script>
<script type="text/javascript" src="http://localhost/Scripts/json2.min.js"></script>
</head>
<body>
<script type="text/javascript">
$(document).ready(function() {
$("#txtInput").autocomplete({
source:function (request, response) {
var paramters = {
isoalpha2: '<%=Session["BusinessCountry"].ToString()%>',
prefixText: request.term
};
$.ajax({
url: 'Service1.asmx/GetCitiesWithState',
type: 'POST',
dataType: 'json',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify(paramters),
success: function(data) {
response($.each(data.d, function(index, value) {
return {
label: value,
value: index
}
}));
}
});
},
minLength:2,
delay:500
});
});
</script>
<p>
Hello, World!</p>
<label for="txtInput">
Enter the string here:</label><input type="text" id="txtInput"/>
</body>
</html>
The asmx file
using System.Web.Script.Services;
using System.Web.Services;
namespace jQueryAutoCompleteBackEnd
{
/// <summary>
/// Summary description for Service1
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
[ScriptService]
public class Service1 : WebService
{
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public string[] GetCitiesWithState(string isoalpha2, string prefixText)
{
return new string[] { "New Orleans, Lousiana", "New York, New York" };
}
}
}
The reason that the asmx webmethod is returning XML rather than JSON is because the HTTP method is GET rather than POST.
In order for the autocomplete plugin to use POST you'll have to implement the source parameter using a callback function, see here