Tuesday, June 15, 2010

Understanding Models part 2: Data Binding and Strongly Typed Views

In the previous post we introduced a simple MVC model. Another approach to implement model is associating the model with a strongly typed view.

Remember the GetData from the previous post, the last line returned a simple view that displayed the string “Thanks”
returnView("Thanks");

now we will implement a strong typed view to display data from the model Products, so here are the steps
  1.  Go to the views folder, go to products folder, right click and choose add view.
  2. You’ll see a dialogue like this, we will call it StrongProducts, then choose the view data class which is our Products Model, then choose empty content and finally choose our master page.

  3. Go to the page you will notice that it inherits from
    Inherits="System.Web.Mvc.ViewPage<CustomersOrders.Models.Product>" %>
    Instead of
    Inherits="System.Web.Mvc.ViewPage" %>

  4. Add the following to the page
    <p>
      Thanks, you just entered <%=Model.Name%>
    </p>
    

  5. Now in the controller class
    ProductsController 
    change the GetData method to be
    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult GetData()
    {
    Product NewProduct = new Product();
    NewProduct.Name = Request["txtName"].ToString();
    NewProduct.Description = Request["txtDesc"].ToString();
    Product.InsertProduct(NewProduct);
     
    //returns a strongly typed view
    return View("StrongProducts", NewProduct);
    } 

  6. Now browse to products page, add a new product then you will be redirected to StrongProducts view. It should be like this

  7. So what happened here: first the strongly typed view is associated with the Products Model, this means that you can use all of your model’s properties and methods in your view and bind them with the controls on the view by referencing the Model property of the view.

Advantages of using strongly typed views:
  1. Better than using loosely typed dictionaries (such as the ViewData ) as it expresses what should the view do. There would be no confusion on what data the view should deal with.
  2. Makes use of Model Binding feature of the MVC framework (link to another post).
  3. Makes use of the intellisense feature so visual studio can help you in development

Understanding MVC Model

In this post we're going to see what the MVC Model is ? The MVC Model is your program representation of real world objects, processes that make up the subject, purpose or the domain of your application
The MVC Model is a class that handles your business logic, Validation logic or database access logic.
Creting Data Model Can be done in many ways: there is the basic way by creating a class that handle the data access logic. And the other way is to use the Entity Framework
Before we begin we will use a simple data base that handles customer orders. The database has the following structure:



you can download the database definition from this link
Now our first task is to create a data entry page for Inserting the products in the database. so we'll desing a Model Class to handle this operation so here are the steps:
  1. Create a New Proeject
  2. Add a new class file named Products.cs in the Models folder.
  3. Add the following Automatic properties
    public string Name {get; set; }
    public string Description { get; set; }

  4. Add a new view named Products.aspx under Views/Products/Products.aspx and add a new controller called ProductsController.cs as this :
  5. Now in Products.aspx add the following controls:



    <%using (Html.BeginForm())
          { %>
          <p>Product Name:<%=Html.TextBox("txtName") %></p>
          <p>Product Description <%=Html.TextBox("txtDesc") %></p>
          <p><input type="submit" value="Add" /></p>
        <% } %>

  6. Now try writing some text in the text boxes and press the button, you'll see that the page posts back and the text disappears as if the form is redrawn. Now that's gonna be a problem cause this means that the data entered won't be passed to the model to insert new record in the database. So what we gonna do for this ?
  7. This happened cause the form posted to [URL]/Products which calls

    public ActionResult Index()
            {
                return View("Products");
            }
    that returns the view and renders the page.
  8. Now we want to receive the data from the form. So we’re going to slice the Products.aspx to two methods:

    One to respond to the HTTP GET request which will be responsible for rendering the initial blank form when a user requests the form

    One to respond to the HTTP POST requests. By default any form rendered by HTML.BeginForm() are submitted by POST method. This action will be responsible for receiving the data from the form.
  9. The first function will be like this just returns the blank view:

    [AcceptVerbs(HttpVerbs.Get)]
            public ActionResult Index()
            {
                return View("Products");
            }
    

  10. The second function will belike this: the attribute
    [AcceptVerbs (HttpVerbs.Post)]
    controller that this function will handle the HTTP POST method
    [AcceptVerbs (HttpVerbs.Post)]
            public ActionResult GetData()
            {
                
            }
    

  11. Back to our Product Model.cs, add a function that inserts the data of a new product in the database:
    static public void InsertProduct(Product NewProduct)
            {
    
                string conString = ConfigurationManager.ConnectionStrings   ["CustomersOrdersDB"].ConnectionString;
                SqlConnection conn = new SqlConnection(conString);
                conn.Open();
                string insertCommand = "insert into products (name,[desc]) values('"+NewProduct.Name+"','"+NewProduct.Description+"')";
                SqlDataAdapter daProducts = new SqlDataAdapter();
                daProducts.InsertCommand = new SqlCommand(insertCommand, conn);
                daProducts.InsertCommand.CommandText = insertCommand;
                daProducts.InsertCommand.CommandType = CommandType.Text;
                daProducts.InsertCommand.ExecuteNonQuery();
                conn.Close();
            }

  12. Now in
    Products.aspx
    in the
    BeginForm()
    function modify it to be
    Html.BeginForm("GetData","Products")
    The BeginForm function has two parameters: ActionName which is the name of the action that will be executed when the form is submitted (GetData function in our case).
    The second parameter is the Controller Name that handles requests from this view which is the
    Products
    Controller
    Note:The name of the controller (Products) must be provided without the Controller suffix despite that the controller class is named ProductsController
  13. Now in
    ProductsController
    our second function GetData() write the following code:
    Product NewProduct = new Product();
                NewProduct.Name = Request["txtName"].ToString();
                NewProduct.Description = Request["txtDesc"].ToString();
                Product.InsertProduct(NewProduct);
                return View("Products");
    
    this function receives the values from the text boxes, creates a new
    Product
    object and inserts it in the data base
  14. Run the form and insert a new product, you’ll see that the record has been inserted in the database.
  15. You will notice that after inserting pressing the submit button the page is refreshed with blank field (Responding to HTTP GET method).
  16. Now we want to redirect the user to another page after inserting a new record so add a new view to Views/Products folder call it thanks.aspx and replace the last line in the GetData() function with this
    return View("Thanks");

  17. So after the user adds a new product he/she will be redirected to Thanks.aspx


Summary
In this post we introduced the MVC Model in its simplest form. The MVC Model represent the real world object of you application

The MVC model in this application handled the data access operations and thus achieving the separation between the interface and the data access layer which is one of the goals of the MVC pattern.

Download the project from here

Saturday, November 14, 2009

Understanding MVC Views

We saw that MVC views are similar to traditional ASP.NET pages except that thay may not be correspondant to the url that the user types in the browser, meaning that if the user types [URL]/Account/MyAccount.aspx there must be an aspx page on the server named MyAccount.aspx under a folder named Account
In MVC it's different this page would be called Index.aspx placed under Views/Account
A view is a standard (X)HTML document that can contain scripts. You use scripts to add dynamic content to a view.
The listing below is the html of a view that has a label displaying the string "Hello"

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage"  %> 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">



<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Demo page</title>
</head>
<body>
    <form id="form1" runat="server">
    
    <div>
        <asp:Label ID="Label1" runat="server" Text="Hello"></asp:Label>
    </div>
    </form>
</body>
</html>

If you want to display the current date and time you can use this:

<% Response.Write(DateTime.Now);%>

you can write any c# code inside the tags and display them like

<% int x = 5;
       int y = 2;
       int z = x + y;
       Response.Write(z);
    %>
which will display the number 7 on the page.
Instead of writing Response.Write() you can replace it with "=" sign
so writing
<% =DateTime.Now %>
will display the current DateTime

Using HTML Helper
HTML Helper is a function that generates a string of the markup of the some of the HTML (not ASP.NET controls) Controls to reduce the amount of HTML you write
the following code displays a text box on the page

<%
            using (Html.BeginForm())
            { %>
        <% =Html.TextBox("txtHello","This is a text box") %>
        <%}
        %>
this resmbles the following html

<input id="txtHello" name="txtHello" type="text" value="This is a text box" />
you can also use the HTML Helper class to produce other types of controlls. more info can be found in this link

View Data
Each Controller class has a property called ViewData
this property is used to pass data between the controller and the view. It is used in a way close to using
Session variables. It uses a Key-Value pair

The following code in the controller class adds a string to the View Data

ViewData["message"]="This is view data";
this code adds an entry with the key message and value This is view data to the ViewData of the view
In the view to display this string you write:

<%= Html.Encode(ViewData["message"]) %>
We use the HTML.Encode method to encode any special characters that can be there like > or <. You can pass any types in the ViewData cosider the following controller code:
ArrayList arr = new ArrayList();
            arr.Add("1");
            arr.Add("2");
            ViewData["message"] = arr;
            return View();
and the following View script

<% ArrayList temp =(ArrayList)ViewData["message"]; %>
       <%= temp[1] %>
this passes an arraylist to the view, then at the view it displays the second element of the arraylist

that was a quick explanation of the MVC View and how they interact with Controllers

Tuesday, November 10, 2009

Understanding MVC Controllers

In a previous post when took an overview of the Hello World application and located where are the major three elements: Models, Views and Controllers.
Now we're going to explore the MVC Controller in details.
We saw that Controllers respond to browser requests, the controller might return a specific view or redirects to another controller
The following code demonstrates a Controller class for a view called Demo



using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Web.Mvc;

using System.Web.Mvc.Ajax;



namespace HelloWorld.Controllers

{

public class DemoController : Controller

{

//

// GET: /Demo/



public ActionResult Index()

{

return View();

}

public ActionResult Page2()

{

return View();

}



}

}





This class has two functions: Index() which returns Index.aspx (located in Views/Demo/Index.aspx) when the user types

[URL]/Demo in the browser.

The second function is Page2() which returns Page2.aspx (located in Views/Demo/Page2.aspx) when the user types [URL]/Demo/Page2 in the browser



The controller exposes Controller Actions, an action is a function on a controller that is invoked when a certain url is entered in the browser.

so when the user types [URL]/Demo/Page2, Page2() function is a controller action on DemoController.cs

The Controller Action must be:


  1. Public: Any function declared as public in a Controller is exposed as Controller Action automatically. So be careful when declaring public methods as they are accessible by the user if the correct URL is typed.

  2. Controller Action can not be overloaded.

  3. Controller Action can not be static.
We saw that the Controller Action returns an object of type ActionResult, so what is the
ActionResul tobject:
The ActionResult can be one of these
  1. ViewResult – Represents HTML and markup.
  2. EmptyResult – Represents no result.
  3. RedirectResult – Represents a redirection to a new URL.
  4. JsonResult – Represents a JavaScript Object Notation result that can be used in an AJAX application.
  5. JavaScriptResult – Represents a JavaScript script.
  6. ContentResult – Represents a text result.
  7. FileContentResult – Represents a downloadable file (with the binary content).
  8. FilePathResult – Represents a downloadable file (with a path).
  9. FileStreamResult – Represents a downloadable file (with a file stream).

All these ActionResults inherit from ActionResult base class.

In our Index() Method we saw that it returns a Viewresult by calling the View() method.
Normally you don't return an ActionResult directly instead you call one of these methods of the Controller base class
  1. View – Returns a ViewResult action result.
  2. Redirect – Returns a RedirectResult action result.
  3. RedirectToAction – Returns a RedirectToRouteResult action result.
  4. RedirectToRoute – Returns a RedirectToRouteResult action result.
  5. Json – Returns a JsonResult action result.
  6. JavaScriptResult – Returns a JavaScriptResult.
  7. Content – Returns a ContentResult action result.
  8. File – Returns a FileContentResult, FilePathResult, or FileStreamResult depending on the parameters passed to the method.

Consider the following functions



public string Index()
{
return "Hello World";
}
public DateTime Page2()
{
return DateTime.Now;
}

The Index method just returns a string "Hello World"
The Page2() method retuns the current date and time as a plain text

Saturday, November 7, 2009

MVC Anatomy

In a previous post we saw how to create a Hello World MVC application.
Now we're going to perform an anatomy to this application to know what each part of the application exactly means.

First: Where is the Model, the View and the Controller ?
MVC Controller:
In tradotional asp.net the url you type corresponds to a page on the server, so when you request yoursite/abou.aspx there must be a page named about.aspx or a 404- page not found error is thrown.

In MVC it's different, there is no correspondance between the url you type and the pages that exist in the application. rather the url corresponds to a controller action than a page on the server.

The Controller is responsible for the way the user interacts with the application.
it manages the flow control logic of the application. It determines what response to make when the user makes a browser request.

The Controller is a C# class. Our Hello World application contains a controller class named HomeController.cs, It contains only one function named:public string Index()

public string Index()

{
return "Hello World";

}
this function is called when the user types URL /Home/Index in the browser cause as we said the controller functions respond to a user request.
Final thing to note that any public method contained in a controller is exposed as a controller action, meaning that it can be invoked by any user by typing it's name in the browser.
so if you have a function declared public as the following:

public void SomeFunction()







{



// Some Code



}

Any user can call this function by typing URL/Home/SomeFunction so be careful when declaring public functions in Controllers.

MVC View:
The view is equivalent to a page in t ASP.NET. It contains HTML markup that appears on the browser.
so for example if you want to create a page called demo , in Views folder create a subfolder named demo then in this subfolder create an aspx called Index.
then go to the Controllers folder and create a new controller with the name

DemoController.cs

in DemoController.cs add the following code


public ActionResult Index()
{
return View();
}

so when the user types url/demo the demo page is displayed
Notice that you must create the controller class in this form [ViewName]Controller.cs
MVC Model:
The MVC Model Contains you business logic, Validation logic or database access logic.
since that the Hello World application is not that complicated, there are no models in this application
Conclusion:
The view contains the logic for the interface, the Controller contains the logic for redirecting the user correctly to pages and respond to the user requests. And the Model contains the business or database access logic.
The Controller should contain minimal amount of code to handle user requests only.
If the Controller contains large bulks of code, consider removing some of them to a Model class in the Models folder

Friday, November 6, 2009

MVC Hello World

Now we're going to introduce the first MVC application: "Hello World".
What do you need to start:

I will use Visual studio 2008 sp1, so let's get started.

  1. After installing the framework open visual studio and select File>New>Project then from the left tab select web then from the right tab select ASP.NET Web Application

  2. Now from the debug menu choose start without debugging or Press ctrl+f5 to see how the application looks like.


  3. Now back to visual studio look at the solution explorer, it should be like this


  4. Now let's examine these folders:
    1. We have the Content folder which contains Site.css file that defines the initial styles for the website
    2. We have the Controllers folder that contains HomeController.cs which
      contains the code for the default view and HomeController.cs which contains the
      code for managing the login process and new user registeration.
    3. An empty Models folder
    4. We have Scripts folder that contains several javascript files (JQuery and Ajax
      files).
    5. We have the Views folder that contains subfolders containing the index page
      (Home page) and the login and registeration pages.
    6. Finally we have a default.aspx and Global.asax file and web.config file.
  5. For the sake of demonstration we're going to delete the following


  6. Now Back to HomeController.cs replace the code with the following:
    public string Index()

    {
    return "Hello World";

    }
  7. Build and run you should see something like that

  8. Now you have created your first MVC Hello World application

Tuesday, November 3, 2009

What is ASP.NET MVC

So you heard of it: MVC. What is it, what does it stand for and why I need to use it, that’s what we are going to know right now !.
ASP.NET MVC is a new web development framework from Microsoft that combines the effectiveness and tidiness of model-view-controller (MVC) architecture, the most up-to-date ideas and techniques from agile development, and the best parts of the existing ASP.NET platform. It’s a complete alternative to the WebForms platform, delivering considerable
advantages for all but the most trivial of web development projects.

Why MVC ?
well its a question I asked my self when I heard about MVC. Why should I use it instead of developing with tradional asp.net ?
After reading the msdn article and by experience I found that I encounterd the following situations:
  • If you're working in an agile development environment, where the customer or your manger requires modifications or new features to your software module. when new requirements evolve, it becomes such a pain to modify your work- especially if there is a modification to the database you're working on.
  • Many datastore applications require good organization of the User-Interface parts so they can be modified easly in response to database modifications
  • In traditional asp.net the developer may have to handle the user-interface design and the database development, whick consumes a lot of time and distract the developer. So separating the user-interface design and database development efforts produces better performance of the final product.
  • You want to reuse the database access code so you don't have to write the same code in each page.
  • Migrating your application to a newer framework would be easy if there is a separation between the user-interface and the business logic.
  • reducing code tied to user interface enhances testability.
  • The actual mechanism of maintaining state across requests
    (ViewState) often results in giant blocks of data being transferred between
    client and server. It can reach hundreds of kilobytes in many real-world
    applications, and it goes back and forth with every request, frustrating site
    visitors with a long wait each time they click a button or try to move to the
    next page on a grid.
  • ASP.NET MVC–generated pages don’t contain any ViewState data, so
    they can be hundreds of kilobytes smaller than typical pages from
    ASP.NET WebForms. Despite today’s fast broadband connections, this
    bandwidth saving still gives an enormously improved end user experience.
  • It supports a new routing system that produces clean url. Instead of writing App_Pages/page1/aspx?action=show%20prop&prop_id=345 it becomes something like products/technology/Laptops. This doesn't expose your application folder and pages names and the file structure of your application, so you are free to change them as you want without changing the public internet url which users may like to keep it in their favourites for later reference.

Finally ASP.NET is built on the ASP.NET Platform so you won't feel strange when dealing with it and it won't take a long time to get your hands on ASP.NET MVC