Hi I have class to sen via ria service.
class look like
[DataContract]
public partial class AttributeNode
{
[DataMember]
[Key]
public int Uid { get; set; }
public AttributeNode()
{
this.Children = new List<String>();
}
private String text;
[DataMember]
public String Text
{
get
{
return text;
}
set
{
text = value;
this.Uid = text.GetHashCode();
}
}
[DataMember]
[Include]
[Association("AttributeNode_AttributeNode", "Uid", "Uid")]
public List<AttributeNode> Children { get; set; }
public void AddChild(AttributeNode child)
{
this.Children.Add(child);
}
}
The problem is that when I recive object to client it's not ok. It always as a Children contain itself. Problem is on List of same type. Help?
Tnx!!
I suppose this is some kind of parent-child tree structure.
The Association tag is used to say "this key" and "other key".
Your AttributeNode class needs a Id property to tell which its parent.
You'd need
[Key]
public int Uid { get; set; }
public int ParentUid { get; set; }
[Include]
[Association("AttributeNode_AttributeNode", "Uid", "ParentUid")]
public List<AttributeNode> Children { get; set; }
Related
I have an AppService solution with the following Classes and i want to map from the SourceObject to the DestinationObject
Source Classes
public class SourceObject
{
public string Id { get; set; }
public string Name { get; set; }
public JsonApiSerializer.JsonApi.Relationship<SourceChildObject[]> childObjects { get; set; }
}
public class SourceChildObject
{
public string Id { get; set; }
public string type { get; set; }
}
Destination Classes
public class DestinationObject
{
public string Id { get; set; }
public string Name { get; set; }
public JsonApiSerializer.JsonApi.Relationship<DestinationChildObject[]> childObjects { get; set; }
}
public class DestinationChildObject
{
public string Id { get; set; }
public string type { get; set; }
}
Auto mapper is setup in the sartup class
services.AddAutoMapper(typeof(EntityMappingProfile));
And my mapping class loos like this
public class EntityMappingProfile : Profile
{
public EntityMappingProfile()
{
CreateMap<SourceObject, DestinationObject>();
CreateMap<Relationship<SourceChildObject[]>, Relationship<DestinationChildObject[]>>();
}
}
When i execute the solution all fields are mapped apart form the array field of type JsonApiSerializer.JsonApi.Relationship. The destination field is null. What am i doing wrong?
You forgot about creating a map between SourceChildObject and DestinationChildObject. Add this line to your EntityMappingProfile.
CreateMap<SourceChildObject, DestinationChildObject>();
And one more thing, when you are mapping generic types, you can enable mapping for all types with:
CreateMap(typeof(Relationship<>), typeof(Relationship<>));
instead of creating a map with concrete use case of a generic type.
I'm making a task management tool using AngularJS for the frontend and ASP.NET WEB API 2 for the backend. I have two entities in the database, a "Task" and a "Type". Each task has one type associated. The user fills a form when he can create a new task, and he has to select a type for that task.
Here's the C# code:
// KBTM_Task.cs file
public class KBTM_Task
{
public int ID { get; set; }
public string TaskID { get; set; } // User defined ID
public string Title { get; set; }
public string Description { get; set; }
}
// KBTM_Type.cs file
public class KBTM_Type
{
public int ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
So my question is: how do I "connect" the two in the database? What I mean is, let's say I want to POST data to the database. I have to make two POSTs, right? One for the Task and one for the Type, since they're two separate entities.
But since they're stored with two different IDs, how do I know that a certain task has a certain type? In other words, if I send a GET request to KBTM_Task, how do I get the type of that task?
Modify your KBTM_Task entity to include the Type Id and foreign key relationship
public class KBTM_Task
{
public int ID { get; set; }
public string TaskID { get; set; } // User defined ID
public string Title { get; set; }
public string Description { get; set; }
public int TypeID { get; set; }
[ForeignKey("TypeID")]
public virtual KBTM_Type Type { get; set; }
}
This way when you get the data from the API your task object will already include the key ("TypeID") that can be updated and related object ("Type") that you can access its properties (Name, Description, ...).
When you update TypeID on the client object (model) you can simply push the updated task object to the API using $http.put() to handle the database update.
1) Add foreign key using fluent api (or data annotation)
// KBTM_Task.cs file
public class KBTM_Task
{
public int ID { get; set; }
public string TaskID { get; set; } // User defined ID
public string Title { get; set; }
public string Description { get; set; }
public int KBTM_TypeID {get;set}
public virtual KBTM_Type {get; set}
}
// KBTM_Type.cs file
public class KBTM_Type
{
public int ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public KBTM_Task KBTM_Task { get; set;}
}
Add the following in the class inheriting from DbContext
public class KbtmContext : DbContext
{
...
//public virtual DbSet<KBTM_Task> KbtmTasks {get; set;}
...
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// Configure KBTM_TypeID as FK for KBTM_Task
modelBuilder.Entity<KBTM_Task>()
.HasRequired(k => k.KBTM_Type)
.WithRequiredPrincipal(ad => ad.KBTM_Task);
}
}
2) If exposing the entity class in API response or request then you need to exclude navigation property from being serialized.
// KBTM_Task.cs file
public class KBTM_Task
{
...
[JsonIgnore]
public virtual KBTM_Type Type { get; set; }
}
To use the [JsonIgnore] atttribute use Install-Package Newtonsoft.Json in package manager console.(One of the popular solutions to manage serialization)
When I build my model to be returned by WCF RIA Services to silverlight, the list properties are not shown in the silverlight client.
Class:
public class Batch
{
[DataMember]
public DateTime Time { get; set; }
[DataMember]
public List<BasicInfoModel> Accepted { get; set; }
[DataMember]
public List<BasicInfoModel> UnAccepted { get; set; }
}
public class Batch
{
[Key]
[DataMember]
public int Id { get; set; }
[DataMember]
public string Name { get; set; }
}
When in the client, it seems the Lists are not generated, for example, this is my loaded callback event:
private void Callback(LoadOperation<Batch> loadOperation)
{
//there is no such property as `Accepted`
var acceptedList = loadOperation.Entities.FirstOrDefault().Accepted;
}
Am I doing something wrong?
I suppose, you've missed DataContract attribute, e.g.
[DataContract]
public class Batch
{
[DataMember]
public DateTime Time { get; set; }
[DataMember]
public List<BasicInfoModel> Accepted { get; set; }
[DataMember]
public List<BasicInfoModel> UnAccepted { get; set; }
}
http://msdn.microsoft.com/en-us/library/ms733127.aspx
I would like a DomainService as follows:
[EnableClientAccess]
public class FamilyService : DomainService
{
public IQueryable<Person> GetPeople() // for the time being fake out a set of people
{
var people = new[]{ new Person(), ... };
return people.AsQueryable();
}
}
The Person class should be simple enough:
public class Person
{
[Key]
public Guid Id { get; set; }
public Person Parent { get; set; }
public String Name { get; set; }
public Person[] Children { get; set; }
}
In the Silverlight client, the Person class that is generated does not include the Parent or Children properties. What am I missing?
(Perhaps I should point out that while this is obviously a mock example, I am planning on using a loosely coupled approach, that this mimics. In fact most of my data doesn't reside in a database at all A significant majority of the RIA samples use an end-to-end parity of model from the database to the UI, which is not an option in my case.)
Try adding the [Include] attribute to the Parent & Children properties.
public class Person
{
[Key]
public Guid Id { get; set; }
[Include]
public Person Parent { get; set; }
public String Name { get; set; }
[Include]
public Person[] Children { get; set; }
}
If the Person class is coming out of the DB (in your real world app) and you are using EF, then you need to force them to be loaded eagerly, using the .Include() method.
I query data with NHibernate in the server side, then I create a WCF service which is the one that publishes these NHibernate objects, they are correctly serialized to Silverlight, I modify them in my application but when I send them back to the server they get serlialized again, and Generic Lists get converted to Array so I cannot modify them anymore in the server side...
this is my class definition
public class BIMenu
{
public virtual Guid ID { get; set; }
public virtual String DisplayName { get; set; }
public virtual String ProgramToCall { get; set; }
public virtual IList<BIMenu> Children { get; set; }
public virtual IList<BISecurityProfile> SecurityProfiles { get; set; }
public virtual Boolean IsApplication
{
get
{
if (Children.Count < 1 && ProgramToCall != null)
return true;
return false;
}
}
public virtual Boolean IsFolder
{
get
{
return !IsApplication;
}
}
public BIMenu()
{
Children = new List<BIMenu>();
SecurityProfiles = new List<BISecurityProfile>();
}
}
and this is my contract
[ServiceContract]
public interface IBISecurityService
{
[OperationContract]
BIMenu GetMenu(String Name);
[OperationContract]
void SaveMenu(BIOnline.Model.BIMenu Menu);
[OperationContract]
void DeleteMenu(BIOnline.Model.BIMenu Menu);
}
Is your BIMenu class marked [DataContract]? I would expect it to be:
[DataContract]
public class BIMenu
{
[DataMember]
public virtual Guid ID { get; set; }
[DataMember]
public virtual String DisplayName { get; set; }
[DataMember]
public virtual String ProgramToCall { get; set; }
[DataMember]
public virtual IList<BIMenu> Children { get; set; }
[DataMember]
public virtual IList<BISecurityProfile> SecurityProfiles { get; set; }
Also, if your IList<BIMenu> Children and IList<BISecurityProfile> SecurityProfiles properties are being set to instances of the Array type, then that is perfectly valid, since Array implements IList. If you want to keep them as actual List<> instances, then just define the properties as List<> instead of IList<>, like this:
// Defined as actual Lists, not IList interfaces.
[DataMember]
public virtual List<BIMenu> Children { get; set; }
[DataMember]
public virtual List<BISecurityProfile> SecurityProfiles { get; set; }