JSONpatch to remove item from ICollection - c#

I am following TPH in my feature and I have these models which are mapped to tables in database
public class HrFormV1
{
public HrFormV1()
{
...
}
public HrFormV1(HrFormV1DTO form)
{
...
}
public string Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string OrganizationId { get; set; }
public Organizations Organization { get; set; }
public List<HrFormSectionV1> FormSections { get; set; }
public DateTime Created { get; set; }
public DateTime Updated { get; set; }
public HrFormType Type { get; set; }
public string CreatedById { get; set; }
public User CreatedBy { get; set; }
public static void DefineDbModel(ModelBuilder modelBuilder)
{
modelBuilder.Entity<HrFormV1>().Property(f => f.Id).ValueGeneratedOnAdd();
}
}
public class HrFormSectionV1
{
public string Id { get; set; }
public int Index { get; set; }
public string FormId { get; set; }
public HrFormV1 Form { get; set; }
public HrFormSectionV1()
{
...
}
public HrFormSectionV1(HrFormSectionV1DTO section)
{
...
BuildingComponents = section.BuildingComponents.Select(b => #switch[b.GetType()](b)).ToList();
}
public ICollection<HrBuildingComponentsV1> BuildingComponents { get; set; }
public static void DefineDbModel(ModelBuilder modelBuilder)
{
modelBuilder.Entity<HrFormSectionV1>(entity =>
{
entity.Property(e => e.Id).ValueGeneratedOnAdd();
});
}
private static readonly Dictionary<Type, Func<HrBuildingComponentV1DTO,HrBuildingComponentsV1>> #switch = new Dictionary<Type, Func<HrBuildingComponentV1DTO,HrBuildingComponentsV1>> {
{ typeof(HrTextBuildingComponentV1DTO), b => new HrTextBuildingComponentV1((HrTextBuildingComponentV1DTO)b) },
};
}
{
public class HrBuildingComponentsV1
{
public HrBuildingComponentsV1() { }
public HrBuildingComponentsV1(HrBuildingComponentV1DTO buildingComponent)
{
Id = buildingComponent.Id;
Label = buildingComponent.Label;
Type = buildingComponent.Type;
Index = buildingComponent.Index;
IsFilter = buildingComponent.IsFilter;
SectionId = buildingComponent.SectionId;
}
public string Id { get; set; }
public string Label { get; set; }
public BuildingComponentType Type { get; set; }
public int? Index { get; set; }
public bool IsFilter { get; set; }
public string SectionId { get; set; }
public HrFormSectionV1 Section { get; set; }
}
public enum BuildingComponentType
{
...
}
}
public class HrTextBuildingComponentV1 : HrBuildingComponentsV1
{
public string Value { get; set; }
public HrTextBuildingComponentV1() : base() { }
public HrTextBuildingComponentV1(HrTextBuildingComponentV1DTO buildingComponentdto)
: base(buildingComponentdto) {
Value = buildingComponentdto.Value;
}
}
So now I have following tables
HrFormV1
HrFormSectionV1
HrBuildingComponentsV1 (TPH) here
I am using Asp.Net core JSON patch to update the records. Add and replace works fine but when I do remove then I get an error
I am removing using this json
{
"op": "remove",
"path": "/formsections/0/buildingcomponents/0"
}
Here I get an error that SectionId cannot be NULL. Can someone guide me here?

Related

Merge entities in Entity Framework 6

I have these entities which represent Menu and Labels SQL tables:
public class Menu
{
public int IdMenu { get; set; }
public int IdLabel { get; set; }
}
public class Label
{
public int IdLabel { get; set; }
public string Value { get; set; }
}
In a controller I have this method:
public IActionResult GetAll()
{
var menu = _service.GetAll();
var model = _mapper.Map<IList<MenuModel>>(menu);
return Ok(model);
}
but obviously, it gives me only IdMenu and IdLabel for each menu item.
What should I do to let it give me IdMenu and Value of Label?
Update n. 1:
Entities:
public class MenuPadre_EL
{
[Key]
public int IdMenuPadre { get; set; }
public int IdEtichetta { get; set; }
public string Icona { get; set; }
public MenuPadreUtente_EL menuPadreUtente { get; set; }
}
public class MenuPadreUtente_EL
{
public int IdMenuPadreUtente { get; set; }
public int IdUtente { get; set; }
public int IdMenuPadre { get; set; }
public MenuPadre_EL menuPadre { get; set; }
}
DataContext:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Etichetta>().HasKey(e => new { e.IdEtichetta, e.Lingua });
modelBuilder.Entity<MenuPadreUtente_EL>().HasKey(m => new { m.IdMenuPadre, m.IdUtente });
modelBuilder.Entity<MenuPadre_EL>()
.HasOne(mpu => mpu.menuPadreUtente)
.WithOne(mp => mp.menuPadre)
.HasForeignKey<MenuPadreUtente_EL>(mpu => mpu.IdMenuPadre);
}
Model:
public class MenuPadreUtente_ELModel
{
public int IdMenuPadreUtente { get; set; }
public int IdMenuPadre { get; set; }
public int IdUtente { get; set; }
public string Etichetta { get; set; }
public MenuPadre_EL menuPadre { get; set; }
}
API Output:
[
{
"idMenuPadreUtente": 1,
"idMenuPadre": 1,
"idUtente": 1,
"etichetta": null,
"menuPadre": null
}
]
why menuPadre is null?
You can do that as bellow:
[HttpGet]
public IActionResult GetAll()
{
var menu = menueList();
var lable = lableList();
var model = (from _menue in menu
join _lable in lable
on _menue.IdLabel equals _lable.IdLabel
select new
{
IdMenu = _menue.IdMenu,
Value = _lable.Value,
}).ToList();
return Ok(model);
}

AutoMapper - Nested Collections Not Getting Mapped

I have an ASP.NET Core application with the following entity classes:
public class CustomerEntity : IAuditableEntity {
private readonly List<AddressEntity> _addresses = new List<AddressEntity>();
public CustomerEntity() {
Id = default;
IsPremierCustomer = false;
}
public int Id { get; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int CustomerTypeId { get; set; }
public string EmailAddress { get; set; }
public bool IsPremierCustomer { get; private set; }
public CustomerTypeEntity CustomerType { get; }
public IReadOnlyCollection<AddressEntity> Addresses => _addresses;
public void AddAddress(AddressEntity address) {
_addresses.Add(address);
}
public void SetPremierStatus(bool premierCustomer) {
if (IsPremierCustomer == premierCustomer) {
return;
}
IsPremierCustomer = premierCustomer;
}
}
public class CustomerTypeEntity {
public CustomerTypeEntity(string description) {
Id = default;
Description = description;
}
public int Id { get; }
public string Description { get; }
}
public class AddressEntity : IAuditableEntity {
public AddressEntity() {
Id = default;
}
public int Id { get; }
public int CustomerId { get; set; }
public int AddressTypeId { get; set; }
public string Line1 { get; set; }
public string Line2 { get; set; }
public string Line3 { get; set; }
public string Province { get; set; }
public string PostalCode { get; set; }
public int CountryId { get; set; }
public AddressTypeEntity AddressType { get; }
public CountryEntity Country { get; }
}
public class AddressTypeEntity {
public AddressTypeEntity(string description) {
Id = default;
Description = description;
}
public int Id { get; }
public string Description { get; }
}
public class CountryEntity {
public CountryEntity(int numericCode, string alpha2Code, string alpha3Code, string englishName, string frenchName) {
NumericCode = numericCode;
Alpha2Code = alpha2Code;
Alpha3Code = alpha3Code;
EnglishName = englishName;
FrenchName = frenchName;
}
public int NumericCode { get; }
public string Alpha2Code { get; }
public string Alpha3Code { get; }
public string EnglishName { get; }
public string FrenchName { get; }
}
Following are the corresponding DTO classes:
public class CustomerWithAddressDTO {
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string CustomerType { get; set; }
public string EmailAddress { get; set; }
public bool IsPremierCustomer { get; set; }
public IEnumerable<AddressDTO> Addresses { get; set; }
}
public class AddressDTO {
public int Id { get; set; }
public string AddressType { get; set; }
public string Line1 { get; set; }
public string Line2 { get; set; }
public string Line3 { get; set; }
public string Province { get; set; }
public string PostalCode { get; set; }
public string Country { get; set; }
}
I have mapping defined as follows:
public class CustomerWithAddressProfile : Profile {
public CustomerWithAddressProfile() {
CreateMap<AddressEntity, AddressDTO>()
.ForMember(dest => dest.AddressType, src => src.MapFrom(x => x.AddressType.Description))
.ForMember(dest => dest.Country, src => src.MapFrom(x => x.Country.Alpha3Code));
CreateMap<CustomerEntity, CustomerWithAddressDTO>()
.ForMember(dest => dest.CustomerType, src => src.MapFrom(x => x.CustomerType.Description))
.ForMember(dest => dest.Addresses, src => src.MapFrom(x => x.Addresses));
}
}
In my code, I fetch the customers including addresses from database and map as below:
[HttpGet]
public ActionResult<IEnumerable<CustomerWithAddressDTO>> GetAllCustomers() {
var customers = _customerWithAddressRepository.FindAll();
var customerDTOs = _mapper.Map<ICollection<CustomerEntity>, IEnumerable<CustomerDTO>>(customers);
return Ok(customerDTOs);
}
The customers are getting populated (mapped) correctly. But the nested addresses are never getting populated. I have searched for a solution but still no luck. Does anyone has any thoughts.
Thanks in advance.

C# how to get a datatable from IQueryable<T> including multi object lists

I have a IQueryable list, which includes some objects lists. I want get a DataTable from the list and shows as a table.
IQuerable<Load> loads;
public class Load
{
public int LoadID { get; set; }
public string CustomerName { get; set; }
public List<PickUp> ShipperPickUps { get; set; }
public List<Deliver> ConsigneeDelivers { get; set; }
public List<string> ReferenceNumbers { get; set; }
...
}
public class PickUp
{
public int? LoadID { get; set; }
public int? ShipperID { get; set; }
public string Name { get; set; }
public string Address { get; set; }
...
}
public class Deliver
{
public int? LoadID { get; set; }
public int? ConsigneeID { get; set; }
public string Name { get; set; }
public string Address { get; set; }
...
}
Now the data like this
IQuery<Load>:
{
{
LoadID:1,
LoadNumber:"0001",
CustomerName:"Customer1",
Pickup:
{
{LoadID:1,ShipperID:1,Name:"Shipper1"...},
{LoadID:1,ShipperID:2,Name:"Shipper2"...},
...
}
Deliver:
{
{LoadID:1,ConsigneeID :1,Name:"Consignee1"...},
{LoadID:1,ConsigneeID :2,Name:"Consignee2"...},
...
}
ReferenceNumbers:
{
"Reference1",
"Reference2",
...
}
},
{
LoadID:2,
LoadNumber:"0002",
CustomerName:"Customer2",
Pickup:
{
{LoadID:2,ShipperID:3,Name:"Shipper3"...},
{LoadID:2,ShipperID:4,Name:"Shipper4"...},
...
}
Deliver:
{
{LoadID:2,ConsigneeID :3,Name:"Consignee3"...},
{LoadID:2,ConsigneeID :4,Name:"Consignee4"...},
...
}
ReferenceNumbers:
{
"Reference3",
"Reference4",
...
}
},
...
}
I defined a class:
public class ExportData
{
public int LoadID { get; set; }
public string LoadNumber { get; set; }
public string CustomerName { get; set; }
public string ShipperName{ get; set; }
public string DeliverName{ get; set; }
public string ReferenceNumber { get; set; }
...
}
I want get another IQuerable list or Datatable like this:
IQuerable<ExportData>:
{
{
LoadID:1,
LoadNumber:"0001",
CustomerName:"Customer1",
ShipperName:"Shipper1",
DeliverName:"Consignee1",
ReferenceNumber:"Reference1"
...
},
{
LoadID:1,
LoadNumber:"0001",
CustomerName:"Customer2",
ShipperName:"Shipper2",
DeliverName:"Consignee2",
ReferenceNumber:"Reference2"
...
},
{
LoadID:2,
LoadNumber:"0002",
CustomerName:"Customer3",
ShipperName:"Shipper3",
DeliverName:"Consignee3",
ReferenceNumber:"Reference3"
...
},
{
LoadID:2,
LoadNumber:"0002",
CustomerName:"Customer4",
ShipperName:"Shipper4",
DeliverName:"Consignee4",
ReferenceNumber:"Reference4"
...
},
...
}
What is the best way to do that?
I tried
IQueryable<ExportData> exportData;
exportData = loads
.Select(load => new ExportData
{
LoadID = load.LoadID,
LoadNumber = load.LoadNumber,
CustomerName = load.CustomerName,
...
});
But I have no idea about the Object lists. Any suggestion?

AutoMapper Map nested ICollection

I want to map one call to another, but I got exception all the time /An exception of type 'AutoMapper.AutoMapperMappingException' occurred in AutoMapper.dll but was not handled in user code/
Here are my Source Classes:
public class Snippet
{
public Snippet()
{
this.Labels = new HashSet<Label>();
this.Commennts = new HashSet<Comment>();
}
public int Id { get; set; }
[Required]
public string Title { get; set; }
public string Description { get; set; }
[Required]
public string Code { get; set; }
public int LanguageId { get; set; }
public string UserId { get; set; }
public DateTime CreatedOn { get; set; }
public ICollection<Label> Labels { get; set; }
public ICollection<Comment> Commennts { get; set; }
public virtual Language Language { get; set; }
public virtual ApplicationUser User { get; set; }
}
public class Label
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Snippet> Snippets { get; set; }
}
Here are my Destination classes:
public class SnippetModels
{
public class Output
{
public int Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public DateTime CreatedOn { get; set; }
public string Code { get; set; }
public string LanguageName { get; set; }
public string UserUsername { get; set; }
public IEnumerable<LabelModels.Output> Labels { get; set; }
//TODO Comments Labels
}
}
public class LabelModels
{
public class Output
{
public int Id { get; set; }
public string Name { get; set; }
}
}
public class HomeViewModel
{
public IEnumerable<SnippetModels.Output> Snippets { get; set; }
public IEnumerable<LabelModels.Output> Labels { get; set; }
}
And finally I tied everything that pop up in my mind but no success:
Mapper.CreateMap<Snippy.Models.Label, LabelModels.Output>();
Mapper.CreateMap<IEnumerable<Snippy.Models.Label>, IEnumerable<LabelModels.Output>>();
Mapper.CreateMap<Snippy.Models.Snippet, SnippetModels.Output>()
.ForMember(dest => dest.Labels, opt => opt.MapFrom(src => src.Labels));
Mapper.CreateMap<IEnumerable<Snippy.Models.Snippet>, IEnumerable<SnippetModels.Output>>();
var newestSnippetsDatabase = this.Data.Snippets
.All()
.OrderByDescending(s => s.CreatedOn)
.Take(HomeVisibleItemsCount)
.Select(s => s)
.ToList();
var homeScreenView = new HomeViewModel
{
Snippets = Mapper.Map<IEnumerable<SnippetModels.Output>>(newestSnippetsDatabase)
};

Paging with Xamarin

I am trying to load old Instagram pictures when the user pulls the UITableView to the bottom of the screen using Xamarin. However I seem to have no clue how to do it. I got it working fine in Objective-C it just seems different in C#. Here is how I am getting the initial posts:
public void getInstagramFeed(UITableView table){
IEnumerable<Account> accounts = AccountStore.Create ().FindAccountsForService ("Instagram");
var enumerable = accounts as IList<Account> ?? accounts.ToList ();
if (enumerable.Any ()) {
Account instagram = enumerable.First ();
var instagramAccessToken = instagram.Properties ["access_token"].ToString ();
var request = new RestRequest { RootElement = "data", Resource = "/users/self/feed" };
request.AddParameter ("access_token", instagramAccessToken);
var client = new RestClient ("https://api.instagram.com/v1");
client.ExecuteAsync (request, response => {
table.InvokeOnMainThread (() => {
RootObject rootObject = JsonConvert.DeserializeObject<RootObject> (response.Content);
var dataSource = new ObservableDataSource<Datum> (rootObject.data);
dataSource.Bind (table);
});
});
}
}
Here is the bind method for my datasource:
public void Bind(Datum datum)
{
this.datum = datum;
if (this.datum == null || this.datum.caption == null)
{
this.captionLabel.Text = "";
}
else
{
this.captionLabel.Text = datum.caption.text;
}
this.pictureImage.InvokeOnMainThread (() => this.pictureImage.SetImage (
url: new NSUrl (datum.images.standard_resolution.url)
)
);
this.profileImage.InvokeOnMainThread (() => this.profileImage.SetImage (
url: new NSUrl (datum.user.profile_picture)
)
);
this.nameLabel.Text = this.datum.user == null ? "user is null" : datum.user.full_name;
}
Here is the class for my tableView:
public TableView ()
{
}
public TableView (IntPtr handle) : base(handle)
{
}
public UITableViewCell GetCell (Datum item)
{
var newCell = this.DequeueReusableCell(InstagramCell.Key)
as InstagramCell ?? InstagramCell.Create();
newCell.Bind (item);
return newCell;
}
public float GetHeightForRow (NSIndexPath indexPath)
{
return 340f;
}
Thanks for all the help before hand, sorry for the long post :)
// PS This is how I did it in OBJc:
NSDictionary *page = instagramResponse[#"pagination"];
NSString *nextPage = page[#"next_url"];
[[InstagramClient sharedClient] getPath:[NSString stringWithFormat:#"%#",nextPage] parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
instagramResponse = [responseObject mutableCopy];
[instagramResponse addEntriesFromDictionary:responseObject];
[instapics addObjectsFromArray:responseObject[#"data"]];
[self updateArrays];
[self.tableView reloadData];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Failure: %#", error);
}];
// Class for InstagramClient:
public class RootObject
{
public Pagination pagination { get; set; }
public Meta meta { get; set; }
public List<Datum> data { get; set; }
}
public class Datum
{
public object attribution { get; set; }
public List<string> tags { get; set; }
public string type { get; set; }
public object location { get; set; }
public Comments comments { get; set; }
public string filter { get; set; }
public string created_time { get; set; }
public string link { get; set; }
public Likes likes { get; set; }
public Images images { get; set; }
public List<object> users_in_photo { get; set; }
public Caption caption { get; set; }
public bool user_has_liked { get; set; }
public string id { get; set; }
public User user { get; set; }
public Videos videos { get; set; }
public override string ToString()
{
if (user == null)
{
return "User is null";
}
return user.full_name;
}
}
public class Videos
{
public LowResolution2 low_resolution { get; set; }
public StandardResolution2 standard_resolution { get; set; }
}
public class StandardResolution2
{
public string url { get; set; }
public int width { get; set; }
public int height { get; set; }
}
public class LowResolution2
{
public string url { get; set; }
public int width { get; set; }
public int height { get; set; }
}
public class User
{
public string username { get; set; }
public string website { get; set; }
public string profile_picture { get; set; }
public string full_name { get; set; }
public string bio { get; set; }
public string id { get; set; }
}
public class Caption
{
public string created_time { get; set; }
public string text { get; set; }
public From from { get; set; }
public string id { get; set; }
}
public class From
{
public string username { get; set; }
public string profile_picture { get; set; }
public string id { get; set; }
public string full_name { get; set; }
}
public class Images
{
public LowResolution low_resolution { get; set; }
public Thumbnail thumbnail { get; set; }
public StandardResolution standard_resolution { get; set; }
}
public class StandardResolution
{
public string url { get; set; }
public int width { get; set; }
public int height { get; set; }
}
public class Thumbnail
{
public string url { get; set; }
public int width { get; set; }
public int height { get; set; }
}
public class LowResolution
{
public string url { get; set; }
public int width { get; set; }
public int height { get; set; }
}
public class Likes
{
public int count { get; set; }
public List<Datum2> data { get; set; }
}
public class Datum2
{
public string username { get; set; }
public string profile_picture { get; set; }
public string id { get; set; }
public string full_name { get; set; }
}
public class Comments
{
public int count { get; set; }
public List<object> data { get; set; }
}
public class Meta
{
public int code { get; set; }
}
public class Pagination
{
public string next_url { get; set; }
public string next_max_id { get; set; }
}
I would recommend using a UiCollectionViewController for this if possible. Or nowadays preferably the equivalent in Xamarin.Forms. With UiCollectionViewController you can easily load more items as the user scrolls down

Categories

Resources