I would like to expose a table of data (e.g. datatable/array) using a Web service (or something similar), and then display this table on any Web site. The Web service would take one date input and output results depending on the date.
Could anyone tell me the best way to go about this (technologies to use), and perhaps point me to any examples?
I would like a datepicker type control (AJAX/jQuery/Whatever) to input the date (defaults to current date). The date is sent to the Web service, and a calendar table produced depending on the date input. This could run on any Web site so I assume I need
to look at jQuery or KnockoutJS or similar? My ASP.NET Web application would expose the Web service, but I need the client side to be any HTML page with a few scripts included.
And then please add a button to your page, after clicking the button, it will access the Web service with the selected date as parameter. The Web service receives the parameter and take it as a select option to get the items which meet your requirement.
I made an example to get user information from Web service, you can refer to it. After entering the UserID in the textbox and clicking the button, we can get other user information we want from the web service.
Html file:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script type="text/javascript">
var xmlHttp = null;
function createXMLHttpRequest() {
try {
if (window.XMLHttpRequest)
xmlHttp = new XMLHttpRequest();
else if (window.ActiveXObject)
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (ex) { }
}
function AsynRequest() {
createXMLHttpRequest();
if (xmlHttp == null) {
alert("Cannot create XmlHttpRequest Object");
return;
}
// To transfer parameter to web service.
xmlHttp.open("GET", "getUsers.asmx/GetUser?UserID=" + document.getElementById('Text1').value, true);
xmlHttp.setRequestHeader("Connection", "close");
xmlHttp.onreadystatechange = function () {
// Get the information from web service.
if (xmlHttp.readyState == 4) {
if (xmlHttp.status == 200) {
var userList = xmlHttp.responseXML.getElementsByTagName("User");
for (i = 0; i < userList.length; i++) {
document.getElementById("get1").innerHTML += userList[i].getElementsByTagName("UserID")[0].firstChild.nodeValue + ":";
document.getElementById("get1").innerHTML += userList[i].getElementsByTagName("UserName")[0].firstChild.nodeValue + "<br/>";
}
}
}
};
xmlHttp.send();
}
</script>
</head>
<body>
<input id="Text1" type="text" />
<input id="Button1" type="button" value="button" onclick="AsynRequest();" />
<p id="get1"></p>
</body>
</html>
getUsers.asmx:
using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Services;
namespace WcfService1
{
/// <summary>
/// Summary description for getUsers
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
// [System.Web.Script.Services.ScriptService]
public class getUsers : System.Web.Services.WebService
{
[WebMethod]
public List<User> GetUser()
{
List<User> u_list = new List<User>();
// To get the parameter:
int UserID = Int32.Parse(HttpContext.Current.Request["UserID"]);
/*
* With the following codes, I get the users I want from database. You can refer to the codes to select your
* items from your table.
*/
//DataTable table = new DataTable();
// string connectionString = WebConfigurationManager.ConnectionStrings["test"].ConnectionString;
// SqlConnection conn = new SqlConnection(connectionString);
// SqlCommand comd = conn.CreateCommand();
// comd.CommandText = "select * from UserInfo where UserID=@UesrID";
// comd.Parameters.AddWithValue("@UesrID", UserID);
// try
// {
// conn.Open();
// SqlDataAdapter adapter = new SqlDataAdapter(comd);
// adapter.Fill(table);
// for (int i = 0; i < table.Rows.Count; i++)
// {
// User user = new User();
// user.UserID = int.Parse(table.Rows[i][0].ToString());
// user.UserName = table.Rows[i][1].ToString();
// u_list.Add(user);
// }
// }
// catch (Exception exc)
// {
// }
// finally
// {
// conn.Close();
// }
return u_list;
}
public class User
{
public int UserID { get; set; }
public string UserName { get; set; }
}
}
}
Would I be right in saying that this is now impossible because as it says
here,
"For security reasons, modern browsers do not allow access across domains. This means, that both the web page and the XML file it tries to load, must be located on the same server." ?
I created a Web service to try and test your suggestion as follows (located
here)
Option Strict On
Imports System.Web.Services
Imports System.Web.Services.Protocols
Imports System.ComponentModel
Imports System.Web.Script.Services
<WebService(Description:="Provision of external services.", _
Name:="dataserv", _
Namespace:="http://www.thecomputerizer.com/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)>
Public Class dataserv
Inherits System.Web.Services.WebService
<WebMethod()> _
Public Function GetCalendar() As List(Of Person)
Try
Dim people As New List(Of Person)
Dim person As New Person
person.PersonID = 1
person.PersonName = "Ed"
people.Add(person)
person = New Person
person.PersonID = 2
person.PersonName = "Shazeroon"
people.Add(person)
Return people
Catch ex As Exception
Throw
End Try
End Function
End Class
Public Class Person
Private _personId As Int32
Private _personName As String
Public Property PersonID() As Int32
Get
Return _personId
End Get
Set(ByVal value As Int32)
_personId = value
End Set
End Property
Public Property PersonName As String
Get
Return _personName
End Get
Set(value As String)
_personName = value
End Set
End Property
End Class
This worked in a development environment with a page called calendar.htm in the same project like this using
"Microsoft JScript runtime error: Access is denied."
when that line of script is run. I guess there is no way around that? I even made sure that GET and POST were enabled for the Web service. I did not try allowing cross site scripting from Web .config but assume that I would be wasting my time.
Can I get this working? If not can you think of another way that I could go about this?
I have this working with jQuery and KnockoutJS but am struggling to make the call cross-domain. I get 'Error: Access is denied." when trying cross domain. I assume I can use JSONP to do this? Is this possible using a .asmx Web service or must I use WCF?
Here is what I have so far:
On the server
Option Strict On
Imports System.Web.Services
Imports System.Web.Services.Protocols
Imports System.ComponentModel
Imports System.Web.Script.Services
<WebService(Description:="Provision of people.", _
Name:="dataserv", _
Namespace:="http://bookingac.com/services/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<ScriptService()> _
Public Class dataserv
Inherits System.Web.Services.WebService
<ScriptMethod(ResponseFormat:=ResponseFormat.Json)> _
<WebMethod()> _
Public Function GetPeople() As List(Of Person)
Try
Dim people As New List(Of Person)
Dim person As New Person
person.PersonID = 1
person.PersonName = "Ed"
people.Add(person)
person = New Person
person.PersonID = 2
person.PersonName = "Shazeroon"
people.Add(person)
Return people
Catch ex As Exception
Throw
End Try
End Function
End Class
Public Class Person
Private _personId As Int32
Private _personName As String
Public Property PersonID() As Int32
Get
Return _personId
End Get
Set(ByVal value As Int32)
_personId = value
End Set
End Property
Public Property PersonName As String
Get
Return _personName
End Get
Set(value As String)
_personName = value
End Set
End Property
End Class
I found that when Firefox called the Web service JSON was being returned. When IE called the same service it seemed to be returning XML which threw an invalid character exception. It seems like the key is to get JSON returned to both browsers.
<WebService(Description:="Provision of people.", _
Name:="dataserv", _
Namespace:="http://thecomputerizer.com/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<ScriptService()> _
Public Class dataserv
Inherits System.Web.Services.WebService
<WebMethod()> _
<ScriptMethod(ResponseFormat:=ResponseFormat.Json)> _
Public Function GetPeople() As String
Try
Dim jsf As New JavaScriptSerializer
Dim people As New List(Of Person)
Dim person As New Person
person.PersonID = 1
person.PersonName = "Ed"
people.Add(person)
person = New Person
person.PersonID = 2
person.PersonName = "Shazeroon"
people.Add(person)
Return jsf.Serialize(people)
Catch ex As Exception
Throw
End Try
End Function
End Class
DATASERV1.ASMX
<WebService(Description:="Provision of people.", _
Name:="dataserv", _
Namespace:="http://thecomputerizer.com/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<ScriptService()> _
Public Class dataserv1
Inherits System.Web.Services.WebService
<WebMethod()> _
Public Function GetPeople() As List(Of Person)
Try
Dim people As New List(Of Person)
Dim person As New Person
person.PersonID = 1
person.PersonName = "Ed"
people.Add(person)
person = New Person
person.PersonID = 2
person.PersonName = "Shazeroon"
people.Add(person)
Return people
Catch ex As Exception
Throw
End Try
End Function
End
Perhaps if I can get the Web service to return JSON to both browsers then this problem will be solved.
cmsesan1
Member
469 Points
188 Posts
Binding a table to a Web Service using JavaScript/KnockoutJS?
Feb 16, 2012 05:34 PM|LINK
I would like to expose a table of data (e.g. datatable/array) using a Web service (or something similar), and then display this table on any Web site. The Web service would take one date input and output results depending on the date.
Could anyone tell me the best way to go about this (technologies to use), and perhaps point me to any examples?
I would like a datepicker type control (AJAX/jQuery/Whatever) to input the date (defaults to current date). The date is sent to the Web service, and a calendar table produced depending on the date input. This could run on any Web site so I assume I need to look at jQuery or KnockoutJS or similar? My ASP.NET Web application would expose the Web service, but I need the client side to be any HTML page with a few scripts included.
Thanks very much for any help.
Ed
Allen Li - M...
Star
10411 Points
1196 Posts
Re: Binding a table to a Web Service using JavaScript/KnockoutJS?
Feb 20, 2012 02:22 AM|LINK
Hi, you can refer to the following link to add jQuery Datepicker to your page.
http://jqueryui.com/demos/datepicker/
And then please add a button to your page, after clicking the button, it will access the Web service with the selected date as parameter. The Web service receives the parameter and take it as a select option to get the items which meet your requirement. I made an example to get user information from Web service, you can refer to it. After entering the UserID in the textbox and clicking the button, we can get other user information we want from the web service.
Html file:
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> <script type="text/javascript"> var xmlHttp = null; function createXMLHttpRequest() { try { if (window.XMLHttpRequest) xmlHttp = new XMLHttpRequest(); else if (window.ActiveXObject) xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); } catch (ex) { } } function AsynRequest() { createXMLHttpRequest(); if (xmlHttp == null) { alert("Cannot create XmlHttpRequest Object"); return; } // To transfer parameter to web service. xmlHttp.open("GET", "getUsers.asmx/GetUser?UserID=" + document.getElementById('Text1').value, true); xmlHttp.setRequestHeader("Connection", "close"); xmlHttp.onreadystatechange = function () { // Get the information from web service. if (xmlHttp.readyState == 4) { if (xmlHttp.status == 200) { var userList = xmlHttp.responseXML.getElementsByTagName("User"); for (i = 0; i < userList.length; i++) { document.getElementById("get1").innerHTML += userList[i].getElementsByTagName("UserID")[0].firstChild.nodeValue + ":"; document.getElementById("get1").innerHTML += userList[i].getElementsByTagName("UserName")[0].firstChild.nodeValue + "<br/>"; } } } }; xmlHttp.send(); } </script> </head> <body> <input id="Text1" type="text" /> <input id="Button1" type="button" value="button" onclick="AsynRequest();" /> <p id="get1"></p> </body> </html>getUsers.asmx:
using System; using System.Collections.Generic; using System.Web; using System.Web.Services; namespace WcfService1 { /// <summary> /// Summary description for getUsers /// </summary> [WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] [System.ComponentModel.ToolboxItem(false)] // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. // [System.Web.Script.Services.ScriptService] public class getUsers : System.Web.Services.WebService { [WebMethod] public List<User> GetUser() { List<User> u_list = new List<User>(); // To get the parameter: int UserID = Int32.Parse(HttpContext.Current.Request["UserID"]); /* * With the following codes, I get the users I want from database. You can refer to the codes to select your * items from your table. */ //DataTable table = new DataTable(); // string connectionString = WebConfigurationManager.ConnectionStrings["test"].ConnectionString; // SqlConnection conn = new SqlConnection(connectionString); // SqlCommand comd = conn.CreateCommand(); // comd.CommandText = "select * from UserInfo where UserID=@UesrID"; // comd.Parameters.AddWithValue("@UesrID", UserID); // try // { // conn.Open(); // SqlDataAdapter adapter = new SqlDataAdapter(comd); // adapter.Fill(table); // for (int i = 0; i < table.Rows.Count; i++) // { // User user = new User(); // user.UserID = int.Parse(table.Rows[i][0].ToString()); // user.UserName = table.Rows[i][1].ToString(); // u_list.Add(user); // } // } // catch (Exception exc) // { // } // finally // { // conn.Close(); // } return u_list; } public class User { public int UserID { get; set; } public string UserName { get; set; } } } }If you have any feedback about my replies, please contact msdnmg@microsoft.com
Microsoft One Code Framework
cmsesan1
Member
469 Points
188 Posts
Re: Binding a table to a Web Service using JavaScript/KnockoutJS?
Feb 20, 2012 07:12 PM|LINK
Would I be right in saying that this is now impossible because as it says here,
"For security reasons, modern browsers do not allow access across domains. This means, that both the web page and the XML file it tries to load, must be located on the same server." ?
I created a Web service to try and test your suggestion as follows (located here)
Option Strict On Imports System.Web.Services Imports System.Web.Services.Protocols Imports System.ComponentModel Imports System.Web.Script.Services <WebService(Description:="Provision of external services.", _ Name:="dataserv", _ Namespace:="http://www.thecomputerizer.com/")> _ <WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> Public Class dataserv Inherits System.Web.Services.WebService <WebMethod()> _ Public Function GetCalendar() As List(Of Person) Try Dim people As New List(Of Person) Dim person As New Person person.PersonID = 1 person.PersonName = "Ed" people.Add(person) person = New Person person.PersonID = 2 person.PersonName = "Shazeroon" people.Add(person) Return people Catch ex As Exception Throw End Try End Function End Class Public Class Person Private _personId As Int32 Private _personName As String Public Property PersonID() As Int32 Get Return _personId End Get Set(ByVal value As Int32) _personId = value End Set End Property Public Property PersonName As String Get Return _personName End Get Set(value As String) _personName = value End Set End Property End ClassThis worked in a development environment with a page called calendar.htm in the same project like this using
xmlHttp.open("GET", "dataserv.asmx/GetCalendar", true);If calendar.htm is placed on my home machine using
xmlHttp.open("GET", "http://thecomputerizer.com/dataserv.asmx/GetCalendar", true);I get
"Microsoft JScript runtime error: Access is denied."
when that line of script is run. I guess there is no way around that? I even made sure that GET and POST were enabled for the Web service. I did not try allowing cross site scripting from Web .config but assume that I would be wasting my time.
Can I get this working? If not can you think of another way that I could go about this?
Thanks for going to the trouble to reply Allen.
Ed
FightAsABull
Contributor
2228 Points
424 Posts
Re: Binding a table to a Web Service using JavaScript/KnockoutJS?
Feb 21, 2012 12:24 AM|LINK
Maybe the following method will help you:
http://forum.jquery.com/topic/ajax-call-cross-domain-asp-net-webservice
http://stackoverflow.com/questions/2697557/accessing-web-service-from-jquery-cross-domain
http://snook.ca/archives/javascript/cross_domain_aj
arunabathan
Member
730 Points
236 Posts
Re: Binding a table to a Web Service using JavaScript/KnockoutJS?
Feb 21, 2012 09:00 AM|LINK
hi,
Please refer below links,
http://weblogs.asp.net/dwahlin/archive/2009/05/03/using-jquery-with-client-side-data-binding-templates.aspx
http://www.dotnetcurry.com/ShowArticle.aspx?ID=573
http://encosia.com/using-jquery-to-consume-aspnet-json-web-services/
download here
Thanks&Regards,
Arunabathan.G
cmsesan1
Member
469 Points
188 Posts
Re: Binding a table to a Web Service using JavaScript/KnockoutJS?
Feb 28, 2012 06:19 PM|LINK
I have this working with jQuery and KnockoutJS but am struggling to make the call cross-domain. I get 'Error: Access is denied." when trying cross domain. I assume I can use JSONP to do this? Is this possible using a .asmx Web service or must I use WCF? Here is what I have so far:
On the server
Option Strict On Imports System.Web.Services Imports System.Web.Services.Protocols Imports System.ComponentModel Imports System.Web.Script.Services <WebService(Description:="Provision of people.", _ Name:="dataserv", _ Namespace:="http://bookingac.com/services/")> _ <WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _ <ScriptService()> _ Public Class dataserv Inherits System.Web.Services.WebService <ScriptMethod(ResponseFormat:=ResponseFormat.Json)> _ <WebMethod()> _ Public Function GetPeople() As List(Of Person) Try Dim people As New List(Of Person) Dim person As New Person person.PersonID = 1 person.PersonName = "Ed" people.Add(person) person = New Person person.PersonID = 2 person.PersonName = "Shazeroon" people.Add(person) Return people Catch ex As Exception Throw End Try End Function End Class Public Class Person Private _personId As Int32 Private _personName As String Public Property PersonID() As Int32 Get Return _personId End Get Set(ByVal value As Int32) _personId = value End Set End Property Public Property PersonName As String Get Return _personName End Get Set(value As String) _personName = value End Set End Property End ClassOn the client
<!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></title> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script> <script type="text/javascript" src="scripts/jquery.tmpl.min.js"></script> <script type="text/javascript" src="scripts/jquery-jsonp-2.2.1.min.js"></script> <script type="text/javascript" src="scripts/knockout-2.0.0.debug.js"></script> </head> <body> <table border="1" data-bind="template: {name:'peopleTemplate', foreach:people}"></table> <script type="text/html" id="peopleTemplate"> <tr><td>${ $data.PersonID }</td><td>${ $data.PersonName }</td></tr> </script> <script type="text/javascript"> function person(PersonID, PersonName) { return { PersonID: ko.observable(PersonID), PersonName: ko.observable(PersonName) }; } var viewModel = { people: ko.observableArray([]) }; //people: ko.observableArray([new person("3", "Marc"), new person("4", "Farley")]) $.support.cors = true; $.ajax({ type: "POST", contentType: "application/json; charset=utf-8", url: "http://thecomputerizer.com/dataserv.asmx/GetPeople", data: "{}", dataType: "json", success: function (data) { ko.dependentObservable(function () { viewModel.people(data.d) }, viewModel); }, error: function (jqXHR, textStatus, errorThrown) { alert(errorThrown); } }) ko.applyBindings(viewModel); </script> </body> </html>Of course if I change the url to "dataserv.asmx/GetPeople" which is in the local project then all is well and the table is displayed.
Thanks very much for the help and links so far. I will look at the example project now...
Ed
Allen Li - M...
Star
10411 Points
1196 Posts
Re: Binding a table to a Web Service using JavaScript/KnockoutJS?
Feb 29, 2012 06:26 AM|LINK
Hi, you can refer to the following links:
http://msdn.microsoft.com/en-us/library/ee834511.aspx
http://pranayamr.blogspot.com/2011/06/calling-cross-domain-wcf-service-using.html
http://www.codeproject.com/Articles/223572/Calling-Cross-Domain-WCF-service-using-Jquery-Java
http://www.codeproject.com/Articles/259832/Consuming-Cross-Domain-WCF-REST-Services-with-jQue
http://jasonkelly.net/2009/05/using-jquery-jsonp-for-cross-domain-ajax-with-wcf-services/
If you have any feedback about my replies, please contact msdnmg@microsoft.com
Microsoft One Code Framework
cmsesan1
Member
469 Points
188 Posts
Re: Binding a table to a Web Service using JavaScript/KnockoutJS?
Feb 29, 2012 09:14 PM|LINK
I got this working in Firefox last night by changing the Web.config as follows to enable CORS (Cross-Origin Resource Sharing).
<location path="dataserv.asmx"> <system.webServer> <httpProtocol> <customHeaders> <add name="Access-Control-Allow-Origin" value="*"/> <add name="Access-Control-Allow-Methods" value="POST"/> <add name="Access-Control-Allow-Headers" value="Content-Type"/> </customHeaders> </httpProtocol> </system.webServer> <system.web> <webServices> <protocols> <add name="HttpPost"/> </protocols> </webServices> </system.web> </location>I assume that this will work with Firefox, Chrome and Safari as it mentions here?
The page is the same
http://video.bookingac.com/attractions.htm
and is calling the Web service (which is the same) here
http://thecomputerizer.com/dataserv.asmx
I just need to figure out how to get it working in Internet Explorer now so my quest will continue tomorrow.
Thanks again for all links etc. sent.
Ed
FightAsABull
Contributor
2228 Points
424 Posts
Re: Binding a table to a Web Service using JavaScript/KnockoutJS?
Mar 02, 2012 12:48 AM|LINK
Does it work with Internet Explorer now ?
cmsesan1
Member
469 Points
188 Posts
Re: Binding a table to a Web Service using JavaScript/KnockoutJS?
Mar 02, 2012 02:46 AM|LINK
Hello FightAsABull
I found that when Firefox called the Web service JSON was being returned. When IE called the same service it seemed to be returning XML which threw an invalid character exception. It seems like the key is to get JSON returned to both browsers.
I have 2 Web services now:
http://thecomputerizer.com/dataserv.asmx Returns a string instead of JSON (needs fixing)
http://thecomputerizer.com/dataserv1.asmx The old one that worked with Firefox.
These are tested by 2 HTML pages on a different domain:
http://video.bookingac.com/dataserv.htm
http://video.bookingac.com/dataserv1.htm Returns JSON in Firefox but XML in IE9.
DATASERV.ASMX
<WebService(Description:="Provision of people.", _ Name:="dataserv", _ Namespace:="http://thecomputerizer.com/")> _ <WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _ <ScriptService()> _ Public Class dataserv Inherits System.Web.Services.WebService <WebMethod()> _ <ScriptMethod(ResponseFormat:=ResponseFormat.Json)> _ Public Function GetPeople() As String Try Dim jsf As New JavaScriptSerializer Dim people As New List(Of Person) Dim person As New Person person.PersonID = 1 person.PersonName = "Ed" people.Add(person) person = New Person person.PersonID = 2 person.PersonName = "Shazeroon" people.Add(person) Return jsf.Serialize(people) Catch ex As Exception Throw End Try End Function End ClassDATASERV1.ASMX
<WebService(Description:="Provision of people.", _ Name:="dataserv", _ Namespace:="http://thecomputerizer.com/")> _ <WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _ <ScriptService()> _ Public Class dataserv1 Inherits System.Web.Services.WebService <WebMethod()> _ Public Function GetPeople() As List(Of Person) Try Dim people As New List(Of Person) Dim person As New Person person.PersonID = 1 person.PersonName = "Ed" people.Add(person) person = New Person person.PersonID = 2 person.PersonName = "Shazeroon" people.Add(person) Return people Catch ex As Exception Throw End Try End Function EndPerhaps if I can get the Web service to return JSON to both browsers then this problem will be solved.
Thanks for your interest.
Ed