I'm not sure if I could make my code cleaner by creating a separate class for the process I'm running but I'm doing it this way because it's how I know to do it.
My main objective is to create a JSON file from data collected through HtmlAgilityPack. I've been working with this problem the last couple days but I managed to figure out a way to do it. I managed to create a JSON file with the information retrieved but it didn't divide the information into separate objects in an object array. Instead it clustered up all the data as 1 object.
This was happening because I never created the objects with the parsed html data in the string list. Instead of creating separate lists and combining them, I need to create a list of objects made from the parsed html data and add them to a list.
To test out this hypothetical method I created 3 class instances and gave them values to see if the JSON file created the desired array of objects. When tested, it created the JSON array of objects as desired.
JSON Created:
[{"FavsGTS":"GT1","FavsGPICS":"GP1","FavsRNS":"RN1","FavsPIS":"PI1","FavsIsOns":"true"},
{"FavsGTS":"GT2","FavsGPICS":"GP2","FavsRNS":"RN2","FavsPIS":"PI2","FavsIsOns":"false"},
{"FavsGTS":"GT3","FavsGPICS":"GP3","FavsRNS":"RN3","FavsPIS":"PI3","FavsIsOns":"true"}]
Now I'm trying to figure out how can I dynamically create instances based out of the collected html data.
What I had in mind was doing something like:
gamertagsFav = new List<string>(FavsGTS.Count);
gamertagsFav.AddRange(FavsGTS);
foreach(string gamertagfav in gamertagsFav)
{
//creates a class instance and adds the parsed data in the same order.
}
An example of a generated instance would be as fallows:
gamerprofileFav gpfav1 = new gamerprofileFav()
{
FavsGTS = "gt1",
FavsGPICS = "gpic1",
FavsRNS = "rn1",
FavsPIS = "pi1",
FavsIsOns = "ison1"
};
This is possible because all the parsed data is in the same order.
My code is a bit messy, but it is as fallows:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using HtmlAgilityPack;
using System.Web.Script.Serialization;
using Newtonsoft.Json;
using System.IO;
namespace Parser_Test_1._0
{
public partial class Form1 : Form
{
public List<string> FavsGTS { get; private set; }
public List<string> FavsGPICS { get; private set; }
public List<string> FavsRNS { get; private set; }
public List<string> FavsPIS { get; private set; }
public List<string> FavsIsOns { get; private set; }
public List<string> allPlayers { get; private set; }
public List<string> gamertagsFav { get; private set; }
public Form1()
{
InitializeComponent();
}
public class gamerprofileFav
{
public string FavsGTS { get; set; }
public string FavsGPICS { get; set; }
public string FavsRNS { get; set; }
public string FavsPIS { get; set; }
public string FavsIsOns { get; set; }
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
doc.Load(#"C:\Users\josec\Documents\Visual Studio 2015\Projects\THE XBOX PROJECT\Parser-Test-1.0\Parser-Test-1.0\bin\Debug\xbFrSourceCode.txt");
string datacollected1 = doc.DocumentNode.SelectNodes("//*[#id=\"favoritesContent\"]/div[2]/div[2]/ul")[0].InnerHtml;
string datacollected2 = doc.DocumentNode.SelectNodes("//*[#id=\"friendsContent\"]/div[2]/div[2]")[0].InnerHtml;
label1.Text = datacollected1;
label2.Text = datacollected2;
//StreamWriter sw = new StreamWriter("datacollected1.txt");
//sw.Write(datacollected1);
//sw.Close();
//Gamertags
HtmlAgilityPack.HtmlDocument favs = new HtmlAgilityPack.HtmlDocument();
favs.LoadHtml(datacollected1);
FavsGTS = new List<string>();
HtmlNodeCollection gts = favs.DocumentNode.SelectNodes("//li[#data-gamertag]");
foreach (var gt in gts)
{
string datagamertag = gt.Attributes["data-gamertag"].Value;
FavsGTS.Add(datagamertag);
}
listBox1.DataSource = FavsGTS;
FavsGPICS = new List<string>();
HtmlNodeCollection gpics = favs.DocumentNode.SelectNodes("//li/a[1]/img[1][#src]");
foreach (var gpic in gpics)
{
string datagpic= gpic.Attributes["src"].Value;
FavsGPICS.Add(datagpic);
}
listBox2.DataSource = FavsGPICS;
FavsRNS = new List<string>();
HtmlNodeCollection rns = favs.DocumentNode.SelectNodes("//li/div[2]/div[2]/div[1]/div[1]");
foreach (var rn in rns)
{
string datarn = rn.InnerText;
FavsRNS.Add(datarn);
}
listBox3.DataSource = FavsRNS;
FavsPIS = new List<string>();
HtmlNodeCollection pis = favs.DocumentNode.SelectNodes("//li/div[2]/div[2]/div[1]/div[2]");
foreach (var pi in pis)
{
string datapi = pi.InnerText;
FavsPIS.Add(datapi);
}
listBox4.DataSource = FavsPIS;
FavsIsOns = new List<string>();
HtmlNodeCollection isons = favs.DocumentNode.SelectNodes("//li[#data-isonline]");
foreach (var ison in isons)
{
string dataison = ison.Attributes["data-isonline"].Value;
FavsIsOns.Add(dataison);
}
listBox5.DataSource = FavsIsOns;
//Test
gamertagsFav = new List<string>(FavsGTS.Count);
gamertagsFav.AddRange(FavsGTS);
foreach(string gamertagfav in gamertagsFav)
{
}
//Merge
allPlayers = new List<string>(FavsGTS.Count + FavsGPICS.Count + FavsRNS.Count + FavsPIS.Count + FavsIsOns.Count);
allPlayers.AddRange(FavsGTS);
allPlayers.AddRange(FavsGPICS);
allPlayers.AddRange(FavsRNS);
allPlayers.AddRange(FavsPIS);
allPlayers.AddRange(FavsIsOns);
//GpsFav //+Start+
gamerprofileFav gpfav1 = new gamerprofileFav()
{
FavsGTS = "GT1",
FavsGPICS = "GP1",
FavsRNS = "RN1",
FavsPIS = "PI1",
FavsIsOns = "true"
};
gamerprofileFav gpfav2 = new gamerprofileFav()
{
FavsGTS = "GT2",
FavsGPICS = "GP2",
FavsRNS = "RN2",
FavsPIS = "PI2",
FavsIsOns = "false"
};
gamerprofileFav gpfav3 = new gamerprofileFav()
{
FavsGTS = "GT3",
FavsGPICS = "GP3",
FavsRNS = "RN3",
FavsPIS = "PI3",
FavsIsOns = "true"
};
List<gamerprofileFav> gpfavs = new List<gamerprofileFav>();
gpfavs.Add(gpfav1);
gpfavs.Add(gpfav2);
gpfavs.Add(gpfav3);
//GgsFav //-END-
listBox6.DataSource = allPlayers;
listBox7.DataSource = gamertagsFav;
//JSON Serialize
//string data = JsonConvert.SerializeObject(gpfavs);
//File.WriteAllText("data.json", data);
}
public class gpsFav
{
}
}
}
This is the Form1 when run:
The data presented in the 5 small lists is the data that I wish to assign to the generated instances in the same order they appear. That way I can create a list based out of these generated instances which I can serialize to a JSON file.
To avoid doing all of the hard work, there is already an option to deserialize a JSON object into a .NET object that you can work with, an example with your piece of code;
public class RootObject
{
public string FavsGTS { get; set; }
public string FavsGPICS { get; set; }
public string FavsRNS { get; set; }
public string FavsPIS { get; set; }
public string FavsIsOns { get; set; }
}
While you simply deserialize it by;
RootObject gamertag_sample = JsonConvert.DeserializeObject<RootObject>(jsonstr);
Of course if you pass it an array of RootObject, you'll need to replace <RootObject> with <RootObject[]> and so on with the type.
As far as I understood this was the only problem you were seeking for a solution or have I missed something?
EDIT:
With dynamic object you can create any value entry you wish, you'll need to go through a series of tasks to do so before however.
// this would contain your key,value for the generated instance.
// {example_key, "value"} would result later in myObject.example_key (returning "value")
var expandoObj = new ExpandoObject();
var eoCollection = (ICollection<KeyValuePair<string, object>>)expandoObj;
// add your key value pairs here
eoCollection.Add(new KeyValuePair<string, object>("example", "example value"));
dynamic myDynamicObject = expandoObj;
// myDynamicObject.example will return "example value", and would result in json:
// "example":"example value"
Related
Here are the full details of my code:
public partial class Form1 : Form
{
List<Sales> sales = new List<Sales>();
BindingSource bs = new BindingSource();
public Form1()
{
InitializeComponent();
LoadCSV();
bs.DataSource = sales;
dgvSales.DataSource = bs;
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void LoadCSV()
{
string filePath = #"c:\Users\demo\Task3_shop_data.csv";
List<string> lines = new List<string>();
lines = File.ReadAllLines(filePath).ToList();
foreach (string line in lines)
{
List<string> items = line.Split(',').ToList();
Sales s = new Sales();
s.TextBook = items[0];
s.Subject = items[1];
s.Seller = items[2];
s.Purchaser = items[3];
s.purchasedPrice = float.Parse(items[4]);
s.SalePrice = items[6];
s.Rating = items[7];
sales.Add(s);
}
}
}
}
my sales class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MichaelSACU301task3
{
internal class Sales
{
public string TextBook { get; set; }
public string Subject { get; set; }
public string Seller { get; set; }
public string Purchaser { get; set; }
public float purchasedPrice { get; set; }
public string SalePrice { get; set; }
public string Rating { get; set; }
}
}
I tried launching it but the error message keeps appearing can someone please help me fix this problem.
Use float.TryParse prior to assigning to purchasedPrice property, if the value can not be converted remember it in a list. In the example below the code to read file data is in a separate class which returns a list of sales and a list of int which is used to remember invalid lines where purchasedPrice data is invalid. You should also consider validating other data and also ensure proper amount of data after performing the line split.
public class FileOperations
{
public static (List<Sales>, List<int>) LoadSalesFromFile()
{
List<Sales> sales = new List<Sales>();
List<int> InvalidLine = new List<int>();
string filePath = #"c:\Users\demo\Task3_shop_data.csv";
List<string> lines = File.ReadAllLines(filePath).ToList();
for (int index = 0; index < lines.Count; index++)
{
var parts = lines[0].Split(',');
// validate purchase price
if (float.TryParse(parts[4], out var purchasePrice))
{
Sales s = new Sales();
s.TextBook = parts[0];
s.Subject = parts[1];
s.Seller = parts[2];
s.Purchaser = parts[3];
s.purchasedPrice = purchasePrice;
s.SalePrice = parts[6];
s.Rating = parts[7];
sales.Add(s);
}
else
{
// failed to convert purchase price
InvalidLine.Add(index);
}
}
return (sales, InvalidLine);
}
}
Call the above code in your form
var (salesList, invalidLines) = FileOperations.LoadSalesFromFile();
if (invalidLines.Count > 0)
{
// use to examine bad lines in file
}
else
{
// uses sales list
}
the error sis probably due the impossiability of float.Parse() parse the items[4] in float
you may track value of items[4] using brake point in VS
I have the following class and method in one cs file. I have assigned the property values for the class inside the method.
How do I read the values that are assigned to the properties in the ReturnValue class using another another form.
public class ReturnValues
{
public int startdate { get; set; }
public string imageurl { get; set; }
public string headline { get; set; }
public string fulldownloadLink { get; set; }
public string imagecopyright { get; set; }
public string filename { get; set; }
public int PreviousFileDate { get; set; }
}
string prtemp_path = Path.GetTempPath();
public void BingWallpaepr()
{
ReturnValues returnValues = new ReturnValues();
string baseurl = "http://bing.com";
//set the link for XML
var xml_link = "http://www.bing.com/HPImageArchive.aspx?format=xml&idx=0&n=1&mkt=en-US";
string xmlStr;
using (var wc = new WebClient())
{
xmlStr = wc.DownloadString(xml_link); //Downloads the xml page
var xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xmlStr); //loads the xml page to the string
XmlElement root = xmlDoc.DocumentElement;
XmlNodeList nodes = root.SelectNodes("/images/image");
foreach (XmlNode node in nodes)
{
returnValues.imageurl = node["url"].InnerText;
returnValues.headline = Regex.Replace(node["headline"].InnerText, "[^A-Za-z0-9 _]", "");
returnValues.imagecopyright = node["copyright"].InnerText;
returnValues.startdate = int.Parse(node["startdate"].InnerText);
//download the new image
returnValues.filename = string.Format(#"\bing_{0}.jpg", returnValues.startdate);
// MessageBox.Show(returnValues.filename.ToString());
returnValues.fulldownloadLink = baseurl + returnValues.imageurl;
wc.DownloadFile(new Uri(returnValues.fulldownloadLink), prtemp_path + returnValues.filename);
}
In my other form, I am trying to get the property value like below:
namespace CrimePortal
{
public partial class Loginfrm : Form
{
public Loginfrm()
{
InitializeComponent();
PlatformCommands.ReturnValues returnValues = new PlatformCommands.ReturnValues();
MessageBox.Show(returnValues.startdate.ToString());
}
}
but it returns null.
You are declaring BingWallpaper as a void. It shouldn't be. The declaration should look like this:
public ReturnValues BingWallpaepr()
And at the end of the method you should return returnValues;
Then, from your first form (login), you need to have a reference to the instance of the other form, let's say called platformCommands. There are many ways to do this and it depends on how you chose to design and structure your UI.
For example, if you want to instantiate the Platform Commands just before displaying the MessageBox, you could do
var platformCommands = new PlatformCommands();
PlatformCommands.ReturnValues returnValues = platformCommands.BingWallpaper();
MessageBox.Show(returnValues.startdate.ToString());
i have populated data reader from db table and i have class like
public class CandidateApplication
{
public string EmailID { get; set; }
public string Name { get; set; }
public string PhoneNo { get; set; }
public string CurrentLocation { get; set; }
public string PreferredWorkLocation { get; set; }
public int RoleApplingFor { get; set; }
public string CurrentJobTitle { get; set; }
public int EducationLevel { get; set; }
public decimal SalaryExpected { get; set; }
public string AvailableTime { get; set; }
public int AdvertID { get; set; }
public bool SignForAlert { get; set; }
public string CVInText { get; set; }
public string CVFileName { get; set; }
public bool IsDownloaded { get; set; }
public string specialization { get; set; }
public bool isallocated { get; set; }
public int id { get; set; }
public string AdvertAdditionalInfo { get; set; }
}
i can populate the above class in loop. we can iterate in data reader and populate class but i want to know is there any short cut way to populate class from data reader.
if data deserialization is possible from data reader to class then also tell me if few fields are there in class which are not there in data reader then how to handle the situation.
You don't need to use a Data Reader, You could just Populate the Data into a DataTable, and use the below method to create a List of your CandidateApplication Class.
The Call :-
List<CandidateApplication> CandidateList = GetCandidateInformation();
The Method that generates the list :-
public List<CandidateApplication> GetCandidateInformation()
{
DataTable dt = new DataTable();
using (OleDbConnection con = new OleDbConnection(ConfigurationManager.AppSettings["con"]))
{
using (OleDbCommand cmd = new OleDbCommand("SELECT * FROM [TableName]", con))
{
var adapter = new OleDbDataAdapter();
adapter.SelectCommand = cmd;
con.Open();
adapter.Fill(dt);
var CandApp = (from row in dt.AsEnumerable()
select new CandidateApplication
{
EmailID = row.Field<string>("EmailID"),
Name = row.Field<string>("Name"),
PhoneNo = row.Field<string>("PhoneNo"),
CurrentLocation = row.Field<string>("CurrentLocation"),
PreferredWorkLocation = row.Field<string>("PreferredWorkLocation"),
RoleApplingFor = row.Field<int>("RoleApplingFor"),
CurrentJobTitle = row.Field<string>("CurrentJobTitle"),
EducationLevel = row.Field<int>("EducationLevel "),
SalaryExpected = row.Field<decimal>("SalaryExpected"),
AvailableTime = row.Field<string>("AvailableTime"),
AdvertID = row.Field<int>("AdvertID"),
SignForAlert = row.Field<bool>("SignForAlert"),
CVInText = row.Field<string>("CVInText"),
CVFileName = row.Field<string>("CVFileName"),
IsDownloaded = row.Field<bool>("IsDownloaded"),
Specialization = row.Field<string>("Specialization"),
Isallocated = row.Field<bool>("Isallocated"),
Id = row.Field<int>("Id"),
AdvertAdditionalInfo = row.Field<string>("AdvertAdditionalInfo")
}).ToList();
return CandApp;
}
}
}
Although not an answer to your question, I would suggest you to consider the following workaround, which uses a SqlDataAdapter instead of a data reader:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Xml.Serialization;
class Program
{
static void Main(string[] args)
{
var cs = "YourConnectionString";
var xml = "";
using (var con = new SqlConnection(cs))
using (var c = new SqlCommand("SELECT * FROM CandidateApplication", con))
{
con.Open();
using (var adapter = new SqlDataAdapter(c))
{
var ds = new DataSet("CandidateApplications");
ds.Tables.Add("CandidateApplication");
adapter.Fill(ds, ds.Tables[0].TableName);
xml = ds.GetXml();
}
}
// We need to specify the root element
var rootAttribute = new XmlRootAttribute();
// The class to use as the XML root element (should match the name of
// the DataTable in the DataSet above)
rootAttribute.ElementName = "CandidateApplications";
// Initializes a new instance of the XmlSerializer class that can
// serialize objects of the specified type into XML documents, and
// deserialize an XML document into object of the specified type.
// It also specifies the class to use as the XML root element.
// I chose List<CandidateApplication> as the type because I find it
// easier to work with (but CandidateApplication[] will also work)
var xs = new XmlSerializer(typeof(List<CandidateApplication>), rootAttribute);
// Deserialize the XML document contained by the specified TextReader,
// in our case, a StringReader instance constructed with xml as a parameter.
List<CandidateApplication> results = xs.Deserialize(new StringReader(xml));
}
}
For those properties that are missing in the retrieved data, you could declare a private field with a default value:
string _advertAdditionalInfo = "default";
public string AdvertAdditionalInfo
{
get
{
return _advertAdditionalInfo;
}
set
{
_advertAdditionalInfo = value;
}
}
If you would like to enforce that the retrieved data will not fill in a specific property, use:
[XmlIgnoreAttribute]
public string AdvertAdditionalInfo { get; set; }
I made a generic function for converting the SELECT result from an OleDbCommand to a list of classes.
Let's say that I have a class that looks like this, which maps to the columns in the database:
internal class EconEstate
{
[Column(Name = "basemasterdata_id")]
public Guid BaseMasterDataId { get; set; }
[Column(Name = "basemasterdata_realestate")]
public Guid? BaseMasterDataRealEstate { get; set; }
[Column(Name = "business_area")]
public string BusinessArea { get; set; }
[Column(Name = "profit_centre")]
public int ProfitCentre { get; set; }
[Column(Name = "rentable_area")]
public decimal RentableArea { get; set; }
}
Then I can get a list of those EconEstate objects using this code:
public void Main()
{
var connectionString = "my connection string";
var objects = ReadObjects<EconEstate>(connectionString, "EMBLA.EconEstates").ToList();
}
private static IEnumerable<T> ReadObjects<T>(string connectionString, string tableName) where T : new()
{
using (var connection = new OleDbConnection(connectionString))
{
connection.Open();
using (var command = new OleDbCommand($"SELECT * FROM {tableName};", connection))
{
var adapter = new OleDbDataAdapter
{
SelectCommand = command
};
var dataTable = new DataTable();
adapter.Fill(dataTable);
foreach (DataRow row in dataTable.Rows)
{
var obj = new T();
foreach (var propertyInfo in typeof(T).GetProperties())
{
var columnAttribute = propertyInfo.GetCustomAttributes().OfType<ColumnAttribute>().First();
var value = row[columnAttribute.Name];
var convertedValue = ConvertValue(value, propertyInfo.PropertyType);
propertyInfo.SetValue(obj, convertedValue);
}
yield return obj;
}
}
}
}
private static object ConvertValue(object value, Type targetType)
{
if (value == null || value.GetType() == typeof(DBNull))
{
return null;
}
if (value.GetType() == targetType)
{
return value;
}
var underlyingTargetType = Nullable.GetUnderlyingType(targetType) ?? targetType;
if (value is string stringValue)
{
if (underlyingTargetType == typeof(int))
{
return int.Parse(stringValue);
}
else if (underlyingTargetType == typeof(decimal))
{
return decimal.Parse(stringValue);
}
}
var valueType = value.GetType();
var constructor = underlyingTargetType.GetConstructor(new[] { valueType });
var instance = constructor.Invoke(new object[] { value });
return instance;
}
As you can see, the code is generic, making it easy to handle different tables and classes.
I'm trying to deserialize a rest uri located at http://ws.geonames.org/countryInfo?lang=it&country=DE and keep getting error (There is an error in XML document (1, 1)). Plug http://ws.geonames.org/countryInfo?lang=it&country=DE into the browser and you can see the result.
I have a class
public class Country
{
public string CountryName {get;set;}
public string CountryCode {get;set;}
}
and the method in my console app is as follows:
static void DeserializeTheXML()
{
XmlRootAttribute xRoot = new XmlRootAttribute();
xRoot.ElementName = "countryName";
xRoot.IsNullable = true;
XmlSerializer ser = new XmlSerializer(typeof(Country), xRoot);
XmlReader xRdr = XmlReader.Create(new StringReader("http://ws.geonames.org/countryInfo?lang=it&country=DE"));
Country tvd = new Country();
tvd = (Country)ser.Deserialize(xRdr);
Console.WriteLine("Country Name = " + tvd.CountryName);
Console.ReadKey();
}
any ideas on how to deserialize this rest service? thanks..
For serialization to work successfully you need to decorate your objects with the proper serialization attributes or use the XmlAttributeOverrides constructor. Also don't forget that XML is case sensitive and your objects must reflect the XML structure you are deserializing:
public class GeoNames
{
[XmlElement("country")]
public Country[] Countries { get; set; }
}
public class Country
{
[XmlElement("countryName")]
public string CountryName { get; set; }
[XmlElement("countryCode")]
public string CountryCode { get; set; }
}
class Program
{
static void Main()
{
var url = "http://ws.geonames.org/countryInfo?lang=it&country=DE";
var serializer = new XmlSerializer(typeof(GeoNames), new XmlRootAttribute("geonames"));
using (var client = new WebClient())
using (var stream = client.OpenRead(url))
{
var geoNames = (GeoNames)serializer.Deserialize(stream);
foreach (var country in geoNames.Countries)
{
Console.WriteLine(
"code: {0}, name: {1}",
country.CountryCode,
country.CountryName
);
}
}
}
}
I'd like to return a list through a web service that takes a string which updates the SQL that supplies the list. I'm not too familiar with building lists, but I already have a list in my class. Again, I'd like to return this list through the web service.
My current list in my table class:
static public List<Skills> GetSkillsList(string like)
{
List<Skills> thelist = new List<Skills>();
string sql = "SELECT * FROM Skills WHERE SkillName LIKE '%" + like + "%'";
SqlDataReader dr = DBUtil.FillDataReader(sql);
while (dr.Read())
{
Skills obj = new Skills();
obj.skillID = Convert.ToInt32(dr["skillID"].ToString());
obj.skillName = Convert.ToString(dr["skillName"].ToString());
obj.skillReviewed = Convert.ToBoolean(dr["skillReviewed"].ToString());
obj.skillActive = Convert.ToBoolean(dr["skillActive"].ToString());
thelist.Add(obj);
}
return thelist;
}
Dummy list in the web service:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.Web.Script.Services.ScriptService]
public class AutoComplete : System.Web.Services.WebService
{
[WebMethod]
public IList<string> GetSkills(string contains)
{
IList<string> output = new List<string>();
output.Add("Apple");
output.Add("Ajax");
output.Add("Alpha");
output.Add("Alphred");
return output;
}
}
I'd like to return the Name and the ID fields in the web service list.
I would think it would be something like:
[WebMethod]
public IList<string> SkillsList(string like)
{
IList<string> output = new List<string>();
output = Skills.GetSkillsList(like);
return output;
}
but I know this is incorrect.
Any help is appreciated!
Here's how to do it in the WebMethod you provided. As suggested, a new class to hold the ID and Name would be best. Although you could do a delimited string if you have a requirement to use List.
public class Pair
{
public string ID { get; set; }
public string Name { get; set; }
}
[WebMethod]
public IList<Pair> SkillsList(string like)
{
IList<Skills> mySkills = new List<Skills>();
IList<Pair> output = new List<Pair>();
mySkills = Skills.GetSkillsList(like);
foreach(Skills currentSkill in mySkills)
{
Pair p = new Pair();
p.ID = currentSkill.ID;
p.Name = currentSkill.Name;
output.Add(p);
}
return output;
}
I would have created another class with only ID and Name property, populate the list of that class and return it to the caller. I have created a sample console app. See the code below and let me know if it helps.
public class Test {
public int A { get; set; }
public string B { get; set; }
public string C { get; set; }
}
public class TestR {
public int A { get; set; }
public string B { get; set; }
}
class Program
{
static void Main(string[] args)
{
List<Test> list = new List<Test>();
list.Add(new Test { A=1, B="AAAAA", C="BBBBB"});
list.Add(new Test { A = 2, B = "BBBBB", C = "CCCCC" });
list.Add(new Test { A = 3, B = "CCCCC", C = "DDDDD" });
List<TestR> r = new List<TestR>();
list.ForEach(l=> r.Add(new TestR { A= l.A, B=l.B }));
Console.ReadLine();
}
}