how set language condition with automapper? - asp.net

I receive the language through endpoint and I want to use the automap to return the same language that I received from endpoint
How can I do something like that knowing I'm using Dependency injection with IMapper
[HttpGet("Products")] public async Task<IActionResult> Get(int SectionId ,bool IsSection, [FromHeader] string lang){....}
public class MappingProfile : Profile
{
public MappingProfile( string lang )
{
CreateMap<Product, ProductDTO>()
.ForMember(dest => dest.Name, (lang== "ar") ? src => src.MapFrom(src => src.NameAr) : src => src.MapFrom(src => src.NameEn))
.ForMember(dest => dest.CountryName, (lang == "ar") ? src => src.MapFrom(src => src.Country.NameAr) : src => src.MapFrom(src => src.Country.NameEn))
.ForMember(dest => dest.HaveSection, src => src.MapFrom(src => src.Id != 0))
.ForMember(dest => dest.ByPiece, src => src.MapFrom(src => src.ProductUnit == Units.number))
.ReverseMap();
}
}
i need to do that but with automapper
List<ProductDTO> productDTOs = new();
if (products !=null)
{
foreach (var product in products)
{
var productDTO = new ProductDTO();
productDTO.Id = product.Id;
productDTO.Name = (lang == "ar") ? product.NameAr : product.NameEn;
productDTO.Price = product.Price;
productDTO.HasOffer = product.HasOffer;
productDTO.OfferPrice = product.OfferPrice;
productDTO.CountryName = (lang == "ar") ? product.Country.NameAr : product.Country.NameEn;
productDTO.ByPiece = (product.ProductUnit == Units.number) ? true : false;
productDTOs.Add(productDTO);
}
}

Personally, I think you should not put domain login inside mappings, but this will become your profile if you want:
public MappingProfile( string lang )
{
CreateMap<Product, ProductDTO>()
.ForMember(dest => dest.Name, src => src.MapFrom(x => (lang == "ar") ? x.NameAr : x.NameEn))
.ForMember(dest => dest.HaveSection, src => src.MapFrom(src => src.Id != 0))
.ForMember(dest => dest.ByPiece, src => src.MapFrom(src => src.ProductUnit == Units.number))
.ReverseMap();
}
Now you need to create a mapper with this profile.
IMapper mapper = new MapperConfiguration(x => x.AddProfile(new MappingProfle("ar"))).CreateMapper();
Now use this to map your object :)

Related

.Net Core 3.1 dynamic multiple filtering of products

Multiple checkbox filter (dynamic)
filter=blue:1,red:1,ram16gb:2,ram38gb:2
.netcore 3.1 Error: could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync(). See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.
public async Task<IActionResult> Index(SearchOption searchOption, int pageSize = 10)
{
var query = _productRepo.Query()
.Include(x => x.AttributeValues)
.Where(x => x.InActive == true);
if (!string.IsNullOrWhiteSpace(searchOption.filter))
{
var list = searchOption.filter.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries)
.Select(item =>
{
var subItems = item.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
return new SplitFilter
{
AttributeId = Convert.ToInt64(subItems[1]),
Search = subItems[0],
};
}).ToList();
if (list?.Any() == true)
{
var attr = _modelAttributeValueRepository
.GetFind(x => list.Any(j => j.Search == x.Value && j.AttributeId == x.AttributeId))
.Select(x => x.ProductId);
query = query.Where(x => attr.Contains(x.ProductId));
}
}
return View(query.ToList());
}
Try changing your code like this
var attr = _modelAttributeValueRepository
.GetFind(x => list.Any(j => j.Search == x.Value && j.AttributeId == x.AttributeId))
.Select(x => x.ProductId)
.ToList(); // add this line
query = query.Where(x => attr.Contains(x.ProductId));
You can also rewrite your query like this:
query = query.Where(x => attr.Any(z => z == x.ProductId));
This code worked.✓
public async Task<IActionResult> Index(SearchOption searchOption, int pageSize = 10)
{
var query = _productRepo.Query()
.Include(x => x.AttributeValues)
.Where(x => x.InActive == true);
if (!string.IsNullOrWhiteSpace(searchOption.filter))
{
var list = searchOption.filter.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries)
.Select(item =>
{
var subItems = item.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
return new SplitFilter
{
AttributeId = Convert.ToInt64(subItems[1]),
Search = subItems[0],
};
})
.GroupBy(x => x.AttributeId).Select(x => new { AttributeId = x.Key, List = x.Select(j => j.Search) })
.ToList();
if (list?.Any() == true)
{
foreach (var item in list)
{
var attr = _modelAttributeValueRepository
.GetFind(x => item.AttributeId == x.AttributeId && item.List.Contains(x.Value))
.Select(x => x.ProductId)
.ToList();
query = query.Where(x => attr.Contains(x.ProductId));
}
}
}
return View(query.ToList());
}

How to ignore mapping with condition

As I'm having a single DTO, we use DTOs for GET, PUT and POST http method in our Web API.
To make simple we have ActivityDO:
public ActivityDTO
{
public int Id;
public string Name;
public string CategoryName;
public DateTime DateCreated;
public DateTime DateModified;
}
The challenge is when you only have a single DTO for handling multiple conditions i.e. post/get/put method, the mapping as follow:
private MapperConfiguration configuration = new MapperConfiguration(cfg => {
cfg.CreateMap<ActivityDTO, Activity>()
.ForMember(dst => dst.UserId, opt => opt.MapFrom(src => HttpContext.Current.User.Identity.GetUserId()))
.ForMember(dst => dst.CategoryId, opt => opt.MapFrom(src => GetCategoryId(HttpContext.Current.User.Identity.GetUserId(), src.CategoryName)))
.ForMember(dst => dst.DateCreated, opt => opt.MapFrom(src => DateTime.UtcNow))
.ForMember(dst => dst.DateModified, opt => opt.MapFrom(src => DateTime.UtcNow));
});
I want to IGNORE the mapping for DateCreated if we do the update and we can do the condition if the id <= 0, the rest is allowed to mapping for DateCreated.
Is this possible? Would rather to have a seperate DTOs between GET/POST (Add) VS PUT (Update)? Is there any better solution to handle this DateCreated VS DateModified thingy?
I'm appreciated your feedback/comment.
This is the way to add conditions.
Is that what you are looking for?
private MapperConfiguration configuration = new MapperConfiguration(cfg => {
cfg.CreateMap<ActivityDTO, Activity>()
.ForMember(dst => dst.UserId, opt => opt.MapFrom(src => HttpContext.Current.User.Identity.GetUserId()))
.ForMember(dst => dst.CategoryId, opt => opt.MapFrom(src => GetCategoryId(HttpContext.Current.User.Identity.GetUserId(), src.CategoryName)))
.ForMember(dst => dst.DateCreated, opt => opt.MapFrom(src => src.Condition(src.DateCreated != null)))
.ForMember(dst => dst.DateModified, opt => opt.MapFrom(src => DateTime.UtcNow));
});
I used src.DateCreated != null but you can specify any condition using the src.Condition() and the variable will only be mapped when the condition is met.
Also
You can use AutoMapper's PreCondition
var configuration = new MapperConfiguration(cfg => {
cfg.CreateMap<Foo,Bar>()
.ForMember(dest => dest.baz, opt => {
opt.PreCondition(src => (src.baz >= 0));
opt.MapFrom(src => {
});
});
});

Nhibernate QueryOver how can I make this query use async?

For this new website I want to use async methods in NHibernate. I have this simple query using QueryOver API but I can't get this one to work with async.
It is a simple query with some where clauses that list all businesses. I want 20 of them each time I execute this.
Query:
BusinessListItem bli = null;
BusinessCategory bc = null;
Category c = null;
BusinessImage bi = null;
Image i = null;
var q = Session.QueryOver<Business>()
.JoinAlias(x => x.Categories, () => bc)
.JoinAlias(() => bc.Category, () => c)
.JoinAlias(x => x.Images, () => bi, JoinType.LeftOuterJoin)
.JoinAlias(() => bi.Image, () => i, JoinType.LeftOuterJoin)
.Where(() => bc.IsMain);
if (!string.IsNullOrEmpty(_name))
q.WhereRestrictionOn(x => x.Name).IsLike($"%{_name}%");
if (!string.IsNullOrEmpty(_streetName))
q.WhereRestrictionOn(x => x.StreetName).IsLike($"%{_streetName}%");
if (_categoryId != null)
q.Where(() => c.Id == _categoryId.Value);
if (_subCategoryIds != null)
q.WhereRestrictionOn(() => c.Id).IsIn(_subCategoryIds);
return q.Select(
Projections.Property<Business>(x => x.Id).WithAlias(() => bli.Id),
Projections.Property<Business>(x => x.Name).WithAlias(() => bli.Name),
Projections.Property("c.Name").WithAlias(() => bli.CategoryName),
Projections.Property("bi.Image").WithAlias(() => bli.Image)
)
.TransformUsing(Transformers.AliasToBean<BusinessListItem>())
.List<BusinessListItem>()
.OrderBy(x => x.Name)
.Skip(_skipCount)
.Take(20)
.ToList();
I know the method .ListAsync() exists but I cannot get it working together with the Skip, Take and OrderBy method.
Any help is much appreciated!
The solution to this question is :
var result = await q.Select(
Projections.Distinct(
Projections.Property<Business>(x => x.Id).WithAlias(() => bli.Id)
)
.TransformUsing(Transformers.AliasToBean<BusinessListItem>())
.OrderBy(x => x.Name).Asc
.Skip(_skipCount)
.Take(_takeCount)
.ListAsync<BusinessListItem>();
return result.ToList();
Thx to #DavidOsborne

KendoGrid - MVC - Entity - Identity column

I am building an MVC, Entities application with KendoGrids.
I have build this kendoGrid
#(Html.Kendo().Grid<ModelApp.Models.Tickets>()
.Name("ticketgrid")
.Columns(columns =>
{
columns.Bound(p => p.TicketID).Title("ID");
columns.ForeignKey(p => p.CustomerID, (System.Collections.IEnumerable)ViewData["customers"], "CustomerID", "CustomerName").Title("Customer");
columns.ForeignKey(p => p.AreaOfBusinessID, (System.Collections.IEnumerable)ViewData["areaofbusinesses"], "AreaOfBusinessID", "AreaOfBusiness1").Title("AreaOfBusiness");
columns.Bound(p => p.OccurredOn).Title("Occured").Format("{0:yyyy-MM-dd}");
columns.ForeignKey(p => p.SeverityID, (System.Collections.IEnumerable)ViewData["severities"], "SeverityID", "Severity1").Title("Severity");
columns.ForeignKey(p => p.AssigneeID, (System.Collections.IEnumerable)ViewData["assignees"], "AssigneeID", "AssigneeName").Title("Assignee");
columns.ForeignKey(p => p.TicketStatusID, (System.Collections.IEnumerable)ViewData["ticketstatuses"], "TicketStatusID", "TicketStatus1").Title("Status");
columns.Bound(p => p.UserID).Title("User");
columns.Bound(p => p.DateRegistered).Title("Registered").Format("{0:yyyy-MM-dd}");
})
.DataSource(dataSource =>
dataSource
.Ajax()
.Model(model => model.Id(p => p.TicketID))
.Read(read => read.Action("Index","Ticket"))
.Create(create => create.Action("Create", "Ticket"))
.Update(update => update.Action("Edit", "Ticket"))
//.Destroy(destroy => destroy.Action("Delete", "Ticket"))
)
.Pageable()
.Editable(editing => editing.Mode(GridEditMode.InCell))
.ToolBar(toolbar =>
{
toolbar.Create();
toolbar.Save();
})
.Navigatable()
.Selectable()
)
and I am facing 2 problems
1)The TicketID column is an identity column. When I select the Create button it fetches a zero. How can I make the Gid understand that it should not mess with this column and that the database will handle it?
Of course, no insert is being made anyway which takes me to the second question
2)The Edit does not post to database
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit([DataSourceRequest] DataSourceRequest request, IEnumerable<ModelApp.Models.Tickets> models)
{
if (models != null)
{
try
{
foreach (var updatedEntity in models)
{
var itemToUpdate = db.Tickets.Where(p => p.TicketID == updatedEntity.TicketID).FirstOrDefault();
if (itemToUpdate != null)
{
itemToUpdate.CustomerID = updatedEntity.CustomerID;
itemToUpdate.AreaOfBusinessID = updatedEntity.AreaOfBusinessID;
itemToUpdate.AssigneeID = updatedEntity.AssigneeID;
itemToUpdate.OccurredOn = updatedEntity.OccurredOn;
itemToUpdate.SeverityID = updatedEntity.SeverityID;
itemToUpdate.DateRegistered = updatedEntity.DateRegistered;
itemToUpdate.UserID = updatedEntity.UserID;
db.SaveChanges();
ModelState.Clear();
}
}
}
catch (Exception e)
{
db.add_exception_log(e.Message, "UPDATE RATES");
}
}
return Json(ModelState.ToDataSourceResult());
}
because models is null. Any clues why?
Thanx in advance
1) You should make the field non-editable inside of the Model configurator of the dataSource
model=>{
model.Fiedl(p=>p.TicketID).Editable(false);
}
2) You are not using batch editing to expect collection - change the signate to expect single record
public ActionResult Edit([DataSourceRequest] DataSourceRequest request, ModelApp.Models.Tickets model)

grid operation in mvc telerik grid

how to perform the edit and delete operations in grid
i have the following grid
<%=Html.Telerik().Grid(Model).Name("Grid").Columns(columns =>
{
columns.Bound(m => m.Keywords);
columns.Bound(m => m.Country).Title("Location");
columns.Bound(m => m.AreaID);
columns.Bound(m => m.JobSearchAgentID).Hidden(false);
}).DataBinding(databinding =>
{
databinding.Server().Select("Agentlist", "Grid", new
{
ajax = ViewData["ajax"]
});
databinding.Ajax().Select("Agentlist",
"Grid").Enabled((bool)ViewData["ajax"]);
})
.DataKeys(keys =>
{
keys.Add(m => m.JobSearchAgentID);
}
)
.Scrollable(scrolling => scrolling.Enabled((bool)ViewData["scrolling"]))
.Sortable(sorting => sorting.Enabled((bool)ViewData["sorting"]))
.Pageable(paging => paging.Enabled((bool)ViewData["paging"]))
.Filterable(filtering => filtering.Enabled((bool)ViewData["filtering"]))
.Groupable(grouping => grouping.Enabled((bool)ViewData["grouping"]))
.Footer((bool)ViewData["showFooter"])
%>
<%}%>
Everything you need about Telerik MVC Grid Control
http://demos.telerik.com/aspnet-mvc/grid/editingajax dead link
http://demos.telerik.com/aspnet-mvc/grid
Here's an example of a grid that allows add and edit within the grid:
<% Html.Telerik().Grid<ReportingPeriodGroupDto>()
.Name("ReportingPeriodGroupAdminGrid")
.DataKeys(keys => keys.Add(o => o.Id))
.Editable(editing => editing.Mode(GridEditMode.InLine))
.ToolBar(commands =>
{
commands.Insert();
})
.DataBinding(dataBinding => dataBinding.Ajax()
.Select("SelectReportingPeriodGroup", "Admin")
.Insert("InsertReportingPeriodGroup", "Admin")
.Update("UpdateReportingPeriodGroup", "Admin")
)
.Columns(columns =>
{
columns.Bound(o => o.ShortDescription).Width("10em").Width("8em");
columns.Bound(o => o.LongDescription).Width("20em");
columns.Command(commands => commands.Edit()).Title("Actions");
})
.Footer(false)
.Render();
%>
NOTE: You must add these Insert and Update methods to your controller
[AcceptVerbs(HttpVerbs.Post)]
[GridAction(GridName = "ReportingPeriodGroupAdminGrid")]
public ActionResult InsertReportingPeriodGroup()
{
ReportingPeriodGroupDto reportingPeriodGroupDto = new ReportingPeriodGroupDto();
TryUpdateModel(reportingPeriodGroupDto);
if (ModelState.IsValid)
{
reportingPeriodGroupDto.CreatedBy = UserId;
reportingPeriodGroupDto.CreatedDate = DateTime.Now.ToString();
ITransformer transformer = ServiceFinder.Instance.ServiceFactory.RedPortalTransformerFactory.GetTransformer(reportingPeriodGroupDto.GetType());
ReportingPeriodGroup parent = (ReportingPeriodGroup)transformer.Transform(reportingPeriodGroupDto);
RedPortalDbContext.ReportingPeriodGroups.Add(parent);
RedPortalDbContext.SaveChanges();
}
return SelectReportingPeriodGroup();
}
[AcceptVerbs(HttpVerbs.Post)]
[GridAction(GridName = "ReportingPeriodGroupAdminGrid")]
public ActionResult UpdateReportingPeriodGroup()
{
ReportingPeriodGroupDto reportingPeriodGroupDto = new ReportingPeriodGroupDto();
if (TryUpdateModel(reportingPeriodGroupDto))
{
reportingPeriodGroupDto.UpdatedBy = UserId;
reportingPeriodGroupDto.UpdatedDate = DateTime.Now.ToString();
ITransformer transformer = ServiceFinder.Instance.ServiceFactory.RedPortalTransformerFactory.GetTransformer(reportingPeriodGroupDto.GetType());
ReportingPeriodGroup parent = (ReportingPeriodGroup)transformer.Transform(reportingPeriodGroupDto);
RedPortalDbContext.ReportingPeriodGroups.Add(parent);
RedPortalDbContext.Entry(parent).State = EntityState.Modified;
RedPortalDbContext.SaveChanges();
}
return SelectReportingPeriodGroup();
}

Resources