16
Oct
07

ASP.NET MVC Framework


Scott Guthrie blogged about the new ASP.NET MVC Framework that they have been cooking up. You can also check out the movie from the ALT.NET conference which includes some good demos and tons of information. I cannot express how happy I am to see Microsoft moving in this direction. Go read the blog, watch the recording, and get excited. I know MVC in ASP.NET is available through MonoRail but having it come from Microsoft means much wider acceptance and usage.

The only thing I noticed in the movie that I didn't like was the need to explicitly pass data to the view. I agree that this is a great option, but I would also love the option to have my local variables automatically available in the view (I am not sure how you would do this in .NET).

I am hoping Scott will see this post and maybe find a way to get it in the framework (since Google Alerts has made everyone like Voldemort, not that Scott is like Voldemort, but you know what I mean)

-James



Comments

13 Responses to “ASP.NET MVC Framework“


  1. #1 Chad Myers 10.16.2007 at 5:15 AM

    I'm not sure what you mean by 'local variables'. Local to which class, the controller? That violates the whole point of MVC and also decreases your ability to test each individually.

  2. #2 JAmes avery 10.16.2007 at 5:20 AM

    Yes, the controller. The data is being passed one way or another, I just want a way to wrap it all up automatically for me. I don't see how manually filling an object somehow makes it better. This is how rails works and I have never had a problem with my testing.

  3. #3 Chad Myers 10.16.2007 at 5:24 AM

    Interesting. I wasn't aware that's how Rails worked. Didn't ScottGu or Hanselman show off the PropertyBag or am I thinking of another presentation? It seems that it wouldn't be that hard to automatically grab all the properties (or may be specially-attributed properties) off the controller and slap them into a PropertyBag that the View could use.


  4. #4 JAmes avery 10.16.2007 at 5:26 AM

    Chad,
    They might of, but I don't remember. But that is exactly what I am looking for, just some way to keep it nice and simple instead of having to specify it.

    -James

  5. #5 Scottgu 10.16.2007 at 5:38 AM

    The policy on how you pass data from a Controller to a View is easy to change if you want (everything on the Controller base class is virtual). So if you want to automatically scoop up local variables and pass them that is easy to-do.

    By default the Controller base class has a ViewData collection that you can use to add just the variables you want to the view. Alternatively, you can pass the viewdata object directly as part of the RenderView method:

    RenderView("Edit", myProduct);

    The reason we currently don't by default send all instance variables was that in app-building we found that you often had instance data that was controller specific (or action specific) and that you didn't necessarily want to send all of this to each view. It felt a little unclean to automatically send everything to the view. It is something we'll ceretainly be interested in feedback on with the first preview. As I mentioned above - it is only about 5 lines of code to change it (so if people prefer it different we can definitely change it). :-)

    Thanks,

    Scott

  6. #6 JAmes avery 10.16.2007 at 4:17 PM

    Scott,
    I didn't know about the ViewData collection, I like that a little bit better than having to send the data explicitly in the call. What might be the best way to handle it would be to include two controller types, one that lets you specify and the other that wraps it up automatically. I guess I could just create that controller type when it comes out, but it would be cool to have it baked in.

    What does everyone else think?

    -James

  7. #7 Magnus Mårtensson 10.16.2007 at 5:27 PM

    Any generic solution to this and the option to choose is alright with me!

    /Magnus

  8. #8 Damien Guard 10.16.2007 at 6:29 PM

    By doing that you are effectively removing the contract or interface between the controller and the view.

    Besides going against the spirit of seperation of concern it also means you could expose sensitive data where you have re-used a view not realising one of the variables the view uses is not sensitive on one controller but sensitive on another.

    [)amien

  9. #9 JAmes avery 10.16.2007 at 6:44 PM

    Damien,
    I don't really buy that rationale. I don't see how it breaks separation of concern either. You are sending data from the controller to the view, why does it matter if it is explicit or implicit? If it is implicit you just have to remember that your properties are going to be exposed to any view you call.

    -James

  10. #10 Scottgu 10.19.2007 at 4:02 AM

    >>>>>> I don't really buy that rationale. I don't see how it breaks separation of concern either. You are sending data from the controller to the view, why does it matter if it is explicit or implicit?

    Consider the scenario where you are using property dependency injection on your controller, and have a public IDataRepository property that you expose from your controller.

    For clean separation of concerns you want to make sure that your data repository isn't directly passed to your view. If all properties were passed automatically you could inadvertainly have your view gain access to this.

    Having said that - if you do want to send all properties of your controller to the view, just pass a "this" reference when rendering the view:

    public class ProductsController : Controller
    {
    public string Message { get; set; }

    [ControllerAction]
    public void Edit(int id)
    {
    this.Message = "Hi James";

    RenderView("Edit", this);
    }
    }

    Alternatively, you could create a JamesController base class that overrides the default RenderView virtual method and does this by default:

    public class JamesController : Controller
    {
    protected override RenderView(string viewName) {
    RenderView(viewName, this);
    }
    }

    You could then just write your controller like below and have the behavior you want:

    public class ProductsController : JamesController
    {
    public string Message { get; set; }

    [ControllerAction]
    public void Edit(int id)
    {
    this.Message = "Hi James";

    RenderView("Edit");
    }
    }

    Hope this helps,

    Scott

  11. #11 JAmes avery 10.19.2007 at 4:43 AM

    Scott,
    Very cool. As long as I can extend it like that I am very happy. :)

    -Jame

  12. #12 Scottgu 10.19.2007 at 5:30 AM

    All methods on the Controller and ControllerBase classes are virtual, and are designed so that you can override all built-in semantics and policy.

    If you want to invent your own policy entirely, you can also just implement the IController interface:

    interface IController
    {
    public void Execute(IHttpContext context, RouteData data);
    }

    This Execute method takes an interface based version of the HttpRequest/Response/Server/Application/Session intrinsics (enabling easy mocking) as a parameter, as well as the tokenized URL route information (based on your route table). If you want to build a completely different controller abstraction you could use this to implement whatever policy you want.

    Hope this helps,

    Scott

  13. #13 Codeville 11.06.2007 at 5:36 PM

    Another angle on this whole design strategy is to get a similar framework running in the browser itself. This way you can allow the data model to be modified, and the UI updated, without any client/server interaction.

    I've been working on an open-source client-side MVC library for ASP.NET 2.0 which you might like to check out if the idea appeals. See blog.codeville.net/.../ />There are some quick demos on the site which show the source code.