Well, since the http request is stateless by nature, the observer pattern doesn't really work in the case of the web. For each request, the state of the objects is created. There's no real "change" for the observer pattern to identify.
So you get this controller, which really just responds to actions from the user. The user says "edit" so the controller knows to get the new data from the view and pass it to the model. You can't really have a true MVC pattern on the web unless you use
a language that supports
continuations, like Smalltalk or Lisp/scheme or use something like Apache's Cocoon framework..
The view might use a re-usable Grid component and the controller will create or show/hide the grid based on the security information it gets from the User model.
Depending on what rights the logged in user has, the controller may query one or more models. If the user can view customers and their orders, it may get a list of customers from the Customers model and a list of related orders. Say from a "Customers.GetOrdersForCustomer(int
cusomerId)" method.
But doesn't this violate the intent of MVC? In your solution, the Controller needs to know fairly specific things about the View and it's controls. The Controller also needs to know fairly specific things about the security aspects of my business logic. Instead
of keeping things separated, we've started to centralize View (UI) and Model (business) logic in the Controller. Am I misunderstanding something about MVC still?
Instead of keeping things separated, we've started to centralize View (UI) and Model (business) logic in the Controller. Am I misunderstanding something about MVC still?
Not Necessarily. The controller knows that it needs to set some conditions on the view based on the information it gets from the model. Whether the conditions are telling the view to enable/disable parts it's UI or what values to set on different form fields
in the view doesn't really matter IMO.
It seems to me that if all the controller is going to do is pass the model on to the view for every action, then the controller could be completely abstracted away and we'd just have, essentially, the model bound directly to the controller. I think, by definition,
the controller has to understand a little bit about both the model and the view and understand how to manipulate one based on information from the other.
Others may disagree with me some and want to keep the controller less involved.
Jumping in because I went through some of these issues once upon a time and here is what I came away with.
In an MVC application, even the desktop-based ones I've applied MVC too, you almost always have a new set of Controllers and Views per application. In my experience controllers are almost
never reusable and are almost always bound to a single view. Even between web applications you rarely reuse just a controller unless you're grabbing the entire vertical slice, model, controller and view. This is where service and helper layers
come in.
Don't get caught up in the word "Service", that doesn't mean it has to be a physical service running on a server somewhere; it just means a discreet, reusable bit of functionality wrapped in a single interface. I've found that a service is really just a
fancy way to say a Facade pattern stretched over your model, or a viewless controller, such as a login service that takes in a login and password and gives the ya or nay on the combo and requires a concrete model-backend.
A perfect example is that for one of my sites I allow developers to access the site's API as long as they have a valid developer token, so I have a "TokenService" that has these methods:
<div mce_keep="true">IsValidToken</div>
<div mce_keep="true">CreateToken</div>
<div mce_keep="true">DeleteToken</div>
I don't have any views that support displaying or editing of tokens, I just create them under the covers so a full Controller is overkill. I also have some desktop-based Windows Services running that do some token maintenance so they need access to the
TokenService as well. Including a full Controller in a Windows Service would be silly, because I don't need the entire MVC framework dragged into my little service app, I literally only want to create and delete tokens using a fully tested interface, my TokenService.
My rule of thumb is that a controller only moves data from the model into a view and back again, applying any needed validation and filtering. If it's logic I may need in non-UI situations, like my tokens, I tend to create services that are either just
class libraries or when I need to expose my service to others, full blown SOAP or REST-based end-points.
Lastly (sorry this is a long, rambling post) I can see how controllers can be confusing. They seem like a perfect place to put *all* of your business logic for a certain entity, so if you have a ProductsController you might have RestockProducts() and CheckInventory()
and IsProductOnSale() and ProductIsOrganic() yet in MVC the controllers tend to be less about those types of methods and more like ways to link data to html. So the question becomes, and I think that's the crux of this thread, where do you put those methods?
I'd like to jump in here and share one of the concerns my team raised when discussing the ASP.NET MVC framework...
We're not so much concerned with controller reuse ACROSS different apps, but we want to be able to reuse controllers WITHIN our app.
So let's say we have a couple different places in the app where we can create a Person object (maybe one view is more detailed, or maybe one view is optimized for rapid data entry, or whatever). We'd like to be able to post that Person data from either
view's form to the PersonController's Create action.
So far so good, right? But the problem we have with the current implementation of ASP.NET MVC is first, that there's no strongly-typed interaction between the View and the Controller when posting to the Controller. So for instance, our PersonController
expects to receive Request.Form data which includes 2 fields (ie, FirstName, LastName). So we go and build the two versions of the form with those two fields on it. The next week, the client calls and says, "hey, we need a MiddleName field in there, too."
Ok, so we go and add the middleName field to one of those forms, but we forget that there's another form that needs modification as well. So we've just introduced a bug, which won't be caught until after we run unit tests.
What we'd like is to be able to specify an interface (INewPersonView) which these two forms would implement, and we'd want the PersonController's Create action to expect this interface. That way, if we forgot to update one of our two forms, we'd have a
compile-time error instead, and we'd have more peace of mind when turning junior developers (who presumably wouldn't know "where all the bodies are buried" in our app) loose on these things.
Does that make any sense to anyone else? Is this even consistent with the concept of MVC on the web?
One thing that strikes me is that you should be running your tests constantly. I pretty much run all unit tests a few dozen times a day and whatever unit I'm working on I run those tests every time I make an atomic change. Unit tests are a much better
way to capture things than relying on compile-time bugs.
<div mce_keep="true">Anyway, test-driven analness aside it seems you could build in this type of checking into your controller without the overhead of creating a new interface that you then have to manage. Since you have to add validation into your Controller's
Create anyway why not have it log or e-mail an exception when you are missing expected fields? I'm assuming you'd already be adding validation and field verification in your controller so if data is sent your way it'll fail the middle name field validation
and you can roll with it.</div> <div mce_keep="true"> </div> <div mce_keep="true">The more I think about it the INewPersonView seems like a lot of extra overhead for very little benefit. You now have *another* place to maintain in your code, you've added
another layer of abstraction and personally as a junior (or even senior) coder I'd find it more confusing because now there is even more disconnect between View and Controller. Plus, your junior coders better be running unit tests like mad!</div> <div mce_keep="true"> </div>
<div mce_keep="true">I can also see how this would cause more headaches. You add "MiddleName" to your INewPersonView and are working on updating View1, so you add it to that views INewPersonView implimentation but your project doesn't compile because View2
is complaining about the missing MiddleName. Because you want to get it to compile you quickly throw a dummy property on View2 while fine tuning View1 and after a long day you completely forget about View2's dummy, non-working MiddleName yet you have a false
sense of confidence because you don't get any compile time issues.</div> <div mce_keep="true"> </div> <div mce_keep="true">Just my two cents, I see where you're going but think it would be best handled directly in the controller and unit-tests vs. an interface
abstraction.</div>
This is not controller logic, this is business logic. This should not be in a controller, winforms or webforms. You push this into your domain layer so that it can be reused.
What we'd like is to be able to specify an interface (INewPersonView) which these two forms would implement, and we'd want the PersonController's Create action to expect this interface.
Yeah, that's a pain. But, there's nothing in the MVC pattern, or in this Web.MVC pattern, that says that a view represents one and only one page. Perhaps writing a RenderPartialView method, with an associated controller, would be a better way to handle that
situation? A partial view would be very close to a Webform User Control. I'm not clear on what the server-side control story is with this framework yet.
That's an excellent point, and obviously one I overlooked. I guess then what we'd want is something that specifies an interface (or contract of some sort) for the post data expected by a controller action. Instead of having to apply that interface/contract
to the entire view, then maybe we're talking about a way to apply it at the HTML form level (what's actually being posted) or at the PartialView level.
Any way a strongly typed contract could be applied between view posts & the receiving controller action would go a long way toward soothing my team's anxieties toward ASP.NET MVC. If something like this were to find its way into the MVC framework, I'd expect
it to be optional, perhaps using optional attributes, or even a config value.
I know a lot of people would rather do it the "Rails way" and keep things simple & quick, but we put a lot of stock into contracts/interfaces & strong typing as a means to aid refactoring & manage change (as well as to provide a bit of design-time quality
control). I wouldn't want to force the rest of the MVC world to work this way, but we consider this to be an important part of the way we want to build our applications.
If this sort of thing doesn't make its way into the MVC framework, does anyone have any ideas as to how we might implement it ourselves (or maybe in MvcContrib)?
lazycoder
Member
36 Points
13 Posts
Re: MVC Architecture
Dec 13, 2007 06:44 PM|LINK
Well, since the http request is stateless by nature, the observer pattern doesn't really work in the case of the web. For each request, the state of the objects is created. There's no real "change" for the observer pattern to identify.
So you get this controller, which really just responds to actions from the user. The user says "edit" so the controller knows to get the new data from the view and pass it to the model. You can't really have a true MVC pattern on the web unless you use a language that supports continuations, like Smalltalk or Lisp/scheme or use something like Apache's Cocoon framework..
cpnet
Member
54 Points
14 Posts
Re: MVC Architecture
Dec 13, 2007 06:48 PM|LINK
But doesn't this violate the intent of MVC? In your solution, the Controller needs to know fairly specific things about the View and it's controls. The Controller also needs to know fairly specific things about the security aspects of my business logic. Instead of keeping things separated, we've started to centralize View (UI) and Model (business) logic in the Controller. Am I misunderstanding something about MVC still?
lazycoder
Member
36 Points
13 Posts
Re: MVC Architecture
Dec 13, 2007 07:27 PM|LINK
Not Necessarily. The controller knows that it needs to set some conditions on the view based on the information it gets from the model. Whether the conditions are telling the view to enable/disable parts it's UI or what values to set on different form fields in the view doesn't really matter IMO.
It seems to me that if all the controller is going to do is pass the model on to the view for every action, then the controller could be completely abstracted away and we'd just have, essentially, the model bound directly to the controller. I think, by definition, the controller has to understand a little bit about both the model and the view and understand how to manipulate one based on information from the other.
Others may disagree with me some and want to keep the controller less involved.
ShawnOster
Member
8 Points
4 Posts
Re: MVC Architecture
Jan 15, 2008 09:58 PM|LINK
Jumping in because I went through some of these issues once upon a time and here is what I came away with.
In an MVC application, even the desktop-based ones I've applied MVC too, you almost always have a new set of Controllers and Views per application. In my experience controllers are almost never reusable and are almost always bound to a single view. Even between web applications you rarely reuse just a controller unless you're grabbing the entire vertical slice, model, controller and view. This is where service and helper layers come in.
Don't get caught up in the word "Service", that doesn't mean it has to be a physical service running on a server somewhere; it just means a discreet, reusable bit of functionality wrapped in a single interface. I've found that a service is really just a fancy way to say a Facade pattern stretched over your model, or a viewless controller, such as a login service that takes in a login and password and gives the ya or nay on the combo and requires a concrete model-backend.
A perfect example is that for one of my sites I allow developers to access the site's API as long as they have a valid developer token, so I have a "TokenService" that has these methods:
I don't have any views that support displaying or editing of tokens, I just create them under the covers so a full Controller is overkill. I also have some desktop-based Windows Services running that do some token maintenance so they need access to the TokenService as well. Including a full Controller in a Windows Service would be silly, because I don't need the entire MVC framework dragged into my little service app, I literally only want to create and delete tokens using a fully tested interface, my TokenService.
My rule of thumb is that a controller only moves data from the model into a view and back again, applying any needed validation and filtering. If it's logic I may need in non-UI situations, like my tokens, I tend to create services that are either just class libraries or when I need to expose my service to others, full blown SOAP or REST-based end-points.
Lastly (sorry this is a long, rambling post) I can see how controllers can be confusing. They seem like a perfect place to put *all* of your business logic for a certain entity, so if you have a ProductsController you might have RestockProducts() and CheckInventory() and IsProductOnSale() and ProductIsOrganic() yet in MVC the controllers tend to be less about those types of methods and more like ways to link data to html. So the question becomes, and I think that's the crux of this thread, where do you put those methods?
jrnail23
Member
13 Points
13 Posts
Re: MVC Architecture
Jan 15, 2008 10:22 PM|LINK
I'd like to jump in here and share one of the concerns my team raised when discussing the ASP.NET MVC framework...
We're not so much concerned with controller reuse ACROSS different apps, but we want to be able to reuse controllers WITHIN our app.
So let's say we have a couple different places in the app where we can create a Person object (maybe one view is more detailed, or maybe one view is optimized for rapid data entry, or whatever). We'd like to be able to post that Person data from either view's form to the PersonController's Create action.
So far so good, right? But the problem we have with the current implementation of ASP.NET MVC is first, that there's no strongly-typed interaction between the View and the Controller when posting to the Controller. So for instance, our PersonController expects to receive Request.Form data which includes 2 fields (ie, FirstName, LastName). So we go and build the two versions of the form with those two fields on it. The next week, the client calls and says, "hey, we need a MiddleName field in there, too." Ok, so we go and add the middleName field to one of those forms, but we forget that there's another form that needs modification as well. So we've just introduced a bug, which won't be caught until after we run unit tests.
What we'd like is to be able to specify an interface (INewPersonView) which these two forms would implement, and we'd want the PersonController's Create action to expect this interface. That way, if we forgot to update one of our two forms, we'd have a compile-time error instead, and we'd have more peace of mind when turning junior developers (who presumably wouldn't know "where all the bodies are buried" in our app) loose on these things.
Does that make any sense to anyone else? Is this even consistent with the concept of MVC on the web?
ShawnOster
Member
8 Points
4 Posts
Re: MVC Architecture
Jan 15, 2008 10:58 PM|LINK
One thing that strikes me is that you should be running your tests constantly. I pretty much run all unit tests a few dozen times a day and whatever unit I'm working on I run those tests every time I make an atomic change. Unit tests are a much better way to capture things than relying on compile-time bugs.
<div mce_keep="true">Anyway, test-driven analness aside it seems you could build in this type of checking into your controller without the overhead of creating a new interface that you then have to manage. Since you have to add validation into your Controller's Create anyway why not have it log or e-mail an exception when you are missing expected fields? I'm assuming you'd already be adding validation and field verification in your controller so if data is sent your way it'll fail the middle name field validation and you can roll with it.</div> <div mce_keep="true"> </div> <div mce_keep="true">The more I think about it the INewPersonView seems like a lot of extra overhead for very little benefit. You now have *another* place to maintain in your code, you've added another layer of abstraction and personally as a junior (or even senior) coder I'd find it more confusing because now there is even more disconnect between View and Controller. Plus, your junior coders better be running unit tests like mad!</div> <div mce_keep="true"> </div> <div mce_keep="true">I can also see how this would cause more headaches. You add "MiddleName" to your INewPersonView and are working on updating View1, so you add it to that views INewPersonView implimentation but your project doesn't compile because View2 is complaining about the missing MiddleName. Because you want to get it to compile you quickly throw a dummy property on View2 while fine tuning View1 and after a long day you completely forget about View2's dummy, non-working MiddleName yet you have a false sense of confidence because you don't get any compile time issues.</div> <div mce_keep="true"> </div> <div mce_keep="true">Just my two cents, I see where you're going but think it would be best handled directly in the controller and unit-tests vs. an interface abstraction.</div>jcteague
Member
211 Points
45 Posts
Re: MVC Architecture
Jan 16, 2008 02:49 PM|LINK
This is not controller logic, this is business logic. This should not be in a controller, winforms or webforms. You push this into your domain layer so that it can be reused.
lazycoder
Member
36 Points
13 Posts
Re: MVC Architecture
Jan 16, 2008 03:15 PM|LINK
Yeah, that's a pain. But, there's nothing in the MVC pattern, or in this Web.MVC pattern, that says that a view represents one and only one page. Perhaps writing a RenderPartialView method, with an associated controller, would be a better way to handle that situation? A partial view would be very close to a Webform User Control. I'm not clear on what the server-side control story is with this framework yet.
This blog entry by Rob Conery explains this a little better.
UserControls Controller GrapeJelly
jrnail23
Member
13 Points
13 Posts
Re: MVC Architecture
Jan 16, 2008 05:44 PM|LINK
That's an excellent point, and obviously one I overlooked. I guess then what we'd want is something that specifies an interface (or contract of some sort) for the post data expected by a controller action. Instead of having to apply that interface/contract to the entire view, then maybe we're talking about a way to apply it at the HTML form level (what's actually being posted) or at the PartialView level.
Any way a strongly typed contract could be applied between view posts & the receiving controller action would go a long way toward soothing my team's anxieties toward ASP.NET MVC. If something like this were to find its way into the MVC framework, I'd expect it to be optional, perhaps using optional attributes, or even a config value.
I know a lot of people would rather do it the "Rails way" and keep things simple & quick, but we put a lot of stock into contracts/interfaces & strong typing as a means to aid refactoring & manage change (as well as to provide a bit of design-time quality control). I wouldn't want to force the rest of the MVC world to work this way, but we consider this to be an important part of the way we want to build our applications.
If this sort of thing doesn't make its way into the MVC framework, does anyone have any ideas as to how we might implement it ourselves (or maybe in MvcContrib)?
typedview suggestion Controller mvc view partial view view interfaces
steve harman
Member
128 Points
38 Posts
Re: MVC Architecture
Jan 16, 2008 07:00 PM|LINK
re: a language that supports continuations
Ye ask and ye shall receive... thanks to lambdas and LINQ we can actually build continuations into C#. Behold the Marvels of Monads. :)
Linq lambda continuations