AutoMapper map additional object - c#

I have a CustomerGroupDTO with the properties:
public string Type { get; set; }
public string Code { get; set; }
public string CustomerType { get; set; }
This DTO is being used when sending the API request. As you can see, the CustomerType here is a string!
Now when the request is being processed, I'm checking if the CustomerType (ID, this is not mentioned here, but in fact, it is kind of a guid) already exists. If it doesn't exist, I'm returning a badrequest. If it exists, I'm browsing the database and find the CustomerType and collect the CustomerType Object, which consists of.
[Key]
public int Id { get; set; }
[Required]
public string ...TypeName { get; set; }
[Required]
public string ....TypeName { get; set; }
public List<...Group> ...Groups { get; set; }
Until here, everything is fine and works, but now I want to Map the CustomerGroupDTO to the CustomerGroup Object. The CustomerGroup object itself contains the following:
public string Code { get; set; }
public bool IsDynamic { get; set; }
public List<Company> Companies { get; set; }
[Required]
public CustomerType CustomerType { get; set; }
You can see, it expects a CustomerType Object and not just the string, which I do have in my DTO. So my question now is, HOW do I pass in the mapping to the CustomerType Object I have created within the POST Request. I did not find any information on how to pass in a parameter (in my case an Object) and map it to the destination. CustomerType attribute?

Related

OData EnableQuery API decorator throwing System.NullReferenceException when OrderBy certain fields

I am working with an API endpoint that allows users to make an OData query.
imports?&$top=10&$skip=0&$orderby=MemberName%20desc&$count=true
Via debugging I can see that there are 24 items in returned by the service layer but, when the controller method completes I get an error.
System.NullReferenceException: Object reference not set to an instance of an object.
This seems to occur when orderby is MemberName, which is a simple string and all the items in the results have a value for this field. If I remove the orderby or change it to another field like Created I get data returned.
The returned type is
public class MemberImportItemModel
{
public Guid Id { get; set; }
public ImportItemStatus Status { get; set; }
public DateTime Created { get; set; }
public string Creator { get; set; }
public string ConnectionExternalId { get; set; }
public ICollection<string> ConnectionTags { get; set; }
public Guid? MemberId { get; set; }
public string MemberName { get; set; }
public string ImportData { get; set; }
}
Can anyone advise?

Returning Nested Objects on .NET API using OData

I am working on a .NET API that uses OData and I am currently having issues returning nested objects back to the client.
Everything seems to be working, even if I put a break point on the Controller just before the response. I can see the Vendor object that is going to be returned with all the info has populated correctly, but when I look at the JSON response the Client received it only has primitive types and enums, every other property that is another object does not get serialized to the JSON result.
public class Vendor : IEntity
{
public virtual int Id { get; set; }
public virtual VendorAddress PrimaryAddress { get; set; }
public virtual string VendorName { get; set; }
}
public class VendorAddress : IEntity
{
public virtual int Id { get; set; }
public virtual Vendor Vendor { get; set; }
public virtual Address Address { get; set; }
}
public class Address : IEntity
{
public virtual int Id { get; set; }
public virtual string Line1 { get; set; }
public virtual string Line2 { get; set; }
public virtual string Country { get; set; }
public virtual string CountryCode { get; set; }
public virtual string City { get; set; }
public virtual string County { get; set; }
public virtual string StateProvince { get; set; }
public virtual string ZipCode { get; set; }
}
public SingleResult<Vendor> Get([FromODataUri] int key)
{
var result = _repository.Query<Vendor>().Where(a => a.Id == key);
return SingleResult.Create(result);
}
Basically I want to return the Vendor info including the PrimaryAddress/Address information on the JSON result but can't seem to figure out how to.
VendorAddress and Address are so called Navigation Properties.
You can get them by using $expand on your query.
First add a [EnableQuery] to your Get method
[EnableQuery]
public SingleResult<Vendor> Get([FromODataUri] int key)
then try a request in the form
<serviceUri>/Vendor(1)?$expand=VendorAddress
<serviceUri>/Vendor(1)?$expand=VendorAddress($expand=Address)
you'll have to add the line
config.Expand()
in your
WebApiConfig.Register(HTTPConfiguration config)
method.
Here is a example request on a test service:
http://services.odata.org/TripPinRESTierService/People('russellwhyte')?$expand=BestFriend($expand=Trips)
and some more information for reference: http://www.odata.org/odata-services/
Hope this helps.

Entity Framework Many To Many Initial in Constructor

I am getting the weirdest error. I'm using code first to initial my database. I have 2 entities that have a many to many relationship. If I attempt to initialize either ICollection in the constructor I get the following error when trying trying to use the context to add a value (initially build the database vie entity framework)
The number of members in the conceptual type 'ClubCraftManager.DataAccess.Club' does not match with the number of members on the object side type 'ClubCraftManager.Model.Models.Club'. Make sure the number of members are the same.
public class Club
{
public Club()
{
this.ClubCrafters = new List<Crafter>();
}
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public virtual Guid ClubIdGuidId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public bool IsActive { get; set; }
public Guid ClubMangerId { get; set; }
[ForeignKey("ClubMangerId")]
public virtual Crafter ClubManager { get; set; }
public virtual ICollection<Crafter> ClubCrafters { get; }
}
If I leave the classes as the following no error, but I hate not initialing Collections and or lists, leaves yourself open for null values later on....
public class Club
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public virtual Guid ClubIdGuidId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public bool IsActive { get; set; }
public Guid ClubMangerId { get; set; }
[ForeignKey("ClubMangerId")]
public virtual Crafter ClubManager { get; set; }
public virtual ICollection<Crafter> ClubCrafters { get; set; }
}
Any idea what's going on here...?

How to fully construct the newly added Entity

In my project i need to add Sales leads to the data context. The sales person user adds the leads and I need to send the email to manager for the Lead.
public partial class Lead
{
public Lead()
{
this.LeadActivities = new HashSet<LeadActivity>();
}
public long LeadID { get; set; }
public System.DateTime CreatedAt { get; set; }
public long CompanyID { get; set; }
public long ProductID { get; set; }
public long CreatedByUserID { get; set; }
public string Remarks { get; set; }
public LeadStatusEnum StatusID { get; set; }
public virtual Company Company { get; set; }
public virtual Product Product { get; set; }
public virtual User User { get; set; }
public virtual ICollection<LeadActivity> LeadActivities { get; set; }
}
[Serializable]
public partial class Person
{
public Person()
{
this.Contacts = new HashSet<Contact>();
this.Users = new HashSet<User>();
}
public long PersonID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Designation { get; set; }
public Nullable<int> Gender { get; set; }
public Nullable<int> Title { get; set; }
public int StatusID { get; set; }
public string Thumbnail { get; set; }
public string Email { get; set; }
public virtual ICollection<Contact> Contacts { get; set; }
public virtual ICollection<User> Users { get; set; }
}
In the above entity, I have property UserID that is associated to Person table through CreatedByUserID. When I add the new lead, by following code, the User field remains null. Do I need to reconstruct it? if yes then how.
Edit1
Entity Creation is done by following code
Entity = new Model.Lead
{
CreatedAt = DateTime.Now,
CreatedByUserID = SessionManagement.GeneralSession.UserDetail.UserID
};
Entity.CreatedAt = Convert.ToDateTime(txtTimestamp.Value);
Entity.CompanyID = Convert.ToInt64(ddlCompany.SelectedValue);
Entity.CreatedByUserID = Convert.ToInt64(ddlUser.SelectedValue);
Entity.ProductID = Convert.ToInt64(lstProducts.SelectedValue);
Entity.Remarks = txtRemarks.Text;
DataSource.Leads.Add(Entity);
DataSource.SaveChanges();
Virtual lazy loading only works with proxy instances. Since you're explicitly constructing your Lead entity, lazy loading of the User navigation property after inserting the entity will not work.
Instead, you should use the DbSet.Create method to new up an instance of the derived proxy type. Then perform your insert, which will attach to the context, and lazy loading will subsequently work.
Alternatively, you can use your existing POCO, perform the insert and then fetch your inserted entity as its proxy from the DbSet by using the DbSet.Find method.
You should also check and make sure your foreign key id and navigation properties are correctly mapped, since properties CreatedByUserID and User would not be automatically associated by convention.

New Model within ViewModel error on ID of 0

I have a viewmodel.
public class RegistrationViewModel
{
public RegisterModel Register { get; set; }
public Producer Producer { get; set; }
public IEnumerable<UserType> UserTypes { get; set; }
public IEnumerable<Producer> Producers { get; set; }
}
In the view, the user puts in their registration credentials and then selects a producer that they are a part of. They can also create a new producer on the page as well. However, when they do this my ModelState is invalid because the Producer doesn't have an ID field. This is a new Producer record and I shouldn't need to assign an ID before it is created in my database, right? ID is my identity field in SQL. I noticed that my scaffolded code for other domain models passes back an ID of 0 without any issues. Am I doing this correctly at all? Is this related to the viewmodel? Any help would be greatly appreciated.
Producer class:
public class Producer
{
public int ProducerID { get; set; }
public string Name { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Postal { get; set; }
public string Country { get; set; }
[DataType(DataType.PhoneNumber)]
public string Phone { get; set; }
[DataType(DataType.EmailAddress)]
public string Email { get; set; }
public string Website { get; set; }
public string CreatedBy { get; set; }
public DateTime CreatedOn { get; set; }
public string UpdatedBy { get; set; }
public DateTime? UpdatedOn { get; set; }
public Boolean Active { get; set; }
public virtual ICollection<Wine> Wines { get; set; }
}
I prefer to have a view model that is specific to the create action that doesn't have this key, although for reuse some do.
In that case, as you mentioned zero should be just fine. Ensure the key is written to the page though, check for a hidden field that has zero in it.
It is true that you do not assign an ID before inserting into the database. But the viewmodel is going to be invalid because it expects ProducerID to be filled. Try annotating the producerID field with
[Key]
public int ProducerID { get; set; }
If, however, the user selects an already existing Producer, and then that ProducerId is not associated with the registration, then you will obviously have an issue where the user is not associated with a Producer.

Categories