Fredrik Normén's Blog - NSQUARED²
Any fool can write code that a computer can understand. Good programmers write code that humans can understand.

Microsoft Most Valuable Professional
     .Net Framework - ASP.Net - Architecture - Development
NOTE: This list of posts will only list the 15 latest posts, to see the rest, select from the Archives located in the menu to the left. The RSS will only list the 10 lastest posts.
Moved my blog.

Category:  Other

Hi everyone that still visit this blog.

I have now moved it to the following address: http://weblogs.asp.net/fredriknormen/ , and will not use http://fredrik.nsquared2.com it will only be  used for accessing my earlier posts.

Kind regards,

Fredrik Normén

Posted: Friday, February 08, 2008 - 14:46 GMT+1    Print     E-mail    Comments (0)
MVC - Expression Language and custom tags

Category:  Design and Architecture

MVC - Expression Language and custom tags
Posted: Tuesday, November 27, 2007 - 12:19 GMT+1    Print     E-mail    Comments (0)
ASP.Net MVC Framework - Security

Category:  ASP.Net MVC Framework

ASP.Net MVC Framework - Security
Posted: Sunday, November 25, 2007 - 12:55 GMT+1    Print     E-mail    Comments (0)
ASP.Net MVC Framework - Exception Handling by Using an Attribute

Category:  ASP.Net MVC Framework

ASP.Net MVC Framework - Handling Exception by using an Attribute

Posted: Wednesday, November 21, 2007 - 23:51 GMT+1    Print     E-mail    Comments (0)
ASP.Net MVC Framework - Exception handling

Category:  ASP.Net MVC Framework

ASP.Net MVC Framework - Exception handling

Posted: Monday, November 19, 2007 - 23:05 GMT+1    Print     E-mail    Comments (1)
VS 2008 is here

Category:  Other

Visual Studio 2008 is now released and can be downloaded from the MSDN download Subscription.. the site is kind of busy right now, though ;)

Posted: Monday, November 19, 2007 - 17:17 GMT+1    Print     E-mail    Comments (0)
ASP.Net MVC Framework - Creating a IRouteHandler which will support Interceptors

Category:  ASP.Net MVC Framework

ASP.Net MVC Framework - Creating a IRouteHandler which will support Interceptors

Posted: Monday, November 19, 2007 - 01:03 GMT+1    Print     E-mail    Comments (0)
I have a new blog.

Category:  Other

I have a new blog up at: http://weblogs.asp.net/fredriknormen

I will still have this blog up and running, but in the future I will only add pointers to my other blog.

The reason why I have a new blog up at the www.asp.net site is because this blog is running on my own Blog engine, and I have no time over to add new features.

Posted: Sunday, November 18, 2007 - 01:22 GMT+1    Print     E-mail    Comments (0)
ASP.Net Framework - Create your own RouteHandler

Category:  ASP.Net MVC Framework

In my previous post I wrote about how we can create our own IControllerFactory for the ASP.Net MVC Framework; in this post I will show you how we can create our own IRouteHandler.

The RouteHandler in this post will replace the IControllerFactory with my own Controller Factory, and also set a default ControllerFactory and a ViewFactory specified in the web.config. This is something the current preview bits of the MVC Framework can’t.

It’s quite easy to create our own RouteHandler, we only need to implement the IRouteHandler interface and implement the GetHttpHandler method ;)

public class N2MVCRouteHandler : IRouteHandler
{
   public IHttpHandler GetHttpHandler(RequestContext requestContext)
   {
       N2MVCHandler handler = new N2MVCHandler();
       handler.RequestContext = requestContext;
       return handler;
    }
}

The GetHttpHandler returns an IHttpHandler. I have created my own IHttpHandler (N2MVCHandler). The N2MVCHandler inherits the MvcHandler shipped with the ASP.Net MVC Framework. The reason why I inherit the MvcHandler is because I don’t want to rewrite stuff that isn’t necessarily. In my IHttpHandler I override the ProcessRequest method and added my own code to create a Controller for the current request.

public class N2MVCHandler : MvcHandler
{
    protected override void ProcessRequest(IHttpContext httpContext)
    {
       if (this.RequestContext == null)
          throw new InvalidOperationException("No RequestContext");

       string controllerName = this.GetRequiredString(this.RequestContext.RouteData, "controller");

       IController controller = this.CreateController(controllerName);
       ControllerContext controllerContext = new ControllerContext(base.RequestContext, controller);

       controller.Execute(controllerContext);
    }

    private IController CreateController(string controllerName)
    {
       N2MVCConfigurationHandler config = ConfigurationManager.GetSection("Nsquared2/N2MVCSection") as N2MVCConfigurationHandler;

       IN2ControllerFactory controllerFactory = N2ControllerFactoryBuilder.GetControllerFactory(config.ControllerFactory);

       IController controller = controllerFactory.CreateController(base.RequestContext, controllerName);

       return controller;
    }
}

In the ProcessRequest method I also create a Controller for the current request by calling the CreateController method. The CreateController method in the N2MvcHandler instantiates a ControllerFactroy which is specified in the web.config file. When the factory is instantiated I make a call to its CreateController method to create an instance of the Controller.

In this example I have replace the IControllerFactory with my own interface, the reason is that I want to pass the name of the Controller and not the Type. The MvcHandler shipped with the MVC Framework will in the ProcessRequest method try to locate the Controller within the references assemblies and create the Type of the Controller and pass it to the IController.CreateController method. But I think it’s up to the ControllerFactory to look up the Controller. Here is my IControllerFactory interface:

public interface IN2ControllerFactory
{
    IController CreateController(RequestContext context, string controllerName);
}

Note: You can still create your own ControllerFactory, but you need to implement my interface instead of IControllerFactory, and you don’t need to make a call to the ControllerBuilder.Current.SetDefaultControllerFactory method in the Application_Start event in Global.asax to specify which ControllerFactory you want to use, instead you can do it in web.config. You will see how to do it later in this post.

I decided to use Spring.Net in this post also to create my Controller within the ControllerFactory.

public class N2ControllerFactory : IN2ControllerFactory
{
    public IController CreateController(RequestContext context, string controllerName)
    {
        IResource input = new FileSystemResource(context.HttpContext.Request.MapPath("objects.xml"));
        IObjectFactory factory = new XmlObjectFactory(input);

        IController controller = (IController)factory.GetObject(controllerName, typeof(IController));

        if (typeof(Controller).IsAssignableFrom(controller.GetType()))
        {
          N2MVCConfigurationHandler config = ConfigurationManager.GetSection("Nsquared2/N2MVCSection") as N2MVCConfigurationHandler;
          ((Controller)controller).ViewFactory = N2ViewFactoryBuilder.GetViewFactory(config.ViewFactory);
        }

        return controller;
    }
}

It's the ControllerFactory's responsibility to create and fill the Controller with all it information it needs. In this case the ViewFactory.

The IViewFactory is used to create a factory which has the responsibility to create a View. Because a Controller don’t need to implement the Controller base class I will in my code use a "code policy". I will check if the created Controller inherits the Controller class, if so I will create a IViewFactory and inject it to the Controller. The IController interface don’t have the ViewFactory property, it’s something we will get from the Controller base class. 

If we take a look again at the CreateContoller method in the IHttpHandler (N2MVCHandler), we can see how I get the ControllerFactory from the web.config

private IController CreateController(string controllerName)
{
    N2MVCConfigurationHandler config = ConfigurationManager.GetSection("Nsquared2/N2MVCSection") as N2MVCConfigurationHandler;

    IN2ControllerFactory controllerFactory = N2ControllerFactoryBuilder.GetControllerFactory(config.ControllerFactory);

    IController controller = controllerFactory.CreateController(base.RequestContext, controllerName);

    return controller;
}

I use some other helper classes in my code to create an instance of the Controller- and ViewFactory specified in the web.config, the code of the helper methods is not relevant for this post. When the public CTP of the MVC Framework is released, you can drop me an e-mail and I can send you my source code.

Here is the config section in the web.config where a conrollerFactory is specified and also a viewFactory. So we can now easy specify our ControllerFactory and ViewFactory in web.config.

<Nsquared2>
    <N2MVCSection
        controllerFactory="MvcApplication.Models.N2ControllerFactory, MvcApplication, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
        viewFactory="MvcApplication.Models.N2ViewFactory, MvcApplication, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</Nsquared2>

By using the Route objects’ RouteHandler, we can easy change the RouteHandler the MVC Framework should use.

RouteTable.Routes.Add(new Route
{
    Url = "[controller]/[action]/[id]",
    Defaults = new { action = "Index", id = (string)null },
    RouteHandler = typeof(N2MVCRouteHandler)
});

In this post you have seen how we can create our own IRouteHandler, and also replace the ControllerFactory with our own.

Posted: Sunday, November 18, 2007 - 01:16 GMT+1    Print     E-mail    Comments (1)
ASP.Net MVC Framework - Create your own IControllerFactory and use Spring.Net

Category:  ASP.Net MVC Framework

In this post I’m going to show you how we can easy create our own IControllerFactory for the ASP.Net MVC Framework and use Spring.Net to create our Controllers. I will in this post also use the Spring.Net Dependency Injection support to pass a Repository that should be used by our Controller.

To create a ControllerFactory we need to implement the IControllerFactory interface. This interface has one method, CreateController. This method takes two arguments a RequestContext and the Type of the controller to create. The MVC Framework will locate our Controller and passed in the Type to our IControllerFactory. This is something I don’t like; I want to be responsible to look up my own Controller in my way, not let the MVC Framework locate the type in their way, It will only creates some magic. If we want to change this behavior in the current preview of the MVC Framework we can create our own RouteHandler, but this is out of topic in this post. When we use Spring.Net to get an instance of an object we use a string, so we can use the Name property or the Type passed as an argument to our CreateController method to get the name of the Controller.

Here is the implementation of an IControllerFactory which will use Spring.Net to instantiate a Controller:

public class SpringControllerFactory : IControllerFactory
{
        public IController CreateController(RequestContext context, Type controllerType)
        {
            IResource input = new FileSystemResource(context.HttpContext.Request.MapPath("objects.xml"));
            IObjectFactory factory = new XmlObjectFactory(input);

            return (IController)factory.GetObject(controllerType.Name);
        }
 }

In this code I use the XmlObjectFactory to create objects out from a specified XML file, in this case the "objects.xml" file. Within the objects.xml file we can specify the objects we want to be instantiated when we are using the Spring.Net framework. I will later in this post show the content of the "objects.xml" file. But first we can take a look at the implementation of a Controller.

public class HomeController : Controller
{
        IHomeRepository _homeRepository;

        public HomeController() : this(new HomeRepository()) {}

        public HomeController(IHomeRepository homeRepository)
        {
            this._homeRepository = homeRepository;
        }

        [ControllerAction]
        public void Index()
        {
            CompanyInfo companyInfo = this._homeRepository.GetCompanyInfo();
            RenderView("Index", companyInfo);
        }

        [ControllerAction]
        public void Contact()
        {
            CompanyInfo companyInfo = this._homeRepository.GetContact();
            RenderView("Contact", companyInfo);
        }

        [ControllerAction]
        public void About()
        {
            CompanyInfo companyInfo = this._homeRepository.GetCompanyInfo();
            RenderView("About", companyInfo);
        }
 }

I decided to modify the HomeController created by the "MVC Web Application" template. My modification of the HomeController was to remove the code to fill a CompanyInfo object, and instead put it into a Repository with the name "HomeRepostory".

public class HomeRepository : IHomeRepository
{
        public CompanyInfo GetCompanyInfo()
        {
            CompanyInfo companyInfo = new CompanyInfo();
            companyInfo.CompanyName = "Your company name here";
            return companyInfo;
        }

        public CompanyInfo GetContact()
        {
            CompanyInfo companyInfo = new CompanyInfo();
            companyInfo.CompanyName = "Your company name here";
            companyInfo.AddressLine1 = "Company address Line 1";
            companyInfo.AddressLine2 = "Company address Line 2";
            companyInfo.City = "City";
            companyInfo.State = "State";
            companyInfo.Zip = "00000";
            companyInfo.Email = "
email@yourcompany.com
";
           
            return companyInfo;
        }
 }

The HomeRepository implements an interface with the name IHomeRepository. I made this design decision so I can easy mock my repositories. If we take a look at the HomeController again we can see that I have added a private field with the type IHomeRepository and also created a constructor which will take an IHomeRepository as an argument. The reason to this design is because of testability. For example if I mock the HomeRepository I can in my Test project easy inject the mock object for the Repository to my Controller.

MockHomeRepository mockHomeRepository = new MockHomeRepository();
HomeController homeController = new HomeController(mockRepository);

homeController.About();

Assert.AreEqual(((CompanyInfo)homeController.ViewData).companyInfo, "Your company name here");

By using a constructor which will take our IHomeRepository as an argument, we can also do a Constructor Injection by using the Sprin.Net framework, and that is exactly what I’m going to do in this post.

Now when we have our Controller and Repository we need to setup the “objects.xml” file with our objects and also setup a Constructor Injection. Here is the content of the “objects.xml” file:

<?xml version="1.0" encoding="utf-8" ?>
<objects xmlns="
http://www.springframework.net"
                xmlns:xsi="
http://www.w3.org/2001/XMLSchema-instance"
                xsi:schemaLocation="
http://www.springframework.net http://www.springframework.net/xsd/spring-objects.xsd">

  <object id="HomeController" type="MvcApplication.Controllers.HomeController, MvcApplication, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
    <constructor-arg name="homeRepository" ref="HomeRepository"/>
  </object>

  <object id="HomeRepository" type="MvcApplication.Models.Repositories.HomeRepository, MvcApplication, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
 
</objects>

The Object element specifies our objects we want to create with the Spring.Net framework. The id attribute specifies the name of the object and the type specifies the type of our object. When we use the Spring.Net framework’s GetObject method we pass in the name of the object to create, the GetObject method will look for an object with the id attribute set to the name, and instantiate the specified type. By using the <constructor-arg> element we can specify what object that should be passed into our constructor when we create the object. In this case I have specified the HomeRepository object.

When our IControllerFactory now will create our HomeController, Spring.net will create an instance of our Controller and do a constructor injection and pass in the HomeRepository object to the constructor and return our controller.

Now when we are done with all the implementation of our IControllerFactory, Controller and Repository we need to make sure our IControllerFactory should be used. This can be done in the Global.asax’s Application_Start event by using the SetDefaultControllerFactory method:

protected void Application_Start(object sender, EventArgs e)
{
   ControllerBuilder.Current.SetDefaultControllerFactory(
                           typeof(MvcApplication.Models.Infrastructure.SpringControllerFactory));
   ...
}

When we now run our application, our IControllerFactory will be used and all the creating of our Controllers will be handled by the Spring.Net framework.

Posted: Saturday, November 17, 2007 - 17:02 GMT+1    Print     E-mail    Comments (0)
ASP.Net MVC Framework - List and Save data

Category:  ASP.Net MVC Framework

I have posted an article about how to list and save data with the ASP.Net MVC Framework. You can find it here:

http://weblogs.asp.net/fredriknormen/archive/2007/11/17/asp-net-mvc-framework-list-and-save-data.aspx

Posted: Saturday, November 17, 2007 - 01:47 GMT+1    Print     E-mail    Comments (0)
My twin brother have blogged about LINQ and LINQ to SQL etc

Category:  Other

My Twin brother Johan Normén are blogging again, he have some interesting posts about LINQ and LINQ to SQL etc. You can find his blog here: http://www.johannormen.com/blog
Posted: Thursday, November 15, 2007 - 17:59 GMT+1    Print     E-mail    Comments (0)
ASP.net MVC Framework and data binding.

Category:  ASP.Net MVC Framework

Note: The content in this blog post is based on the an early prototype of the ASP.Net MVC Framework and stuff can or will change.

I got a question if it’s possible to use data binding with the ASP.Net MVC Framework. Sort of it’s possible, at least to display data but not to do a two-way data binding with existing controls. The reason of that is because it’s not implemented yet ;) The way the data-bound controls work today with data-binding will not work with the MVC Framework, but we will probably see a solution to solve this in the future. When we do a POST and post data a controller’s action method will be invoked. This method can take some arguments as input parameters, for example:

/Products/Edit/1      /Products/Edit?id=1

[ControllerAction]
public void Edit(int? id)
{
}


Note: The URL is routed to the controller, and invokes an action method.

We can’t from the control get access to the controls by using an id as in a normal postback scenario. What we can do is to use the Request property of the base class of our controller (If we decide to inherit the Controller class). The Request property is of type IHttpRequest. The reason why it uses an interface is because we should easy mock out the Request to make sure we can simply do unit-testing without needing to run our controllers within ASP.Net. By using the Request property we can simply get the data from our input fields and map them to our model:

<input type=”text” name=”Description” …>

product.Description = Request[“Description”]


In an early prototype from
Scott Guthrie, he used an Extension method that could take the Request.Form as an argument and do the mapping between user input fields and model.

product.UpdateFrom(Request.Form)

In the view he used a naming convention to easy see which user input field should be mapped to which property of the model:

<input name=”Product.Description” …>

There are other different prototypes to make it easy to fill a model out from the posted data.

We can use some of the controls to do one-way data binding to display data.
Scott Guthrie has a good example in his post about how we can bind data to the ListView control that is shipped with ASP.Net 3.5 (ASP.Net 3.5 will be available at the end of this month, so really soon).

If we have a ListView control in our View we can bind data like this:

<asp:ListView id=”productList” runat=”server”>
    <LayoutTemplate>
          <table>
                 <asp:PlaceHolder Id=”itemPlaceHolder” runat=”server”/>
         </table>
    </LayoutTemplate>
    
   <ItemTemplate>
         <tr>
              <td><%# Eval(“Description”) %></td>
         </tr>
   </ItemTemplate>
</asp:ListView>


Because the View is responsible to render the model, we will do the data binding in the code-behind of the View.

public partial class Products : ViewPage<List<Product>>
{
   public void Page_Load()
   {
      productList.DataSource = ViewData;
      productList.DataBind();
   }
}


Note: Because the View inherits the ViewPage<T>, we can specify the type of the ViewData (ViewData will be of type T). The ViewData is a property of the ViewPage which will contain the data we passed to the RenderView method in our control:

[ControllerAction]
public void List()
{
      List<Products> products = ProductRepository.GetAll();
      RenderView(“Products”, products);
}

As you have seen in this post, we can do one-way data binding, but at the moment we can't easy do a two-way data binding. You will see more post about the MVC Framework from me.

Posted: Thursday, November 15, 2007 - 13:50 GMT+1    Print     E-mail    Comments (1)
New RSS feed address

Category:  Other

I will soon remove my old RSS address and if you have subscribed to my RSS I want you all to change the address to: http://feeds.feedburner.com/FredrikNormnsBlog

 

Posted: Monday, November 12, 2007 - 19:35 GMT+1    Print     E-mail    Comments (2)
ASP.Net MVC Framework an early look

Category:  ASP.Net MVC Framework

NOTE: “The information in this post is from an early stage of the MVC Framework and only an overview of the basics. The MVC Framework can and will be changed over time.”

As many of you already know Microsoft is working on a MVC Framework for ASP.Net. MVC stands for “Model View Controller”. The Model View Controller is a design pattern and the idea is to separate business logic from the View (The View is the page that will display content, for example an .aspx page). The MVC in general maintain a clean separation of concerns, it will be easier to test business logic because it’s separated from the View and the View will not have any knowledge of the underlying model. Today when we build ASP.Net applications we have a code-behind which is a partial class of the “View”. With the code-behind model we can’t easy use Test Driven Development (TDD) or unit-test, at least is not easy. We can use the MVP (Model View Presenter), but that require us to write some extra code. With the MVC Framework it will be much easier to apply TDD.

The ASP.Net MVC Framework is integrated with ASP.Net and can use existing infrastructure like caching, session and profile etc. It will also support static and dynamic languages. The MVC Framework will only as it looks now work on ASP.Net 3.5. The .Net 3.5 will be released within any weeks now. The final build of the framework was done only some days ago. With the MVC Framework we will get a Project Template and great tool support. The MVC Framework is extensible and pluggable, so we can replace any system components, it also support Inversion Of Control (IoC)/Dependency Injection (DI). It’s the lifecycle that makes the model extensible. It looks like this:

Request -> Route (IRouteHandler) –> ControlFactory (IControllerFactory) -> Controller (IController) -> ViewFactory (IViewFactory) -> View (IView) -> Response

The Web Server gets browser request, for example http://localhost/Product, the Route to Controller is determined. The Controller is activated and the “Action” method on Controller is invoked. The Controller will then access the model. The Controller will then render View and passing in custom ViewData to the View. The View is rendered.
When we use the MVC Framework we will not specify an URL to a specific page and pass QueryStrings etc. Instead we use a cleaner URL. For example:
http://localhost/Products or http://localhost/Producsts/Edit/4 etc.
We will map this URL to a specific controller which will be executed when we enter the URL. In the Global.asax we can create routes, which will be handled by an IRouteHandler. The following is the default way to add a route:


protected void Application_Start(object sender, EventArgs e)
 {
            RouteTable.Routes.Add(new Route {
                Url = "[controller]/[action]/[id]",
                Defaults = new { action = "Index", id = (string)null },
                RouteHandler = typeof(MvcRouteHandler)
            });
 }

Note: In a later release we will probably be able to add this to a configuration file instead of writing code.

The Route that is added to the RouteTable will use an URL with the following format “[controller]/[Action]/[id]”. The controller is the controller that should be used, the action is the method in the controller that should be executed and the id is a value that can be passed to the controller’s method. If we use this format and enter a URL like the following: http://localhost/Product, the MVC Framework’s IControlleFactory will create and return the controller that belongs to the Product. It will try to locate a controller with the name ProductController. So if you enter an URL like http://localhost/Customer, it will try to instantiate a controller with the name CustomerController. When the controller is instantiated the Index method of the controller will be executed. The Defaults property of the Route class specify the default settings for the route, such as which action method of the controller is the default action (in this case the Index is the default one specified, this can also be specified on a controller with an attribute.), and the default values of the action method’s parameters that should be passed to the method. If we specify a URL like this one: http://localhost/Product/List the List method of the ProductController will be executed instead of the one that is default specified on the Route. The format of the URL specified for the Route was [controller]/[action]/[id], and the [action] in the format specifies which part of the URL is the name of the action method that should be executed. The [id] in the URL is the name of the action method’s parameter and the value enter at this location of an URL will be passed to the action method. If we enter a URL like this one: http://localhost/Product/Edit/4, the Edit method of the ProductController will be executed and the value 4 will be passed as a value to the Edit method’s id argument. The interface of the action method will look like this:

public void Edit(int? id)

I will later in this post write more about the controller.

We can of course change the format of the URL if we want to pass more values to a controller’s action method, for example: “[controller]/[action]/[id]/[pageIndex]”.

The RouteHandler property of the Route specifies which IRouteHandler we want to use.

If we don’t need to use the format “[controller]/[action]/[id]”, for example instead of letting the URL have the name of the controller we can skip the [controller] from the URL and instead specify the type of the controller we want to use when we setup the Route. For example:

RouteTable.Routes.Add(new Route {
        Url = "products/[category]",
        Defaults = new {
               controller = "Product",
               action = "Index"
          },
          RouteHandler = typeof(MvcRouteHandler)
});

Now when we have looked at how we can map a URL to a controller we can take a look at how we can implement a controller. A controller is a normal class that inherits the base class Controller located in the System.Web.Mvc namespace:

using System;
using System.Collections.Generic;
using System.Web.Mvc;

namespace MyControllers
{
    public class ProductController : Controller
    {
    }
}

An action method is a normal method that has the ControllerActionAttribute specified. The ControllerActionAttribute is used because of security reason so not anyone can enter an action in the URL and execute it. The ControllerActionAttbibute has some properties also, for example the DefaultAction which can be used to specify the default action method of the controller.

[ControllerAction(DefaultAction = true)]
 public void Index()
 {
        RenderView("MyView");
 }

The RenderView method will render the specified view. In this case the view with the name “MyView”. The RenderView will not do a call to Response.Redirect; instead it will use the Server.Execute method. By default the RenderView will look into a sub folder of your project with the name Views and then the sub folder with the name of the controller attached to the view.

/root
    /Views
          /Product
             MyView.aspx

The RenderView method is located in the Controller’s base class. This method will execute the IView’s RenderView method. We can create our own IViewFactory which will return our IView representation where we can create our own implementation of the RenderView. For example if we want to render a view based on another format than HTML, for example a jpg or gif image etc. We can create our own IView and make sure our RenderView will render binary data to the output stream instead of text.

The code-behind of the View inherits form the ViewPage instead of the Page object.

Note: We can easy create our own IViewFactory and IView for mock out the views for testing and replace .aspx with other technologies.

To send data to the View that should be displayed we can use the ViewData property of the Controller base class, or we can pass our data to the RenderView method:

[ControllerAction]
public void List(int? page)
 {
       PagedList<Product> products = repository.GetProducts(page ?? 0, 10);
       RenderView("List", products);
 }

 [ControllerAction]
 public void Edit(int id)
 {
        Product product = repository.GetProductByID(id);
         RenderView("Edit", product);
 }

[ControllerAction]
public void ShowCustomer(int? id)
{
    ...
    ViewData["CustomerName"] = customer. Name;
    RenderView("ShowCustomer");
}

To display this information in our View we can user server side script block:

<table class="product_listing">
        <tr>
            <th></th>
            <th>Product Name</th>
            <th>Unit Price</th>
        </tr>
       
        <% foreach(var p in ViewData) { %>
       
            <tr>
                <td>
                    <%=Html.Link("Edit", "Products", new { Action="Edit", ID=p.ProductID }) %>
                </td>
                <td><%=p.ProductName %></td>
                <td><%=p.UnitPrice.ToCurrency() %></td>
            </tr>
       
        <% } %>
       
</table>

 

<h2><%=ViewData.ProductName %></h2>


<h1><%=ViewData["CustomerName"] %></h1>

By using the ViewData collection we can pass several of objects to our view that should be displayed. If we want to pass typed data to the View, we can inherit the Controller<T> where ViewData will be of type T. If we use the Controller<T>, the page which uses the Controller<T> needs to inherit the ViewPage<T> instead of ViewPage.

The MVC Framework doesn’t support postbacks and the use of ViewState, so most of the Controls shipped with ASP.Net can’t be used. Microsoft will probably add new Controls for the MVC Framework.

Note: This framework is not Web Form 4.0 or will replace the existing postback model. The postback model will still exists and Microsoft will still provide new feature to it in the future.

The MVC Framework will be added to the SP1 of VS 2008. This framework is for people that would like to use this MVC design pattern instead of the postback model. The MVC Framework will work better with Test Driven Development and unit-testing, so people that will make it easier to test web apps will also probably use this model. I will use it in every Web project in the future. With this model it would also be easier to maintain applications because we will have more control over the HTML. We don’t need to hook up to an event of a control and try to figure out how to add extra data into a GridView if we want to extend it etc. This model reminds of the old classic ASP, and it will be easier for people that work with classic ASP to move to ASP.net if they start using the MVC Framework.

Testing with MVC will as I mentioned before be much easier. We have several of interfaces that we can use. The Mockable intrinsic objects are IHttpContext, IHttpResponse and IHttpRequest. Because the MVC Framework have interfaces for IRouteHandler, IController, IControllerFactory, IView and IVewFactory we have more extensibility options. If we want to test a Controller’s action we can for example create our own IViewFactory and IView, by doing this we can change the implementation of the RenderView method.

[TestMethod]
Public void TestTheEditActionFotTheProductContoller()
{
    ProductController controller = new ProductController(mpr);

    TestViewEngine testView = new TestViewEngine();
    controller.ViewFactory = testView

    controller.Edit(5);

    Assert.Equal(testView.Template, "Edit");
    Asssert.Equal(testView.GetViewData<Product>().ProductID, 5);
}

If you want to see some sample code, you can download it from Scott Hanselman’s blog.

Watch out for more information on Scott Guthrie blog.

Posted: Sunday, November 11, 2007 - 20:18 GMT+1    Print     E-mail    Comments (3)
   fredrik.nsquared2.com - 2007