I have a method which serializes an object, into a SQL Server XML field. I see the XML in SQL server in Managmenet Studio, and now I need to display that in a HTML page.
I use an AJax function calling into a WebMethod, which calls a stored procedure as follows:
using (conn){
using (SqlCommand cmd = new SqlCommand()){
conn.Open();
cmd.CommandText = "GetMessage_Sel";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#messageId", SqlDbType.VarChar, 50).Value = str;
cmd.Connection = conn;
try{
rdr = cmd.ExecuteReader();
if (rdr.HasRows){
while (rdr.Read()){
returnValue1 = rdr.GetString(0);
returnValue2 = rdr.GetString(1);
}
}
else{
Console.WriteLine("No rows found.");
}
rdr.Close();
}
catch (Exception err){
// handle the error
//messageInsert = false;
}
finally{
conn.Close();
}
}
}
return new string[] {returnValue1,returnValue2};
the ajax is therefore set up as follows:
$('.view-details').click(function (e) {
e.preventDefault();
$('#ticket-id').text("Ticket id: " + $(this).closest('tr').children().eq(1).html());
$.ajax({
type: "POST",
url: "Default.aspx/PopulatePopUp",
cache: false,
data: "{'arg':'" + $(this).closest('tr').children().eq(1).html() + "'}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg)
{
$("#CompleteMessage").text(msg.d[0]);
$("#lblaka").text(msg.d[1]);
}
});
}
so #lblaka displays the entire XML message, but i need to break this down into a more readable manner. So eithe in my WebMethod or the Ajax function, how do i iterate through the rdr.GetString(1), so something like this
foreach (var item in rdr.GetString(1)) {
string 1 = xml node value 1 ..... etc
}
EDIT:
Here is an example of the XML being stored.
<Person xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<AKA>
<string>Name 1</string>
<string>Name 2</string>
</AKA>
<Countries>
<string>USA</string>
<string>UK</string>
</Countries>
<Names>
<string>Name 1</string>
<string>Name 2</string>
</Names>
<Gender>Male</Gender>
</Person>
Here is how you could do it with jQuery:
declare this function:
function GetNestedElements(aThis, name) {
$(aThis).find(name).each(function(index){
$("#lblaka").append('<span>'+ name +' : ');
$(this).find('string').each(function(index){
$("#lblaka").append($(this));
});
$("#lblaka").append('</span><br/>');
});
}
Use this in your success call:
var xml = $.parseXML(msg),
$xml = $( xml );
$xml.find('Person').each(function(index){
GetNestedElements(this, 'AKA');
GetNestedElements(this, 'Countries');
GetNestedElements(this, 'Names');
var gender = $(this).find('Gender').text();
$("#lblaka").append('<span>Gender : ' + gender + '</span><br/>');
});
Please see this jsFiddle for a working version (select 'Show Person' to view it):
http://jsfiddle.net/MZ5Xs/2/
If its pure XLM in your SQL string you could load the string into and XDocument like so and query using linq to get your list to loop over.
XDocument xDoc = XDocument.Parse(rdr.GetString(1));
var query = xDoc.Descendants("AKA").Elements("string").ToList();
//If you want to add them to an Array
string[] array = new string[query.Count() -1];
int i = 0
// this will add the values Name 1 and Name 2 to an array
foreach (var element in query)
{
array[i] = element.Value;
i++;
}
Related
In this project the user will have the opportunity to create an array of objects with properties and those properties match up with a database table, with the properties of the object being the same as the columns in the database cable. The SQL looks like:
create table ServiceData
(ServiceId int
,ServiceDescription varchar(50)
)
go
create type ServiceType as table
(ServiceId int
,ServiceDescription varchar(50)
)
go
create proc spInsertService
#service ServiceType readonly
as
begin
insert into ServiceData(ServiceId,ServiceDescription)
select * from #service
end
Here I create a custom type and pass that custom type to a stored procedure in the form of a table valued parameter. The SQL and the following C# code execute and work fine:
[WebMethod]
public void InsertServiceData()
{
List<ServiceData> sdList = new List<ServiceData>();
ServiceData sd1 = new ServiceData(1, "first");
ServiceData sd2 = new ServiceData(2, "second");
sdList.Add(sd1);
sdList.Add(sd2);
DataTable dt = new DataTable();
dt.Columns.Add("ServiceId");
dt.Columns.Add("ServiceDescription");
foreach (var data in sdList)
{
dt.Rows.Add(data.ServiceId, data.ServiceDescription);
}
string cs = ConfigurationManager.ConnectionStrings["dbcs"].ConnectionString;
using (var con = new SqlConnection(cs))
{
using (var cmd = new SqlCommand("spInsertService",con))
{
con.Open();
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#service", dt);
cmd.ExecuteNonQuery();
}
}
}
You can see that in this working example I'm not using any AJAX call to send data to the web method. This code currently works and inserts the data from that hardcoded list fine. So when I change the code to actually try to take a JavaScript array like so:
$(document).ready(function ()
{
sd1 = {};
sd1.ServiceId = 1;
sd1.ServiceDescription = "test";
sd2 = {};
sd2.ServiceId = 2;
sd2.ServiceDescription = "other test";
//create array which is meant to mirror the List<ServiceData> in the
//earlier example
service = new Array();
service.push(sd1);
service.push(sd2);
//wrap the array in a data transfer object
var dto = {'sdList': service};
$('#btnSubmit').click(function ()
{
$.ajax(
{
type: "POST",
url: "WebService.asmx/InsertServiceData",
contentType: "application/json",
dataType: "json",
//stringify the dto
data: JSON.stringify(dto),
success: function(data)
{
console.log('success');
},
error: function(thrownError)
{
console.log(thrownError);
}
});
});
});
new C#
[WebMethod]
//this attempts to deserialize the DTO into a list of ServiceData objects
//which are then inserted into the TVP and then to the database
public void InsertServiceData(string sdList)
{
var jss = new JavaScriptSerializer();
List<ServiceData> list = jss.Deserialize<List<ServiceData>>(sdList);
DataTable dt = new DataTable();
dt.Columns.Add("ServiceId");
dt.Columns.Add("ServiceDescription");
foreach (var data in list)
{
dt.Rows.Add(data.ServiceId, data.ServiceDescription);
}
string cs = ConfigurationManager.ConnectionStrings["dbcs"].ConnectionString;
using (var con = new SqlConnection(cs))
{
using (var cmd = new SqlCommand("spInsertService",con))
{
con.Open();
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#service", dt);
cmd.ExecuteNonQuery();
}
}
}
Currently that code gives me the error: Type\u0027System.String\u0027isnotsupportedfordeserializationofanarray
If I don't wrap the array in a DTO object, but still stringify it I get
`System.Collections.Generic.IDictionary`2[[System.String,mscorlib,Version=4.0.0.0,Culture=neutral,PublicKeyToken`
I would like to not have to use SessionState of ViewState for this. Since I know the code works fine if I'm not passing a JavaScript array to the WebMethod, it has to been somewhere in the serialization and deserialization of the array that's breaking it. How can I fix this? It's been driving me nuts for days now
Please note following steps and then change your code lines.
Dont create sd1={} and sd2{}.
Create var list = []; at top then push json object like list.push({"ServiceId":1,"ServiceDescription":"test"}, {"ServiceId":2,"ServiceDescription":"other test"})
Create ajax parameter like var data = "{'sdLists':" +JSON.stringify(list)+"}"; and pass date as param.
Create a bean with variables to map json object as added in list above. see blow.
public class SdList{
private int Serviceid;
public int Serviceid
{
get { return Serviceid; }
set { Serviceid= value; }
}
private string ServiceDescription;
public string ServiceDescription
{
get { return ServiceDescription; }
set { ServiceDescription= value; }
}
}
Now Pass List<SdList> sdLists as parameter list to method as under
var data = "{'sdLists':"+JSON.stringify(list)+"}";
public void InsertServiceData(List sdLists)
Then Convert Json List in to generic list using java script serializer as under,
JavaScriptSerializer jss= new JavaScriptSerializer();
List<SdList> list = jss.ConvertToType<List<SdList>>(sdLists);
I have followed above steps and it is working fine.
I am using PageMethod to retrieve Table data in Json format using the following C# Code
[WebMethod]
public static string GetJson2()
{
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
JsonWriter jsonWriter = new JsonTextWriter(sw);
try
{
string connstr = "server=localhost;user=root;database=cm_users;port=3306;password=root";
MySqlConnection conn = new MySqlConnection(connstr);
conn.Open();
string sql = "select * from users";
MySqlCommand cmd = new MySqlCommand(sql, conn);
MySqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
int fieldcount = reader.FieldCount; // count how many columns are in the row
object[] values = new object[fieldcount]; // storage for column values
reader.GetValues(values); // extract the values in each column
jsonWriter.WriteStartObject();
for (int index = 0; index < fieldcount; index++)
{ // iterate through all columns
jsonWriter.WritePropertyName(reader.GetName(index)); // column name
jsonWriter.WriteValue(values[index]); // value in column
}
jsonWriter.WriteEndObject();
}
reader.Close();
}
catch (MySqlException mySqlException)
{ // exception
return mySqlException + "error";
}
// END of method
// the above method returns sb and another uses it to return as HTTP Response...
string jsonString = sb.ToString();
return jsonString; ;
}
Now I am Catching the out put of the method into an html Page using an Java Scipt
Using Ajax JavaScript I am consuming the returned string which is in Json format.
function getUsers() {
$.ajax({
type: "POST",
url: "http://{address}:8078/Default.aspx/GetJson2",
data: "{}",
contentType: "application/json",
dataType: "json",
success: function (msg) {
$("#Result").text(msg.d);
var myTable1 = '';
myTable1 += '<table id="myTable1" cellspacing=0 cellpadding=2 border=1>';
myTable1 += "<tr><td><b>ID</b></td><td><b>UserName</b></td><td><b>Password</b></td><td><b>Email</b></td></tr>";
$.each(msg, function(i,v){
alert(i + v);
myTable1 += "<tr><td>" + v.id + "</td><td>" + v.username + "</td><td>" + v.password + "</td><td>" + v.Email + "</td></tr>";
});
$("#user_tb1").html(myTable1) ;
},
error: function () {
alert("error");
}
});
};
I am getting Json string as
{"id":1,"username":"karthik","password":"karthik","Email":"karthikdheeraj#gmail.com"}{"id":2,"username":"Lohith","password":"Lohith","Email":"lohith#cnonymn.com"}
and Html as
A table structure in which each cell is filled with "undefined"
What might be the Issue in the above code.
It looks like the json being retrieved from the server is incorrect, it's not an array of objects.
The correct format should be:
[
{"id":1,"username":"karthik","password":"karthik","Email":"karthikdheeraj#gmail.com"},
{"id":2,"username":"Lohith","password":"Lohith","Email":"lohith#cnonymn.com"}
]
Here's a plnkr showing your table filling code working with correctly formatted data
There's something up with the JSON that you are getting back. The proper format needs to be:
var json = [{
"id": 1,
"username": "karthik",
"password": "karthik",
"Email": "karthikdheeraj#gmail.com"
}, {
"id": 2,
"username": "Lohith",
"password": "Lohith",
"Email": "lohith#cnonymn.com"
}];
Below is a fiddle I created showing that the loop now alerts the username properly.
http://jsfiddle.net/77YBq/
After more investigation:
To continue to drill into this issue I believe the root of your JSON problem "if the documentation is correct" JsonWriter Documentation
I beleive your server code needs to have
jsonWriter.WriteStartArray(); // Starts Json Array notation;
// This is your existing code
//================================================================================
while (reader.Read())
{
int fieldcount = reader.FieldCount; // count how many columns are in the row
object[] values = new object[fieldcount]; // storage for column values
reader.GetValues(values); // extract the values in each column
jsonWriter.WriteStartObject();
for (int index = 0; index < fieldcount; index++)
{ // iterate through all columns
jsonWriter.WritePropertyName(reader.GetName(index)); // column name
jsonWriter.WriteValue(values[index]); // value in column
}
jsonWriter.WriteEndObject();
}
reader.Close();
//================================================================================
// End of your existing code
jsonWriter.WriteEndArray(); // Ends Json Array notation;
The JsonTextWriter is not intended to be used in the way you are using it.
You should take advantage of a serialization library so that you aren't writing code to serialize JSON.
Here is a solution that uses JSON.NET.
Include the package at http://json.codeplex.com/ in your solution.
Add this using statement to your file:
using Newtonsoft.Json;
Add a class to map your records to.
public class User{
... properties here
}
[WebMethod]
public static string GetJson2()
{
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
JsonWriter jsonWriter = new JsonTextWriter(sw);
var users = new List<User>();
try
{
string connstr = "server=localhost;user=root;database=cm_users;port=3306;password=root";
MySqlConnection conn = new MySqlConnection(connstr);
conn.Open();
string sql = "select * from users";
MySqlCommand cmd = new MySqlCommand(sql, conn);
MySqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
int fieldcount = reader.FieldCount; // count how many columns are in the row
object[] values = new object[fieldcount]; // storage for column values
reader.GetValues(values); // extract the values in each column
users.add(new User { id = reader["id"], username = reader["username"] ..});
}
reader.Close();
}
catch (MySqlException mySqlException)
{ // exception
return mySqlException + "error";
}
return JsonConvert.SerializeObject(users);
}
You should also consider naming your id, username etc as Id, Username etc so that you are following the correct naming conventions.
I have the following JQUERY code that I'm expecting to return 3 json results to the console. What's happening is I'm getting 3 copies of the results of the first return.
so for example I'm trying to see filename's, and I'm getting back "first name, first name, first name" instead of "first name, second name, third name"
here's my code:
$.ajax({
type: "POST",
url: "front.aspx/GetData",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
var obj = msg.d;
$.each(obj, function(index, value){
console.log(value);
});
}
});
what am I doing wrong with the each function?
I don't think you need my CS code to tell me what I'm doing wrong, but incase you do, here it is:
public class LoadData {
public string filename;
public string date;
public string filetype;
public Int32 height;
public Int32 width;
public string uploadGroup;
public string title;
public string uniqueID;
public string uploader;
public string uniqueIDnoExt;
}
[WebMethod]
public static List<LoadData> GetData() {
LoadData b = new LoadData();
List<LoadData> info = new List<LoadData>();
SqlDataReader reader;
string connectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ToString();
SqlConnection connection = new SqlConnection(connectionString);
connection.Open();
SqlCommand command = new SqlCommand("SELECT * FROM uploads ORDER BY id DESC", connection);
command.Parameters.Add(new SqlParameter("uploader", "anonymous"));
reader = command.ExecuteReader();
while (reader.Read()) {
b.filename = reader.GetString(1);
b.date = reader.GetSqlDateTime(3).ToString();
b.filetype = reader.GetString(4);
b.height = (Int32)reader.GetSqlInt32(5);
b.width = (Int32)reader.GetSqlInt32(6);
b.uploadGroup = reader.GetString(7);
b.title = reader.GetString(8);
b.uniqueID = reader.GetString(9);
b.uploader = reader.GetString(10);
b.uniqueIDnoExt = reader.GetString(12);
info.Add(b);
}
return info;
}
Move this line
LoadData b = new LoadData();
inside the loop.
while (reader.Read()) {
LoadData b = new LoadData();
b.filename = reader.GetString(1);
b.date = reader.GetSqlDateTime(3).ToString();
b.filetype = reader.GetString(4);
b.height = (Int32)reader.GetSqlInt32(5);
b.width = (Int32)reader.GetSqlInt32(6);
b.uploadGroup = reader.GetString(7);
b.title = reader.GetString(8);
b.uniqueID = reader.GetString(9);
b.uploader = reader.GetString(10);
b.uniqueIDnoExt = reader.GetString(12);
info.Add(b);
}
The way you have it now you make only one line of data. The List<> holds the reference, it does not recreate them. So if you're not making new data, you're not inserting any new data (as it is now). You're just adding first one in memory, and then changing the values.
Also you can read :
http://en.wikipedia.org/wiki/Linked_list
By the way.
You have left open many things, you will soon end up without resources. Use the using keyword on the objects that need to be closed. And, for speed, use a static string (to read only) on the connection string.
You are creating list in wrong way.. Follow #Aristos way to add object correctly.
and at your ajax request sucess: section..
Loop Throuh d.data. Check this JQuery Ajax with Class Arrays
for (var i in d.data) { }
And you can Manually convert result dataset to JSON
I have jquery using ajax/json to grab an elements ID and then hits:
[System.Web.Services.WebMethod]
public static string EditPage(string nodeID)
{
DataTable dt = new DataTable();
using (SqlConnection con = new SqlConnection(Global.conString))
using (SqlCommand cmd = new SqlCommand("contentPageGetDetail", con))
{
cmd.Parameters.Add("#ID", SqlDbType.UniqueIdentifier).Value = Global.SafeSqlLiteral(nodeID, 1);
cmd.CommandType = CommandType.StoredProcedure;
cmd.ExecuteNonQuery();
using (SqlDataAdapter da = new SqlDataAdapter(cmd))
{
da.Fill(dt);
}
}
if (dt.Count > 0)
{
string pageTitle = dt.Rows[0]["Title"].toString();
string contentID = dt.Rows[0]["ContentID"].toString();
return pageTitle, contentID, nodeID;
}
else
{
return "Failed";
}
}
When it's time to return I want to grab all content returned from the stored procedure back to the jquery method in the success section and set a hiddenfield, dropdown value, and a title in a textfield.
In the jQuery I tried using "pageTitle" but it came up undefined. What do I need to do jQuery side to grab whats being returned and populate fields in my Web Form before showing the form?
You'll need to create a struct or class to return:
public struct TheStruct
{
public string pageTitle;
public int contentID,
public int nodeID;
}
[System.Web.Services.WebMethod]
public static TheStruct EditPage(string nodeID)
{
<your code here>
var result = new TheStruct();
result.pageTitle = "Test";
result.contentID = 1;
return result;
}
If you pass:
contentType: "application/json; charset=utf-8",
in the AJAX call, you'll get a JSON reply, which you can parse like:
var obj = jQuery.parseJSON(webserviceReply);
alert(obj.pageTitle);
public class stuff {
string pagetitle;
string contentID;
string nodeID;
}
[System.Web.Services.WebMethod]
public static stuff EditPage(string nodeID) {
... get the stuff
stuff returnme = new stuff();
returnme.pagetitle = ...
returnme.contentid = ...
return returnme;
}
==== jquery side:
Assuming you're using the AJAX call of jquery do something like this:
.ajax({ type: "GET", url: "./return.asmx", async: true, dataType: "xml",
success: function (respons, status) {
$(respons).find("WebServiceCallName stuff pagetitle").text();
}});
You'll need to look at the webservice output directly (just navigate to it as if it were a webpage) to make sure your jQuery selector is correct.
If you want to use the string you return from jquery try:
success: function(msg) {
alert(msg.d);
}
msg.d will hold the string you return from your webservice call. If you want to return multiple strings, try to add a predefined string between them and split them in your jquery success function. like:
yourfirststring||##||yoursecondstring||##||yourthirdstring
var strings = msg.d.split("||##||");
I'm using tableDnD to re-order table rows, and then serialize them using "$.tableDnD.serialize()"
I want to send this to C# for processing, what's the best of doing so?
The below is an example of the serialization
pages[]=&pages[]=21&pages[]=23&pages[]=34&pages[]=37&pages[]=40&pages[]=43&pages[]=46&pages[]=49&pages[]=31&pages[]=50&pages[]=51&pages[]=52&pages[]=53&pages[]=54&pages[]=55&pages[]=56&pages[]=57&pages[]=58&pages[]=61&pages[]=65&pages[]=70&pages[]=74&pages[]=77&pages[]=78&pages[]=79&pages[]=82&pages[]=85&pages[]=88&pages[]=91&pages[]=94&pages[]=97&pages[]=100&pages[]=103&pages[]=106&pages[]=109&pages[]=112&pages[]=115&pages[]=119&pages[]=122&pages[]=123
Important Information
I tagged this as MVC but forgot to mention it. I'm using ASP.NET MVC
You can send that as-is using one of jQuery's ajax methods. I would prefer to turn it into a smaller, neater CSV string before sending it to the server as follows:
var str = 'pages[]=&pages[]=21&pages[]=23&pages[]=34&pages[]=37&pages[]=40&pages[]=43&pages[]=46&pages[]=49&pages[]=31&pages[]=50&pages[]=51&pages[]=52&pages[]=53&pages[]=54&pages[]=55&pages[]=56&pages[]=57&pages[]=58&pages[]=61&pages[]=65&pages[]=70&pages[]=74&pages[]=77&pages[]=78&pages[]=79&pages[]=82&pages[]=85&pages[]=88&pages[]=91&pages[]=94&pages[]=97&pages[]=100&pages[]=103&pages[]=106&pages[]=109&pages[]=112&pages[]=115&pages[]=119&pages[]=122&pages[]=123';
var tmpArr = str.split('&');
var pagesArr = [];
for(var i = 0;i < tmpArr.length; i++) {
var paramArr = tmpArr[i].split('=');
if(paramArr[1] != null && paramArr[1] != '') {
pagesArr.push(paramArr[1]);
}
}
alert(pagesArr); //now much prettier
//turn it into a CSV string
var pagesCsv = pagesArr.join(',');
$.ajax({
type: "POST",
url: "some.aspx",
data: pagesCsv,
success: function(msg){
alert( "Data Saved: " + msg );
}
});
Based on the example of karim79 :
var str = 'pages[]=&pages[]=21&pages[]=23&pages[]=34&pages[]=37&pages[]=40&pages[]=43&pages[]=46&pages[]=49&pages[]=31&pages[]=50&pages[]=51&pages[]=52&pages[]=53&pages[]=54&pages[]=55&pages[]=56&pages[]=57&pages[]=58&pages[]=61&pages[]=65&pages[]=70&pages[]=74&pages[]=77&pages[]=78&pages[]=79&pages[]=82&pages[]=85&pages[]=88&pages[]=91&pages[]=94&pages[]=97&pages[]=100&pages[]=103&pages[]=106&pages[]=109&pages[]=112&pages[]=115&pages[]=119&pages[]=122&pages[]=123';
var pos = null;
var index = 0;
while ((pos=str.indexOf("[]"))>-1)
{
str = str.substr(0, pos-1) + "_" + (index) + str.substr(pos+2);
index++;
}
alert(str);
$.ajax({
type: "POST",
url: "some.aspx",
data: str,
success: function(msg){
alert( "Data Saved: " + msg );
}
});
In C#
string[] keys = Request.QueryString.AllKeys;
Array.Sort(keys);
StringBuilder sb = new StringBuilder();
foreach (string key in keys)
{
if (key.IndexOf("pages_")!=-1)
{
sb.Append(Request.QueryString[key]);
}
}
// sb container the all values
You can also put everything in to one object like this:
var prm = { pages=[...], someOtherPages=[], additionalParam="", integer=1324 }
jQuery.ajax({
url: "someurl.aspx",
type: "POST",
data: {prm: JSON.stringify(prm)},
});
and parse prm on C# side by using this JSON Parser:
JObject json = JObject.Parse(Request.Form["prm"]);
JArray items = json["pages"] as JArray;
foreach (JToken item in items)
{
int i = item["type"].Value<int>(); // take an item as int
string s = item["type"].Value<string>(); // take an item as string
JArray ar = item["complex"] as JArray; // that an item as an array
}
much simplier and flexible