Preparing models for ASP.NET MVC views - c#

When returning strongly typed models for views such as Create and Edit (when validation of the object we are editing fails) I usually prepare the models like this:
//
// GET: /Invoice/Create
public virtual ActionResult Create()
{
// prepare the empty model
Invoice model = new Invoice();
model.Client = new Client();
model.Client.PostCode = new PostCode();
return View(model);
}
//
// POST: /Invoice/Create
[HttpPost]
public virtual ActionResult Create(Invoice document,
FormCollection collection)
{
// check for errors
if (!ViewData.ModelState.IsValid)
{
document.Client = new Client();
document.Client.PostCode = new PostCode();
return View(document);
}
Now I know that this is how others do it too, in fact you can see this same approach in MVC Music Store sample and others. However, this is very error prone because one might accidentally left out a referenced entity which is required in the view. It also requires too much thinking about view/model interaction. What I would want is some sort of automatism. Value typed properties in models usually aren't the problem because they default either to zero or empty strings. Reference types however should be initialized with new..but sooner or later we end up with code blocks that are being repeated, reference type properties being left out, etc..And I don't think it's good coding practice either.
What are other options we could take?
UPDATE:
Because replies kinda missed the point (they do not relief us of thinking about models in any way and require additional code in model classes), I was thinking if this option would work:
Use custom Action filter,
override OnActionExecuted()
use Reflection inside this method to take out the object from the Model and enumerate its public properties and try to initialize them.
I have steps 1, 2 and 3 partially implemented but I cannot figure out how to do "... = new Client();" programatically with Reflection.

Make the properties of your model return a new instance if it is null
private Client client;
public Client Client
{
get
{
if (client == null)
client = new Client();
return client;
}
}

I suggest that you use a Strongly typed view bound to a ViewModel that is distinct from the Domain Model you're trying to create, and put whatever necessary logic into the constructor of the ViewModel

I'm not sure I fully understand your question. You want what automated? ViewModels and Views? Are you creating strongly typed views?
I have created a T4 template that I point to a database and it generates a ViewModel for every table. Foreign keys become drop down lists, long strings get a TextArea instead of TextBox, etc. I then delete the ones I don't need and modify the ones I want to keep. It's not a totally automated process, but it does 80 to 90 percent of the work, depending upon the project.
Then I generate strongly typed Views from those ViewModels.
It also sounds like you might be interested in AutoMapper.

Related

Pass data between Views in MVC

I'm working on a Web Application project using C# and MVC that will take in two URLs in a form and use them to create an instance of a class I have created called "ImageSwap." This model has some data (a username of the person performing the swap; two variables which hold the URLs of two images to be swapped; two variables which save the actual names of these files without all of the rest of the URL information; and two arrays which represent the file locations to check for these files). Right now, I have it so that the initial index view creates the instance of the class and passes it to the same view with the information put in through the form, submitted via POST, like so:
public ActionResult Index()
{
Ops.Operations.Models.ImageSwapModel newImageSwap = new Models.ImageSwapModel();
return View(newImageSwap);
}
[HttpPost]
public ActionResult Index(ImageSwapModel imageSwap)
{
var oldFileFound = false;
var newFileFound = false;
if (ModelState.IsValid)
{
//Perform data manipulation and set needed values
}
}
It then performs some functions on the data, such as parsing out the filename at the end of the URL, and a directory number (which is the first part of this filename, i.e. directory#_fileName.jpg). All of this works fine.
My problem is that I would like to pass this model to another view once it has data populated in all of its fields by this initial ActionResult so that I can have a verification view, which would allow the user to preview the two files side by side so that they can ensure they are swapping the appropriate images. They should then be able to hit another submit button which will initiate the actual moving/replacing of the images and be taken to a page confirming.
Is there a way to pass data from this controller to a different view? My confusion arises because I cannot create another version of an ActionResult of Index with the same input, but I do not want to have the actual swapping of the images occur without a preview and a prompt. Should I re-write my Index view so that it utilizes partial views in order to accomplish this? What is the easiest way to have data persist through multiple steps and views?
What is the easiest way to have data persist through multiple steps
and views?
Your question sounds like you're trying to achieve what you can easily do with sessions. The session object allows you to persist data between requests simply by adding it to the Session object on the HttpContext that exists within the base class that your controller extends, like so:
(Note the Serializable attribute. This allows your object to be serialized into the session object).
[Serializable]
public class ImageSwapModel {
// Your class's properties
}
Then in your controller you can do the following:
[HttpPost]
public ActionResult Index(ImageSwapModel imageSwap)
{
var oldFileFound = false;
var newFileFound = false;
if (ModelState.IsValid)
{
this.HttpContext.Session["ImageSwap"] = imageSwap;
}
}
When you want to retrieve the model you can grab it from the session like so:
var imageSwap = (ImageSwapModel)this.HttpContext.Session["ImageSwap"];
Taking it one step further:
Whilst the above will work fine, generally it's not a good practice to reference the HttpContext object directly in your code as it creates unnecessary coupling to the HttpContext object that can easily be avoided. Instead you should opt to inject an instance of the session object via Dependency Injection. Here is a similar answer that provides a basic idea as to how you can do this.
You can return different views with Models being passed to them in your one Index action like
if(some condition)
{
Return View("ViewVersion1", MyModelVersion1);
}
else
{
Return View("ViewVersion2", MyModelVersion2);
}

Keep data in ViewModel when validating in MVC5

In my asp.NET MVC5 app I have a controller that supplies a view which is strongly typed vs a viewmodel. This viewmodel has a SelectList property (among others), and the controller supplies the data on creation from the database:
public ActionResult Simulation() {
var SimVM = new SimulationVM(
StrategyRepository.GetStrategies().Select(n => n.Name),
);
return View(SimVM);
}
The SelectList is then used as data source for a DropDown choice in a form. The HttpPost method does some datavalidation, i.e.,
[HttpPost]
public ActionResult Simulation(SimulationVM _simVM) {
if (ModelState.IsValid) {
// ...
}
else return View(_simVM);
}
So with the code above, the DropDown data is empty, since on posting, the SimulationVM object is created new. The usual trick of using Html.HiddenFor does not work on collections.
Of course, I could go back and fetch the data again from the database, but that seems to be bad, a database fetch for such a simple thing as a validation where I know the data hasn't changed.
What is the best (or for the sake of not being subjective: any) way to keep some data in the ViewModel (or repopulate it efficiently)?
If it is a requrement that you not go back to the database and you're 100% confident that the data will not change (i.e. this is a list of states as opposed to a list of orders or something) then you can add the collection to a session variable. Here's a link to a decent article:
https://code.msdn.microsoft.com/How-to-create-and-access-447ada98
That being said, I usually just go to the database and get the data again. If doing so for a second time is causing huge performance issues, it is most likely causing performance issues the first time and you should treat the problem rather than the symptom.

MVC 3 - How is this ever going to work?

I have made this post over a year ago, and I think it makes sense to update it as it's getting quite a few views.
I'm either missing something out or Microsoft has really messed up MVC. I worked on Java MVC projects and they were clean and simple. This is however a complete mess IMO. Examples online such as NerdDinner and projects discussed on ASP.Net are too basic, hence why they "simply" work. Excuse if this sounds negative, but this is my experience so far.
I have a repository and a service that speaks to the repository. Controllers call service.
My data layer is NOT persistence independent, as the classes were generated by SQL metal. Because of this I have a lot of unnecessary functionality. Ideally I'd like to have POCO, but I didn't find a good way to achieve this yet.
*Update: Of course Microsoft hasn't messed anything up - I did. I didn't fully understand the tools that were at my disposal. The major flaw in what I have done, was that I have chosen a wrong technology for persisting my entities. LINQ to SQL works well in stateful applications as the data context can be easily tracked. However, this is not a case in stateless context. What would be the right choice? Entity Framework code first or code only work pretty well, but what's more importantly, is that it shouldn't matter. MVC, or front end applications must should not aware of how data is persisted. *
When creating entites I can use object binding:
[HttpPost]
public ActionResult Create(Customer c)
{
// Persistance logic and return view
}
This works great, MVC does some binding behind the scene and everything is "jolly good".
It wasn't "Jolly Good". Customer was a domain model, and what was worse, it was dependent on persistence medium, because it was generated by SQL metal. What I would do now, is design my domain model, which would be independent of data storage or presentation layers. I would then create view model from my domain model and use that instead.
As soon as I'd like to do some more complex, e.g. - save Order which is linked to the customer everything seems to break:
[HttpPost]
public ActionResult Create(Order o)
{
// Persistance logic and return view
}
To persist an order I need Customer or at least CustomerId. CustomerId was present in the view, but by the time it has got to Create method, it has lost CustomerId. I don't fancy sitting around debugging MVC code as I won't be able to change it in a hosting envrionment either way.
Ok, a bit of moaning here, sorry. What I would do now, is create a view model called NewOrder, or SaveOrder, or EditOrder depending on what I'm trying to achieve. This view model would contain all the properties that I'm interested in. Out-of-the-box auto binding, as the name implies, will bind submitted values and nothing will be lost. If I want custom behaviour, then I can implement my own "binding" and it will do the job.
Alternative is to use FormCollection:
[HttpPost]
public ActionResult Create(FormCollection collection)
{
// Here I use the "magic" UpdateModel method which sometimes works and sometimes doesn't, at least for LINQ Entities.
}
This is used in books and tutorials, but I don't see a point in a method which has an alternative: TryUpdateModel - if this crashes or model is invalid, it attempts to update it either way. How can you be certain that this is going to work?
Autobinding with view models will work the most of the time. If it doesn't, then you can override it. How do you know it will always work? You unit test it and you sleep well.
Another approach that I have tried is using ViewModel - wrapper objects with validation rules. This sounds like a good idea, except that I don't want to add annotations to Entity classes. This approach is great for displaying the data, but what do you do when it comes to writing data?
[HttpPost]
public ActionResult Create(CustomViewWrapper submittedObject)
{
// Here I'd have to manually iterate through fields in submittedObject, map it to my Entities, and then, eventually, submit it to the service/repository.
}
** View model is a good way forward. There would have to be some mapping code from view model to the domain model, which can then be passed to the relevant service. This is not a correct way, but it's one way of doing it. Auto mapping tools are you best friends and you should find the one that suits your requirements, otherwise you'll be writing tons of boilerplate code.**
Am I missing something out or is this the way Microsoft MVC3 should work? I don't see how this is simplifying things, especiialy in comparisson to Java MVC.
I'm sorry if this sounds negative, but this has been my experience so far. I appreciate the fact that the framework is constantly being improved, methods like UpdateModel get introduced, but where is the documentation? Maybe it's time to stop and think for a little bit? I prefer my code to be consistent throughout, but with what I have seen so far, I have no confidence whatsoever that this is a right way forward.
I love the framework. There is so much to learn and it's not a lot more exciting then it has ever been. Should probably make another post regarding web forms. I hope this is helpful.
1) For the case of saving an order, and not having CustomerId present. If Order has a CustomerId property on it, and you have a stongly typed view, then you can persist this back to your controller action by adding
#Html.HiddenFor(model => model.CustomerId)
Doing this will have the default model binder populate things for you.
2) With respect to using a view model, I would recommend that approach. If you utilize something like AutoMapper you can take some of the pain out of redundant mapping scenarios. If you use something like Fluent Validation then you can separate validation concerns nicely.
Here's a good link on a general ASP.NET MVC implementation approach.
I don't think your issue is with asp.net MVC but with all the pieces You Choose to use together.
You want it raw and simple?
Use POCOs all around, and implement the repository where you need it.
I haven't used Java MVC, but it'd make the whole question look less like a rant if you include how you solved the particular problem in there.
Let's clear some misconceptions or maybe miscommunication:
You can pass complex objects through a post to the view. But you only want to do so if it makes sense, see next bullet
The sample you picked there rings some alarms. Accepting Customer data or CustomerID for an order and not checking authorization can be a Big security hole. The same could be said for an Order depending on what you are accepting/allowing. This is a Huge case for the use of ViewModels, regardless of POCOs, LINQ, Asp.net MVC or Java MVC.
You can pass simple values not being showed through a post to the view. It's done with hidden fields (which asp.net MVC supports very simply to use the model value), and in some scenarios it generates the hidden fields for you.
You are in no way forced to use linq2sql with Asp.net MVC. If you find it lacking for how you intend to use it, move away from it. Note I love linq2sql, but how it is tied to your view of what you can do with asp.net mvc is weird.
" I worked on Java MVC projects and they were clean and simple". Working on a project is not the same as designing the project yourself. Design skills does affect what you get out of anything. Not saying is your case, but just wanted to point that out given the lack of specifics on what you're missing from Java MVC.
"My data layer is NOT persistence independent, as the classes were generated by SQL metal. Because of this I have a lot of unnecessary functionality. Ideally I'd like to have POCO, but I didn't find a good way to achieve this yet". You picked the wrong technology, linq2sql is Not meant to fit that requirement. It haven't been a problem in the projects I've used it, but everything is designed in such a way that way less tied to its specifics than you seem to be. That said, just move to something else. btw, You should have shared what you used with Java MVC.
"CustomerId was present in the view, but by the time it has got to Create method, it has lost CustomerId." If the property is in Order, You can bet your code has the bug. Now, that'd have been a totally different Real question, why it isn't using the CustomerId / such question would come with: your Customer class, the View, what you are passing to the View ... answers would include, but not be limited to: inspect the HTML source in the browser to see what value you are really posting with the source (alternatively use fiddler to see the same), make sure that CustomerId really has the value when you pass it to the View.
You said: ""magic" UpdateModel method which sometimes works and sometimes doesn't". It's not magic, you can see what it does and certainly find information on it. Something is off in the information you are posting, my bet is non optional fields or wrong values for information that's parsed ... views support adding validations for that. Without the validations, this can be lacking.
You said in a comment: "After UpdateModel is called, i can't explicitly set the CustomerId, I'll have to retrieve a customer object and then assign it to the order, which seems like an overhead as all that I need is CustomerId" ... you are accepting a CustomerId that is user input (even if it is a hidden field), you really want to Validate that input. Additionally you are contradicting yourself, you claim to just need CustomerId, but then you say you need the full Customer Object related to the order bound. Which is it, if you are only binding the CustomerId, you still need to go get that Customer and assign it to the property. There is no magic besides the scenes ...
Also in a comment: "Update model is something I'm avoiding completely now as I don't know how it will behave with LINQ entities. In the view model class I have created constructor that converts LINQ entity to my view model. This decreased amount of code in controller, but still doesn't feel right". Reason to use ViewModel (or EditModel) is not because it is linq2sql ... it is because, among many other reasons, you are exposing a model that allows to manipulate way beyond what you actually want to allow the user to modify. Exposing the raw model, if it has fields the user shouldn't be allowed to modify, is the real issue.
If your view is correctly defined then you can easily do this >
[HttpPost]
public ActionResult Create(Order o, int CustomerId)
{
//you got the id, life back to jolly good (hopefully)
// Persistance logic and return view
}
EDIT:
as attadieni mentioned, by correct view I meant you have something like this inside the form tag >
#Html.HiddenFor(model => model.CustomerId)
ASP.NET MVC will automatically bind to the respective parameters.
I must be missing the problem.
You have a controller Order with an Action of Create just like you said:
public class OrderController()
{
[HttpGet]
public ViewResult Create()
{
var vm = new OrderCreateViewModel {
Customers = _customersService.All(),
//An option, not the only solution; for simplicities sake
CustomerId = *some value which you might already know*;
//If you know it set it, if you don't use another scheme.
}
return View(vm);
}
[HttpPost]
public ActionResult Create(OrderCreateViewModel model)
{
// Persistance logic and return view
}
}
The Create action posts back a view model of type OrderCreateViewModel that looks like such.
public class OrderCreateViewModel
{
// a whole bunch of order properties....
public Cart OrderItems { get; set; }
public int CustomerId { get; set; }
// Different options
public List<Customer> Customers { get; set; } // An option
public string CustomerName { get; set; } // An option to use as a client side search
}
Your view has a dropdown list of customers which you could add as a property to the viewmodel or a textbox which you wire up to to searching on the server side via JQuery where you could set a hidden field of CustomerId when a match is made, however you decide to do it. And if you already know the customerId ahead of time (which some of the other posts seems to imply) then just set it in the viewmodel and bypass all the above.
You have all of your order data. You have the customer Id of the customer attached to this order. You're good to go.
"To persist an order I need Customer or at least CustomerId. CustomerId was present in the view, but by the time it has got to Create method, it has lost CustomerId."
What? Why? If CustomerId was in the view, set, and posted back, it's in the model for the HttpPost Create method which is exactly where you need it. What do you mean it's being lost?
The ViewModel gets mapped to a Model object of type order. As suggested, using AutoMapper is helpful...
[HttpPost]
public ActionResult Create(OrderCreateViewModel model)
{
if(!ModelState.IsValid)
{
return View(model);
}
// Persistance logic and return view
var orderToCreate = new Order();
//Build an AutoMapper map
Mapper.CreateMap<OrderCreateViewModel, Order>();
//Map View Model to object(s)
Mapper.Map(model, orderToCreate);
//Other specialized mapping and logic
_orderService.Create(orderToCreate);
//Handle outcome. return view, spit out error, etc.
}
It's not a necessity, you can map it manually, but it just makes things easier.
And you're set. If you don't want to use data annotations for validation, fine, do it in the service layer, use the fluent validation library mentioned, whatever you choose. Once you call the Create() method of your service layer with all the data, you're good to go.
Where's the disconnect? What are we missing?
ataddeini's answer is correct, I'm just trying to show a bit more code. Upvote ataddeini
If the Customer Id is already in the Order model (in this example) it should be available without extending the method signature. If you view the source on the rendered view, is the customer id correctly emitted in a hidden field within the form? Are you using the [Bind] attribute on the Order model class and inadvertently preventing the Customer Id from being populated?
I would think the Order table would include a CustomerID field, if so, the only problem is maybe you are not including any control in the view to keep that value, then is lost.
Try to follow this example.
1) GET action before sending to the View, let's say you assign the CustomerID at this point.
public ActionResult Create()
{
var o = new Order();
o.CustomerID = User.Identity.Name; // or any other wher you store the customerID
return View(o);
}
2) The View, if you don't use any control for the CustomerID, like textbox, combobox, etc, you must use a hidden field to keep the value.
#using (Html.BeginForm())
{
#Html.HiddenFor(m => m.CustomerID)
<label>Requested Date:</label>
#Html.TextBoxFor(m => m.DateRequested)
...
}
3) Finally, the POST action to get and persist the order. In here, as CustomerID was kept in the hidden value, the Model Binder will automatically put all the Form values into the Order object o, then you just need to use CRUD methods and persist it.
[HttpPost]
public ActionResult Create(Order o)
{
return View();
}
Can be two approaches for this, one to implicit save all Model values even if not used in the View, and the other is to keep only those values used. I think MVC is doing the right thing to follow the later, avoid unnecessary keep a lot of junk for bigger models, when the only think is, to name one, a CustomerName, somehow it can give you control on what data to keep through the whole cycle action-view-action and save memory.
For more complex scenarios, where not all fields are in the same model, you need to use ViewModels. For example for mater-detail scenarios you would create a OrderViewModel that has two properties: Order o, and IEnumerable< OrderDetail > od, but again, you will need explicit use the values in the View, or use hidden fields.
In recent releases now you can use POCO classes and Code-First that makes all cleaner and easier, You may want to try EF4 + CTP5.
if you are using services (aka; service layer, business facade), to process lets say the OrderModel, you can extract an Interface, and get your ViewModel/DTO to implement it, so that you can pass back the ViewModel/DTO to the service.
If you are using Repositories to directly manage the data (without a servie layer) in the controller, then you can do it the good old way of Loading the object from a repository and then doing an UpdateModel on it.
[HttpPost]
public ActionResult Create(string customerCode, int customerId, Order order)
{
var cust = _customerRepository.Get(customerId);
cust.AddOrder(order);//this should carry the customerId to the order.CustomerId
}
Also, URLs might help a bit where it makes sense, I mean you can add the customer identifier in the url to create the order for.
UpdateModel should work, if your FormCollection has values for non-nullable properties and they are empty/null in the FormCollection, then UpdateModel should fail.

What is the preferred model configuration for CRUD?

I am attempting to perform crud operations within a simple content management website. In attempting to create my CRUD views for the entering of a piece of content, there are several drop-downs that need to be populated, and in the case of an edit operation they need to have specific values pre-selected. I have been reading a textbook on it and absorbing as much as I can through articles on the web, but I'm having trouble in determining where the best place is for the information belonging to these drop-downs. I could easily create model classes to identify them, and then I would have an option of either getting the data to fill them one at a time or have this information populated as properties in my content model class so that the value of the class is selected, but an IEnumerable property would be available to bind to directly.
Either way seems to work with using templates to create the drop-downs, but I'm trying to eliminate some of the "Select N+1" issues of retrieving these things individually, but I also don't want to pack my model full of too much junk that really doesn't belong there as considered against the MVC architecture.
So the basic question is: Does supporting information like drop-downs, filters, etc belong as sub-classes in the primary model class or should these be retrieved individually and presented as separate items by themselves? Or is there some other aspect to the architecture that should be used and I'm just missing the boat completely?
Articles, links, redirects are all welcomed. I have Googled this, and what I have found has either not answered this question or the answer is hiding within the mass of results.
example: Books and Authors entities
when creating a new book in a view, you need a select control that has its options populated as all the available authors.
the Book model should be clean and contain only the relevant fields e.g. Title, Author
the controller should have an IAuthorRepository _authorRepository; field that could have been set by a DependencyResolver or manually in the controllers constructor. IAuthorRepository would have a method such as IEnumerable GetAvailableAuthors();
the [HttpGet] Create() action could return an empty Book model directly and then stuff the _authorRepository into the dynamic ViewBag. ViewBag.AuthorRepository = _authorRepository;
The view would then pass the ViewBag.AuthorRepository to a partial view or a custom editor. Your model is kept clean in this scenario.
Some people don't like any use of ViewBag.Xxx (or ViewData["Xxx"]) because it's less than perfect MVC. I've seen examples that would Create a new type like BookViewModel. BookViewModel would then contain Book and IAuthorRepository in itself. the [HttpGet] Create() action would then return a BookViewModel object and the view would render its Author Select partial view by passing it the model.AuthorRepository instead of the ViewBag.AuthorRepository. This sort of starts to look more like MVVM here rather than MVC. Your instinct to keep any such collections or repositories out of the actual model (Book) is right. A clean model is very important and will give you the most flexibility in any pattern.
Not sure if this is the thing you are after but I use my own class library called Web.Shared which holds all my helper methods. I have a SelectListHelper class which I use to populate all my dropdownlists. That way my code is seperated from the main domain model and can be reused through this and any other MVC app which is part of my solution.
// Return days of the month for a dropdownlist
public static class SelectListHelper
{
public static SelectList DayList()
{
return NumberList(1, 31);
}
}
// Use in view
#Html.DropDownListFor(m => m.Day, SelectListHelper.DayList())
// Another one for selecting genders
public static SelectList GenderList(string selectedValue = null)
{
IList<KeyValuePair<string, string>> genders = new List<KeyValuePair<string, string>>();
genders.Insert(0, new KeyValuePair<string, string>("F", "Female"));
genders.Insert(0, new KeyValuePair<string, string>("M", "Male"));
genders.Insert(0, new KeyValuePair<string, string>("", "Choose Gender"));
return new SelectList(genders, "Key", "Value", selectedValue);
}
// Use in my edit view
#Html.DropDownListFor(m => m.Gender, SelectListHelper.GenderList())
Failing this take a look at MVC Scaffolding for creating data bound CRUD Views.
I agree with Tion's answer but my response can't fit in a comment.
First, the simple solution if you're using NHibernate: you can setup batching on has-many collections to load many entities in one query (instead of N!). We use a batch size of 100 with very noticeable performance gains. This won't help if you're just loading everything from a single table.
Now the trickier, but still very worthwhile solution.
If you have fairly static content that gets queried often (drop down lists, account name lookups, etc) you should really think about caching it in memory. If you're using IOC it's very easy to swap in a CachingRepository implementation for IRepsoitory<>. At my company we borrowed FubuCache from FubuMVC, but I think it's just a dictionary behind the scenes. If you have a server farm or multiple servers accessing the same data, you can use Memcached to share data.
The important thing about caching is knowing when to clear it. (ie, reload content from the database.) For us that means
1) every 5 minutes no matter what (other applications interact with the db so we need to pick up their changes.
2) any time an entity is inserted or updated we clear all the relevant caches.
Since most of our applications are reporting over large datasets with many joins we cache nearly everything. As long as your server has enough RAM you'll be fine.
ps http://axisofeval.blogspot.com/2010/11/numbers-everybody-should-know.html

Understanding the MVC Pattern

I am having some trouble understanding the MVC Pattern. I do understand we are trying to decouple the GUI from the business logic, although I'm having problems understanding how.
From what I understood, the View, is what the user sees. So it generally is the window/form. The Controller is inbetween the View and the Model. The Controller will make the data "flow" in both directions. It will also persist state when needed (if I have a wizard with 5 steps, it is the Controller's responsability to ensure they are made in the correct order, etc). The Model, is where the core of my application logic lives.
Is this view correct?
To try to turn this into something more meaningful, I'll try to sketch out a simple example with WinForms(no ASP.NET or WPF, please! - to the java crowd, from what I come to understand, Swing works in a similar way to WinForms!), to see if I get it right, and I'll raise the questions I always come to while doing it.
Let's assume I have a model that contains just a class (just to make it easier. I know it will make the example look dumb but its easier this way):
class MyNumbers {
private IList<int> listOfNumbers = new List<int> { 1, 3, 5, 7, 9 };
public IList<int> GetNumbers() {
return new ReadOnlyCollection<int>(listOfNumbers);
}
}
Now it's time to make my Controller:
class Controller
{
private MyNumbers myNumbers = new MyNumbers();
public IList<int> GetNumbers() {
return myNumbers.GetNumbers();
}
}
The View should just have a ListBox that has as items all the numbers retrieved in MyNumbers.
Now, the first question arises:
Should the Controller be responsible for creating MyNumbers? In this simple case, I think its acceptable(as MyNumbers will do exactly the same, no matter what, and has no associated state). But let's assume I would want to use for all the different Controllers my app has the same instance of MyNumbers. I would have to pass to this Controller(and all others that need it) that instance of MyNumbers that I want to use. Who is going to be responsible for that? In this WinForms examples, would that be the View? Or would that be the class that creates the View?
Turning the question around: what is the order of instantiation of these 3 parts? What is the code that the "owner" of the MVC called to create it?
Should the Controller create both the View and Model? Should the View instantiate the Controller and the Controller the Model?
Second question:
How is the main method supposed to look like, assuming I only want my application to have the Use Case this Controller portrays?
Third:
Why does in the following MVC diagram, the View have an arrow to the Model? Shouldn't the Controller be always the bridge between both View and Model?
I'll have one or two more questions, but they probably will make more sense asked after I understand this first detail. Or maybe after I understand that first question all the others tear apart.
Thanks!
The easiest way to get a handle on MVC is to use it in a framework that enforces it, that being said..
The Model interacts with the datasource (DB or whatever) and gives you access to your data.
The View interacts with the outside world, it receives input from somewhere and hands off the data to the Controller it also listens to the Controller to make sure its displaying the correct data.
The Controller is where all the magic happens; the Controller manipulates data, pushes events, and handles changes in both directions (to/from the View and to/from the Model).
This diagram is very helpful (it makes much more sense than Wikipedia's):
Source, and a great article on MVC!
As for the criticism within my post I thought I would give a post on how i tend to create an MVC Pattern in PHP
Within PHP i spit the framework up into several sections, of witch some are the normal when it comes to MVC.
Primaries:
Controller
Model
View
Secondariness
- ModelLayer
ViewLoader
Library
ErrorLayer
Within the controller I usually allow all access the secondary layers and the View and Model from Primary.
Here's the way I would structure it
|---------| |------------| |------------|
| Browser | ----> | Controller | ----> | Model |
|---------| |------------| |------------|
| | | |
| | |----------------|
| |
| |------------|
-------------| View |
|------------|
From my diagram I usually bypass the View <-> Model connection and do a Controller <-> Model and then the link from Controller <-> View assigns the data.
Within my framework I tend to create a object storage system so that i can easily fetch objects and so forth. an example of my object storage is like so
class Registry
{
static $storage = array();
public static function get($key)
{
return isset(self::storage[$key]) ? self::storage[$key] : null;
}
public static function set($key,$object)
{
self::"storage[$key] = $object;
}
}
Somewhat more advanced by that's the outline, so with this when I first initialize objects i store them like Registry::set("View",new View()); so that there always accessible.
So within my controller witch is the base controller i create several magic methods __get() __set() so that any class that extends the controller I can easily return teh request for example:
abstract class Controller
{
public function __get($key)
{
//check to make sure key is ok for item such as View,Library etc
return Registry::get($key); //Object / Null
}
}
And the user controller
class Controller_index extends Controller
{
public function index()
{
$this->View->assign("key","value"); // Exucutes a method in the View class
}
}
The model will also be placed into registry but only allowed to be called from ModelLayer
class Model_index extends ModelLayer_MySql
{
}
or
class Model_index extends ModelLayer_MySqli
{
}
or filesystem
class Model_file extends ModelLayer_FileSystem
{
}
so that each class can be specific to the storage type.
This is not the Traditional type of MVC Pattern but it can be called Adoptive MVC.
Other objects such as the View Loader should not be placed into registry as there not specifically for the users interests but used by other entites such as View
abstract class ViewLoader
{
function __construct($file,$data) //send the file and data
{
//Include the file and set the data to a local variable
}
public function MakeUri()
{
return Registry::get('URITools')->CreateURIByArgs(func_get_args());
}
}
as the template file is being included in the View loader and NOT the View class it separates the user methods from teh system methods and also allows methods to be used within the views themselves for general logic.
Example of template file.
<html>
<body>
<?php $this->_include("another_tpl_file.php"); ?>
<?php if(isset($this->session->admin)):?>
<?php echo $this->lang->admin->admin_link ?>
<?php endif; ?>
</body>
</html>
I hope my examples help you understand that little bit more.
Answer to the third question:
When the model changes, it notifies the view, then the view gets the data from the model using its getters.
"From what I understood, the View, is what the user sees. So it generally is the window/form. The Controller is inbetween the View and the Model. The Controller will "handle" data in both directions. It will also persist state when needed (if I have a wizard with 5 steps, it is the Controller's responsability to ensure they are made in the correct order, etc). The Model, is where the core of my application logic lives."
This is almost correct. The controller doesn't persist data. It calls a service that persists data. The reason is, persisting data is never just a call to save. You might want to do validation checks on the data to make sure it is sane according to your business needs. You might want to do some authentication to make sure the data can be saved by a user. If you do that in a service, then you have a nice bundle of functionality that you can use over and over again, say for a webapp and a web service. If you do it in a controller, say for a web app, when you go to write your web service you will have to refactor and/or duplicate code.
In response to your comment "I am not sure I totally understood your point. Does the Controller check UI input, or is the Model that does it?"
You controller should only control which business functionality paths get executed. Thats its. Controllers should be the easiest part of the code to write. You can do some validation on the gui (i.e. view, e.g. like making sure email addresses are properly formatted, text inputs dont exceed maximums), but the business layer should also validate the input -- for the reason I mentioned earlier, that when you start standing up more endpoints, you don't have to refactor.
Should the Controller be responsible
for creating MyNumbers?
I would say 'definitely not.'
If the MVC pattern is designed to decouple the M, V, & C elements, how can this work if the C simply instantiates the M with new MyNumbers()?
In Java, we would use something like the Spring Framework here. You need a way to express the dependency relationship -- or rather the details of how it gets fulfilled -- in a configuration file or other suitable place (i.e. not in compiled code).
But there is another element to this issue: you probably shouldn't define the myNumbers variable (inside C) with the concrete, runtime type you intend to use. Use an interface or an abstract class, and leave it open as to what the actual runtime type is. This way, in the future you can re-implement the IMyNumbers interface to satisfy emerging requirements (those you don't know today) and your C component will continue to work perfectly, none the wiser.
This is from Java, but hopefully it will help.
For the main:
public static void main(String[] args)
{
MyNumbers myNums = new MyNumbers(); // Create your Model
// Create controller, send in Model reference.
Controller controller = new Controller(myNums);
}
Your controller needs a reference to your model. In this case, the controller actually creates all the Swing components. For C#, you may want to leave the form initialization here, but the View/Form needs a reference to the Model (myNums) and the Controller (controller). Hopefully some C# people can help on this front. The View also needs to register as an Observer of the Model (see Observer Pattern).
Here is the constructor I have (adjusted for your case):
public NumberView(Controller controller, MyNumbers myNums)
{
this.controller = controller; // You'll need a local variable for this
this.myNums = myNums; //You'll need a local variable for this
myNums.registerObserver(this); // This is where it registers itself
}
The View passes the work to the Controller to handle the user's actions (buttons, whatever). The Controller decides what to call/do in the Model. In general, the Model then does something and changes its state(maybe more numbers in your list. Whatever it does). At the point, the Model will let its Observers know it has changed and to update themselves. Then the View goes and gets the new data and updates itself. That is why the Model and View talk (your 3rd question).
So the Model will have:
public void notifyObservers()
{
for (Observer o: observers)
{
o.update(); // this will call the View update below since it is an Observer
}
}
So in the View, you'll have something like this:
public void update()
{
setListBox(myNums.getNumbers()); // Or whatever form update you want
}
Hope that helps. I know it is Java, but the concept still applies. You'll have to do a little reading on the Observer pattern to fully get it. Good luck!
I will try to answer this from a relatively less technical stand for what it's worth. I'll try walk through a general example.
Controller controls what view is used. So, say, if you are writing to the page the controller will direct you to the input view (say) while if you are reading the same page it will direct you to it's success view (say).
After one writes to the page the controller will pass those parameters to the relevant model where the logic pertaining to what has to be done with them resides. If there is as error then the controller will direct you to the error view.
My knowledge is based on my one month experience with Agavi. Hope this helps.
Why does in the following MVC diagram, the View have an arrow to the Model? Shouldn't the Controller be always the bridge between both View and Model?
It is the MVC model 2. You can see it usually in Java enterprise application
where CONTROL does the business as well as processes data from/to MODEL and choose which VIEW to render back to client. When rendering to client, VIEW will use data from MODEL:
(source: blogjava.net)
Here is an example how to access data from a JSP(VIEW) file which a bean (MODEL):
class Person {String name;} // MODEL
My name is ${bean.name} // VIEW
View draws the model and represents it to the user
Controller handles the user input and translates them to the modifications into the model
Model holds the data and modification logic
There's no point translating it into code. You won't get it correct straight out anyway.
View
user interface / responsible with input output / some validation / needs to have a way to notify outside world of UI level events
knows only about the model
Model
data structure / represents the data that is presented / should not contain business logic (maybe only some data/structure validation at most)
knows only about himself (think of a Person class that has only Name and Age)
Controller
is responsible for business logic / it crates Views and glues the respective models onto them / has to be able to respond to View events / accesses other layers of the application (persistence / external services / business layers etc.)
knows everything (at least View and model) and is responsible of gluing everything together

Categories

Resources