asp.net web service to interact with database - c#

Sorry Im new to this approach.
I wanted to write various web servers at my sql server using .net c#.
to perform various operations to my database, e.g update customer, delete customer, select customer etc..
I am writing a client side web app (to deploy eventually on a mobile) that will send and retrieve data to these web services.
I am unsure of the methods that allow me to do this from my client that allow authentication and are reasonably secure.
So far I am thinking of Jquery AJAX?

Ajax will allow you to exchange data between server and client within a page without reloading it. It sends and receives data using HTTP messages.
Setup REST service and add jQuery to HTML page. At this point you have a communication channel. Now you have to think about security model.
You may require client to send username+password or authentication token in every request. You also may place these credentials anywhere within HTTP message (cookie, header, body).
If it's your first experience with ASP.NET, try to use standard Forms Authentication (it stores authentication token in ASPX_AUTH cookie) or any .NET builtin authentication models.
See articles below to see examples:
Security in ASP.NET
Secure a Web API with Individual Accounts and Local Login in ASP.NET Web API 2.2

first Create ASMX File
second Create Class inside or outside the ASMX File
public class NationalityInfo
{
public int ID { get; set; }
public string Name { get; set; }// any Other
}
[WebMethod]
[ScriptMethod]
public List<NationalityInfo> LoadNat()
{
string Conn = System.Configuration.ConfigurationManager.ConnectionStrings["GPS_TrackingConnectionString"].ConnectionString;
List<NationalityInfo> NatInformation = new List<NationalityInfo>();
DataSet ds;
using (SqlConnection con = new SqlConnection(Conn))
{
using (SqlCommand cmd = new SqlCommand("select * from Nationality", con))
{
con.Open();
cmd.Connection = con;
cmd.CommandType = CommandType.Text;
using (SqlDataAdapter da = new SqlDataAdapter(cmd))
{
ds = new DataSet();
da.Fill(ds);
}
}
}
try
{
if (ds != null)
{
if (ds.Tables.Count > 0)
{
if (ds.Tables[0].Rows.Count > 0)
{
foreach (DataRow dr in ds.Tables[0].Rows)
{
NatInformation.Add(new NationalityInfo()
{
ID = Convert.ToInt32(dr["Id"]),
Name = dr["Name"].ToString()
});
}
}
}
}
}
catch (Exception ex)
{
throw ex;
}
return NatInformation;
}
in the client side
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "Query.asmx/LoadNat",
data: "{}",
dataType: "json",
success: function (Result) {
Result = Result.d;
$.each(Result, function (key, value) {
var id=value.ID;
var Name=value.Name;
});
},
error: function (Result) {
}
});
Note in the client side you get object (Array ) not json
For saving (Get values from client to server)
function SaveNat() {
var Nat = {};
Nat.ID = txtID.value;
Nat.Name = txtName.value;
var NatVar = JSON.stringify(Nat);
$.ajax({
type: "POST",
url: "Query.asmx/SaveNat",
data: '{Nat: ' + NatVar + '}',
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (response) {
alert('Saved');
}
});
}
Server Save Function
[WebMethod(EnableSession = true)]
[ScriptMethod]
public void SaveNat(NationalityInfo Nat)
{
string Conn = ""// Your Connection
using (SqlConnection con = new SqlConnection(Conn))
{
using (SqlCommand cmd = new SqlCommand())
{
//Save }
}
}
as for security you must not sent user name and passwor in plain text it will be visible in the Browser trafic
you should send it encrypted and decrypt it on your server

Related

SqlDependency OnChange event firing multiple times

I'm have a comment system on a project where you can view different pages and they have their own comments. I'm trying to use signalR with SqlDependency to automatically pull new comments on the page.
My problem is that if multiple people have a connection open with SqlDependency the number of "onchange" events called from the sqlnotification start getting multiplied. Instead of the onchange even getting called once it will be called multiple times for each user. (Even if they are not viewing the same comments page)
I've pretty much exhausted all searching here with the most common response being that I need to unsubscribe the event when it's called like this:
private void dependency_OnChange(object sender, SqlNotificationEventArgs e)
{
SqlDependency dependency = (SqlDependency)sender;
dependency.OnChange -= new OnChangeEventHandler(dependency_OnChange);
if (e.Info.ToString().ToLower().Trim() == "insert")
{
MyHub.Show();
}
}
This didn't seem to change anything for me so I'm lost on what the best way to prevent this would be.
GetData method:
[WebMethod]
public IEnumerable<DUpdates> GetData(string dnum, string date)
{
if (Common.IsValidInt32(dnum)) //just a function that check for valid int
{
using (var connection =
new SqlConnection(ConfigurationManager.ConnectionStrings["SConnectionString"].ConnectionString))
{
connection.Open();
using (SqlCommand command = new SqlCommand(#"SELECT [Comment] FROM dbo.DUpdates WHERE (DID = " + dnum + ") AND (Deleted = 0) AND CreateDate > #Date ORDER BY CreateDate DESC", connection))
{
command.Parameters.Add("#Date", SqlDbType.DateTime);
command.Parameters["#Date"].Value = date;
command.Notification = null;
SqlDependency dependency = new SqlDependency(command);
dependency.OnChange += new OnChangeEventHandler(dependency_OnChange);
if (connection.State == ConnectionState.Closed)
connection.Open();
using (var reader = command.ExecuteReader())
{
return reader.Cast<IDataRecord>().Select(x => new DUpdates()
{
comment = x.GetString(0)
}).ToList();
}
}
}
}
JS stuff:
$(function() {
var job = $.connection.myHub;
job.client.displayStatus = function () {
getData();
};
$.connection.hub.start();
getData();
});
function getData() {
var params = (new URL(document.location)).searchParams;
var id = params.get("id");
var dt = $("#accessdate").val();
$.ajax({
url: 'dupdatesservice.asmx/GetData',
data: JSON.stringify({dnum: id, date: dt}),
contentType: "application/json; charset=utf-8",
dataType: "json",
type: "POST",
success: function (data) {
if (data.d.length > 0) {
$("#testdiv").prepend(data.d[0].comment);
}
}
});
}
Can provide other code if needed.
The issue here is that I was creating a new SqlDependency for each user that was on a page (or same user with multiple windows). So if 2 windows were open for a page, then it would check for notifications twice and send the response twice if there was something new. Because of the ajax request, now all of those SqlDependencies were doubled so I'd get 4 responses the next time, then 8 and so on.
What I decided to do instead was to essentially change my pages to private chats using signalr and just ditched the SqlDependency stuff. So now if a user goes to one page, they are connected with anyone else on the page and anytime someone submits a "comment" it also gets sent to other people viewing the page.

Why SignalR change function hitting many many times?

I try to develop an asp.net mvc application and also trying to use signalr. The problem is that i have two tables that control user notificitaions in project. I have a Notification table and also NotificationUser table which is many to many table of notification and user tables. I am trying achive that if a user create a notification to another user in system I try to show a pop-up that confirm user with a simple message like 'Hey!New notification received'. The problem is javascript change function of signalr hitting so many times.All step i used in signalR listed below
the stored procedure
ALTER PROCEDURE [dbo].[GetNotifications]
#userid int
AS
BEGIN
select n.Ntf_Title,Ntf_Description,n.Ntf_Date from dbo.SysNotifications n INNER JOIN dbo.SysNotificationUser u on n.Ntf_ID =u.NtU_NtfID where NtU_UserID=#userid AND NtU_IsRead=0
END
The Hub
[HubName("signalRHub")]
public class NtfHub : Hub
{
[HubMethodName("notifyChanges")]
public static void NotifyChanges()
{
var context = GlobalHost.ConnectionManager.GetHubContext<NtfHub>();
context.Clients.All.notifyChanges();
}
}
The StartUp Class
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
}
The Partial View
[HttpGet]
public ActionResult GetNtf()
{
//NtfRepo rp = new NtfRepo(this.HttpContext);
string connectionString = ConfigurationManager.ConnectionStrings["conn"].ConnectionString;
int userid =id;
using (SqlConnection sqlcon = new SqlConnection(connectionString))
{
using (SqlCommand sqlcom = new SqlCommand("[GetNotifications]", sqlcon))
{
sqlcon.Open();
sqlcom.CommandType = CommandType.StoredProcedure;
sqlcom.Parameters.AddWithValue("#userid", userid);
sqlcom.Notification = null;
SqlDependency dependancy = new SqlDependency(sqlcom);
dependancy.OnChange += dependancy_OnChange;
var reader = sqlcom.ExecuteReader();
var ntf= reader.Cast<IDataRecord>()
.Select(e => new PopulateNtfBar()
{
Title = e.GetString(0),
Description = e.GetString(1),
TimeDiff = FindDifferenceTime(e.GetDateTime(2))
}).ToList();
return PartialView("~/Views/Shared/CheckNotification.cshtml", ntf);
}
}
}
At Last,The Script
$(function () {
var notification = $.connection.signalRHub;
// Create a function that the hub can call to broadcast messages.
notification.client.notifyChanges = function () {
getData();
toastr.warning("Hey,You have Ntf");
};
// Start the connection.
$.connection.hub.start().done(function () {
getData();
}).fail(function (e) {
});
});
function getData() {
var tbl = $("#header_notification_bar")
$.ajax({
url: '#Url.Action("GetNtf","Home")',
contentType: 'application/html ; charset:utf-8',
type: 'GET',
dataType: 'html'
}).success(function (result) {
tbl.empty().append(result);
}).error(function () {
});
}
notification.client.notifyChanges hitting so many times if a user create a notification.Where is the problem? Any idea? i cannot optimize it
EDIT 1
I am calling NtfHub.NotifyChanges in controller.
void dependancy_OnChange(object sender, SqlNotificationEventArgs e)
{
if (e.Type == SqlNotificationType.Change)
{
NtfHub.NotifyChanges();
}
}
Although I think that SqlDependency is wrong approach for this feature, you could try to solve this specific problem this way:
Add parameter "subscribeToNotifications" to your controller action
public ActionResult GetNtf(bool subscribeToNotifications)
Create SqlDependency only if it is True.
Then subscribe to notifications only on hub started (this will prevent creation of multiple SqlDependencies for same user):
$(function () {
var notification = $.connection.signalRHub;
// Create a function that the hub can call to broadcast messages.
notification.client.notifyChanges = function () {
getData(false);
toastr.warning("Hey,You have Ntf");
};
// Start the connection.
$.connection.hub.start().done(function () {
getData(true);
}).fail(function (e) {
});
});
function getData(subscribeToNotifications) {
var tbl = $("#header_notification_bar")
$.ajax({
url: '#Url.Action("GetNtf","Home")' + '?subscribeToNotifications=' + subscribeToNotifications,
contentType: 'application/html ; charset:utf-8',
type: 'GET',
dataType: 'html'
}).success(function (result) {
tbl.empty().append(result);
}).error(function () {
});
}
But be aware that every page refresh will still create new listener without managing subscriptions on server side.
Option 2 is to create single SqlDependency (on server app start) omitting userId parameter - anyway you are sending notification to all users no matter which one got the message.
Option 3 - the real solution is get rid of SqlDependency at all and send notification only to specific user (recipient of the message)
The reason is that you are not unsubscribing from the dependancy_OnChange event, a sqldependency trigger is a one shot execution, so you have to subscribe to the new one every time it fires, what you are not doing is unsubscribing from the previous event handler, so when you subscribe to the new one, you now have multiple handlers for the same trigger.
private void dependency_OnChange(object sender, SqlNotificationEventArgs e)
{
SqlDependency dependency = sender as SqlDependency;
if (dependency != null) dependency.OnChange -= dependency_OnChange;
//Recall your SQLDependency setup method here.
SetupDependency();
}

webservice error 500 Internal Error asp.net

I have written a webservice call in JQuery in document ready function but its not calling the function
Below is the code
JQuery
`<script type="text/javascript">
$( document ).ready(function() {
var section = "Table - TLI (STOCK)";
$.ajax({
type: "GET",contentType: "application/json; charset=utf-8",
url: "pgWebService.aspx/SliderBlock",
dataType: "json",
data: "{'section':'" + section + "'}",
success: function (res) {
//$("#Text1").val(res.text);
console.log(res);
alert("DONE");
}
});
});
</script>`
C# Code
pgWebService
public static string SliderBlock(string section)
{
string html = "<ul class='maketabs listing-table search-filter change-view'>";
SqlConnection cn = new SqlConnection(ConfigurationManager.ConnectionStrings["TLI"].ConnectionString);
SqlCommand cmd = new SqlCommand();
cn.Open();
cmd.Connection = cn;
cmd.CommandText = "Select * from CategoryDetails where section=" + section;
SqlDataReader rs = cmd.ExecuteReader();
while (rs.Read())
{
html="<li>"+rs.getValue(0).toString()+"</li>";
}
rs.Close();
cmd.Dispose();
cn.Close();
html = html + "</ul>";
return html;
}
If your method SliderBlock is in code behind than make your method WebMethod to be called by ajax.Also you need to make it static and to be called by GET you need to enable GET requests on your WebMethod.
[System.Web.Services.WebMethod]
[System.Web.Script.Services.ScriptMethod(UseHttpGet = true)]
public static string SliderBlock(string section)
{
//Your code here
}
As your code has the extension .aspx I assume that you are using the code-behind ( Page Method ). So you need to make these changes to your function signature
[System.Web.Services.WebMethod]
public static string SliderBlock(string section)
That is,
your method should be static.
your method should be decorated with System.Web.Services.WebMethod
And in your $.ajax call, change the dataType to json.
dataType: "json"
Also, please bear in mind that the PageMethid in pgWebService.aspx.cs can be only called from pgWebService.aspx
You still have errors in the ajax request:
Content-Type: When sending data to the server, use this content type. But you are not sending data to the server except the query string parameters because you are doing a GET. So, if you inspect with webbrowser developer tools the request you see a GET with this URL: localhost/pgWebService.aspx/SliderBlock?section=selectedSection because...
Data: Data to be sent to the server. It is converted to a query string, if not already a string. It's appended to the url for GET-requests.
dataType: The type of data that you're expecting back from the server. But in your webService your are returning a string with HTML not JSON.

How enable cors in ajax?

I am trying to call data from the following host url test.domain.com/test2.aspx/BindDatatable, however i keep getting 404 response and the following message in my console window:
error message:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://test.domain.com/test2.aspx. This can be fixed by moving the resource to the same domain or enabling CORS
i have added the following cors header in the web.config file of my host(url ) file:
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="origin" />
<add name="Access-Control-Request-Method" value="POST" />
<add name="Access-Control-Allow-Headers" value="content-type, accept" />
</customHeaders>
</httpProtocol>
</system.webServer>
it also contains the following web-method behind test2.aspx.cs:
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
[WebMethod()]
public static string BindDatatable()
{
DataTable dt = new DataTable();
List<UserDetails> details = new List<UserDetails>();
using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["#####"].ConnectionString))
{
using (SqlCommand cmd = new SqlCommand("######", con))
{
con.Open();
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(dt);
foreach (DataRow dtrow in dt.Rows)
{
UserDetails user = new UserDetails();
user.Name= dtrow["###"].ToString();
user.Loan = dtrow["###"].ToString();
user.Evnt = dtrow["###"].ToString();
details.Add(user);
}
}
}
JavaScriptSerializer serializer = new JavaScriptSerializer();
return serializer.Serialize(details);
}
ajax function called from corsTest.aspx
$(document).ready(function () {
$.support.cors = true;
$.ajax({
type: "Post",
crossDomain: true,
contentType: "application/json; charset=utf-8",
url: "http://wwww.test.domain.com/test2.aspx/BindDatatable",
data: "{}",
dataType: "json",
success: function (data) {
alert(data.toSource());
console.log(data);
var myData = JSON.parse(data.d)
for (var i = 0; i < myData.length; i++) {
$("#tbDetails").append("<tr><td>" + myData[i].Name + "</td><td>" + myData[i].Loan + "</td><td>" + myData[i].Evnt + "</td></tr>");
}
},
error: function (result) {
alert("Error");
}
});
});
I am not sure, what else i am suppose to update further to get this to work. Do I also need, to define the cors header in the head tag of the text2.aspx page as well.
thanks in advance for any further feedback/guide.
I stuck into similar situation today so sharing my solution, hope it could help somebody. I used jsonp to fetch the data from cross domain. Taking your example, if one has access to BindDatatable() method in test2.aspx.cs, then we can modify json object to be returned in the format like jsonData({..your json..}). By wrapping the method with jsonData(), it could be read by jsonp during ajax call made like:
var url = "http://wwww.test.domain.com/test2.aspx/BindDatatable";
$.ajax({
url: url,
dataType: 'jsonp',
jsonpCallback: 'jsonData',
success: function (response) {
console.log('callback success: ', response);
},
error: function (xhr, status, error) {
console.log(status + '; ' + error);
}
});
Otherwise as suggested in the above post, you can create a function in your own application corsTest.aspx.cs and access cross domain link through it in C# and return json as shown below:
$.ajax({
type: "Post",
contentType: "application/json; charset=utf-8",
url: "/corsTest.aspx/BindDatatableTest",
dataType: "json",
.
.
error: function (result) {
alert("Error");
}
});
Define function in corsTest.aspx.cs like:
private string BindDatatableTest()
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
string url = "http://wwww.test.domain.com/test2.aspx/BindDatatable";
WebClient wc = new WebClient();
ServicePointManager.Expect100Continue = false;
ServicePointManager.MaxServicePointIdleTime = 2000;
string json = wc.DownloadString(url);
object jsonData = new
{
jsonFinal = jsonD
};
return Content(serializer.Serialize(jsonData), "application/json");
}
Also, in order to call cross domain url you have to add the following code to web.config:
<system.net>
<settings>
<httpWebRequest useUnsafeHeaderParsing="true" />
</settings>
</system.net>
Check if the remote method is available. Check the firewall of the server where the service is hosted if it allows connections for the specific port. Also check on your machine if output port is not blocked.
Another way to enable cors is to make the connection on the server side.
For instance you can add service reference to the remote method and use that method on the server side in your local project. Then on the client you have to call only the local method that is within your solution and you don't have to enable cors on the client.

auto complete on asp.net control

hey I want to use autocomplete jquery in asp.net on a control which is used on a default1.aspx page. My control is searchinput.ascx which is in Registration folder. My ploblem is I have written web method (getmylist) on code file of searchinput control. but that method is never called. can anyone help me
Jquery website
You can find wat you need there for a start.
Also, show your ajax call so that I can try helping on y it is not working.
Your approach of writting a web method and making a ajax call from the jquery auto complete should work out fine otherwise.
Its hard to help you without the code but some common causes could be:
You are not using ClientID value correctly - asp.net controls dont have the same id in the actual mark-up as they do in the designer
your web method has an error in it - you should press f12 to open your web developers toolbar and go to NET tab (in firefox at least) to see if a 500 error code or similar is being returned
Create a web method like the following:
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public string[] GetPatientFirstName(string prefix)
{
List<string> customers = new List<string>();
using (SqlConnection conn = new SqlConnection())
{
string connectionstring = CCMMUtility.GetCacheForWholeApplication();
conn.ConnectionString = connectionstring;
using (SqlCommand cmd = new SqlCommand())
{
cmd.CommandText = "select distinct top(10) PatientFirstname from tblMessage where " +
"PatientFirstname like '%'+ #SearchText + '%' order by PatientFirstname";
cmd.Parameters.AddWithValue("#SearchText", prefix);
cmd.Connection = conn;
conn.Open();
using (SqlDataReader sdr = cmd.ExecuteReader())
{
while (sdr.Read())
{
customers.Add(string.Format("{0}", sdr["PatientFirstname"]));
}
}
conn.Close();
}
return customers.ToArray();
}
}
here is the html code :
$(document).ready(function () {
$('[ID$=txtPatientFirstname]').live('keyup.autocomplete', function () {
$(this).autocomplete({
source: function (request, response) {
$.ajax({
url: '<%=ResolveUrl("~/Resources/WebService.asmx/GetPatientFirstName") %>',
data: "{ 'prefix': '" + request.term + "'}",
dataType: "json",
type: "POST",
contentType: "application/json; charset=utf-8",
success: function (data) {
response($.map(data.d, function (item) {
return {
label: item.split('-')[0],
val: item.split('-')[1]
}
}))
},
error: function (response) {
alert(response.responseText);
},
failure: function (response) {
alert(response.responseText);
}
});
},
select: function (e, i) {
},
minLength: 1
});
});
});
This is the working example ......hope this will solve your problem..

Categories

Resources