Monday, June 15, 2009

ASP.NET MVC Translated for the Web Forms Programmer (3 in a series)

Obviously I've been putting this off a little. I think the controller has been haunting me, it's very intimidating. I've become such a good friend to System.Web.UI.Page, it's hard to imagine my life without him. However, we all get older, grow apart. It's time for me (and you) to go head first into the next layer of MVC, we've started our project, set up our model. Now it's time for View -> Controller.


The thing about the controller is, it's a lot like normal code behind. The biggest adjustment? There is no page load. The View gets all its data from the Controller at runtime. There are a few key terms we need to learn. The first one is ActionResult. This is going to be a little confusing so strap in. The Action Result is what each method returns with relation to the View. Each method in the controller that returns data to a view is called an "Action Method"


To demo this we're going to do something super easy, we're going to do some simple math and post the result as a string on our page. Sounds easy? I think so too, don't forget, we're doing this for the first time together.


I must digress for a moment and move over to our global.asax. We're going to look at a method it's called RegisterRoutes and what it does is let our application know how to look at the Urls we're passing it. The way it's set up now, the first term being passed is the name of our controller, MVC now knows what to do with that, and the second term is the name of our Action Method, the third term will be any parameters, and so on. MVC has some serious RESTful goodness, so the RegisterRoutes method shows our application what to look at and where to go when it gets one of our pretty Urls. I left in the defaults, you can customise it for your application, take a look:


 

Routes


Also, before we get started, we need to cover something that's very important in MVC, and that's naming. In order to implement the intuitive functionality of MVC we need a few things to be the same. The name of our controller (plus the word "controller"), and the folder that contains our views related to it (as children of the "Views" folder). Mine is called CapsuleController.cs and My folder is called Capsule. Two more things that need to match are the name of your view, and the name of your action method that returns the view (though not always, it does make things more convenient). Capsule contains a view called Math and we have a an action method in our controller called Math. Take a look at our tree:



 

Tree

 


This is going to look weird the first time you're looking at it. Our action method is being passed no parameters, this is the action that automatically is called by the controller when our view (of the same name) is loaded. If you have named your view (or action) something different, you can just call View("ViewName") and pass the name of the view you want into your method. When this guy is called we get our page as is, with no data passed in.



 

 

So, say we want to populate a label on the load of this ViewPage?  We can pass data through to our page like so:

 Label Action

 

We can now display "Message" in our page by adding this to our View:

 

View

Our page ends up like this:

First Page

It displays our string as if it were an asp:textbox or an asp:label that we were binding it to. So this kind of makes sense. In order to load something at runtime or bind something to the page we reference it from the controller. How do we handle our events?.

MVC introduces us to a keyword "AcceptVerbs" that tells our action method what HTTP action to look for within our view. In the beta of MVC this was required to use HTTP commands, however, now MVC just searches for the applicable action when your view gets a command. We're going to enter a value, and have it save to our DB as a new Link for this project (a Link is one of our objects). So, we're going to do a POST, and we're going to grab a property of the link from our view that the user has entered in a text box (we will cover validation in the future, right now, though, we have a magical user that does no wrong).  

First we add a form to our method, we can pass the values entered into the form when we do our POST.  I am doing this here by overloading our Math method with a FormCollection. You can also use Model Binders which allow you to specify what objects go with which controls. These are a great alternative to the asp:Repeater and asp:GridView. We will go over them more in depth in the next installment. My action grabs all the data entered into our form through the passing of the FormCollection. In order for MVC to know what data is located where we identify it this way on our form, we are only setting one property of an object called Link, as well as creating a new Link:

Here is the way our Action looks (remember I'm using LINQ to SQL):

 view

And our View:

 Final View

When we are done our page looks like so, I enter my value and save:

 Page Second

 

That is it! That's all you have to do to CRUD it up in MVC.

However, what happens when you have more than one submit button or POST per page? I guess you're going to just have to tune in next time and find out.

 

 

 


8 comments:

  1. I think maybe that last C# code snippet is incomplete?

    ReplyDelete
  2. Sara,
    I'd not access the link property using the Form object.
    It's better to have the action read into the FormCollection object instead of the Request.Form collection.
    Or even better, just pass the link as parameter for the action

    ReplyDelete
  3. Nice write up!
    I do agree with @simone and not access the Link value via the Forms property of request. You can easily pass the information to the view through a ViewModel.
    This way you have clear path between view and controller and know the specifics of data that gets passed along.

    ReplyDelete
  4. agreed and changed!

    ReplyDelete
  5. Hi vey nice interesting blog im from leeds i found this on msn I'm in the crane hire company business, i found this blog very interesting good luck with it i will return to this blog soon

    ReplyDelete
  6. Nice content, I think this is a nice blog. Keep going.

    ReplyDelete
  7. What a wonderful blessing indeed. I love good news like this.

    ReplyDelete
  8. Her advice to me was to work harder!!

    ReplyDelete