Map DTO to Entity - c#

These are my Entities: In this scenario, each user can make a Post. Each post can have a list of Items and each item can have a list of users that Tagged in it.
public class Post
{
public int Id { get; set; }
public int UserId { get; set; }
public string Body { get; set; }
public int LikeCount { get; set; }
public PostStatuses Status { get; set; }
[ForeignKey("UserId")]
public User User { get; set; }
public List<PostItem> PostItems { get; set; }
public Post()
{
PostItems = new List<PostItem>();
}
}
public class PostItem
{
public int Id { get; set; }
public int PostId { get; set; }
public long AttachmentId { get; set; } // Refer to CDN file Id
[ForeignKey("PostId")]
public Post Post { get; set; }
public List<PostItemTag> TaggedUsers { get; set; }
}
public class PostItemTag
{
public int PostItemId { get; set; }
public int TaggedUserId { get; set; }
public int X { get; set; }
public int Y { get; set; }
[ForeignKey("PostItemId")]
public PostItem PostItem { get; set; }
[ForeignKey("TaggedUserId")]
public User User { get; set; }
}
These are my DTOs:
public class CreatePostRequestDTO
{
public int UserId { get; set; }
public string Body { get; set; }
public List<PostItemDTO> PostItems { get; set; }
}
public class PostItemDTO
{
public long AttachmentId { get; set; }
public List<PostItemTagDTO> TaggedUsers { get; set; }
}
public class PostItemTagDTO
{
public int UserId { get; set; }
public int X { get; set; }
public int Y { get; set; }
}
And this is my API:
public async Task<BaseResponseDTO<bool>> CreatePost(CreatePostRequestDTO createPostRequestDTO)
{
Post post = new Post()
{
Body = createPostRequestDTO.Body,
Status = PostStatuses.Posted,
UserId = createPostRequestDTO.UserId,
};
post.Mentions = createPostRequestDTO.Mentions.Select(x => new PostMention()
{
Post = post,
UserId = x,
}).ToList();
post.PostItems = createPostRequestDTO.PostItems.Select(x => new PostItem()
{
AttachmentId = x.AttachmentId,
Post = post,
PostAttachmentType = x.PostAttachmentType,
TaggedUseres = x.TaggedUseres.Select(c => new PostItemTag()
{
UserId = c.UserId,
X = c.X,
Y = c.Y,
PostItemId = ? // My problem is here.
}).ToList(),
}).ToList();
...
}
How can I solve it?
Edit:
Some extra code removed.
Edit2:
And also some extra descriptions removed.

For model binding with Automapper, follow steps below:
Install package AutoMapper and AutoMapper.Extensions.Microsoft.DependencyInjection
Add services.AddAutoMapper(typeof(Startup)); to Startup.cs
Add ModelProfile.cs like
public class ModelProfile: Profile
{
public ModelProfile()
{
CreateMap<CreatePostRequestDTO, Post>();
CreateMap<PostItemDTO, PostItem>();
CreateMap<PostItemTagDTO, PostItemTag>();
}
}
UseCase
public class HomeController : Controller
{
private readonly IMapper _mapper;
private readonly ApplicationDbContext _context;
public HomeController(IMapper mapper
, ApplicationDbContext context)
{
_mapper = mapper;
_context = context;
}
public async Task<IActionResult> Index()
{
CreatePostRequestDTO createPostRequestDTO = new CreatePostRequestDTO {
Body = "B1",
UserId = 1,
PostItems = new List<PostItemDTO> {
new PostItemDTO { AttachmentId = 1, TaggedUsers = new List<PostItemTagDTO>{
new PostItemTagDTO{ UserId = 1, X = 1, Y= 11 }
} }
}
};
var post = _mapper.Map<Post>(createPostRequestDTO);
await _context.AddAsync(post);
await _context.SaveChangesAsync();
return View();
}
}

Related

How can I make Post, Put , Delete requests from fake api with RestSharp? I am getting Json Deserialize error

public class ProductViewModel
{
public int id { get; set; }
public string title { get; set; }
public string description { get; set; }
public int price { get; set; }
public double discountPercentage { get; set; }
public double rating { get; set; }
public int stock { get; set; }
public string brand { get; set; }
public string category { get; set; }
public string thumbnail { get; set; }
public List<string> images { get; set; }
}
public class RootViewModel
{
public ProductViewModel[] Products { get; set; }
public int total { get; set; }
public int skip { get; set; }
public int limit { get; set; }
}
public ProductClient()
{
_url = "https://dummyjson.com/products/";
var options = new RestClientOptions(_url);
_client = new RestClient(options);
}
public async Task Delete(int id)
{
var request = new RestRequest()
.AddQueryParameter<int>("Id", id);
// https://jsonplaceholder.typicode.com/users?id=12
await _client.DeleteAsync(request);
}
ProductController
[HttpDelete]
public async Task<IActionResult> Deleted(int id)
{
var response = await _client.Delete(id);
return Ok(response);
}
Fake API JSON URL : https://dummyjson.com/products
I tried everything since yesterday, but I couldn't. I'm trying to pull post put and delete operations from fake api to my own api, but I can't.
There is an example that I tried to delete above, but I couldn't manage to write a method for the current post and put.

JSONpatch to remove item from ICollection

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?

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);
}

How to Manually mapa viewmodel with lists to dto

I'm new to backend development, having some trouble mapping a viewmodel to dto that has a list.
Can you help me figure out whats wrong with the mapper. The result is coming in correct from the dto. I have a list of 7 items. When it maps to the view they are gone.
Here is the viewmodel
public class StatisticsViewModel : BaseViewModel
{
public string StartDate { get; set; }
public string EndDate { get; set; }
public string ProviderId { get; set; }
public List<StatisticsTotalsViewModel> Totals { get; set; } = new List<StatisticsTotalsViewModel>();
public List<StatisticsProvidersViewModel> Providers { get; set; } = new List<StatisticsProvidersViewModel>();
}
public class StatisticsTotalsViewModel
{
public string PayerName { get; set; }
public string PayerType { get; set; }
public short Status { get; set; }
public int TotalCount { get; set; }
public decimal TotalBalance { get; set; }
}
Heres the dto
public class StatisticsDto
{
public string StartDate { get; set; }
public string EndDate { get; set; }
public string ProviderId { get; set; }
public List<StatisticsTotalsDto> Totals { get; set; } = new List<StatisticsTotalsDto>();
public List<StatisticsProvidersDto> Providers { get; set; } = new List<StatisticsProvidersDto>();
}
public class StatisticsTotalsDto
{
public string PayerName { get; set; }
public string PayerType { get; set; }
public short Status { get; set; }
public int TotalCount { get; set; }
public decimal TotalBalance { get; set; }
}
Here's the mapper
public static StatisticsViewModel MapToView(StatisticsDto dto)
{
var viewmodel = new StatisticsViewModel();
viewmodel.StartDate = dto.StartDate;
viewmodel.EndDate = dto.EndDate;
viewmodel.ProviderId = dto.ProviderId;
var dtoTotals = new List<StatisticsTotalsDto>();
var totals = new List<StatisticsTotalsViewModel>();
foreach (var item in dtoTotals)
{
var totalsModel = new StatisticsTotalsViewModel();
item.PayerName = totalsModel.PayerName;
item.PayerType = totalsModel.PayerType;
item.Status = totalsModel.Status;
item.TotalBalance = totalsModel.TotalBalance;
item.TotalCount = totalsModel.TotalCount;
totals.Add(totalsModel);
}
viewmodel.Totals = totals;
return viewmodel;
}
Problem in this line. Instead
var dtoTotals = new List<StatisticsTotalsDto>();
You need to receive list of StatisticsTotalsDto, instead of create new empty list
var dtoTotals = dto.Totals;
You can try Automapper.
Say for example:
public static StatisticsViewModel MapToView(StatisticsDto dto)
{
Mapper.Initialize(cfg => cfg.CreateMap<StatisticsDto, StatisticsViewModel>());
var ViewModel = Mapper.Map<StatisticsViewModel>(dto);
return viewModel;
}
Take a look at here to know more about Automapper. You can also check here and here if you face problem mapping list items.
P.S Don't forget to include Automapper to your project and add using Automapper() at the top where you are using it

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