How to show dynamic category in razor page? - c#

i have create dynamic category with subcategory ...
i can't show on my razor page i used foreach but foreach for 2 step category or 3 step my category have unlimited step
plz help me
public class vmCategoryForSearch
{
public int CategoryId { get; set; }
public string titleEn { get; set; }
public bool isDelete { get; set; }
public List<vmCategoryForSearch> Children { get; set; }
}
how to call this code
public List<vmCategoryForSearch> GetAllCategoryForSearchClients()
{
return catsearchList.Where(mm => mm.ParentId == 0).Select(m => new vmCategoryForSearch
{
titleEn = m.titleEn,
titleFa = m.titleFa,
Children = GetAllCategoryForSearchClients(m.SubId)
}).ToList();
}
private List<vmCategoryForSearch> GetAllCategoryForSearchClients(int id)
{
return catsearchList.Where(sm => sm.ParentId == id).Select(vm => new vmCategoryForSearch
{
titleEn = vm.titleEn,
titleFa = vm.titleFa,
Children = GetAllCategoryForSearchClients(vm.SubId)
}).ToList();
}
my razor page

Here is a simple worked example , you could refer to :
Category model
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
public int ParentId { get; set; }
}
vmCategoryForSearch
public class vmCategoryForSearch
{
public int CategoryId { get; set; }
public string Name { get; set; }
public List<vmCategoryForSearch> Children { get; set; }
}
PageModel
private readonly RazorPages2_1Project.Data.RazorPagesDbContext _context;
private readonly List<Category> list;
public CreateModel(RazorPages2_1Project.Data.RazorPagesDbContext context)
{
_context = context;
list = _context.Category.ToList();
}
public IActionResult OnGet()
{
CategoryList = GetAllCategoryForSearchClients();
return Page();
}
[BindProperty]
public List<vmCategoryForSearch> CategoryList { get; set; }
public List<vmCategoryForSearch> GetAllCategoryForSearchClients()
{
var result= list.Where(mm => mm.ParentId == 0).Select(m => new vmCategoryForSearch
{
Name = m.Name,
Children = GetAllCategoryForSearchClients(m.Id)
}).ToList();
return result;
}
private List<vmCategoryForSearch> GetAllCategoryForSearchClients(int id)
{
var result1 = list.Where(sm => sm.ParentId == id).Select(vm => new vmCategoryForSearch
{
Name = vm.Name,
Children = GetAllCategoryForSearchClients(vm.Id)
}).ToList();
return result1;
}
}
Razor Pages
<div class="c-box_item">
#foreach(var item in Model.CategoryList)
{
<ul >
<li>
<span> #item.Name</span>
<div>
#foreach(var subitem in item.Children)
{
<ul>
<li>
<span> #subitem.Name</span>
<div>
#if (subitem.Children.Count > 0)
{
#foreach (var subitems in subitem.Children)
{}
}
</div>
</li>
</ul>
}
</div>
</li>
</ul>
}
</div>

Related

how to retrieve parent data and child data in the same view

I want to retrieve the data of parent and child in the same view mvc5 c#
<ul class="circle2">
<li style=" border:0px">
<div class="text">#Html.DisplayFor(model => model.Name)</div>
</li>
<ul class="circle3">
#foreach (var item1 in Model)
{
<li>
<div class="text">#Html.Display(modelItem => item1.Name)</div>
</li>
}
<li>
<div class="text" data-toggle="tooltip" data-placement="left" title="add family member">#Html.ActionLink("+", "Create")</div>
</li>
Your model must look like this:
public class newtree
{
public string User_ID { get; set; }
public string Name { get; set; }
public string perantID { get; set; }
List<Child> Children { get; set; }
}
You need to fill up the Children-list with the correct data, then iterate it with #foreach (var item1 in Model.Children)
Model
public class EmployeeViewModel {
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public EmployeeDepartment employeeDepartment { get; set; }
}
public class EmployeeDepartment {
public int Id { get; set; }
public string DepartmentName { get; set; }
}
Controller
public ActionResult EmployeeData() {
EmployeeViewModel model = new EmployeeViewModel();
EmployeeDepartment ed = new EmployeeDepartment();
model.Id = 1;
model.Name = "Muhammmad Ashraf Faheem";
model.Email = "it.ashraffaheem#gmail.com";
ed.Id = 1;
ed.DepartmentName = "Development";
model.employeeDepartment = ed;
return View(model);
}
View
#model UploadFileDemo.Models.EmployeeViewModel
#{ViewBag.Title = "EmployeeData";}
<label>#Model.Id</label><br />
<label>#Model.Name</label><br />
<label>#Model.Email</label><br />
<label>#Model.employeeDepartment.Id</label><br />
<label>#Model.employeeDepartment.DepartmentName</label>
with this way we can use parent and child model in same view :

AutoMapper not able to convert from entity model to viewmodel

I just followed this guide to install and set up AutoMapper, and I think I got it correctly set up. But when I try to map from IEnumerable<ProductCategory> to IEnumerable<ViewModelProductCategory>, like this:
var categories = _context.ProductCategories.Include(e => e.Children).ToList();
var topLevelCategories = categories.Where(e => e.ParentId == null);
var VMCategory = _mapper
.Map<IEnumerable<ProductCategory>,
IEnumerable<ViewModelProductCategory>>(topLevelCategories);
return View(VMCategory);
(Thank you to #Anton Gorbunov, for pointing out that I had my objects swapped!)
... my view complains about receiving the wrong model. I'm pretty sure it's because of the children categories not being mapped to a sub-list, so in the view, item.Children is not properly set up as a viewmodel.
How can I map a list of lists?
This is my Index-view:
#model IEnumerable<MyStore.Models.ViewModels.ViewModelProductCategory>
<ul>
#Html.Partial("_CategoryRecursive", Model)
</ul>
... and this is _CategoryRecursive.cshtml:
#model IEnumerable<MyStore.Models.ViewModels.ViewModelProductCategory>
<ul style="list-style:none;padding-left:0px;">
#if (Model != null)
{
foreach (var item in Model)
{
<li style="margin:8px 0px 0px 0px;">
<ul>
#Html.Partial("_CategoryRecursive.cshtml", item.Children)
</ul>
</li>
}
}
</ul>
Mapping profile:
public class MappingProfile : Profile
{
public MappingProfile()
{
CreateMap<ProductCategory, ViewModelProductCategory>();
CreateMap<ViewModelProductCategory, ProductCategory>();
CreateMap<Product, ViewModelProduct>();
CreateMap<ViewModelProduct, Product>();
}
}
Entity model:
public class ProductCategory
{
public int Id { get; set; }
public int SortOrder { get; set; }
public string Title { get; set; }
[ForeignKey(nameof(ParentCategory))]
public int? ParentId { get; set; }
public ProductCategory ParentCategory { get; set; } //nav.prop to parent
public ICollection<ProductCategory> Children { get; set; } //nav. prop to children
public List<ProductInCategory> ProductInCategory { get; set; }
}
Viewmodel:
public class ViewModelProductCategory
{
public int Id { get; set; }
public int? ParentId { get; set; }
public string Title { get; set; }
public int SortOrder { get; set; }
public string ProductCountInfo
{
get
{
return Products != null && Products.Any() ? Products.Count().ToString() : "0";
}
}
public ProductCategory ParentCategory { get; set; } // Nav.prop. to parent
public IEnumerable<ProductCategory> Children { get; set; } // Nav.prop. to children
public List<ViewModelProduct> Products { get; set; } // Products in this category
public List<ViewModelProduct> OrphanProducts { get; set; } // Products with no references in ProductInCategory
}
Problem here:
var VMCategory = _mapper.Map<IEnumerable<ViewModelProductCategory>, IEnumerable<ProductCategory>>(topLevelCategories);
you should change code to
var VMCategory = _mapper.Map<IEnumerable<ProductCategory>, IEnumerable<ViewModelProductCategory>>(topLevelCategories);
Description:
TDestination = Map<TSource,TDestination>(TSource sourceObject), but you swapped the types TSource and TDestination inside brackets <,>

ASP.NET MVC Insert CheckBoxList values to Database

I'm having trouble understanding how to add my CustId and selected DevId values from the CheckBoxList to my CustomerDevice table in my database.
My Index Action Method for the CustomerDeviceController displays a list of Customers from my Customers table. I have a link labeled "Add Device(s)" that passes the CustId value to the CustomerDeviceController [HttpGet] Create Action Method which displays my CheckBoxListItem values from the Devices table which works fine.
The part that I'm having trouble understanding and figuring out, is how can I add the selected DevId values from the CheckBoxList along with the CustId value to my CustomerDevice Table on the [HttpPost] Create Action Method.
Please see the following code below that I have so far.
CheckBoxListItem Model
public class CheckBoxListItem
{
public int ID { get; set; }
public string Display { get; set; }
public bool IsChecked { get; set; }
}
Customer Model
public class Customer
{
public int CustId { get; set; }
public string CustDisplayName { get; set; }
public string CustFirstName { get; set; }
public string CustLastName { get; set; }
public string CustCompanyName { get; set; }
public string CustAddress { get; set; }
public string CustPhoneNumber { get; set; }
public string CustMobileNumber { get; set; }
public string CustEmailAddress { get; set; }
}
Device Model
public class Device
{
public int DevId { get; set; }
public string DevType { get; set; }
}
CustomerDevice Model
public class CustomerDevice
{
public int CustId { get; set; }
public int DevId { get; set; }
public Customer Customer { get; set; }
public Device Device { get; set; }
}
Shared/EditorTemplates/CheckBoxListItem.cshtml
<div class="checkbox">
<label>
#Html.HiddenFor(x => x.ID)
#Html.CheckBoxFor(x => x.IsChecked)
#Html.LabelFor(x => x.IsChecked, Model.Display)
</label>
<br />
CustomerDeviceFormViewModel
public class CustomerDeviceFormViewModel
{
public int CustId { get; set; }
public string CustDisplayName { get; set; }
public List<CheckBoxListItem> Devices { get; set; }
}
CustomerDeviceController
public class CustomerDeviceController : Controller
{
private CheckBoxAppContext db;
public CustomerDeviceController(CheckBoxAppContext context)
{
db = context;
}
// GET: /<controller>/
public IActionResult Index()
{
return View(db.Customers.ToList());
}
public ActionResult Create(int? id)
{
if (id == null)
{
return NotFound();
}
var customervm = new CustomerDeviceFormViewModel();
{
Customer customer = db.Customers.SingleOrDefault(c => c.CustId == id);
if (customer == null)
{
return NotFound();
}
customervm.CustId = customer.CustId;
// Retrieves list of Devices for CheckBoxList
var deviceList = db.Devices.ToList();
var checkBoxListItems = new List<CheckBoxListItem>();
foreach (var device in deviceList)
{
checkBoxListItems.Add(new CheckBoxListItem()
{
ID = device.DevId,
Display = device.DevType,
IsChecked = false //On the create view, no devices are selected by default
});
}
customervm.Devices = checkBoxListItems;
return View(customervm);
}
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(CustomerDeviceFormViewModel vm)
{
if (ModelState.IsValid)
{
var customerDevices = new CustomerDevice();
{
customerDevices.CustId = vm.CustId;
var deviceList = db.Devices.ToList();
var checkBoxListItems = new List<CheckBoxListItem>();
foreach (var deviceId in deviceList)
{
}
}
db.CustomerDevices.Add(customerDevices);
db.SaveChanges();
return RedirectToAction("Index");
}
else
{
return View(vm);
}
}
}
Index View
<table class="table">
<tr>
<th>Id</th>
<th>Display Name</th>
<th>Actions</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.CustId)
</td>
<td>
#Html.DisplayFor(modelItem => item.CustDisplayName)
</td>
<td>
#Html.ActionLink("Add Device(s)", "Create", new { id = item.CustId })
</td>
</tr>
}
Create View
<div class="form-group">
#Html.EditorFor(x => x.Devices)
</div>
#Html.HiddenFor(c => c.CustId)
<div class="form-group">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
Assuming that your CustomerDevice is the join table for a M:N relation between Customer and Device entities, I think you need something like this in your POST action:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(CustomerDeviceFormViewModel vm)
{
if (ModelState.IsValid)
{
foreach (var deviceId in vm.Devices.Where(x => x.IsChecked).Select(x => x.ID))
{
var customerDevices = new CustomerDevice
{
CustId = vm.CustId,
DevId = deviceId
};
db.CustomerDevices.Add(customerDevices);
}
db.SaveChanges();
return RedirectToAction("Index");
}
return View(vm);
}
You create an entity of the join table and add it to the context. EF will associate the records when you call SaveChanges.
Hope this helps!

#Html.DropDownList or #Html.DropdownlistFor doesn't show current value

So I have an Html.DropDownList that I want to use on an edit page to allow users to edit the categories of different recipe ingredients. So for example if a user wants to edit the chili recipe they are shown all the different properties for the recipe including a list of all the ingredients which they should be able to add to or delete from or edit the quantity, name and category of. And I only want to have a drop down list to edit the category because I only want them to be able to choose from a preselected list of categories. Here is what I have.
<table>
<tr>
<th></th>
</tr>
#for (int i = 0; i < #Model.Recipe.RecipeIngredients.Count; i++)
{
<tr>
<td>#Html.EditorFor(model => model.Recipe.RecipeIngredients[i].Quantity)</td>
<td>#Html.EditorFor(model => model.Recipe.RecipeIngredients[i].IngredientName)</td>
<td>#Html.DropDownList("AvailableCategories")</td>
</tr>
}
</table>
//// GET: /Recipe/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
EditViewModel vm = new EditViewModel();
vm.Recipe = Db.Recipes.Find(id);
if (vm.Recipe == null)
{
return HttpNotFound();
}
List<SelectListItem> items = new List<SelectListItem>();
foreach (var item in Db.Categories)
{
items.Add(new SelectListItem { Text = item.CategoryName, Value = item.CategoryId.ToString() });
}
vm.AvailableCategories = items;
return View(vm);
}
public class EditViewModel
{
public Recipe Recipe { get; set; }
public List<SelectListItem> AvailableCategories { get; set; }
public EditViewModel()
{
AvailableCategories = new List<SelectListItem>();
}
}
public class RecipeIngredient
{
public int IngredientId { get; set; }
public int RecipeId { get; set; }
public int CategoryId { get; set; }
public string IngredientName { get; set; }
public string Quantity { get; set; }
public int IsOnMenu { get; set; }
public bool IsOnTheDamnMenu
{
get
{
return IsOnMenu == 1;
}
set
{
IsOnMenu = value ? 1 : 0;
}
}
public virtual Recipe Recipe { get; set; }
public virtual Category Category { get; set; }
}
I actually just found that I can pass more properties into this. So something like
#Html.DropDownListFor(model => model.Recipe.RecipeIngredients[i].CategoryId, new SelectList(Model.AvailableCategories, "Value", "Text", Model.Recipe.RecipeIngredients[i].CategoryId), "-Select-")
Shows the correct category now.

MVC 5 Dynamic Navigation Bar 2 Tier

I currently have a navigation bar which is dynamically created from a MS SQL Database, but I would like to add a second sub layer. Below is what I have so far for the current working single level navigation bar.
Navigation
public partial class Navigation
{
public int Id { get; set; }
public string Title { get; set; }
public Nullable<int> Position { get; set; }
public bool Main { get; set; }
public string Action { get; set; }
public string Controller { get; set; }
}
HomeController
[ChildActionOnly]
public ActionResult Navigation()
{
var navigationModel = (from m in db.Navigations where (m.Main == true) orderby m.Position select m);
return View(navigationModel);
}
Navigation
#{ Layout = null; }
#model IEnumerable<WebApplication1.Models.Navigation>
<ul class="nav sf-menu clearfix">
#foreach (var item in Model)
{
#Html.MenuLink(item.Title, item.Action, item.Controller)
}
</ul>
The second tier needs to link to the Contents table, the relationship is db.Navigations.Id = db.Contents.NavigationId.
Content
public partial class Content
{
public int Id { get; set; }
public Nullable<int> NavigationId { get; set; }
public string Title { get; set; }
public string Content1 { get; set; }
public Nullable<int> Position { get; set; }
public string Image { get; set; }
public string Sub { get; set; }
public Nullable<bool> Active { get; set; }
public string Url { get; set; }
public string Summary { get; set; }
}
Could someone please provide a tutorial or example code of how I can bind child data to the parent dataset and then in the View, how to check if a parent holds child records and if so loop through them.
Any help would be much appreciated :-)
I added a new class called NavigationViewModel to declare the tables I wish to use and modified the HomeController to use NavigationViewModel for querying the respective tables.
NavigationViewModel
namespace WebApplication1.Models
{
public class NavigationViewModel
{
public List<Navigation> Navigation { get; set; }
public List<Content> Content { get; set; }
}
}
HomeController
[ChildActionOnly]
public ActionResult Navigation()
{
var navigationModel = new NavigationViewModel();
navigationModel.Navigation = (from m in db.Navigations where (m.Main == true) orderby m.Position select m).ToList();
navigationModel.Content = (from n in db.Contents where (n.Active == true) orderby n.Position select n).ToList();
return View(navigationModel);
}
Navigation
#model WebApplication1.Models.NavigationViewModel
<ul class="nav sf-menu clearfix">
#foreach (var navigation in Model.Navigation)
{
int records = Model.Content.Count(c => c.NavigationId == navigation.Id);
if (records > 0)
{
#Html.SubMenuLink(navigation.Title, navigation.Action, navigation.Controller)
#Html.Raw("<ul>")
foreach (var content in Model.Content.Where(c => c.NavigationId == navigation.Id))
{
if (string.IsNullOrEmpty(content.Url))
{
if (string.IsNullOrEmpty(content.Content1))
{
}
else
{
#Html.MenuLink(content.Title, "Home/Article/" + content.Id + "/" + ToFriendlyUrl(content.Title), "Home");
}
}
else
{
#Html.MenuLink(content.Title, content.Url, "Home");
}
}
#Html.Raw("</ul>")
#Html.Raw("</li>")
}
else
{
#Html.MenuLink(navigation.Title, navigation.Action, navigation.Controller)
}
}
</ul>
I'm not sure this is the most elegant or efficient way to achieve the end goal, any suggestions to make the code more efficient I am happy to listen.

Categories

Resources