I basically have a model that consists of another model that is a base class with 2 sub classes. How would I use this in my view. Obviously the main model would be passed into the view; however how would I cast the the submodel to one of it's subsclassesclasses? Please see the following for an example of what I mean. In my view I would have the TransporationModel. Say we are collecting data for this model from a form, and the current form is getting details for a Car type Vehicle. On submitting the form how would I cast the Car to its base type Vehicle?
public class TransaportationModel
{
public VehicleModle vehicle { get; set; }
...other fields
}
Many thanks,
James
Car car = new Car { /*Properties*/ };
Vehicle vehicle = (car as Vehicle);
From Wikipedia:
"The model manages the behavior and data of the application domain, responds to requests for information about its state (usually from the view), and responds to instructions to change state (usually from the controller). In event-driven systems, the model notifies observers (usually views) when the information changes so that they can react."
This means the individual classes that manage your data aren't 'models' perse. It is all of these classes together that create the model. You should look more into MVC pattern and thinking in objects.
Related
I have the following model:-
[MetadataType(typeof(TMSServer_Validation))]
[Bind(Exclude = "TMSRack,ServerModel")]
public partial class TMSServer
{
}
and I have the following drop down inside my view:-
#Html.DropDownListFor(model =>model.Server.TMSRack.DataCenterID, ((IEnumerable<TMS.Models.DataCenter>)ViewBag.DataCenters).Select(option => new SelectListItem {
Text = (option == null ? "None" : option.Name),
Value = option.ID.ToString(),
Selected = (Model.Server.TMSRack != null) && (option.ID == Model.Server.TMSRack.DataCenterID)
}), "Choose...")
Then on my controller class I have the following :-
ViewBag.Racks = repository.getrelatedracks(Server.TMSRack.DataCenterID);
But since I have excluded the TMSRack navigation property (mainly to avoid over-posting attacks), so the Server.TMSRack.DataCenterID will always be null. And to get its value I wrote the following:-
ViewBag.Racks = repository.getrelatedracks(Int32.Parse( Request.Form["Server.TMSRack.DataCenterID"]));
But I know that using Request.Form is not the right approach to follow, so my question is there a way to get the excluded property using more reliable way ?
Thanks
My answer is going to assume TMSServer is a domain model.
With that in mind, this is the perfect example of when to use a view model. By using a view model instead, you have complete control over how the properties are mapped from the view model to the domain model. Something like:
public class RackViewModel
{
public int DataCenterID
// other Rack properties
}
Then either send a list of RackViewModel to your view, or create a view model that encompasses all of that, too:
public class ContainerViewModel
{
public List<RackViewModel> Racks { get; set; }
// other view-specific properties
}
Now, when you POST the data back, not only do you have complete control over what properties you want to bind to your view models, you also have complete control over the mapping that takes place from converting your view models to domain models.
The bottom-line is this: if your view accepts a view model that only allows the user to POST the data they should be allowed to POST, over-posting doesn't even exist. Well-designed view models, or even making the distinction between a view model and an input model (i.e. a separate model that represents the data you want to bind back to in your action), eliminates over-posting entirely.
Over-posting only exists because you're not restricting the model binding process enough. If you ask it to bind to a class that has 10 properties in it when you only need 3 you're allowing the user to potentially stuff data into those other 7 properties.
This is one reason why view models are so popular. They allow you to narrow the scope of your view, whilst also narrowing the scope of the model binder. That leaves you free to properly manage the process of mapping from your view model to your domain model, without introducing a vulnerability.
Update
As you don't want to go the view model approach, your idea will work but you can do it slightly differently. Something along the lines of:
public ActionResult SomeAction(SomeModel model, TMSRack rack)
Where:
SomeModel is the type of model you're decorating with Bind(Exclude...) (it's not obvious what type that is from your question.
TMSRack is the type I assume you want to bind to.
As TMSRack is defined in your main model anyway, as long as you're using the Html.* helpers, it will have the correct names generated for it on the form in order to bind straight back to it as a separate parameter on your action. Then you can do whatever you want with it, without resorting to Request.Form.
Wanna get views on a very basic structure as follows:
"Person lives inside town ABCTown. ( ABCTown consists of "Person" visually). And "Person" has information about town ABCTown", ie. he has knowledge about his town.
That's all .
A very basic approach would be making two classes Class_Person and Class_ABCTown . And exchanging references of each other.
public class Class_ABCTown
{
var person:Person ;
.....
.....
public function get personInfo()
{
return person.info() ;
}
}
public class Person
{
var abcTown:ABCTown ;
....
....
public function get townInfo()
{
return abcTown.info() ;
}
}
Now as a programmer, i want to extend the project more towords MVC design pattern. So what do you think, what classes can i add here, and how can i arrange them, to get a MVC design.
( For example Class_ABCTownView can be created to store the reference of PersonView, because visually, person is present inside the town )
Share your views.
Thanks
"Person lives inside town ABCTown. ( ABCTown consists of "Person" visually). And "Person" has information about town ABCTown", ie. he has knowledge about his town.
Based off of this I'd create a Person Class, a Town Class and have them consists of a One-Many relationships (one town can have many people). This is all that is needed for the model.
The Controller is sort of like a pointer that directs all user input to the correct action (so if you click the details button the controller will direct the application to go to the view page and display the model).
The view page essentially is used to display information and forms.
If you want an action to happen such as a person moving to a town, you can put in an Edit action for example in the Person Controller to edit information about a person such as which town they live in. This will cause the application to go to an edit view where users can make changes.
This is a well-known tutorial that teaches you what MVC is and how to use it: http://www.asp.net/mvc/tutorials/mvc-music-store
I think you are misunderstanding the MVC pattern. The code above represents the M part of MVC - the data Model. The V (View) would be the classes, JSPs, etc that present the information to the user, and the C (Controller) is the code that handles user interaction, retrieves the data model from persistence, updates the model, binds the model data to the View, etc.
I've read a few articles about MVC but there's one thing that isn't clear to me. What is the role of the model in practical term.
Does the model represent the business object?
Or is it just a class that help send information from the controller to the view?
Take for example two business class (data populated from the database)
Class Image
Property FileName As String
Property CreatedBy As User
End Class
Class User
Property UserName as String
End Class
Will "Image" be the model or should I create a new class?
In the model, should I create a UserName property that will fetch it's data from the User object?
Class ImageModel
Property FileName As String
Property CreatedBy As User
ReadOnly Property UserName As String
Get
Return User.UserName
End Get
End Property
End Class
There are many views on this, but in my experience, there are 2 major views of the Model:
ViewModel
This is a POCO that simply contains all the data necessary to display the View. The data is usually populated by the Controller.
Fat Model, Skinny Controller
The Model does the majority of the business-work. It contains and populates all the data that is needed by the View, and is used by the Controller to save data, etc.
The beauty of MVC
The beauty of MVC is that it's OPEN! You can choose any type of model you want ... you can put all your data into ViewState, into a Model, into a ViewModel that contains a bunch of Models, whatever. It's really up to you. The Model, View, and Controller are blank canvases that can be used however you like.
What I use
My team has done a lot of MVC work, and we have tried many of these different methods. We finally decided that our favorite was the Fat Model, Skinny Controller paradigm.
I believe that this pattern is the best at "keeping it simple" and "don't repeat yourself", and it definitely maintains the "separation of concerns".
Here's how our code is organized:
Controllers
Handles everything that pertains to HTTP requests - redirects, authentication, web safety, encoding, etc.
Gives all "input" to a Model, and gives the Model to the view. Does NOT access Business or Data layers.
Views
Handles all HTML and JSON generation
Only accesses data from the strongly-typed Model
Models
Responsible for making all updates, calling Business and Data layers, loading all data
Handles all validation and errors, and returns these to the Controller
Contains properties of all data that is required for the View, and populates itself
Even though this sounds like a generic principle of MVC, it quickly becomes obvious that MVC does not require these principles, which is why many projects use other principles.
Example
Here's an example Model. The Controller creates it, it populates itself, and the Controller passes it to the View.
public class UsersModel
{
protected UserBusiness userBusiness = new UserBusiness();
public UsersModel(string editUserName)
{
// Load all users:
this.Users = userBusiness.GetAllUsers();
// Load the user to be edited:
this.EditUser = (editUserName == null) ? null : userBusiness.GetUser(editUserName);
}
public List<User> Users { get; private set;}
public User EditUser { get; private set; }
}
All the "user business logic" in this case is in a different project (our "Business Layer"), because we have a large system. But smaller projects don't require this ... the Model can contain business logic, and even data-access code.
There are many models. It both can be business data (or domain) objects (Controller -> Datasource, and vice-versa), business rules (act on domain objects) or view models (Controller to View, and vice-versa).
You don't explicitly have to define the username again in ImageModel.
I am pretty new to MVC and I am looking for a way to design my models.
I have the MVC web site project and another class library that takes care of data access and constructing the business objects.
If I have in that assembly a class named Project that is a business object and I need to display all projects in a view ... should I make another model class Project? In this case the classes will be identical.
Do I gain something from doing a new model class?
I don't like having in views references to objects from another dll ... but i don't like duplicating the code neither.
Did you encounter the same problem?
I usually use a combination of existing and custom classes for models, depending on how closely the views map to the actual classes in the datastore. For pure crud pages, using the data class as the model is perfect. In real world use though you usually end up needing a few other bits of data. I find the easiest way to combine them is something like
// the class from the data store
public class MyDataObject {
public string Property1 {get;set;}
public string Property2 {get;set;}
}
// model class in the MVC Models folder
public class MyDataObjectModel {
public MyDataObject MyDataObject {get;set;}
// list of values to populate a dropdown for Property2
public List<string> Property2Values {get;set;}
// related value fetched from a different data store
public string Property3 {get;set;}
}
I also have quite a few model classes that are just a set of form fields - basically corresponding to action parameters from a particular form rather than anything that actually ends up in the database.
If it is exactly the same project then obviously don't need to duplicate the Project class, just use it as is in the view. But in real life often views have specific requirements and it it a good practice to define view model classes in your MVC application. The controller will then map between the model class and the view model to be passed to the view.
You will likely find differing opinions on this. I will give you mine:
I tend to, by default, reuse the object. If the needs of the view change and it no longer needs most/all of the data in the business object, then I'll create a separate view. I would never change the business object to suit the view itself.
If you need most/all of the information in the business object, and need additional data, then I would create a view that holds a reference to the business object and also has properties for the additional data points you need.
One benefit of reusing the business object is that, depending on the data access technology you are using, you can get reuse out of validation. For isntance, ASP.NET MVC 3 coupled with Entity Framework is nice as they both use the attributes in the System.ComponentModel namespace for validation.
That depends on what you mean by model. In the architecture I typically use, I have my Domain model, which is a collection of classes in a separate class library. I use DataAnnotations and built in validation to automatically validate my model when saving.
Then there is the View model, which I place in my MVC project. View models only have the information relevant to the view. I use data annotations here as well since MVC will automatically use them for my validation.
The reason for splitting the model this way is that you don't always use every piece of your domain model in a view. That means you either have to rebuild the data on the backend or you have to stash it in hidden fields. Neither is something I like,.
I am pretty new to ASP.NET MVC and I am trying to get my head around some of the design concepts at the moment. One thing I am currently stuck on is how (best) to handle a situation such as that described below.
Suppose I have a page that needs to render a number of "sections". For example, on the left hand side there is a list that is data driven and then the selected item in the list displays a further list in another section on the page. For better understanding lets suggest the left hand list is a list of movie categories and the other list displays a list of movies that are contained within that category, along with the various movie details.
Now, I have some form of ORM such as Entity Framework, LINQ to SQL or whatever that maps the tblCategory and tblMovie database tables into Category and Movie entities respectively. These entities live in the MyMVCApp.Data.Entities namespace. I then use a repository pattern located in the MyMVCApp.Data namespace to encapsulate the queries (via LINQ) against these entities to return our model entities.
This is where my first question lies. Should the repository be returning view model entities or domain entities which are then extended to produce view model entities? In my naive mind I see the entities returned from the ORM as simply containers for the data with domain entities containing the business logic. So surely there should be an abstration here?
Anyway, back to my scenario. Now lets assume I wish to present the two sections described at the beginning of this. I am assuming that what should be happening here is my domain entity model would contain a list of categories and their associated movies. So something like a List each of which contains a List.
This model would have been populated somewhere. This is my second question. Say my assumption above is correct and it is simply data entities are returned from the ORM. Now I have a namespace/project called MyMVCApp.Core.Model (or the like) with some domain entities such as the Movie and Category entities mentioned in the previous paragraph. Do these entities have methods on them to retrieve the data from the ORM and populate themselves? Or does the repository retrieve these populated entity models? And another question on this part, if I have a Movie and Customer entity in my ORM is it acceptable to be having domain entities named the same?
Finally, I assume the controller now has this populated list of Category and Movie objects and passes it back to the view. I am guessing it is best to have each of the sections described at the beginning as partial views and passing the populated model to each? So, it may be the IndexController which retrieves the populated CategoryMovies entity, passing this to the Categories partial view and the Movies partial view. I would then need to somehow determine the selected Category (quesrystring?) and display the appropriate list of Movies in that category within the view.
OK, so if anyone has got to this point in my ramblings I will take a deep bow. I hope I have explained my mixed up thoughts and questions in sufficient detail for someone to provide some kind of enlightenment.
Thanks for listening! :-)
Since you didn't mention it, I will assume you are new to DDD concepts. DDD compliments the "M" in MVC by placing logic where it belongs. And, I think a good amount could be applied here.
In strict DDD form, I would use your Movie example as an Aggregate Root (a DDD concept). Within Movie, you would have business logic (methods) that obtain the categories and related entities directly related to Movie (i.e. Categories-this-movie-belongs-in). This assumes the "category" list you want to display is a list of categories this movie is in.
public class Movie
{
private IList<Category> _categories;
public IList<Category> FetchCategories()
{
// you can lazy-load here, use Linq-to-Sql, etc.
return _categories;
}
public void AddCategory(Category c)
{
_categories.Add(c);
}
}
Of course, you can treat Categories as a Value Object (VO, a DDD concept) here if you don't have an identity on them.
Now, what gets more interesting is if you do want to keep an identity on your Categories, treating them as Aggregate Roots with multiple entities and relations to other VOs and alike. In this case, you would want to utilize the DDD concept of Services to combine the two aggregates into your requested Model you want to pass to your Controller. This allows you to create business rules around loading the categories.
public class Movie
{...}
public class Category
{...}
public class MovieCategory : Movie
{
private IList<Category> _categories;
public IList<Category> Categories
{
get
{
return _categories;
}
internal set
{
_categories = value;
}
}
}
public class MovieCategoryService
{
public MovieCategory FetchMovieCategoryByMovieId(int id)
{
MovieCategory mc = _movieRepository.FetchMovie(id);
// do some logic here, some checks, etc
// to obtain your Categories list. Maybe querystring?
IList<Category> cats = ...;
mc.Categories = cats;
return mc;
}
}
The concept is that you now have logic in the domain layer, in this MovieCategoryService, to handle the complex creation of these relationships, or using Factories to create complex types as well.
This gives you a model you can pass around to different View and PartialViews.
The final step in your original post is how to get this into the View. I've been playing with the ViewModel approach to this issue. Creating ViewModels either dynamically, or as a class, and hanging all of the entities on this ViewModel. A recent StackOverflow question hits on this concept. ViewModel Best Practices
I've passed the Model directly into Views, and I am now trying this approach. It does clean things up, as your DOmain Model really should be disconnected from the "logic" on your page. I find myself thinking, "Dang it. I need to get this partialview populated based on this ID. Guess that means another method on the entity." Going the ViewModel approach removes the logic/thinking from the Domain Model, and puts it where it belong - in the Application/UI layer of where you are fine-tuning your view/partialview.
First of all, I think you should just get started with a simple project and try the various scenarios out you pictured in your long question :). There is nothing written in stone, you can use whatever architecture with datalayers and services or whatever, you like !
Or does the repository retrieve these populated entity models?
I would say yes. Your controller graps these from the service and gets them, populated and all and just moves them to the view in order to be displayed.
I am guessing it is best to have each of the sections described at the beginning as partial views and passing the populated model to each?
And again i think you're on the right track ;).
It is a nice idea to give a view model entity to the view instead of the whole domain entity itself thereby providing the view only the required stuffs to work on
First of all return a List of Categories from your Domain, then construct a Movie view which takes the category name as a parameter something like this
- <Host>/Movies/Comedy
- <Host>/Movies/Horror
which would in turn display the movies which belongs to that particular category