How to Properly use Custom Class Generics - c#

I am trying to use Custom Generic class and interface.Im having problems to find a solution for the logic and code of my small Project.
THE BLUEPRINT INTERFACE
public interface IDepartment<T>
{
T CreateAndGetValues(SqlDataReader dataReader);
}
THE POSSIBLE DTO
public class Bank<T> : IDepartment<T>
{
public int LfdNr { get; set; }
public string Kennung { get; set; }
public string Name { get; set; }
public string Straße { get; set; }
public string PLZ { get; set; }
public string Ort { get; set; }
public DateTime TSCREATE { get; set; }
public DateTime TSUPDATE { get; set; }
public T CreateAndGetValues(SqlDataReader dataReader)
{
Bank<T> TheReturnObject = new Bank<T>();
ThereturnObject.LfdNr = Convert.ToInt32(dataReader.GetValue(0));
ThereturnObject.Kennung = dataReader.GetValue(1).ToString();
ThereturnObject.Name = dataReader.GetValue(2).ToString();
ThereturnObject.Straße = dataReader.GetValue(3).ToString();
ThereturnObject.PLZ = dataReader.GetValue(4).ToString();
ThereturnObject.Ort = dataReader.GetValue(5).ToString();
ThereturnObject.TSCREATE = DateTime.ParseExact(dataReader.GetValue(6).ToString().Trim(), "dd.MM.yyyy HH:mm:ss", System.Globalization.CultureInfo.InvariantCulture);
ThereturnObject.TSUPDATE = DateTime.ParseExact(dataReader.GetValue(7).ToString().Trim(), "dd.MM.yyyy HH:mm:ss", System.Globalization.CultureInfo.InvariantCulture);
return TheReturnObject;
}
}
THE GENERAL DATABASE READER.
public class Mssql<T> where T :class, IDepartment<T>, new()
{
public List<T> ReadTable()
{
string sqlcommand = "Select * from Bank; ";
List<T> TheListofObject = new List<T>();
using (SqlConnection cnn = new SqlConnection(connetionString))
{
cnn.Open();
using (SqlCommand command = new SqlCommand(sqlcommand, cnn))
{
SqlDataReader dataReader;
try
{
dataReader = command.ExecuteReader();
while (dataReader.Read())
{
IDepartment<T> Object = new T();
Object.CreateAndGetValues(dataReader);
TheListofObject.Add(Object);
}
return TheListofObject;
}
catch (Exception ex)
{
throw;
}
dataReader.Close();
}
cnn.Close();
}
}
}
THE MAIN PROGRAM
class Program
{
static void Main(string[] args)
{
Mssql<Bank<T>> TEST = new Mssql<Bank<T>>();
List<Bank<T>> TheList = TEST.ReadTable();
Console.ReadLine();
}
}
I am expecting that i can use a interface with a method where classes can inherit and return a new type of itself with the Type T and to pass the Type. So that the classes are not dependent that much to each other. And code can be reusable. I hope that is not confusing. Thanks

For this task I strongly recommend using an ORM. They are popular and mostly free. Stackoveflow runs on one of them.
Wikipedia's List of object-relational mapping software gives 9 .NET examples as of Oct 2019.
Here is an example from Dapper's doco.
public class Dog
{
public int? Age { get; set; }
public Guid Id { get; set; }
public string Name { get; set; }
public float? Weight { get; set; }
public int IgnoredProperty { get { return 1; } }
}
var guid = Guid.NewGuid();
var dog = connection.Query<Dog>("select Age = #Age, Id = #Id", new { Age = (int?)null, Id = guid });
If you add Dapper.Contrib you don't even need to write the query if you want all records.
public class Car
{
public int Id { get; set; } // Works by convention
public string Name { get; set; }
}
(...)
var cars = connection.GetAll<Car>();

Thank You for your time guys.
I have found an answer with out using any tool to my Problem. And I would like to share it.
//THE BLUEPRINT INTERFACE
public interface IDepartment
{
Object GetAndReadValues(SqlDataReader dataReader);
}
// The Possible DTO
public class Bank : IDepartment
{
public int LfdNr { get; set; }
public string Kennung { get; set; }
public string Name { get; set; }
public string Straße { get; set; }
public string PLZ { get; set; }
public string Ort { get; set; }
public DateTime TSCREATE { get; set; }
public DateTime TSUPDATE { get; set; }
public void CreateAndGetValues(SqlDataReader dataReader)
{
}
public Object GetAndReadValues(SqlDataReader dataReader)
{
Bank ThereturnObject = new Bank();
ThereturnObject.LfdNr = Convert.ToInt32(dataReader.GetValue(0));
ThereturnObject.Kennung = dataReader.GetValue(1).ToString();
ThereturnObject.Name = dataReader.GetValue(2).ToString();
ThereturnObject.Straße = dataReader.GetValue(3).ToString();
ThereturnObject.PLZ = dataReader.GetValue(4).ToString();
ThereturnObject.Ort = dataReader.GetValue(5).ToString();
ThereturnObject.TSCREATE = DateTime.ParseExact(dataReader.GetValue(6).ToString().Trim(), "dd.MM.yyyy HH:mm:ss", System.Globalization.CultureInfo.InvariantCulture);
ThereturnObject.TSUPDATE = DateTime.ParseExact(dataReader.GetValue(7).ToString().Trim(), "dd.MM.yyyy HH:mm:ss", System.Globalization.CultureInfo.InvariantCulture);
return ThereturnObject;
}
//THE GENERAL DATABASE READER.
public class Mssql<T> where T :class, IDepartment, new()
{
public List<T> ReadTable()
{
string sqlcommand = "Select * from Bank; ";
List<T> TheListofObject = new List<T>();
using (SqlConnection cnn = new SqlConnection(connetionString))
{
cnn.Open();
using (SqlCommand command = new SqlCommand(sqlcommand, cnn))
{
SqlDataReader dataReader;
try
{
dataReader = command.ExecuteReader();
while (dataReader.Read())
{
IDepartment Object = new T();
object ReturnObject = Object.GetAndReadValues(dataReader);
TheListofObject.Add((T)ReturnObject);
}
return TheListofObject;
}
//Error handling with th DB must be handeld correctly with the specific error
catch (Exception ex)
{
throw;
}
dataReader.Close();
}
cnn.Close();
}
}
}
//THE MAIN PROGRAM
class Program
{
static void Main(string[] args)
{
Mssql<Bank> TEST = new Mssql<Bank>();
List<Bank> TheList = TEST.ReadTable();
foreach (var item in TheList)
{
Console.WriteLine(item.LfdNr);
Console.WriteLine(item.Kennung);
Console.WriteLine(item.Name);
Console.WriteLine(item.Ort);
Console.WriteLine(item.PLZ);
Console.WriteLine(item.Straße);
Console.WriteLine(item.TSCREATE);
Console.WriteLine(item.TSUPDATE);
Console.WriteLine("");
Console.WriteLine("");
Console.WriteLine("");
}
Console.ReadLine();
}
}

Related

How to return correct values for listview using WCF?

I want to populate listview with information retrieved from database using WCF in C# and am not able to retrieve correct data for listview binding.
public interface IServicePl
{
[OperationContract]
[OperationContract]
IEnumerable<InterventiiCuEchipament> GetInterventiiCuEchipaments();
}
[DataContract]
public class InterventiiCuEchipament
{
[DataMember]
public string EchipamentInterventie { get; set; }
public int id_interventie { get; set; }
public string tip_interventie { get; set; }
public string responsabil { get; set; }
public DateTime data_finalizare { get; set; }
public bool status { get; set; }
}
public IEnumerable<InterventiiCuEchipament> GetInterventiiCuEchipaments()
{
try
{
IEnumerable<InterventiiCuEchipament> query = from sel1 in dataP.interventiis
join sel2 in dataP.sesizaris
on sel1.id_interventie equals sel2.id_sesizare
select new InterventiiCuEchipament()
{
id_interventie = sel1.id_interventie,
EchipamentInterventie = sel2.echipament,
tip_interventie = sel2.tip_sesizare,
responsabil = sel1.responsabil,
data_finalizare = (DateTime)sel1.data_finalizare,
status = (bool)sel1.status
};
return query;
}
On the client side I have the following code :
if (client.InnerChannel.State != CommunicationState.Faulted)
{
List<InterventiiCuEchipament> ListaInterventii = new List<InterventiiCuEchipament>();
ListaInterventii = client.GetInterventiiCuEchipamentsAsync().Result.ToList();
InterventiiList.ItemsSource = ListaInterventii;
InterventiiList.Items.Refresh();
}
Output from query is ok, like in this image
Output for listview binding is like in this image
Why I can see just the count of query? and not correct values returned by query.
If the query returns values, then ListaInterventii should also have values.
I wrote a similar demo, you can compare it.
You can use foreach to see if there is a value.
ListaInterventii = client.GetInterventiiCuEchipamentsAsync().Result.ToList();
foreach(var a in ListaInterventii)
{
int A = a.id_interventie;
}
Demo
public class ProductService : IServicePl
{
public IEnumerable<InterventiiCuEchipament> GetInterventiiCuEchipaments()
{
// This comes from database.
var _dbCountries = new List<InterventiiCuEchipament>
{
new InterventiiCuEchipament {id_interventie = 1, tip_interventie="1"},
new InterventiiCuEchipament {id_interventie = 2, tip_interventie="2"},
new InterventiiCuEchipament {id_interventie = 3, tip_interventie="3"},
};
return _dbCountries;
}
}
[ServiceContract]
public interface IServicePl
{
[OperationContract]
IEnumerable<InterventiiCuEchipament> GetInterventiiCuEchipaments();
}
[DataContract]
public class InterventiiCuEchipament
{
[DataMember]
[Key]
public int id_interventie { get; set; }
public string tip_interventie { get; set; }
}
client side
ServicePlClient client = new ServicePlClient();
List<InterventiiCuEchipament> ListaInterventii = new List<InterventiiCuEchipament>();
ListaInterventii = client.GetInterventiiCuEchipamentsAsync().Result.ToList();

Posting data to sql server using servicestack and c#

I'm just starting to learn servicestack and c# and I need some help with posting data to sql server. When I test using swagger I get a 200 response but nothing is actually being inserted into the database and I'm not sure where I'm going wrong.
Model.Type
public class Book
{
[PrimaryKey]
[AutoIncrement]
public int BookID { get; set; }
public string Author { get; set; }
public string Title { get; set; }
public int NumberOfPages { get; set; }
public int Isbn { get; set; }
}
Manager Interface:
namespace ServiceStackServiceLog4NetTemplate.Interfaces.Managers
{
public interface IPostBookManager
{
Book CreateBooks();
}
}
Repository Interface:
namespace ServiceStackServiceLog4NetTemplate.Interfaces.Repositories
{
public interface IPostBookRepository
{
Book PostBooks();
}
}
Messages.Request
namespace ServiceStackServiceLog4NetTemplate.ServiceModel.Messages
{
[Route("/PostBooks", Verbs = "POST")]
public class PostBooksRequest
{
[AutoIncrement]
public int BookID { get; set; }
public string Author { get; set; }
public string Title { get; set; }
public int NumberOfPages { get; set; }
public int Isbn { get; set; }
}
}
Messages.Response
namespace ServiceStackServiceLog4NetTemplate.ServiceModel.Messages
{
public class PostBooksResponse : IHasResponseStatus
{
public Book Book { get; set; }
public ResponseStatus ResponseStatus { get; set; }
}
}
Manager
class PostBooksManager : IPostBookManager
{
private IPostBookRepository postRepo;
public PostBooksManager(IPostBookRepository pRepo)
{
postRepo = pRepo;
}
public Book CreateBooks()
{
var bookCreations = postRepo.PostBooks();
return bookCreations;
}
}
}
Repository
namespace ServiceStackServiceLog4NetTemplate.Repositories
{
public class PostBookSqlRepo : IPostBookRepository
{
private readonly string connection = ConfigurationManager.AppSettings["BooksDB"];
public Book PostBooks()
{
var postBooks = CreateBooks();
return postBooks;
}
private Book CreateBooks()
{
var newBooks = new Book();
string query = "INSERT INTO dbo.BooksTable(BookID, Author, Title, NumberOfPages, ISBN)" +
"VALUES(#BookID, #Author, #Title, #NumberOfPages, #ISBN)";
SqlConnection dbConnect = new SqlConnection(connection);
SqlCommand cmd = new SqlCommand(query, dbConnect);
using (dbConnect)
{
dbConnect.Open();
var b = new Book()
{
BookID = newBooks.BookID,
Author = newBooks.Author,
Title = newBooks.Title,
NumberOfPages = newBooks.NumberOfPages,
Isbn = newBooks.Isbn
};
cmd.Parameters.AddWithValue("#BookID", b.BookID);
cmd.Parameters.AddWithValue("#Author", b.Author);
cmd.Parameters.AddWithValue("#Title", b.Title);
cmd.Parameters.AddWithValue("#NumberOfPages", b.NumberOfPages);
cmd.Parameters.AddWithValue("#ISBN", b.Isbn);
dbConnect.Close();
}
return newBooks;
}
}
}
Service Definition
namespace ServiceStackServiceLog4NetTemplate.ServiceDefinition
{
[EnableCors(allowedMethods: "GET,POST,DELETE")]
class PostBooksServiceDefinition : Service
{
private IPostBookManager postManager;
public PostBooksServiceDefinition(IPostBookManager bookP)
{
postManager = bookP;
}
public object Post(PostBooksRequest request)
{
var postBook = request.ConvertTo<Book>();
PostBooksResponse resp = new PostBooksResponse()
{
Book = postBook
};
return resp;
}
}
}
First you shouldn't have [AutoIncrement] on your Request DTO, you're converting the DTO to a Book object which is the data model you're saving, not the Request DTO. (It doesn't have any impact on anything, it's just unnecessary and unused).
Secondly, you're using OrmLite Data Attributes in your Book data model but you're not using OrmLite to insert the record.
To use OrmLite to insert a new Book in your ServiceStack Services you can just use:
Db.Insert(postBook);
If you also need to create the Book RDBMS table, you can create it if it doesn't already exist with:
using (var db = dbFactory.Open())
{
db.CreateTableIfNotExists<Book>();
}
If you haven't registered your OrmLiteConnectionFactory with ServiceStack, you can register it with:
container.Register<IDbConnectionFactory>(c =>
new OrmLiteConnectionFactory(connString, SqlServer2012Dialect.Provider));
See the docs on OrmLite project page for more info:
https://github.com/ServiceStack/ServiceStack.OrmLite
Using a Repository
If you want to use PostBookSqlRepo to save your books you should configure it with your IDbConnectionFactory, e.g:
public class PostBookSqlRepo : IPostBookRepository
{
IDbConnectionFactory dbFactory;
public PostBookSqlRepo(IDbConnectionFactory dbFactory)
{
this.dbFactory = dbFactory;
}
//...
public Book CreateBooks(Book book)
{
using (var db = dbFactory.OpenDbConnection())
{
db.Insert(book);
}
}
}
Which you can configure in your ServiceStack IOC with:
container.Register<IPostBookRepository>(c =>
new PostBookSqlRepo(c.Resolve<IDbConnectionFactory>()));

Type Casting Exception With Inheritance

Here is my code below. It gives me Casting exception problem at selIngs.Add(da). tried with the 2nd way. it still give me the same exception. I wonder where I am doing wrong? Once I implement the interface or inherit the base class it should be ok to treat child class as the same. Any idea please?
//1st way
public interface IngredientInterface
{
double Concentration { get; set; }
string DateCreated { get; set; }
string DevCode { get; set; }
}
public class IngredientData : INotifyPropertyChanged, IngredientInterface
{
public string GroupCode
{
get { return groupCode; }
set
{
groupCode = value;
}
}
public double Setpoint { get; set; }
public bool IsHighlighted { get; set; }
public double PPT { get; set; }
}
public class FormulaUploadViewModelData: IngredientData
{
//.....
}
public class FormulaUploadViewModel :INotifyPropertyChanged
{
public FormulaUploadViewModel()
{
selIngs = new List<FormulaUploadViewModelData>();
}
private void IngsUp()
{
List<IngredientData> someIngData = new List<IngredientData>();
foreach (FormulaUploadViewModelData da in someIngData)
{
selIngs.Add(da); //here gives me casting exception
}
}
}
//2nd way
public class FormulaUploadViewModelData: IngredientInterface
{
//.....
}
public class FormulaUploadViewModel :INotifyPropertyChanged
{
public FormulaUploadViewModel()
{
selIngs = new List<FormulaUploadViewModelData>();
}
private void IngsUp()
{
List<IngredientInterface> someIngData = new List<IngredientInterface>();
foreach (FormulaUploadViewModelData da in someIngData)
{
selIngs.Add(da); //here gives me casting exception
}
}
}
All FormulaUploadViewModelData are IngredientInterface. So this will work:
var ingredients = new List<IngredientInterface>();
ingredients.Add(new FormulaUploadViewModelData());
But the opposite does not work because not all IngredientInterface are FormulaUploadViewModelData which is what should follow from allowing:
var formulas = new
List<FormulaUploadViewModelData>();
formulas(someIngredientInterface);
Solution? Make sure the da you are adding is in fact a FormulaUploadViewModelData. There is quite a few ways to do it, to name a couple:
Pattern matching
foreach (var da in someInData)
if (da is FormulaUploadViewModelData formula)
selIngs.Add(formula)
Use Enumerable.OfType<> extension method
foreach (var formula in
someInData.OfType<FormulaUploadViewModelData>())
selIngs.Add(formula)
Etc.

How to change element name 'ArrayOfResponse' in Soap XML WCF services

My problem How to change The ArrayOfResponse Element in SOAP XML WCF services
using Message class.... see image I want change the element in red box ....
any ideas ???
enter image description here
that my code to get this result !
my interface
[ServiceContract()]
public interface IEvaluationWebService
{
[OperationContract(ReplyAction = "Evaluations")]
Message GetEvaluations(EvaluationRequest evaluationRequest);
}
this method tasks one parameter EvaluationRequest class ,to return Message ( List of Evaluation class )
Message IEvaluationWebService.GetEvaluations(EvaluationRequest evaluationRequest)
{
SqlConnection cnn = new SqlConnection("");
DateTime dtstart = new DateTime();
DateTime.TryParseExact(evaluationRequest.PeriodStart, "dd/MM/yyyy", CultureInfo.InvariantCulture, DateTimeStyles.NoCurrentDateDefault, out dtstart);
evaluationRequest.PeriodStart = dtstart.ToString("yyyy-MM-dd");
DateTime dtend = new DateTime();
DateTime.TryParseExact(evaluationRequest.PeriodEnd, "dd/MM/yyyy", CultureInfo.InvariantCulture, DateTimeStyles.NoCurrentDateDefault, out dtend);
evaluationRequest.PeriodEnd = dtend.ToString("yyyy-MM-dd");
SqlCommand cmd = new SqlCommand("GetEmployeeEvaluation", cnn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#PeriodStart", SqlDbType.VarChar, 10).Value = evaluationRequest.PeriodStart;
cmd.Parameters.Add("#PeriodEnd", SqlDbType.VarChar, 10).Value = evaluationRequest.PeriodEnd;
cnn.Open();
SqlDataReader sdr = cmd.ExecuteReader();
List<Evaluation> evaluationList = new List<Evaluation>();
MessageVersion ver = OperationContext.Current.IncomingMessageVersion;
while (sdr.Read())
{
Evaluation evaluation = new Evaluation();
evaluation.EstLaborOfficeId = Convert.ToInt32(sdr["EstLaborOfficeId"].ToString());
evaluation.EstSequenceNumber = Convert.ToInt32(sdr["EstSequenceNumber"].ToString());
evaluation.IdNumber =
evaluationList.Add(evaluation);
}
Evaluation eval = new Evaluation();
cnn.Close();
return Message.CreateMessage(ver, "Evaluations", evaluationList);
}
The request class to passing the dates for method and gets data ....
[MessageContract(IsWrapped = true, WrapperName = "GetEvaluation", WrapperNamespace = "http://tempuri.org/")]
[XmlType(Namespace = "http://tempuri.org/")]
public class EvaluationRequest
{
[MessageBodyMember(Order = 1)]
public string PeriodStart { get; set; }
[MessageBodyMember(Order = 2)]
public string PeriodEnd { get; set; }
}
request class(the parameters for GetEvaluations method )
[MessageContract(IsWrapped = true, WrapperName = "GetEvaluation", WrapperNamespace = "http://tempuri.org/")]
[XmlType(Namespace = "http://tempuri.org/")]
public class EvaluationRequest
{
[MessageBodyMember(Order = 1)]
public string PeriodStart { get; set; }
[MessageBodyMember(Order = 2)]
public string PeriodEnd { get; set; }
}
Evaluation class
[DataContract()]
public class Evaluation
{
private int _EstLaborOfficeId;
private int _EstSequenceNumber;
private long _IdNumber;
[DataMember]
public int EstLaborOfficeId
{
get { return _EstLaborOfficeId; }
set { _EstLaborOfficeId = value; }
}
[DataMember(Order = 2)]
public int EstSequenceNumber
{
get { return _EstSequenceNumber; }
set { _EstSequenceNumber = value; }
}
}
Anyone, who wants to consume your service, does not know what kind of result he will reveice. It is just "Message" and has not specific MessageContract.
As far as I can see from here, you want to give back a list of Evaluation.
What you could try is this: (Untested)
[MessageContract]
public class Evaluation
{
private int _EstLaborOfficeId;
private int _EstSequenceNumber;
private long _IdNumber;
[MessageBodyMember]
public int EstLaborOfficeId
{
get { return _EstLaborOfficeId; }
set { _EstLaborOfficeId = value; }
}
[MessageBodyMember]
public int EstSequenceNumber
{
get { return _EstSequenceNumber; }
set { _EstSequenceNumber = value; }
}
}
[MessageContract]
public class EvaluationList
{
[MessageBodyMember]
public List<Evaluation> Values {get;set}
}
[ServiceContract()]
public interface IEvaluationWebService
{
[OperationContract]
EvaluationList GetEvaluations(EvaluationRequest evaluationRequest);
}
...or just try use List as return and forget EvaluationList.
[ServiceContract()]
public interface IEvaluationWebService
{
[OperationContract]
List<Evaluation> GetEvaluations(EvaluationRequest evaluationRequest);
}
Now, EvaluationList and EvaluationRequest are both MessageContracts.
Please keep in mind, that you ONLY want to use MessageContract, if you want full control of the SOAP Message. This does not seem to be the case here.
So, the more easy way would be, to change your EvaluationRequest back to DataContract:
[DataContract()]
public class Evaluation
{
private int _EstLaborOfficeId;
private int _EstSequenceNumber;
private long _IdNumber;
[DataMember]
public int EstLaborOfficeId
{
get { return _EstLaborOfficeId; }
set { _EstLaborOfficeId = value; }
}
[DataMember(Order = 2)]
public int EstSequenceNumber
{
get { return _EstSequenceNumber; }
set { _EstSequenceNumber = value; }
}
}
[DataContract]
public class EvaluationRequest
{
[DataMember]
public string PeriodStart { get; set; }
[DataMember]
public string PeriodEnd { get; set; }
}
[ServiceContract()]
public interface IEvaluationWebService
{
[OperationContract]
List<Evaluation> GetEvaluations(EvaluationRequest evaluationRequest);
}
The GOLDEN RULE IS: Try not to mix DataContract and MessageContract in a service operation, because WCF will see this as security flaw.
So define BOTH classes, result AND parameter, as DataContract OR MessageContract, but don't mix it up.

Parsing JSON into Object

Trying to get the result from a webservice call to return a Model. I eep getting the error:
Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'CI.Models.Schedule' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.
public Schedule getCourseSchedule()
{
var obj = new
{
States = new[] { new { State = "MX" } },
Zip = "",
Miles = "",
PaginationStart = 1,
PaginationLimit = 3
};
using (var client = new WebClient())
{
client.Headers[HttpRequestHeader.ContentType] = "apoplication/json";
var url = "http://192.168.1.198:15014/ShoppingCart2/CourseSchedule";
var json = JsonConvert.SerializeObject(obj);
byte[] data = Encoding.UTF8.GetBytes(json);
byte[] result = client.UploadData(url, data);
string returnjson = Encoding.UTF8.GetString(result);
Schedule sched = JsonConvert.DeserializeObject<Schedule>(returnjson);
return sched;
}
}
Schedule Model:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Globalization;
namespace CI.Models
{
public class Schedule
{
public IEnumerable<Course> Courses { get; set; }
}
public class Course
{
/*
JSON Data returned from web service:
{
"ProgramGroup":"MR",
"ProgramCode":"RM",
"EventCode":"20160901MXMR",
"FormalDate":"September 1-2, 2016",
"StartDate":"2016\/09\/01",
"Price":5,
"LocName":"WB Hotel",
"LocAddress":"Av. Speedy Gonzales 220",
"LocCity":"Monterrey",
"LocState":"MX",
"LocZipCode":null,
"LicenseeURL":null,
"AgendaURL":"NA",
"SeatsAreAvailable":"2",
"GeneralInfoHTML":"General Info goes here.",
"GateKeeperHTML":null,
"EventType":"SS",
"TotalCourses":3
}
*/
public string ProgramGroup { get; set; }
public string ProgramCode { get; set; }
public string EventCode { get; set; }
public string FormalDate { get { return FormalDate; } set { FormalDate = convertFormalDateToSpanish(value); } }
public string StartDate { get; set; }
public double Price { get; set; }
public string LocName { get; set; }
public string LocAddress { get; set; }
public string LocCity { get ; set; }
public string LocState { get; set; }
public string LocZipCode { get; set; }
public string LicenseeURL { get; set; }
public string AgendaURL { get { return AgendaURL; } set { AgendaURL = buildAgendaLink(value); } }
public string SeatsAreAvailable { get; set; }
public string GeneralInfoHTML { get; set; }
public string GateKeeperHTML { get; set; }
public string EventType { get; set; }
public int TotalCourses { get; set; }
public string convertFormalDateToSpanish(string val)
{
DateTime TheDate = DateTime.Parse(StartDate);
string[] FormalDate = val.Split(" ".ToCharArray());
CultureInfo ci = new CultureInfo("es-ES");
string _Date = FormalDate[1].Replace("-", " al ").Replace(",", "");
string _Month = ci.TextInfo.ToTitleCase(TheDate.ToString("MMMM", ci));
val = string.Concat(_Date, " ", _Month);
return val;
}
private string buildAgendaLink(string val)
{
if (val.Trim() != "")
{
val = string.Concat("Agenda");
}
else
{
val = "Agenda";
}
return val;
}
}
}
Your server returns an array. Just try
Course[] courses = JsonConvert.DeserializeObject<Course[]>(returnjson);
Note that this is not an answer to your original problem, but I added it like an answer in order to explain my comment above with some actual code.
First problem with your code is that FormalDate and AgendaUrl properties simply won't work. Accessing them will result in a StackOverflowException, because you basically defined them recursively.
A property is merely syntax sugar for two separate getter/setter methods, so by writing this:
public class Course
{
public string FormalDate
{
get { return FormalDate; }
}
}
You are basically writing this:
public class Course
{
public string GetFormalDate()
{
// recursive call, with no terminating condition,
// will infinitely call itself until there is no
// more stack to store context data (and CLR
// will then throw an exception)
return GetFormalDate();
}
}
To fix that, you need to add an actual backing field, e.g.:
public class Course
{
private string _formalDate; // <-- this is a backing field;
// and this property uses the backing field to read/store data
public string FormalDate
{
get { return _formalDate; }
set { _formalDate = convertFormalDateToSpanish(value); }
}
}
Additionally, it's unusual for a property getter to return a different value than the one set through a setter. In other words, I would never expect this from a class:
var course = new Course();
course.StartDate = "2016/09/01";
course.FormalDate = "September 1-2, 2016";
Console.WriteLine(course.FormalDate); // prints "1 al 2 Septiembre" ?
I would rather move this functionality into a different class, or at least create different properties which return these values:
public class CourseInfo
{
// this is now a "dumb" auto-implemented property
// (no need for a backing field anymore)
public string FormalDate { get; set; }
// this read-only property returns the converted value
public string LocalizedFormalDate
{
get
{
return convertFormalDateToSpanish(FormalDate);
}
}
}

Categories