I'm working in Asp.Net MVC, and I want to populate menu from database, but I don't really have an idea how can I do it to insert sub-menus into each menu, and each of this sub-menu can have another submenu, etc.
I was is something similar like facebook comment and reply model.
First I have model of menu like:
public int MenuId { get; set; }
public string Name { get; set; }
public string Controller { get; set; }
public string Action { get; set; }
public int Order { get; set; }
public string Icon { get; set; }
public bool IsAdmin { get; set; }
Sub-menu:
public int SubMenuId { get; set; }
public int MenuId { get; set; } // Menu Fk
public string Name { get; set; }
public string Controller { get; set; }
public string Action { get; set; }
public int Order { get; set; }
public string Icon { get; set; }
public bool IsAdmin { get; set; }
It's my logic correctly?, someone implement something similar? What I need to do into controller to make it works?, if someone have an example I really apreciated it. Thanks in Advance
The traditional way is to just have your Menu model and have a nullable ParentMenuId. If the ParentMenuId is null, your Menu is a root node. You can set your navigation properties so from each Menu node you can access .Children to get all of the nodes that point to it.
I believe #Dobbins has the correct idea. In the database you can have a MenuLink table:
MenuLink
- ID int IDENTITY(1,1) NOT NULL <- Primary Key
- ParentId int NULL <- Foreign Key
- OrderNumber int
- LinkUri varchar(1024) <- Can be replaced with Controller, Action
- IconUri varchar(1024)
- Text nvarchar(256)
You can then select all menu links and their sub-links from the database.
Your Menu Object can then have a list of Menu Objects:
public class MenuLink
{
int Id { get; set; }
int ParentId { get; set; }
int OrderNumber { get; set; }
Uri LinkUri { get; set; }
Uri IconUri { get; set; }
string Text { get; set; }
IList<MenuLink> SubMenuItems { get; set; }
}
Now you can use razor, or your JavaScript framework of choice to create the dynamic menu in code.
Related
I'm trying to build a recipe app for my spouse. I'm trying to set it up so she can add new recipes to the database as the app grows.
When adding new recipe, she will have three drop-down to pick from to construct her new recipe ingredients. First one will contain a list of ingredients that she can choose from, the second one a list of measuring units and the third one a list of quantities.
Here is what I got so far. Am I heading in the right direction or am I off? I'm using Entity Framework with a code-first approach:
public class Recipes
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Image { get; set; }
}
public class Units model
{
[Key]
public int Id { get; set; }
public string UnitName { get; set; }
}
public class UnitQty
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
}
public class IngredientsModel
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
}
public class RecipeIngredients
{
public int Id { get; set; }
public int RecipesId { get; set; }
[ForeignKey("RecipesId")]
public Recipes Recipes { get; set; }
public int IngredientsModelId { get; set; }
[ForeignKey("IngredientsModelId")]
public IngredientsModel IngredientsModel { get; set; }
public int UnitQtyId { get; set; }
[ForeignKey("UnitQtyId")]
public UnitQty UnitQty { get; set; }
public int UnitsModelId { get; set; }
[ForeignKey("UnitsModelId")]
public UnitsModel UnitsModel { get; set; }
}
After creating the table, controller and the views, this is what I get in the recipe ingredients index view.
Any suggestion will be more than welcome please and thank you
RecipeIngredient class's view
First of all. You are over engineering your domain model. On relational databases Join is bottleneck you should prevent from joins if it doesn't helps you.
public class Recipt
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Image { get; set; }
public ICollection<RecipeIngredient> Ingredients { get; set; }
}
public class IngredientModel
{
public int Id { get; set; }
public string Name { get; set; }
public IngredientUnit UnitType { get; set; } // Unit model is best to be added here. if it doesn't change in a single IngredientModel.
}
public class RecipeIngredient
{
public int Id { get; set; }
public int UnitQuantiy { get; set; } // No need to more classes.
public IngredientModel Model { get; set; }
public Recipt Recipt { get; set; }
}
public Enum IngredientUnitType // Same Unit Model but less database relation as its small finite collection.
{
Killogram,
Count,
....
}
and according to the Microsoft documents its best to use fluentApi configuration for the relations.
Override this method in your Context:
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<Recipt>.HasMany(P => P.Ingredients).WithOne(P => P.Recipt);
builder.Entity<RecipeIngredient>.HasOne(P => P.Model);
// There is no need to explicit foreign key definition. but you can explicitly define your foreign keys.
}
And for the last part. in Views you can use extra models called ViewModels.
As above domain turned to a minimal domain you just need to pass a list of IngredientModels to your view to complete your View.
I'm trying to create a little asset management application, like an inventory. There are asset types (like notebook, mobile phone, desk, dishwasher etc.) and assets (like notebook-001, mobile-010 etc.).
So this is my AssetType model:
public class AssetType
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<AssetTypeMeta> AssetTypeMetas { get; set; }
}
And this is my Asset model:
public class Asset
{
public int Id { get; set; }
[ForeignKey("TypeId")]
public AssetType AssetType { get; set; }
public int TypeId { get; set; }
public string SerialNumber { get; set; }
public double PurchasePrice { get; set; }
public ICollection<AssetMeta> FieldNames { get; set; }
public ICollection<AssetTypeMeta> FieldValues { get; set; }
}
As you can see, there are only 2 fields in my asset table, SerialNumber and PurchasePrice. But I want user to be able to define new fields specific to the device type and be able to enter information to those fields. When I test it in my database, everything looks fine.
For this I have created two more models. One of them is AssetTypeMeta, which is meant to hold new (user-defined) field names for the user.
public class AssetTypeMeta
{
public int Id { get; set; }
[ForeignKey("AssetTypeId")]
public AssetType AssetType { get; set; }
public int AssetTypeId { get; set; }
public string FieldName { get; set; }
}
And I've added a new model, AssetMeta, which is a link between an asset type, an asset and user defined fields for that asset type.
public class AssetMeta
{
public int Id { get; set; }
[ForeignKey("AssetTypeMetaId")]
public AssetTypeMeta AssetTypeMeta { get; set; }
public int AssetTypeMetaId { get; set; }
[ForeignKey("AssetId")]
public Asset Asset { get; set; }
public int AssetId { get; set; }
public string? FieldValue{ get; set; }
}
I can define fields like IMEI, NFC, Operator etc. for the device type "Mobile Phone" in AssetTypeMeta table and link them to the actual devices in AssetMeta table, like mobile-phone01's IMEI is 11111111111 and Operator is Vodafone etc.
But I can't make all those information visible in my page. For example, if a user clicks on the device mobile-phone01, I have to also show the user defined fields for that device, like IMEI and Operator (even if they don't have any values assigned in AssetMeta table).
How do I set up my viewmodel, action and view to do that?
I am trying to relate my Tables with ForeignKey and PrimaryKey on the other end. But now i will be using a ForeignKey which is not the primary for the said table. I was using [InverseProperty] but i think there's a bug with it since i've been looking around for hours already and all of them says the same thing about it.
Documents Table:
public class Document
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int DocumentId { get; set; }
public int ProjectId { get; set; }
public int DepartmentId { get; set; }
public int AuthorId { get; set; }
[NotMapped]
public virtual User Author { get; set; }
}
Users
public class User
{
[Key]
public int UserId { get; set; }
public int AuthUserId { get; set; }
public string DisplayName { get; set; }
[NotMapped]
[ForeignKey("AuthorId")]
public virtual Document Document { get; set; }
}
Context:
modelBuilder.Entity<User>(entity =>
{
entity.HasOne(u => u.Document)
.WithMany("AuthorId");
});
I am trying to use the solution they here, but no luck.
Any help would really be appreciated. Thanks!
But now i will be using a ForeignKey which is not the primary for the said table.
To do this you can use EF Core Alternate Keys feature. But first correct your model class set up as follows: (As you said a User will have multiple Document)
public class Document
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int DocumentId { get; set; }
public int ProjectId { get; set; }
public int DepartmentId { get; set; }
public int AuthorId { get; set; }
public User Author { get; set; }
}
public class User
{
[Key]
public int UserId { get; set; }
public int AuthUserId { get; set; }
public string DisplayName { get; set; }
public ICollection<Document> Documents { get; set; }
}
Then in the Fluent API configuration as follows:
modelBuilder.Entity<Document>()
.HasOne(p => p.Author)
.WithMany(b => b.Documents)
.HasForeignKey(p => p.AuthorId)
.HasPrincipalKey(b => b.AuthUserId); // <-- here you are specifying `AuthUserId` as `PrincipalKey` in the relation which is not primary key
I'm trying to learn how to use the ASP.NET MVC 4 and Entity FrameWork 5, and I'm a bit confused by scaffolding for Drop Down Lists.
I have three classes:
public class ScopeType
{
public int ScopeTypeId { get; set; }
[Required]
public string Type { get; set; }
}
public class ScopeManufacturer
{
public int ScopeManufacturerId { get; set; }
[Required]
[Display(Name="Manufacturer Name")]
public string Name { get; set; }
}
public class Scope
{
public int ScopeId { get; set; }
[Required]
public ScopeManufacturer ScopeManufacturer { get; set; }
[Required]
public string Name { get; set; }
[Required]
public ScopeType ScopeType { get; set; }
[Required]
public int Aperture { get; set; }
[Required]
public int FocalLength { get; set; }
}
Essentially, the first two classes are just lists of values that I want to appear in the drop downs on the 'Scope' create/edit forms. It's a 1 to 1 relationship.
I build the solution, and then add scaffolded controllers and views. Unfortunately, for the 'Scope' controller and views, the ScopeType and ScopeManufacturer navigation properties are ignored; no drop down lists are generated.
I then found on Google examples where people describe specifying the relationship between items by creating properties of integers, with the same name as the Id on the related thing. Therefore, I deleted the controllers and views, and tried again with:
public class Scope
{
public int ScopeId { get; set; }
[Required]
public int ScopeManufacturerId { get; set; }
[Required]
public string Name { get; set; }
[Required]
public int ScopeTypeId { get; set; }
[Required]
public int Aperture { get; set; }
[Required]
public int FocalLength { get; set; }
}
This still didn't scaffold drop down lists for me - rather, it gave me 2 extra fields for me to type integers into.
What am I doing wrong, or am I mistaken in believing that the scaffolding in MVC 4 will generate drop down lists for 1 to 1 relationships like that?
In Silverlight, how does one get row data from a DataGrid that is full of data?
I have gotten this far (in a method that receives a button click on a row(:
DataGridRow item = (DataGridRow)dg.SelectedItem;
Now, how do I get the individual components of the item that I guess is the selected row?
Help me out here. How do you bind an observablecollection to the grid?
How do you use the cast system when you cast to the object?
When I read the data into the grid, I used this class:
public class Data
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public bool Available { get; set; }
public int index_1 { get; set; }
public int index_2 { get; set; }
public int index_3 { get; set; }
public int index_4 { get; set; }
public int index_5 { get; set; }
public int index_6 { get; set; }
public int index_7 { get; set; }
public int index_8 { get; set; }
public int index_9 { get; set; }
public int index_10 { get; set; }
public int index_11 { get; set; }
public int index_12 { get; set; }
public int index_13 { get; set; }
public int index_14 { get; set; }
public int index_15 { get; set; }
}
So how so I cast when I read back out
This does not work:
Data _mydata = new Data();
YValue = (_mydata.index_1)dg.SelectedItem;
This does not work:
YValue = (index_1)dg.SelectedItem;
This does not work:
YValue = (Data().index_1)dg.SelectedItem;
DataGridRow item = (DataGridRow)dg.SelectedItem;
int index1 = ((Data)item).index_1;
That will give you the value of the first index.
If you have bound a ObservableCollection<Foo> to your grid, your selected item can just be cast into your object - (Foo)dg.SelectedItem
EDIT-- UPDATE TO ANSWER UPDATED QUESTION
The simple answer is, if you are not using MVVM (which I assume by your post your not), in the code behind create a collection (preferably ObservableCollection) of Data and set the grids itemsource property to your collection
public ObservableCollection<Data> MyCollection{get;set;}
void SetGridItemsSource()
{
// populate your collection here, then use the below line to associate it with your
// grids itemssource
MyGrid.ItemsSource = MyCollection;
}
public void GetSelectedItem()
{
//Simply cast the selected item to your type
Data selectedItem = (Data)MyGrid.SelectedItem;
}