I have a C# MVC Model as follows;
public class MyModel
{
...
public IEnumerable<MyModel> allDetails { get; set; }
public int age { set; get; }
public string gender { set; get; }
public int schoolid { set; get; }
...
}
Now want to retrieve data from allDetails. How can i do it ?
In the controller;
model.allDetails = MyDetails.getAllDetails(); // Saves all details in the Model
Now how can i retrieve age, gender and school from this model; My approach as follows (but its doesn't work)
model.allDetails.age; // This doesn't work
In your code model.allDetails is a list (or smth else that implements IEnumerable), so you have to use foreach or another loop, or just First() to get first value from it: model.allDetails.First().age
I think you got your desing for class MyModel wrong, You should probably have two classes like:
public class MyClass
{
...
public IEnumerable<MyModel> allDetails { get; set; }
public int age { set; get; }
public string gender { set; get; }
public int schoolid { set; get; }
...
}
public class MyModel
{
...
public IEnumerable<MyClass> allDetails { get; set; }
...
}
Where your MyModel class will contain an IEnumerable of your other class which contains properties. Later you can fill your model through controller.
In your current MyModel class, you are keeping IEnumerable of the class itself, so each object for that class will have another IEnumerable and so on.
You may also see: C# Coding Conventions (C# Programming Guide) for your properties names.
Related
This is my first question on StackOverflow, so please forgive and tell me if I'm doing something wrong.
Problem:
I write some kind of dictionary connected to DB and text files etc. nothing commercial, just learning. For better explanation it can be English-French.
I want to refactor the code to have possibility of use one "general" method to process entrance for English-French and French-English dictionary model. On the begining i made separate model for each of them(I will paste if necessary) and now i would like to make everything "universal". What I did till i stop:
public interface IWordModel
{
int Id { get; set; }
string Name { get; set; }
string Definition { get; set; }
}
class implementing IWordModel:
public class EnglishWordModel: IWordModel
{
public int Id { get; set; }
public string Name { get; set; }
public string Definition { get; set; } = null;
}
public class FrenchWordModel : IWordModel
{
public int Id { get; set; }
public string Name { get; set; }
public string Definition { get; set; } = null;
}
Interface implementing IWordModel and problematic List of this interface:
public interface IDictionairyModel<T> where T : IWordModel
{
int Id { get; set; }
T BaseWord { get; set; }
List<T> DerivativeWords { get; set; }
}
Class implementing IDicionairyModel
public class EnglishFrenchDictionairyModel<T>: IDictionairyModel where T : IWordModel
{
public int Id { get; set; }
public IWordModel BaseWord { get; set; } = new EnglishWordModel();
public List<IWordModel> DerivativeWords { get; set; } = = new
List<IWordModel>(new List<FrenchWordModel>());
}
public class FrenchDictionairyModel: IDictionairyModel<T> where T : IWordModel
{
public int Id { get; set; }
public IWordModel BaseWord { get; set; } = new FrenchWordModel();
public List<IWordModel> DerivativeWords { get; set; } = = new
List<IWordModel>(new List<EnglishWordModel>());
}
And my Question
How to make that i.e in FrenchDictionairyModel instance we will be able to define BaseWord only as FrenchWordModel and add to DerivativeWords list ONLY EnglishWordModel? I know it have something common with covariance and contrvariance but i dont have idea how to apply this here.
Is it above code have some sense from experienced coder point of view or it's look like OK only in my head? If answer is NO then how it should look like, what pattern should i use?
How to use it properly in other methods? As now i was using i.e
public List<EnglishFrenchDictionairyModel>
CreateEnglishFrenchEntrance(List<EnglishFrenchDictionairyModel> model){
( ... )}
but its already showing "Using generic type requires 1 type arguments".
Thanks and have a Great Day!
It sounds like you need two generic parameters - one to apply to BaseWord and one to apply to DerivativeWords:
public interface IDictionairyModel<T,U>
where T : IWordModel, U : IWordModel
{
int Id { get; set; }
T BaseWord { get; set; }
List<U> DerivativeWords { get; set; }
}
Then define your FrenchDictionaryModel as so:
public class FrenchDictionairyModel:
IDictionairyModel<FrenchWordModel, EnglishWordModel>
{
public int Id { get; set; }
public FrenchWordModel BaseWord { get; set; } = new FrenchWordModel();
public List<EnglishWordModel> DerivativeWords { get; set; } = new List<EnglishWordModel>();
}
Thanks D Stanley! it works fine, just need to add two where clauses for U and T like:
public interface IDictionairyModel<T,U>
where T : IWordModel,
where U : IWordModel {(...)}
But now i have another issue which i would like to implement here.
For example i would like to create some method which will be remove duplicates from List but i want to this to be ONE method for all class which implementing IDictionairyModel
public static List<IDictionairyModel<IWordModel, IWordModel>> RemoveDuplicates(this List<IDictionairyModel<IWordModel, IWordModel>> model)
{
(...) return model;
}
What I need to do to be able to use this extension method on
List<FrenchDictionairyModel> model = new List<FrenchDictionairymodel>();
model.RemoveDuplicates();
As for now it return error.
Should I make FrenchDictionairyModel also generic like:
public class PoznanPolishDictionairyModel<T,U> : IDictionairyModel<PoznanWordModel, PolishWordModel>
where T:IWordModel
where U:IWordModel
??? What is the proper way
Thanks a lot!!!
Have a wonderful Sunday!
Best Regards
I am considerably new to MVVM implementation. This might sound like a repetitive question but there is nothing that I could find that would help me understand better with my knowledge which is basic. I have a Model class with members as shown here:
public class Model
{
public string Name { get; set; }
public int Age { get; set; }
public List<Model> Children { get; set; }
}
I have wrapped this model class in a view model but with ObservableCollection in place of List.
public class ViewModel
{
private Model model;
public ViewModel()
{
model = new Model();
}
//getters and setters for both Name and Age
public ObservableCollection<ViewModel> Children
{
//how to convert List<Model> to ObservableCollection<ViewModel> here?
}
}
I definitely do not want to expose my Model class to the view which is why I need to create an ObservableCollection of the VM class. Not sure how to achieve this though. Any help appreciated.
You are probably looking for the following:
public class Model
{
public string Name { get; set; }
public int Age { get; set; }
public List<Model> Children { get; set; }
}
public class ViewModel
{
public ViewModel(Model m)
{
Name = m.Name;
Age = m.Age;
Children = new ObservableCollection<ViewModel>(m.Children.Select(md=>new ViewModel(md)));
}
public string Name { get; set; }
public int Age { get; set; }
public ObservableCollection<ViewModel> Children { get; set; }
public Model GetModel()
{
return new Model()
{
Age = Age,
Name = Name,
Children = Children.Select(vm=>vm.GetModel()).ToList(),
};
}
}
You will note that a lot of that is boilerplate code. But if you do it this way, your model/viewmodel are completely separated, which will save you SO many problems down the line.
I've two tables as Models in my project Like:-
public partial class TblAlbum
{
public int ID { get; set; }
public string Album { get; set; }
public string Artists { get; set; }
public Nullable<int> AudioID { get; set; }
public Nullable<int> VideoID { get; set; }
public virtual TblVideo TblVideo { get; set; }
public virtual TblAudio TblAudio { get; set; }
}
and
public partial class TblAudio
{
public int ID { get; set; }
public string Name { get; set; }
public string Alt { get; set; }
public string Artist { get; set; }
public string Image { get; set; }
public int LangID { get; set; }
public virtual TblLanguage TblLanguage { get; set; }
public virtual ICollection<TblAlbum> TblAlbums { get; set; }
}
Now I've Made a ViewModel as GetDetailsVM that have access to both tables and has the LINQ Query as:-
public class GetDetailsVM
{
private MusicEntities db = new MusicEntities();
public IEnumerable<dynamic> GetAudio()
{
var AudioList = from au in db.TblAudios
join al in db.TblAlbums on au.ID equals al.AudioID into ar
from al in ar.DefaultIfEmpty()
select new { au,al };
return AudioList.ToList();
}
}
My ViewModel(AudioAlbumVM) to read Getaudio() should be something like this:-
public class AudioAlbumVM
{
public IEnumerable<dynamic> AudioObjList { get; set; }
public string AlbumName { get; set; }
}
Now I want to access this ViewModel in my controller and then use it in my cshtml.
My Controller:-
public ActionResult Audio()
{
ViewBag.Title = "Audio";
var AudioSummary = new GetDetailsVM();
var viewModel = new AudioAlbumVM
{
AudioObjList = AudioSummary.GetAudio().First()
};
return View(viewModel);
}
UPDATE
My View(Audio.cshtml) is as follows:-
#model GarhwalMusic.Models.AudioAlbumVM.AudioObjList
<a class="art" href="single.html"> #Model.AudioObjList</a>
I was going through this question LINQ left join only works in the ActionResult but I'm completely lost . Need help and explanation on how to create AudioAlbumVM using another ViewModel(GetDetailsVM) then in controller and then in cshtml. Any help is greatly appreciated!!
Taking this from your comments
Now I'm getting this error:- The model item passed into the dictionary is of type 'GarhwalMusic.Models.AudioAlbumVM', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable`1[GarhwalMusic.Models.AudioAlbumVM]'.
Problem is with this code
var viewModel = new AudioAlbumVM //its a single model
{
AudioObjList = AudioSummary.GetAudio().First()
};
But it seems like your view is expecting a model of type IEnumerable<GarhwalMusic.Models.AudioAlbumVM> or (List<GarhwalMusic.Models.AudioAlbumVM>). You need to either pass a List<GarhwalMusic.Models.AudioAlbumVM> to your view or change your view to accept a model of type GarhwalMusic.Models.AudioAlbumVM.
But looking at your code I assume that you are trying to pass the collection of AudioObjList into your View. So your view must accept a model of type
GarhwalMusic.Models.AudioAlbumVM.AudioObjList and you need to just Pass in only the viewModel.AudioObjList from your controller.
EDIT 1: After you added more details of your view, You are making a mistake in the way you are accessing the data.
your Model.AudioObjList is of type IEnumerable<dynamic> and how can you just print something on the Vie like #Model.AudioObjList ?? I am referring to this code
<a class="art" href="single.html"> #Model.AudioObjList</a>
You need to typecast this dynamic type into what ever object you have created in your linq and then extract its property value. Something like
#((yourObject)Model.AudioObjList[0]).propertyName
(yourObject)Model.AudioObjList[0] type casts your dynamic data into a type yourObject.
you need [0] because your AudioObjList is of type IEnumerable<dynamic>. So taking the first data.
I have a model which is storing mycustomer new request information.
In another history model i am storing all previous request of the customer.
In view i would like to take new order and also see his previous orders and suggest some food after seeing his previous order.
Here are my models...
public class CustomerFoodModel
{
public DateTime FoodRequestCreated { get; set; }
public string FoodRequestType { get; set; }
...
...
}
public class CustomerHistoryModel
{
public string Name { get; set; }
public DateTime FoodRequestCreated { get; set; }
public string FoodRequestType { get; set; }
...
...
}
Helper.cs file
public static CustomerFoodModel getCustomerDetails(int id) // id is loyalty card number
{
// get details from (cutomer) sql table
//store it in (CustomerFoodModel)
// check if it has previous orders
getCustomerHistoryDetails(id);
....
}
public static CustomerHistoryModel getCustomerHistoryDetails(int id)
{
// get deails from (history) sql table
// store it in (CustomerHistoryModel
}
In my controller, I am passing my (CustomerFoodModel) to the view.
public ActionResult EditCustomerRequest(int id, string name, string date)
{
CustomerFoodModel CRequest = Helper.getCustomerDetails(id);
...
return PartialView("EditCustomerRequest",CRequest);
}
How do I show the (CustomerHistoryModel) in the same view.? Is there possible to include (CustomerHistoryModel) in (CustomerFoodModel)?
Create a new class to wrap both of the model.
public class CustomerFoodModel
{
public CustomerFoodModel CustomerFood { get; set; }
public CustomerHistoryModel CustomerHistory { get; set; }
}
And on your controller
public ActionResult EditCustomerRequest(int id, string name, string date)
{
CustomerFoodModel CRequest = Helper.getCustomerDetails(id);
CustomerHistoryModel CHModel = Helper. getCustomerHistoryDetails(id);
return PartialView("EditCustomerRequest",new CustomerFoodModel(){
CustomerFood = CRequest,
CustomerHistory = CHModel
});
}
I think the best approach is to use a partial view inside the main view. The partial view can call back to another controller to get a new model and pass that model to the partial view. This keeps things better seperated.
Look at this post for a similar issue.
Using partial views in ASP.net MVC 4
Use wrapper class which contain both of class
public class CustomerViewModel
{
public CustomerFoodModel FoodModel { get; set; }
public CustomerHistoryModel HistoryModel { get; set; }
}
You have a few options. I would probably could create a view model that contains both of your models:
public class CustomerViewModel
{
public CustomerFoodModel FoodModel { get; set; }
public CustomerHistoryModel HistoryModel { get; set; }
}
Or, depending on your data structure, you may have multiple history entries per customer:
public class CustomerViewModel
{
public CustomerFoodModel FoodModel { get; set; }
public List<CustomerHistoryModel> HistoryModels { get; set; }
}
Then your getCustomerDetails function would return a CustomerViewModel instead.
I have two entities: Person and Quote (in one to many relationship)
Person:
public class Person
{
public int PersonID { get; set; }
[Required]
[StringLength(20]
public string Name { get; set; }
[StringLength(30]
public string Relation { get; set; }
public byte[] Image { get; set; }
[StringLength(50)]
public string ImageMimeType { get; set; }
public virtual ICollection<Quote> Quotes { get; set; }
}
Quote:
public class Quote
{
public int QuoteID { get; set; }
public int PersonID { get; set; }
[Required]
[StringLength(200)]
public string QuoteName { get; set; }
[StringLength(400)]
public string Context { get; set; }
public DateTime? Date { get; set; }
public virtual Person Person { get; set; }
}
I want to make a ViewModel for displaying quotes in short format - I need just a few properties - Person Name, QuoteName and Person Image. I could do something casual like they're showing in every ASP.NET MVC tutorial:
public class QuoteViewModel
{
public IEnumerable<Quote> Quotes { get; set; }
}
Is there a better way rather than creating IEnumerable with type of Quote and loading all properties?
How about creating QuoteShort model and making QuoteViewModel as IEnumerable<QuoteShort> QuotesShort.
In controller I would map every 3 fields from repository to QuoteShort and add it to QuotesShort IEnumerable (even though I don't know how to persist them to QuotesShort IEnumerable )
Some examples appreciated.
You can make a QuoteShort ViewModel with just the few properties you need, and then have your view expect IEnumerable<QuoteShort> as its model. You don't necessarily have to wrap that up in another container.
If you have this:
public class QuoteShort{
public Person Person {get;set;}
public string Name {get; set;}
// etc
}
You can do this in the controller:
var quotes = //however you get your list of quotes
var model = (from q in quotes select new QuoteShort
{ Person = q.Person, Name = q.Name /*etc*/ }).ToList();
return View(model);
What about something like
public class QuotesShortViewModel
{
public IEnumerable<QuoteShortViewModel> QuotesShort { get; set; }
}
public class QuoteShortViewModel
{
// ... the properties you need
}
Create a View that receives a QuotesShortViewModel and iterates through the list, rendering the short quotes as it pleases you.
AutoMapper is useful to map between Models and ViewModels in your controllers.