MVC Architecture

Last post 01-16-2008 6:46 PM by sliderhouserules. 39 replies.

Sort Posts:

  • Re: MVC Architecture

    12-11-2007, 5:56 PM
    • Member
      36 point Member
    • lazycoder
    • Member since 05-01-2007, 11:59 PM
    • Posts 13

     
    In my opinion, the ValidateLogin method isn't a controller method at all. It's a model method and that's where it should go.

     The way I would go about doing this would be to create an ISecurityController interface, with a Login method. You could then implement the interface in both your ASP.NET MVC controller and your WinForm controller. The Login method would call ValidateLogin method on a User model object. The big benefit to MVC is 1) separation of concerns as Phil stated before 2) reuse of models. Because of #1, the models are far removed from any specific V or C implementation, making it easier to re-use them. You could even reuse the in non-MVC applications. Heck, slap a COM interface on them and call them from VBScript if you want. :)
     

     
    public interface ISecurityController {

    void Login(string username, string password) { }

    }



    public class HomeController : Controller, ISecurityController {

    public void Login(string username, string password) {

    UserModel um = new UserModel();

    IsLoggedIn = um.ValidateLogin(username, password);


    }

    }

     I'm taking inspiration for this directly from the RailsEngine:LoginEngine plugin.

     

        # File vendor/plugins/login_engine/app/controllers/user_controller.rb, line 18
    18: def login
    19: return if generate_blank
    20: @user = User.new(params[:user]) # what does this achieve?
    21: if session[:user] = User.authenticate(params[:user][:login], params[:user][:password])
    22: session[:user].logged_in_at = Time.now
    23: session[:user].save
    24: flash[:notice] = 'Login successful'
    25: redirect_to_stored_or_default :action => 'home'
    26: else
    27: @login = params[:user][:login]
    28: flash.now[:warning] = 'Login unsuccessful'
    29: end
    30: end
      
  • Re: MVC Architecture

    12-12-2007, 11:32 AM
    • Member
      54 point Member
    • cpnet
    • Member since 04-12-2004, 8:01 PM
    • Posts 13

    I've been looking at this new MVC stuff the last two days, and I have had questions similar to frparel.  From what I've read in this thread, MVC is not (as I had thought) primarily intended to support Controller reuse.  If I want to be able to put the same business logic behind different UI's (Silverlight, webpages, WFC, WinForms), I need to use a different pattern.  MVC's primary value in this implmentation seems to be the support of Test Driven Development?

    It seems that in this implementation of MVC, the Controllers do two primary things.  The first thing Controllers do is pass subset(s) of Model data to a View.  While the View knows about the complete structure of the Model (i.e. a model of the Northwind database) the Views don't actually get any data directly from the Model.  The Controller acts as the actual Datasource for the View.  A Controller may only pass a partial list of Customers from the Model to a Customer View.  The second thing Controllers do is to orchestrate the flow from one View to another.  Views don't know about each other, they only know about the Controller.  The Controller knows about all of the Views and transitions the user from one to the next as appropriate.  Have I got this right so far?

    One thing I'm not clear on is how I'd handle (what is for me) a typical scencario.  Maybe MVC isn't meant to deal with this, so maybe this isn't an issue, but it is bugging me.  I might have a page/form that displays Customers, Orders, Order Details, and Product Detail info in 4 related grids as a sort of multi-level Master-Detail display.  For ease of use I want these grids all on the same form/page.  Some users will only have the rights to edit Customers.  Some can edit Customers but only see Orders.  Some can edit and Customers, Orders, and Order Details.  Only a select few can see right down to the Product Details, and even fewer can edit those Product Details.  From a user's perspective, I think  a grid should only be visible if the user can view the data in it.  And there should only be an edit button available for the grids the user can edit.  But doesn't this require either the View knowing all the security rules from the Model, or creating a different View for each permutation of grid view and edit-ablility, and then having that Controller know about the Model's security rules so it can select the correct View for the particular user?

     

  • Re: MVC Architecture

    12-13-2007, 11:33 AM
    • Member
      36 point Member
    • lazycoder
    • Member since 05-01-2007, 11:59 PM
    • Posts 13

     Don't think of MVC in term of controller reuse. Think of it in terms of Model reuse. Supporting TDD is just a side-effect of the separation of concerns.

     For your example, I might architect things like so:

    A User model which gives the controller information about what items (orders, customers, etc...) the user can/cannot see as well as whether or not they can create/update/delete the items.

     
    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.
     
     

  • Re: MVC Architecture

    12-13-2007, 12:13 PM
    • Member
      102 point Member
    • NeoAdroit
    • Member since 02-03-2004, 7:27 PM
    • Posts 28

    One thing i see  different in APS.NET MVC framwork, from my understanding of Original MVC is the responsibility of Contorller. In asp.net mvc implementation, controller is used to decouple view from the model, controller passes the viewdata to view, through which view gets its hands on model, but then, view cannot access model on its own. In original MVC, it ws the observer pattern, that was used to decouple the model from view, and not the controller.

    Am i missing something ?

    neo.

  • Re: MVC Architecture

    12-13-2007, 12:34 PM
    • Contributor
      5,953 point Contributor
    • Haacked
    • Member since 09-17-2003, 2:43 PM
    • Posts 388
    • AspNetTeam

    That is a spot on observation. The reason for that is the stateless nature of the web. By the time the view is rendered and sent to the browser, the model is no longer in memory, so it would be hard for the view to update itself from the model via the observer pattern.

    We could possibly fake it by having the object stick around in memory and using Ajax to poll the object, but that wouldn't scale well and add a lot of complexity. Embrace statelessness I always say. Wink

    This key difference is why many call this pattern the Web MVC pattern.

    Phil Haack (http://haacked.com/)
    Senior Program Manager, Microsoft

    What wouldn’t you do for a Klondike bar?
  • Re: MVC Architecture

    12-13-2007, 2:44 PM
    • Member
      36 point Member
    • lazycoder
    • Member since 05-01-2007, 11:59 PM
    • Posts 13

     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..
     

  • Re: MVC Architecture

    12-13-2007, 2:48 PM
    • Member
      54 point Member
    • cpnet
    • Member since 04-12-2004, 8:01 PM
    • Posts 13

    lazycoder:
    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?

  • Re: MVC Architecture

    12-13-2007, 3:27 PM
    • Member
      36 point Member
    • lazycoder
    • Member since 05-01-2007, 11:59 PM
    • Posts 13

    cpnet:
    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. 


  • Re: MVC Architecture

    01-15-2008, 5:58 PM
    • Member
      8 point Member
    • ShawnOster
    • Member since 01-15-2008, 9:14 PM
    • Posts 4

    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:

    • IsValidToken
    • CreateToken
    • DeleteToken

    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?

  • Re: MVC Architecture

    01-15-2008, 6:22 PM
    • Member
      13 point Member
    • jrnail23
    • Member since 08-01-2007, 10:21 PM
    • Posts 10

    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?

  • Re: MVC Architecture

    01-15-2008, 6:58 PM
    • Member
      8 point Member
    • ShawnOster
    • Member since 01-15-2008, 9:14 PM
    • Posts 4

    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.

    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.
     
    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!
     
    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.
     
    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.
  • Re: MVC Architecture

    01-16-2008, 10:49 AM
    • Member
      211 point Member
    • jcteague
    • Member since 02-26-2003, 11:48 PM
    • Austin, TX
    • Posts 45

    frparel:

    In controller:

    If (Model.CustomerAmount < 0) {
       DoX;
    } else {
      DoY;
    }

    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.

  • Re: MVC Architecture

    01-16-2008, 11:15 AM
    • Member
      36 point Member
    • lazycoder
    • Member since 05-01-2007, 11:59 PM
    • Posts 13

    jrnail23:
    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.
     

    This blog entry by Rob Conery explains this a little better. 

  • Re: MVC Architecture

    01-16-2008, 1:44 PM
    • Member
      13 point Member
    • jrnail23
    • Member since 08-01-2007, 10:21 PM
    • Posts 10

    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)?

  • Re: MVC Architecture

    01-16-2008, 3:00 PM
    • Member
      128 point Member
    • steve harman
    • Member since 07-10-2006, 3:32 AM
    • Posts 38

     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. :) 

    Filed under: , ,
Page 2 of 3 (40 items) < Previous 1 2 3 Next >