I am new to MVC. I went through the getting started guide for MVC 5 by Microsoft and have some really basic understanding of how things work. What I am looking to do is create a view page which display data from my domain model and related data that is not part of the domain model (the related data is on another sql server which I am not inserting or updating records. It's just related data I can associate with the data in my domain model).
For simplicity lets say I have a domain model that includes:
Student with Id Firstname, LastName, CourseId
Course with Id, Name, Department, ExtraInfoId
and I want to create another "model" (not sure if model is the correct term for this)
ExtraInfo with ExtraInfoId, Time, Location
The ExtraInfo is related to the Course by ExtraInfoId. ExtraInfo won't be in the database I am creating or updating. It is a external database that I want to connect to and pull data out of for display purpose, exampe get a student's Firstname, the course taken and then any "ExtraInfo" related to the Course.
I hope this makes sense. Any information or some quick sample code would be much appreciated.
Thanks!
Let's assume you have two class, one for your model
public class Student{
public string Name {get;set;}
public string LastName {get;set;}
public int CourseId {get;set;}
public string Name {get;set;}
public string Department {get;set;}
public ExtraInfo ExtraInfos {get;set}
}
public class ExtraInfo {
public int ExtraInfoId {get;set;}
public DateTime? Time {get;set;}
public string Location {get;set;}
}
Then in you controller you valorize first the Student class, then the ExtraInfos property of the student class and return the student class to you view, as a viewmodel.
var student = GetMyStudent(id); //method for accessing your student's data, could be linq with EF, or a httpclient call
student.ExtraInfos = GetExtraInfo(id); //same
return View(student);
Related
This question already has answers here:
What is ViewModel in MVC?
(16 answers)
Closed 5 years ago.
I have a Account class for account models.
public class Account
{
[Key]
public Int64 UID { get; set; }
[Required]
public string ID { get; set; }
[Required]
public string PassWord { get; set; }
[Required]
public string UserName { get; set; }
}
My project is not a code first project and this is a model class for database 'Account'.
But I use only two properties in login view, string ID and string PassWord.
So I can not use ModelState.Isvalid() in the login controller when I check the validation of model because I use
just two properties...
So I searched about that then, now I found about 'ViewModel' which is the model class for view.
Then I created a new class 'AccountViewModel' and then I mapped this with view instead of 'Account' model.
Did my way was right?
I understood the ViewModel is a model class just for View.
And The model class is for all. (like a global meaning...? for DB,view and so on)
What is different between Model and ViewModel class?
May I get some a nice way to solve this?
As the name says, view model is very specific to the view.It will be a simple POCO with only those properties needed for the view.
Your other model class is your entity models. So if you are using EF code first approach, you need entity class definitions from which EF will generate the database tables. So basically these entity classes look very similar to your db schema structure.
By creating a view model, you are removing the strong coupling of your entity classes to the UI layer. Now your UI layer is independent of your entity classes and if you ever decide to change the data access code from EF to something else, you do not need to touch the views at all.You simply need to update the mapping part(from the view model to the data access/service layer entities)
View models sometimes looks very similar to your entity models, especially if your entity model is a simple table/class.
In your case, since your view is passing a userid and password, you need a simple view model which has only those 2 properties. When user submits the form,you can read the values and use it to build an domain entity class object as needed.
public class LoginViewModel
{
public string UserId { set;get;}
public string Password { set;get; }
}
You can use data annotations with the view models. The MVC model validation framework these data annotations to do the validations. For example, since user should enter a UserId and Password, you may decorate them with appropriate annotations.
public class LoginViewModel
{
[Required]
public string UserId { set;get;}
[Required]
public string Password { set;get; }
}
The [Key] attribute is more useful when you define an entity class. So i would not think it is needed for a view model. Remember view model is more like a UI concern. It has no idea about your underlying data storage mechanism at all.
Some of the most used attributes with view model properties are
Required
MinLength
Range
Url
Phone
StringLength
DataType
Well hi everyone I'm kinda new on Asp.net Mvc, and need some help to improve, in my project that I'm working at, I need to register a user and in the register the user must choose some tags that are categories related to the subject of my website, the thing is that i have a database that looks like this
Tag
public int TagId{get;set;}
public string TagName{get;set;}
public string TagColor{get;set;}
TagUser
public int TagUserId{get;set;}
public int UserId{get;set;}
I read that EF constructs the tables when there is a many to many relationship, it construct the middle table automatically so in my case do i just need to have the first model and my user model? or should i use the 2 models above plus the user model, with the second approach i don't know how to relate de data i can define the TagUserId as primary key and UserId as foreignkey and relate the tables, but do i need this? or can i do that with the first approach if someone can give me a tip i appreciate a lot. :)
Ps: Sorry for my bad English
You can keep a Tags property of type IList<Tag> in your User class and a Users property in your Tag class of type IList<User>. Entity Framework will create a third table to store the many to many association between Tag and User.
public class Tag
{
public int Id {set;get;}
public string TagName {set;get;}
public virtual IList<User> Users { get; set; }
}
public class User
{
public int Id {set;get;}
public string UserName {set;get;}
public virtual IList<Tag> Tags { get; set; }
}
I have a CustomersController and in the Detail.cshtml view I need to display a list of that Customer's contacts and a list of that Customer's locations. I have a Detail(int? id) ActionResult and I have access to my CustomerService from within the controller. As of now in my Detail ActionResult I am able to do:
var cust = _custService.GetCustomerById(id);
return View(cust);
How would one recommend getting the rest of my lists in the view. I think I will create a GetContacts(customerID), GetLocations(CustomerID) within my CustomerService and then call them just like I call GetCustomerByID above. If I were to do it this way how would I have access to these lists in my view.
The next thing I was thinking about was possibly creating a ViewModel that has all of the basic customer properties like customer.Name, customer.Phone but then trying to figure out how I also make sure the ViewModel has the customer's contacts and locations. Would I just add 2 more properties to the ViewModel like customer.contacts and customer.locations since EF6 will make them available to me?
Any suggestions on the best way to go about getting multiple lists of information related to an entity in a view? Customer contacts and Customer locations are both one-to-many
The best practice is using a view model to transfer the data, as you have thought about.
public class CustomerDetailViewModel {
public string Name { get; set; }
public string Phone { get; set; }
public List<Contact> Contacts { get; set; }
public List<Location> Locations { get; set; }
}
Let's say I have two classes, a Company class and a Customer class.
public class Company
{
public int Id {get; set;}
public Customer Customer {get; set;}
}
public class Customer
{
public int Id {get; set;}
public string Name {get; set;}
}
I want to be able to update the customer associated with the company using a drop down list. So, the edit method in my controller creates a viewmodel.
public class ViewModel
{
public List<Customer> AvailableCustomers {get; set;}
public Company Company {get; set;}
}
The view creates a form with a drop down list from which to select a customer (using Knockout).
<select data-bind="attr: {name: 'Company.Customer.Id'}, options: AvailableCustomers(), optionsText: 'Name', optionsValue: 'Id', value: Company.Customer.Id"></select>
When the form is posted back to the server, I have the Company model with the new Customer Id selected by the user. Now I want to update the database using Entity Framework.
I get the Company being updated out of the database using the id for the Company that was posted back in the form data, which is just my viewmodel from earlier. Now I want to update the Company with a new Customer. The only information I have at this point is the Id of the Company that the user selected from the drop down list. So I do something like this:
var companyBeingUpdated = repository.GetByKey<Company>(Company.Id);
companyBeingUpdated.Customer.Id = Company.Customer.Id;
As soon as I call update on my repository, I get an exception that says "The property 'Id' is part of the object's key information and cannot be modified". The update method on my repository looks like this:
public void Update<TEntity>(TEntity entity) where TEntity : class
{
var entry = this._dbContext.Entry(entity);
if (entry.State == EntityState.Detached)
{
this._dbContext.Set<TEntity>().Attach(entity);
}
entry.State = EntityState.Modified;
}
I am clearly doing something wrong with Entity Framework. I could easily do this with a SQL statement, but I want to understand what I am doing wrong with EF.
How do I go about updating the Customer related entity of the Company object with EF when the only information I have is the Customer Id posted back in the form data?
I know I could probably retrieve the Customer entity from the database using the Id and assign the Company.Customer to that retrieved Customer, but this is actually a very simplified example. In reality, I have quite a bit more than just one related entity and if I have to make a trip to the database to look up each related entity in order to do the update, I can see performance quickly becoming a problem.
What you want to do with your entities is have access to the Foreign Key. however, you cannot directly access the Foreign Key through the related entity, instead you are accessing the Primary Key of that related entity.
i.e. instead of accessing the Company Customer_Id property in SQL, you are accessing the Customer Id property.
You can expose the Foreign Keys to your model in Entity Framework, allowing you to do the types of updates you are after.
public class Company
{
public int Id {get; set;}
[ForeignKey("CustomerId")]
public Customer Customer {get; set;}
public int CustomerId {get;set;}
}
now, you can do updates as companyBeingUpdated.CustomerId = Company.CustomerId; and not have to do a lookup to retrieve the full Customer Entity.
i have two simple models that have one-many relation
public class X{
public int id {get;set;}
public virtual Y y{ get; set; }
public string description{get;set;}
}
public class Y{
public int id{get;set;}
public string name{get;set;}
}
and from the entity framework i set the relation
I'm trying to submit a form that creates a new X record with existing Y value
the returned data from the form to the action is the string description and y_id.
on the action when i try to specify the object from the parameters
public ActionResult sth(X x){}
the x.y is set to null (which is expected...) while when i tried the following ...
x.y = (from i in Y where i.id == that_id select i).first();
...
db.saveChanges();
the entity framework inserted a new Y record to the database ...
i know that i'm doing something wrong ... your help will be very appreciated !
Looking at the code you have an ID for x and y with a Virtual Y in x. Along with this Virtual Y in x you will also need a reference to y's id. Along with a Virtual ICollection of x in y.
public class X{
public int x_id {get;set;}
public int y_id {get;set}
public virtual Y y{ get; set; }
public string description{get;set;}
}
public class Y{
public int y_id{get;set;}
public string name{get;set;}
public virtual ICollection<X> X {get;set;}
}
This helps the relationship in entity. You may also want to pass a list of y(s) to the controller in charge of your form, unless you already selecting your y value from a dropdown on the form.
It seems an issue with tracking Y objects in the dbContext. how are you generating the collection Y you querying with linq? do you fetch it from the database using a dbContext? or from some other source?
if not, you need to be fetching it using a context or using the Attach() function so it could be properly tracked.
Another question pops up. how come a new Y is inserted? Don't you have a primary key defined in the database? or is it try to insert then an exception is thrown?
These are my thoughts on the matter.