asp.net dropdownlist caching for Huge data - c#

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

Related

How can I perform an ajax call to .aspx.cs

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

View data from the database

this year I need to build a project on HTML
I choose to build a store so I build a database for all the items (i call it items)
every item has a logo(link to photo), name, price, and description.
and now I want to show all the items on the main page (every single item on an item card)
but! I need to show it Dynamically(That it will only show products that exist in the database)
I try to do it with function with response.write but it did not succeed...
If you can help it would be great!
Create web APIs of return Json type in MVC architecture with C# and include and display the Jquery library in the project.
Jquery library CDN link in;
https://code.jquery.com/jquery-3.6.0.min.js
Example backend code;
public JsonResult AllProduct()
{
var list = db.products.ToList(); //products name table
return Json(list, JsonRequestBehavior.AllowGet);
}
To connect with jquery in html page;
$.ajax({
type: "GET",
url: "AllProduct",
contentType: "application/json",
dataType: "json",
success: function(response) {
$("#table").html(response); //Example #table div show return all value
},
error: function(response) {
console.log(response);
}
});
The database is unknown so let me try to explain the logic. Let me give an example over MVC since you use c# and html tags by definition. In Razor view it will look like below
#foreach(var product in ProductList){
<div>
<div><img src="#product.logoImgConvertedToBase64" /></div>
<div>#product.name</div>
<div>#product.price</div>
<div>#product.description</div>
</div>
}

Invalid postback or callback argument - Button OnClick

I have seen many posts about this error on an aspx web form page.
Invalid postback or callback argument. Event validation is enabled using in configuration or <%# Page EnableEventValidation="true" %> in a page. For security purposes, this feature verifies that arguments to postback or callback events originate from the server control that originally rendered them. If the data is valid and expected, use the ClientScriptManager.RegisterForEventValidation method in order to register the postback or callback data for validation.
My issue seems to be a little different. All of the posts I have read seem to be related to grid views, drop down lists, and other controls loading outside of Page_Load event.
In this case, I get this error with a simple Button click:
<asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />
Button1_Click just calls a simple method.
Now, in this Codebehind file, I do have 2 WebMethods that load a dropdown list from another drop down list value in jQuery Ajax. Could the fact that I have WebMethods exposed be the issue with the error?
All of the Click events on the page are now blocked.
Here is the jQuery and WebMethod code.
<script type="text/javascript">
$("#<%= ddlJobNumber.ClientID %>").change(function (e) {
var jobNumber = $(this).val();
FillPhaseCode(jobNumber);
SetDescription(jobNumber);
});
function FillPhaseCode(jobNumber)
{
$.ajax({
type: "POST",
<%--//url: '<% ResolveUrl("~/Pages/JobTimecard.aspx/FillPhaseCode"); %>',--%>
url: "JobTimecard.aspx/FillPhaseCode",
contentType: "application/json; charset=utf-8",
data: '{"jobNumber":"' + jobNumber + '"}',
dataType: "json",
success: function (result) {
$("#<%= ddlPhaseCode.ClientID %>").empty();
$.each(result.d, function (key, value) {
$("#<%= ddlPhaseCode.ClientID %>").append("option value='0'>Select</option>");
$("#<%= ddlPhaseCode.ClientID %>").append($("<option></option>").val(value.PhaseCode).html(value.PhaseDesc));
});
},
error: function ajaxError(result) {
alert("Error result: " + result.status);
}
});
}
function SetDescription(jobNumber)
{
$.ajax({
type: "POST",
url: "JobTimecard.aspx/SetJobDescription",
contentType: "application/json; charset=utf-8",
data: '{"jobNumber":"' + jobNumber + '"}',
dataType: "json",
success: function (result) {
$("#<%= lblJobName.ClientID %>").text(result.d);
},
error: function ajaxError(result) {
alert("Error result: " + result.status);
}
});
}
</script>
public class PhaseCodes
{
public string PhaseCode { get; set; }
public string PhaseDesc { get; set; }
}
[WebMethod]
public static List<PhaseCodes> FillPhaseCode(string jobNumber)
{
SpectrumSim clsSpectrum = new SpectrumSim();
DataTable dt = new DataTable();
dt = clsSpectrum.GetPhaseCodes(jobNumber, "1");
List<PhaseCodes> list = new List<PhaseCodes>();
foreach (DataRow dr in dt.Rows)
list.Add(new PhaseCodes
{
PhaseCode = dr["Phase_Code"].ToString(),
PhaseDesc = dr["Description"].ToString()
});
return list;
}
[WebMethod]
public static string SetJobDescription(string jobNumber)
{
DataTable dt = new DataTable();
SpectrumSim clsSpectrum = new SpectrumSim();
dt = clsSpectrum.GetJobNumbers();
var dataRow = dt.AsEnumerable().Where(x => x.Field<string>("Job_Number") == jobNumber).FirstOrDefault();
string description = dataRow["Job_Description"].ToString();
return description;
}
I hope it is that simple, but I can't find the issue.
EDIT:
here is my Page Load event
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
FillJobNumberDropdown();
if (TimeId != 0)
{
LoadTimecard();
}
}
}
I'm guessing that on PostBack Web Forms is detecting a value in the server-side DropDownList that it doesn't recognise as a valid option because you are adding options to it client-side.
Does the DropDownList(s) that is being changed client-side need to be server-side controls?
If so, you will need to populate it with the same options on PostBack before Page_Load (eg. Page_Init) so it can recognise the selected option.
Alternately, change to a non-server-side HTML control instead and use Request.Form to get the selected value.
To solve this problem in a Web Forms scenario, I just ended up using an UpdatePanel to build the cascade dropdownlist.
The HTML control will work too, but I did not want a mix of controls.

How do I create a single-page ASP.NET application that submits info to a database?

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! :)

jQuery Ajax call to database on click ASP.net

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!

Categories