Using AutoMapper to Map List<object> to ConfigurationElementCollection - automapper

I am having a bit of a problem using AutoMapper with some Configuration Elements.
I have the following classes:
public class SocialLinkSettingConfiguration : ConfigurationSection
{
[ConfigurationProperty("name", IsRequired = true, IsKey = true)]
public string Name
{
get { return this["name"] as string; }
set { this["name"] = value; }
}
[ConfigurationProperty("description", IsRequired = true)]
public string Description
{
get { return this["description"] as string; }
set { this["description"] = value; }
}
[ConfigurationProperty("url", IsRequired = true)]
public string Url
{
get { return this["url"] as string; }
set { this["url"] = value; }
}
[ConfigurationProperty("fontAwesomeClass", IsRequired = false)]
public string FontAwesomeClass
{
get { return this["fontAwesomeClass"] as string; }
set { this["fontAwesomeClass"] = value; }
}
[ConfigurationProperty("imageUrl", IsRequired = false)]
public string ImageUrl
{
get { return this["imageUrl"] as string; }
set { this["imageUrl"] = value; }
}
}
public class SocialLinkSettingConfigurationCollection : ConfigurationElementCollection
{
public SocialLinkSettingConfiguration this[int index]
{
get { return (SocialLinkSettingConfiguration)BaseGet(index); }
set
{
if (BaseGet(index) != null)
{
BaseRemoveAt(index);
}
BaseAdd(index, value);
}
}
public void Add(SocialLinkSettingConfiguration serviceConfig)
{
BaseAdd(serviceConfig);
}
public void Clear()
{
BaseClear();
}
protected override ConfigurationElement CreateNewElement()
{
return new SocialLinkSettingConfiguration();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((SocialLinkSettingConfiguration)element).Name;
}
public void Remove(SocialLinkSettingConfiguration serviceConfig)
{
BaseRemove(serviceConfig.Name);
}
public void RemoveAt(int index)
{
BaseRemoveAt(index);
}
public void Remove(string name)
{
BaseRemove(name);
}
}
public class SocialLinkSetting
{
public string Name { get; set; }
public string Description { get; set; }
public string Url { get; set; }
public string FontAwesomeClass { get; set; }
public string ImageUrl { get; set; }
}
I can create a mapping between SocialLinkSetting and SocialLinkSettingConfiguration just fine.
However, when I am trying to convert a list of SocialLinkSetting to SocialLinkSettingConfigurationCollection, I fail every time.
What I am trying to do is take a list of Social Links, and convert it to a single SocialLinkSettingConfigurationCollection object that has all of the SocialLinkSetting inside and converted to SocialLinkSettingConfiguration.
I can't seem to do this. Each time, it doesn't know how to convert List to the SocialLinkSettingConfigurationCollection, then add each of the items.
Any help would be greatly appreciated.
Thanks,
Ben

You can do something like this:
Mapper.Initialize(cfg =>
{
cfg.CreateMap<SocialLinkSetting, SocialLinkSettingConfiguration>();
cfg.CreateMap<List<SocialLinkSetting>, SocialLinkSettingConfigurationCollection>()
.AfterMap((source, dest, resolutionContext) =>
{
dest.Clear();
source.ForEach(i => dest.Add(resolutionContext.Mapper.Map<SocialLinkSettingConfiguration>(i)));
});
});

Related

In Orchard how do I create a query that includes an associated Part?

I'm working in a new module for an orchard project. We've build a Company Part which is associated with an Address Part. What I'm eventually trying to get to is allowing users to enter various search criteria via the ui (non-admin interface), perform a search against all companies and return any matching results.
Where I'm struggling is how to build the query which allows me to include info from the associated address. So far I've only been able to successfully return results based on the CompanyPartRecord as opposed to the CompanyPart. The CompanyPartRecord obviously only contains the Address_Id of the associated AddressPart.
In essence I'm trying to get to something like this which will return an enumerable or list of companies which match the entered search criteria. There are more search options beyond zip so I'm looking for an extensible solution.
var query = _companyRepository.Table.AsQueryable();
if (!string.IsNullOrEmpty(Zip))
query = query.Where(c => c.Address.Zip == Zip);
var queryResult = query.ToList();
I've tried using both an IRepository (shown above) and with IContentManager such as the following:
var query = _contentManager.Query<CompanyPart, CompanyPartRecord>();
//var query = _contentManager.Query<CompanyPart>();
if (!string.IsNullOrEmpty(Zip))
query = query.Where(c => c.Address.Zip == Zip);
var queryResult = query.ToList();
Here's the actual Company and Address (Parts and Records):
public class CompanyPartRecord : ContentPartRecord
{
public virtual string Name { get; set; }
public virtual string Description { get; set; }
public virtual int Address_Id { get; set; }
public virtual string Phone { get; set; }
public virtual string OtherInformation { get; set; }
public virtual string Website { get; set; }
public virtual bool Inactive { get; set; }
// Keywords - Taxonomy
// Logo - associated part
// HasMissingData - derived
// NumberOfEmployees - associated part
}
public class CompanyPart : ContentPart<CompanyPartRecord>, ITitleAspect
{
internal readonly LazyField<AddressPart> AddressField = new LazyField<AddressPart>();
public string Name
{
get { return Record.Name; }
set { Record.Name = value; }
}
public string Description
{
get { return Record.Description; }
set { Record.Description = value; }
}
public AddressPart Address
{
get { return AddressField.Value; }
set { AddressField.Value = value; }
}
public string Phone
{
get { return Record.Phone; }
set { Record.Phone = value; }
}
public string OtherInformation
{
get { return Record.OtherInformation; }
set { Record.OtherInformation = value; }
}
public string Website
{
get { return Record.Website; }
set { Record.Website = value; }
}
public bool Inactive
{
get { return Record.Inactive; }
set { Record.Inactive = value; }
}
public string Title
{
get { return Name; }
}
}
public class AddressPartRecord : ContentPartRecord
{
public virtual string Street { get; set; }
public virtual string Street2 { get; set; }
public virtual string City { get; set; }
public virtual string CountyName { get; set; }
public virtual NationRecord State { get; set; }
public virtual string Zip { get; set; }
}
public class AddressPart : ContentPart<AddressPartRecord>
{
public string Street
{
get { return Record.Street; }
set { Record.Street = value; }
}
public string Street2
{
get { return Record.Street2; }
set { Record.Street2 = value; }
}
public string City
{
get { return Record.City; }
set { Record.City = value; }
}
public string CountyName
{
get { return Record.CountyName; }
set { Record.CountyName = value; }
}
public NationRecord State
{
get { return Record.State; }
set { Record.State = value; }
}
public string Zip
{
get { return Record.Zip; }
set { Record.Zip = value; }
}
}
I assume that you have a Content Type that contains both Parts (ie. named Company), if that is the case this should work:
var query = _contentManager.Query("Company").Where<AddressPartRecord>(x => x.Street == "query street");
var list = query.ToList();
The list contains the ContentItems filtered by street. Using .As() and .As() over the items of the list you get access to each part.

Autoroute URL patterns containing custom tokens

I'm having trouble getting my custom tokens to work with my ContentPart. My problem is the same as what is described here:
Is it possible to create an orchard autoroute using contents of a custom type property?
I have created my tokens:
namespace MyNS.Types.Providers
{
public class BioPartTokens : ITokenProvider
{
public BioPartTokens() {
T = NullLocalizer.Instance;
}
public Localizer T { get; set; }
public void Describe(dynamic context) {
context.For("Bio", T("Bio"), T("Tokens for the Bio content type"))
.Token("FirstName", T("FirstName"), T("First name of person."))
.Token("LastName", T("LastName"), T("Last name of person."));
}
public void Evaluate(dynamic context) {
context.For<BioPart>("Bio")
.Token("FirstName", (Func<BioPart, object>) (f => f.ContentItem.Parts.OfType<BioPart>().First().FirstName.ToLower()))
.Chain("FirstName", "FirstName", (Func<BioPart, object>)(f => f.ContentItem.Parts.OfType<BioPart>().First().FirstName.ToLower()))
.Token("LastName", (Func<BioPart, object>)(f => f.ContentItem.Parts.OfType<BioPart>().First().LastName.ToLower()))
.Chain("LastName", "LastName", (Func<BioPart, object>)(f => f.ContentItem.Parts.OfType<BioPart>().First().LastName.ToLower()))
;
}
}
}
My model:
namespace MyNS.Types.Models
{
public class BioPart: ContentPart<BioPartRecord>
{
public string FirstName {
get { return Record.FirstName; }
set { Record.FirstName = value; }
}
public string LastName
{
get { return Record.LastName; }
set { Record.LastName = value; }
}
public RoleInSchool RoleInSchool
{
get { return Record.RoleInSchool; }
set { Record.RoleInSchool = value; }
}
public bool IsBlogger {
get { return Record.IsBlogger; }
set { Record.IsBlogger = value; }
}
}
}
Though I've tried URL patterns with all of the following tokens, I've not been able to get a value back from the form that I've submitted:
{Content.Bio.FirstName}
{Content.BioPart.FirstName}
{Bio.FirstName}
{BioPart.FirstName}
No errors are being logged.

An error occured while updating the feature OrchardCMS

I have a problem with my OrchardCMS migrations, the following code fails doing the migration (because I created the ContentItem for illustrative purposes), the error raises creating the content type:
public class Migrations : DataMigrationImpl {
private readonly IContentManager _contentManager;
public Migrations(IContentManager contentManager)
{
_contentManager = contentManager;
}
public int Create() {
SchemaBuilder.CreateTable("MedioPartRecord", table => table
.ContentPartRecord()
.Column<string>("Identificador")
.Column<string>("Matricula")
.Column<string>("NumeroSistemaGPS")
.Column<string>("Observaciones")
.Column("Matriculacion",DbType.DateTime)
.Column<int>("IdTipoMedio")
.Column("InicioTrabajo", DbType.DateTime)
.Column<int>("Kms"));
ContentDefinitionManager.AlterTypeDefinition("TipoMedio", type => type
.Creatable()
.WithPart("TitlePart")
.WithPart("CommonPart"));
ContentDefinitionManager.AlterPartDefinition(typeof(MedioPart).Name, part => part.Attachable());
ContentDefinitionManager.AlterTypeDefinition("Medio", type => type
.Creatable()
.WithPart("CommonPart")
.WithPart("MedioPart")
);
return 1;
}
public class MedioPartRecord : ContentPartRecord {
public virtual string Identificador { get; set; }
public virtual string Matricula { get; set; }
public virtual string NumeroSistemaGPS { get; set; }
public virtual string Observaciones { get; set; }
public virtual DateTime Matriculacion { get; set; }
public virtual DateTime InicioTrabajo { get; set; }
public virtual int IdTipoMedio { get; set; }
public virtual int Kms { get; set; }
}
public class MedioPart : ContentPart<MedioPartRecord>
{
public virtual int IdTipoMedio { get { return Record.IdTipoMedio; } set { Record.IdTipoMedio = value; } }
public virtual string Identificador { get { return Record.Identificador; } set { Record.Identificador = value; } }
public virtual string Matricula { get { return Record.Matricula; } set { Record.Matricula = value; } }
public virtual string NumeroSistemaGPS { get { return Record.NumeroSistemaGPS; } set { Record.NumeroSistemaGPS = value; } }
public virtual string Observaciones { get { return Record.Observaciones; } set { Record.Observaciones = value; } }
public virtual DateTime Matriculacion { get { return Record.Matriculacion; } set { Record.Matriculacion = value; } }
public virtual DateTime InicioTrabajo { get { return Record.InicioTrabajo; } set { Record.InicioTrabajo = value; } }
public virtual int Kms { get { return Record.Kms; } set { Record.Kms = value; } }
}
public class MedioPartHandler : ContentHandler {
public MedioPartHandler(IRepository<MedioPartRecord> repository)
{
Filters.Add(StorageFilter.For(repository));
}
}
Thank you
The problem was that I forgot to set the datetime as nullable type.

Web.config nested lists

I would like to use nested list in my web.config. I see pieces of code that work, but not mine, i have an error when i try to read the configuration section :
System.Configuration.ConfigurationErrorsException : Élément non
reconnu IsochroneServicesTestImbrique'.
My config :
<IsochroneServicesTest>
<add name="TC">
<IsochroneServicesTestImbrique>
<add name="DEFAULT" path="success"/>
</IsochroneServicesTestImbrique>
</add>
</IsochroneServicesTest>
and the code :
[ConfigurationProperty("IsochroneServicesTest")]
[ConfigurationCollection(typeof(CollectionIsochrone), AddItemName = "add")]
public CollectionIsochroneType IsochroneServicesTest
{
get { return (CollectionIsochroneType)this["IsochroneServicesTest"]; }
set { this["IsochroneServicesTest"] = value; }
}
public class CollectionIsochroneType : ConfigurationElementCollection
{
public void Add(ProviderElement element)
{
base.BaseAdd(element);
}
protected override ConfigurationElement CreateNewElement()
{
return new IsochroneElement();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((IsochroneTypeElement)element).Name;
}
public IsochroneTypeElement this[int index]
{
get { return (IsochroneTypeElement)BaseGet(index); }
set
{
if (BaseGet(index) != null)
{
BaseRemoveAt(index);
}
BaseAdd(index, value);
}
}
public new IsochroneTypeElement this[string Name]
{
get { return (IsochroneTypeElement)BaseGet(Name); }
}
public int IndexOf(IsochroneTypeElement element)
{
return BaseIndexOf(element);
}
protected override void BaseAdd(ConfigurationElement element)
{
BaseAdd(element, false);
}
}
public class IsochroneTypeElement : ConfigurationElement
{
[ConfigurationProperty("name", IsRequired = true)]
public string Name
{
get { return (string)this["name"]; }
set { this["name"] = value; }
}
[ConfigurationProperty("IsochroneServicesTestImbrique", IsRequired = true)]
[ConfigurationCollection(typeof(CollectionIsochrone), AddItemName = "add")]
public CollectionIsochrone IsochroneServicesImbrique
{
get { return (CollectionIsochrone)this["IsochroneServicesTestImbrique"]; }
set { this["IsochroneServicesTestImbrique"] = value; }
}
}
public class CollectionIsochrone : ConfigurationElementCollection
{
public void Add(ProviderElement element)
{
base.BaseAdd(element);
}
protected override ConfigurationElement CreateNewElement()
{
return new IsochroneElement();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((IsochroneElement)element).Name;
}
public IsochroneElement this[int index]
{
get { return (IsochroneElement)BaseGet(index); }
set
{
if (BaseGet(index) != null)
{
BaseRemoveAt(index);
}
BaseAdd(index, value);
}
}
public new IsochroneElement this[string Name]
{
get { return (IsochroneElement)BaseGet(Name); }
}
public int IndexOf(IsochroneElement element)
{
return BaseIndexOf(element);
}
protected override void BaseAdd(ConfigurationElement element)
{
BaseAdd(element, false);
}
}
public class IsochroneElement : ConfigurationElement
{
[ConfigurationProperty("name", IsRequired = true)]
public string Name
{
get { return (string)this["name"]; }
set { this["name"] = value; }
}
[ConfigurationProperty("path", IsRequired = true)]
public string Path
{
get { return (string)this["path"]; }
set { this["path"] = value; }
}
}
Thanks for your help
You are getting that error because you are missing the declaration for IsochroneServicesTestImbrique in your <configSections> section. Also, at least one class must inherit from ConfigurationSection. See the example here.

Orchard Content Type is null

i am new in orchard module development.i create a module.when i try to save data.
i use this code fore save data
public ActionResult Create(FormCollection input)
{
var product = contentManager.New<ProductPart>("Product");
product.EmployeeName = input["EmployeeName"];
product.EmployeeFathersName = input["EmployeeFathersName"];
product.DOB = Convert.ToDateTime(input["DOB"]);
product.Email = input["Email"];
product.Address = input["Address"];
product.JoiningDate = Convert.ToDateTime(input["JoiningDate"]);
if (!ModelState.IsValid)
{
return View(product);
}
contentManager.Create(product);
return RedirectToAction("Index");
}
this class i use in Model
public class ProductRecord:ContentPartRecord
{
public virtual string EmployeeName { get; set; }
public virtual string EmployeeFathersName { get; set; }
public virtual DateTime DOB { get; set; }
public virtual string Email { get; set; }
public virtual string Address { get; set; }
public virtual DateTime JoiningDate { get; set; }
}
public class ProductPart : ContentPart<ProductRecord>
{
/*
public int Id
{
get { return Record.Id; }
set{Record.Id = value;}
}
*/
[Required]
public string EmployeeName
{
get { return Record.EmployeeName; }
set { Record.EmployeeName = value; }
}
[Required]
public string EmployeeFathersName
{
get { return Record.EmployeeFathersName; }
set { Record.EmployeeFathersName = value; }
}
[Required]
public DateTime DOB
{
get { return Record.DOB; }
set { Record.DOB = value; }
}
[Required]
public string Email
{
get { return Record.Email; }
set { Record.Email = value; }
}
[Required]
public string Address
{
get { return Record.Address; }
set { Record.Address = value; }
}
[Required]
public DateTime JoiningDate
{
get { return Record.JoiningDate;}
set { Record.JoiningDate = value; }
}
}
i use content type "Product" but when it goes orchard ContentCreateExtension in belows method
public static T New<T>(this IContentManager manager, string contentType) where T : class, IContent {
var contentItem = manager.New(contentType);
if (contentItem == null)
return null;
var part = contentItem.Get<T>();
if (part == null)
throw new InvalidCastException();
return part;
}
here i face var part is null that means it content part is null.
please help me....
Have you setup your migrations class?
i.e.
public class Migrations : DataMigrationImpl {
public int Create() {
SchemaBuilder.CreateTable("ProductRecord",
table => table
.ContentPartRecord()
.COLUMNS NEED TO BE SPECIFIED
);
ContentDefinitionManager.AlterTypeDefinition("Forum",
cfg => cfg
.WithPart("ProductPart")
.WithPart("CommonPart")
);
Also have you setup your repository?
i.e.
public class ProductPartHandler : ContentHandler {
public ProductPartHandler(IRepository<ProductPartRecord> repository) {
Filters.Add(StorageFilter.For(repository));
}
In addition to the Nicholas answer, I want to mention, that missing driver for the ProductPart can cause such error. Make sure, that you have at least empty driver defined.
public class ProductPartDriver : ContentPartDriver<ProductPart> {}
Just went through a similar situation, be sure that the handler class is declared as public.

Resources