I want to ignore some properties from my Object during run time. The properties are decorated with data member attribute (Without data member attribute excludepropertyreferencces is working fine). Can you please provide some insight? Thanks
Question : HOW TO EXCLUDE PROPERTIES AT RUN TIME, IF THEY ARE DECORATE WITH DATAMEMBER ATTRIBUTE ?
ServiceStack , ExcludePropertyReferences
var model = new Model {
FirstName = "First Name",
LastName = "Last Name",
Children = new List<ModelChild>{
new ModelChild { ChildFirstName = "ChildFirstName 1", ChildLastName = "ChildLastName 1" },
new ModelChild { ChildFirstName = "ChildFirstName 2", ChildLastName = "ChildLastName 2" }
}
};
var model1 = new Model1 {
FirstName = "First Name",
LastName = "Last Name",
Children = new List<Model1Child>{
new Model1Child { ChildFirstName = "ChildFirstName 1", ChildLastName = "ChildLastName 1" },
new Model1Child { ChildFirstName = "ChildFirstName 2", ChildLastName = "ChildLastName 2" }
}
};
Console.WriteLine("Properties won't get ignored because the Model is decorated with Serialization Attributes");
using(MemoryStream stream = new MemoryStream())
using (var jsConfig = JsConfig.BeginScope()) {
jsConfig.ExcludeTypeInfo = true;
jsConfig.ExcludePropertyReferences = new [] { "Model.LastName", "ModelChild.ChildLastName" }.ToArray();
JsonSerializer.SerializeToStream(model, model.GetType(), stream);
LINQPad.Extensions.Dump(System.Text.Encoding.Default.GetString(stream.ToArray()));
}
Console.WriteLine();
Console.WriteLine();
Console.WriteLine("Properties will get ignored because the Model is not decorated with Serialization Attributes");
using(MemoryStream stream = new MemoryStream())
using (var jsConfig = JsConfig.BeginScope()) {
jsConfig.ExcludeTypeInfo = true;
jsConfig.ExcludePropertyReferences = new [] { "Model1.LastName", "Model1Child.ChildLastName" }.ToArray();
JsonSerializer.SerializeToStream(model1, model1.GetType(), stream);
LINQPad.Extensions.Dump(System.Text.Encoding.Default.GetString(stream.ToArray()));
}
// Define other methods and classes here
[DataContract()]
public class Model {
[DataMember(Name = "first_name",EmitDefaultValue = false )]
public string FirstName { get; set; }
[DataMember(Name = "last_name")]
public string LastName { get; set; }
[DataMember(Name = "collections")]
public List<ModelChild> Children { get; set; }
}
[DataContract()]
public class ModelChild {
[DataMember(Name = "child_first_name")]
public string ChildFirstName { get; set; }
[DataMember(Name = "child_last_name")]
public string ChildLastName { get; set; }
}
public class Model1 {
public string FirstName { get; set; }
public string LastName { get; set; }
public List<Model1Child> Children { get; set; }
}
public class Model1Child {
public string ChildFirstName { get; set; }
public string ChildLastName { get; set; }
}
Related
This is the class of the customer
namespace test2.Models
{
public class Customer
{
public int Id { get; set; }
public string Full_Name { get; set; }
public Driver Driver { get; set; }
[Required]
[Display(Name = "Route")]
public int DriverId { get; set; }
[DataType(DataType.ImageUrl)]
[DisplayName("Driver's License ")]
public string ImageUrl { get; set; }
}
}
Controller
[HttpPost]
public ActionResult Save(Customer customer, HttpPostedFileBase file)
{
if (!ModelState.IsValid)
{
var viewModel = new CustomerFormViewModel
{
Customer = customer,
Drivers = _context.Drivers.ToList()
};
string imageLocation = "";
if ((file == null || file.ContentLength < 1))
{
ViewBag.Msg = "Please select an image";
return View();
}
if (!SaveImg(file, out imageLocation))
{
ViewBag.Msg = "An error occured while saving the image";
}
customer.ImageUrl = imageLocation;
return View("CustomerForm", viewModel);
}
//customer.ImageUrl = imageLocation;
if (customer.Id == 0)
_context.Customers.Add(customer);
else
{
var customerInDb = _context.Customers.Single(d => d.Id == customer.Id);
customerInDb.Full_Name = customer.Full_Name;
customerInDb.DriverId = customer.DriverId;
customerInDb.ImageUrl = customer.ImageUrl;
}
_context.SaveChanges();
return RedirectToAction("Index", "Customers");
}
public bool SaveImg(HttpPostedFileBase file, out string imageLocation)
{
imageLocation = "";
string serverPath = Server.MapPath("~/Images");
if ((file == null || file.ContentLength < 1))
{
//throw an exception showing that no file is present
}
var imageString = file.ToString();
var allowedExtensions = new[]
{
".jpg", ".png", ".jpg", ".jpeg"
};
var fileName = Path.GetFileName(file.FileName); //eg myImage.jpg
var extension = Path.GetExtension(file.FileName); //eg .jpg
if (allowedExtensions.Contains(extension.ToLower()))
{
string ordinaryFileName = Path.GetFileNameWithoutExtension(file.FileName);
string myFile = ordinaryFileName + "_" + Guid.NewGuid() + extension;
var path = Path.Combine(serverPath, myFile);
file.SaveAs(path);
string relativePath = "~/Images/" + myFile;
imageLocation = relativePath;
return true;
//return a success message here
}
else
{
//file save error
return false;
}
}
Include the file as part of the model:
public class Customer
{
public int Id { get; set; }
public string Full_Name { get; set; }
public Driver Driver { get; set; }
[Required]
[Display(Name = "Route")]
public int DriverId { get; set; }
[DataType(DataType.ImageUrl)]
[DisplayName("Driver's License ")]
public string ImageUrl { get; set; }
[NotMapped]
public HttpPostedFileBase ImageFile { get; set; }
}
Reference in the view like so:
#using (Html.BeginForm("Save", "Image", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div class="form-group">
#Html.TextBoxFor(model => model.ImageFile, new { htmlAttributes = new { #class = "form-control" }, type = "file" })
</div>
The not mapped property will ensure it is ignored in the db context. It can then be accessed using:
[HttpPost]
public bool Save(Customer customer)
{
if (customer.ImageFile != null)
{
// do something
}
}
It wouldn't be good practise to save the file to the database. Instead, store it in the project directory and either store the name or the image of the path to the image in the database.
I'm new in AutoMapper and I'm trying to map list to list in this way:
public class Person
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address { get; set; }
public int Age { get; set; }
}
public class PersonMin
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<List<Person>, List<PersonMin>>();
});
IMapper iMapper = config.CreateMapper();
List<Person> source = new List<Person>
{
new Person { Id = 1, FirstName = "Bob", LastName = "Davis", Address = "Street1", Age = 40},
new Person { Id = 2, FirstName = "Rob", LastName = "Mavis", Address = "Street2", Age = 42}
};
List<PersonMin> destination = iMapper.Map<List<Person>, List<PersonMin>>(source);
foreach (var item in destination)
{
Console.WriteLine(item.Id + ", " + item.FirstName + ", " + item.LastName);
}
The destination is empty.
You don't need to care about the list.
Just simply map the models
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Person, PersonMin>();
});
I want to create a dropdown list based on the contents of a db entity.
This seems like a simple enough concept but I can't really seem to pin it down.
Here's my code:
MODEL
public partial class Escuela
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Escuela()
{
this.Empleadoes = new HashSet<Empleado>();
}
public int ID { get; set; }
public string Nombre { get; set; }
public int PuestoID { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Empleado> Empleadoes { get; set; }
public virtual Puesto Puesto { get; set; }
}
public partial class ESCUELAEntities : DbContext
{
public ESCUELAEntities()
: base("name=ESCUELAEntities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<Alumno> Alumnoes { get; set; }
public virtual DbSet<Empleado> Empleadoes { get; set; }
public virtual DbSet<Escuela> Escuelas { get; set; }
public virtual DbSet<Grupo> Grupoes { get; set; }
public virtual DbSet<Puesto> Puestoes { get; set; }
}
CONTROLLER
public ActionResult Index()
{
// HAVE TRIED THESE THREE
// #1
var EscQry = from d in db.Escuelas
select d.Nombre;
var escuelas = new SelectList(EscQry, "ID", "Nombre");
ViewData["esc"] = escuelas;
// #2
var escuelas = new SelectList(from d in db.Escuelas
select new SelectListItem { Text = d.Nombre, Value = d.ID.ToString() });
ViewData["esc"] = escuelas;
// #3
IEnumerable<Escuela> model = from p in db.Escuelas
select new Escuela { Nombre = p.Nombre };
// #1
return View();
// #2
return View();
// #3
return View(model);
}
VIEW
#model IEnumerable<_3E_III.Models.Escuela>
#{
ViewBag.Title = "Home Page";
}
#Html.DropDownList("Escuelas", ViewData["esc"] as List<SelectListItem>)
I get this error.
There is no ViewData item of type 'IEnumerable' that has the key 'Escuelas'.
I would make a View Model of the domain class, based on what properties I would need to show in my view.
public class EscuelaViewModel
{
public int ID { get; set; }
public string Nombre { get; set; }
public int PuestoID { get; set; }
.............. etc.
public Collection<SelectListItem> Escuelas {get; set;}
private static Collection<SelectListItem> CreateEscuelasOptions(string selectedOption == "")
{
var model = from p in db.Escuelas select new Escuela { Number = p.Nombre, Id= p.Id };
var options = new Collection<SelectListItem>();
foreach(var esc in model)
options.Add(new SelectListItem {Value = esc.Id, Text = esc.Number, Selected = selectedOption.Equals(esc.Number)});
return options;
}
public void LoadViewData()
{
Escuelas = CreateEscuelasOptions(Nombre);
}
}
Then, in the Controller:
public ActionResult Index()
{
var EscuelaViewModel = new EscuelaViewModel();
EscuelaViewModel.LoadViewData();
return View(EscuelaViewModel);
}
And the View:
#model EscuelaViewModel
#{
ViewBag.Title = "Home Page";
}
#Html.DropDownListFor(x => x.Nombre, Model.Escuelas, --Select option--)
I have created the following example to test Foreign Keys and up to this point, it works well. What I would like to be able to do, is use this framework that I built to set the property of the relationship and have it Save the child object when the Parent is saved and automatically set the PrimaryKey and Foreign Key.
The DataManager class exposes the Connection
public class DataManager
{
DataManager()
{
OrmLiteConfig.DialectProvider = SqliteDialect.Provider;
ConnectionString = SqliteFileDb;
updateTables();
}
private void updateTables()
{
using (var dbConn = OpenDbConnection())
{
dbConn.DropAndCreateTable<Person>();
dbConn.DropAndCreateTable<PhoneNumber>();
}
}
public static string SqliteFileDb = "~/App_Data/db.sqlite".MapAbsolutePath();
private static DataManager manager;
public static DataManager Manager {
get
{
if (manager == null)
manager = new DataManager();
return manager;
}
}
public IDbConnection InMemoryDbConnection { get; set; }
public IDbConnection OpenDbConnection(string connString = null)
{
connString = ConnectionString;
return connString.OpenDbConnection();
}
protected virtual string ConnectionString { get; set; }
protected virtual string GetFileConnectionString()
{
var connectionString = SqliteFileDb;
return connectionString;
}
}
These are my POCO's with the BaseClass used to Achieve my results:
public class Person : LiteBase
{
[AutoIncrement]
[PrimaryKey]
public int Id { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
private List<PhoneNumber> numbers;
public List<PhoneNumber> PhoneNumbers {
get
{
if (numbers == null)
numbers = GetList<PhoneNumber>(p => p.Person == Id);
return numbers;
}
}
}
public class PhoneNumber
{
public string Number { get; set; }
public string Description { get; set; }
[AutoIncrement]
[PrimaryKey]
public int Id { get; set; }
[References(typeof (Person))]
public int Person { get; set; }
public void AddPerson(Person person)
{
Person = person.Id;
}
}
public class LiteBase:INotifyPropertyChanged
{
public List<T> GetList<T>(Expression< Func<T,bool>> thefunction) where T : new()
{
var objects = new List<T>();
using (var conn = Data.DataManager.Manager.OpenDbConnection())
{
objects = conn.Where<T>(thefunction);
}
return objects;
}
public T GetItem<T>(Expression<Func<T, bool>> thefunction) where T : new()
{
T obj = new T();
using (var conn = Data.DataManager.Manager.OpenDbConnection())
{
obj = conn.Where<T>(thefunction).FirstOrDefault<T>();
}
return obj;
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
Simple Class to Create Person and PhoneNumber objects
public class PersonManager
{
public void CreatePerson(string name, string surname, string number)
{
using (var conn = DataManager.Manager.OpenDbConnection())
{
var pnum = new PhoneNumber { Number = number };
var person = new Person
{
Name=name,
Surname = surname,
};
conn.Save<Person>(person);
var id = conn.GetLastInsertId();
person.Id = (int)id;
pnum.AddPerson(person);
conn.Save<PhoneNumber>(pnum);
}
}
public List<Person> GetPeople()
{
List<Person> people;
using (var conn = DataManager.Manager.OpenDbConnection())
{
people = conn.Select<Person>();
}
return people;
}
public List<PhoneNumber> GetNumbers()
{
List<PhoneNumber> numbers;
using (var conn = DataManager.Manager.OpenDbConnection())
{
numbers = conn.Select<PhoneNumber>();
}
return numbers;
}
}
And here is the usage:
var manager = new PersonManager();
manager.CreatePerson("John", "Doe", "12345679");
manager.CreatePerson("Jack", "Smith", "12345679");
manager.CreatePerson("Peter", "Jones", "12345679");
manager.CreatePerson("Dan", "Hardy", "12345679");
var people = manager.GetPeople();
var numbers = manager.GetNumbers();
for (int i = 0; i < people.Count; i++)
{
Console.WriteLine("{0} {1} {2}",
people[i].Name,people[i].Surname,people[i].Id);
}
for (int n = 0; n < numbers.Count; n++)
{
Console.WriteLine("PN: {0} {1}",
numbers[n].Number,numbers[n].Person);
}
for (int p = 0; p < people.Count; p++)
{
var person = people[p];
Console.WriteLine("{0}: {1} {2} {3}",
person.Id,person.Name,person.Surname,person.GetItem<PhoneNumber>(x=>x.Person==person.Id).Number);
}
The output is as I expected :
John Doe 1
Jack Smith 2
Peter Jones 3
Dan Hardy 4
PN: 12345679 1
PN: 12345679 2
PN: 12345679 3
PN: 12345679 4
1: John Doe 12345679
2: Jack Smith 12345679
3: Peter Jones 12345679
4: Dan Hardy 12345679
What I really would like to be able to do is the following:
var john = new Person
{
Name = "John",
Surname = "Smith",
PhoneNumber = new PhoneNumber { Number = "123456789" }
};
conn.Save<Person>(john);
var number = john.PhoneNumber.Number
Is this at all possible?
By default OrmLite v3 blobs all complex types properties in a string field and you need to explicitly set all references.
In the next major v4 release (ETA late Nov 2013), OrmLite adds some support for external references with the [Reference] attribute, which lets you tell OrmLite these properties should be stored in an external table and not blobbed, e.g:
public class Customer
{
[AutoIncrement]
public int Id { get; set; }
public string Name { get; set; }
[Reference]
public CustomerAddress PrimaryAddress { get; set; }
[Reference]
public List<Order> Orders { get; set; }
}
This will allow you to call db.SaveReferences() to save the reference properties, e.g:
var customer = new Customer
{
Name = "Customer 1",
PrimaryAddress = new CustomerAddress {
AddressLine1 = "1 Humpty Street",
City = "Humpty Doo",
State = "Northern Territory",
Country = "Australia"
},
Orders = new[] {
new Order { LineItem = "Line 1", Qty = 1, Cost = 1.99m },
new Order { LineItem = "Line 2", Qty = 2, Cost = 2.99m },
}.ToList(),
};
Assert.That(customer.Id, Is.EqualTo(0)); //Id is not saved yet
//Inserts customer, populates auto-incrementing customer.Id
//Specify `references:true` to populate the ForeignKey ids and
//save the related rows as well, e.g:
db.Save(customer, references:true);
Assert.That(customer.Id, Is.GreaterThan(0));
Assert.That(customer.PrimaryAddress.CustomerId, Is.EqualTo(customer.Id));
Assert.That(customer.Orders.All(x => x.CustomerId == customer.Id));
Saving References manually
For more fine-grained control you can also choose which references you want to save, e.g:
db.Save(customer); //Doesn't save related rows
//1:1 PrimaryAddress Reference not saved yet
Assert.That(customer.PrimaryAddress.CustomerId, Is.EqualTo(0));
//1:1 PrimaryAddress Reference saved and ForeignKey id populated
db.SaveReferences(customer, customer.PrimaryAddress);
//1:Many Orders References saved and ForeignKey ids populated
db.SaveReferences(customer, customer.Orders);
Loading all related rows with the entity
You can then load the master row and all its references with db.LoadSingleById, e.g:
var dbCustomer = db.LoadSingleById<Customer>(customer.Id);
dbCustomer.PrintDump();
Assert.That(dbCustomer.PrimaryAddress, Is.Not.Null);
Assert.That(dbCustomer.Orders.Count, Is.EqualTo(2));
I receive an XML file from a server, which contains many elements, and one attribute.
When Try and serialize/deserialize the xml, all the elements are serialized/deserialized properly, except for the attribute. Why does this happen?
here is the XML file:
"<msg><msisdn>123456789</msisdn><sessionid>535232573</sessionid><phase>2</phase><request type=\"1\">*120*111#</request></msg>"
and the class:
[Serializable]
[XmlRoot(ElementName = "msg", Namespace = "")]
public class myClass
{
[XmlElement(ElementName = "msisdn")]
public string number = string.Empty;
[XmlElement(ElementName = "sessionid")]
public string sessionID = string.Empty;
[XmlAttribute(AttributeName = "type")]
public string requestType = string.Empty;
[XmlElement(ElementName = "request")]
public string request = string.Empty;
[XmlElement(ElementName = "phase")]
public string phase = string.Empty;
public override string ToString()
{
return number + " - " + sessionID;
}
}
Thanks for any help
Try defining a sub class for request because type is attribute of the request and not of the root MyClass:
[XmlRoot(ElementName = "msg", Namespace = "")]
public class MyClass
{
[XmlElement(ElementName = "msisdn")]
public string Number { get; set; }
[XmlElement(ElementName = "sessionid")]
public string SessionID { get; set; }
[XmlElement(ElementName = "request")]
public Request Request { get; set; }
[XmlElement(ElementName = "phase")]
public string Phase { get; set; }
public override string ToString()
{
return Number + " - " + SessionID;
}
}
public class Request
{
[XmlAttribute(AttributeName = "type")]
public string Type { get; set; }
[XmlText]
public string Value { get; set; }
}
class Program
{
static void Main()
{
var serializer = new XmlSerializer(typeof(MyClass));
using (var stringReader = new StringReader("<msg><msisdn>123456789</msisdn><sessionid>535232573</sessionid><phase>2</phase><request type=\"1\">*120*111#</request></msg>"))
using (var xmlReader = XmlReader.Create(stringReader))
{
var obj = (MyClass)serializer.Deserialize(xmlReader);
Console.WriteLine(obj.Request.Type);
}
}
}