ASP. net mvc Framework (Part 1)

Source: Internet
Author: User
Tags php template url example commerce store actionlink

[Original address] ASP. net mvc Framework (Part 1)
[Original article publication date] Tuesday, November 13,200 7 AM

Two weeks ago, I discussed a new MVC (model, view, Controller) framework in ASP. NET in my blog. We will support it as an optional feature in the near future. This framework provides a structured model to enhance the separation of clear attention in applications and facilitate unit testing.CodeAnd supports TDD processes. It also provides more control over the URL you publish in the application, and more control over the HTML output from the application.

Afterwards, I answered many questions from people who are eager to learn more details. In view of this high interest, I think it may be more meaningful to write a few posts to describe how to use this framework in more detail. This is the first post I will write in the next few weeks.

A simple e-commerce store Application

I will use a simple e-commerce store application to demonstrate how ASP. NET MVC framework works. In today's post, I will implement a product list and related browsing application scenarios.

Specifically, we will build an online store that allows users to access/Products/CategoriesProduct Category list:

When you click the product category link on the above page, they will go to a product category list URL/Products/LIST/categorynameThis page lists the products that are still being sold in the specified category:

When users click a product, they will go to the product details URL./Products/detail/productidOn, this page will show more details about the products selected by the user:

We will use the new ASP. net mvc framework to implement all the above functions. This will allow us to maintain a "clear separation of Focus" between different components of the application, allowing us to integrate unit testing and test-driven development more easily.

Create a new ASP. net mvc application

The ASP. Net MVC Framework contains a Visual Studio Project template to help you create a new MVC web application. Select File> new project menu, select the "ASP. net mvc web application" template, and use it to create a new Web application.

By default, when you use this option to generate a new application, Visual Studio creates a new solution for you and adds two projects to it. The first project is a web project in which you implement the functions of your web application. The second project is a test project where you can write unit tests to test your application code:

You can use any unit testing framework in the ASP. net mvc Framework, including nunit, mbunit, mstest, xunit, and other frameworks. Vs 2008 Professional Edition now supports built-in mstest test projects (VS 2005 mstest requires you to have Visual Studio team system version for use). When you use vs 2008, default ASP. the net MVC project module automatically generates such a test project.

We will also release project templates for nunit, mbunit, and other unit test frameworks, so if you prefer those frameworks, you can easily click to generate your application and corresponding test projects that can be used immediately.

Understand the directory structure of a project

The default directory structure of ASP. net mvc applications has three top-level directories:

    • /Controllers
    • /Models
    • /Views

You can probably guess that we suggest placing the Controller class in the/controllers directory, your data model class in the/models directory, and your view template in the/views directory.

Although ASP. net MVC Framework does not force you to always use this structure, but the default Project template uses this pattern. We also recommend it as an easy way for structured applications. Unless you have a good reason to use another file layout, I suggest you use this default mode.

Map URL to Controller class

In most web frameworks (such as ASP, PHP, JSP, and ASP. NET webforms), the URLs are generally mapped to the template files stored on the hard disk. For example, "/products. aspx" or "/products. php" URLs generally have a corresponding products. aspx or products. php template file on the hard disk to process requests. When an HTTP request of a Web application enters the web server, the Web framework runs the code specified by the template file on the hard disk, and then the code is responsible for processing the request. Most of the time, this Code uses the HTML identifier in the products. aspx or products. php file to help generate a response to the client.

The MVC framework maps URLs to the server code in different ways. Instead of ing a URL to a template file on the hard disk, It maps the URL directly to the Code class. These classes are called "controllers" and are responsible for processing incoming requests, processing user input and interaction, and executing corresponding applications and data Logic Based on Input and interaction. Then, a controller class generally calls a separate "View" component, which generates the actual HTML output of the request.

The ASP. net mvc framework includes a very powerful URL ing engine, which provides a lot of flexibility in how to map URLs to Controller classes. You can use it to easily set routing rules. Then ASP. NET evaluates the incoming URLs based on these rules and selects a controller to run them. Then, you can let the routing engine automatically analyze the variables you defined in the URL, so that ASP. NET can automatically pass these variables as parameters to your controller. I will discuss more advanced scenarios involving the URL routing engine in a future post of this series.

Default ASP. net mvc url routing rules mapped to the Controller class

By default, the ASP. Net MVC project has a set of pre-configured URL routing rules that allow you to easily access the Web without configuring anything. In this way, you can start coding by using a set of default name-based URL ing conventions in global. asax file (created by ASP. net MVC Project template generated) in ASP.. NET application class.

The default naming convention is as follows: maps the starting part of the URL path of the incoming HTTP request, such as/products/, to a class. The name of this class followsUrlpathController mode. For example, by default, a URL starting with/products/will be mapped to a URL namedProductsController class.

To build our e-commerce product browsing function, we will add a new "productscontroller" class in our project (you can use the "Add new project" menu in Visual Studio to easily create a controller class from the template ):

Our productscontroller is from system. web. MVC. the controller base class is inherited. It is not necessary to inherit from this base class, but it contains some useful auxiliary methods and functions that we can use in the future:

After defining this productscontroller class in the project, Asp. net MVC framework uses it to process all application requests starting with "/products. This means that it will be automatically called to process the "/products/categories", "/products/LIST/beverages ", and "/products/detail/3.

In future posts, we will also add a shoppingcartcontroller (to allow users to manage their shopping cart) and accountcontroller (to allow users to create new member accounts on the website, logon and logout ). After adding these two new controller classes to our project, the URLs starting with/shoppingcart/AND/account/are automatically directed to these classes for processing.

Note: The ASP. Net MVC Framework does not require you to always use this naming convention mode. The only reason why our applications use this mode by default is that we use Visual Studio to create a new ASP. net MVC project, a ing rule configured with this mode is automatically added to our ASP.. NET application class. If you do not like this rule or want to use another URL ing mode to customize it, you can change it to the ASP. NET application class in global. asax. I will discuss how to do this in a later post, and I will also show some very cool scenarios allowed by the URL routing engine.

Understanding the Controller Action Method

Now that we have created a productscontroller class in the project, we can add logic to process the "/products/" URL of the application.

Before defining our e-commerce store use cases, I said that we will implement three scenarios on the website: 1) Browse all product categories; 2) list the products in a specific category, and 3) display the details of a specific product. We will use the following Seo-friendly URLs to deal with these three scenarios:

URL format behavior URL example
/products/Categories browse all product categories /products/Categories
/products/LIST/ Category list products in a specific category /products/LIST/beverages
/products/detail/ productid display details of a specific product /products/detail/34

You can write code in the productscontroller class in several ways to process these three types of URLs. One way is to overwrite the "execute" method in the controller base class, manually write our own if/else/switch logic, and compare it with the URL requested by the user, then execute the appropriate logic to process the request.

However, a much easier way is to use the built-in functions in the MVC framework, which allows us to define the "Action Method" in our controller ", then, the controller base class automatically calls the appropriate action method to execute according to the URL routing rules used by our application.

For example, we can add the following three controller action methods to our productscontroller class to process the preceding three e-commerce URL scenarios:

When a project is created, the URL routing rule configured by default treats the sub-path following the Controller name as the requested action name. Therefore, if we receive a/products/Categories URL request, the routing rule treats "categories" as an action name, categories () the method is called to process the request. If we receive a/products/detail/5 URL request, the routing rule calls the action name in "detail" and the detail () method to process the request, and so on.

Note: The ASP. Net MVC Framework does not require you to always use this action naming convention mode. If you want to use different URL ing modes, make changes to the ASP. NET application class in the global. asax file.

Map URL parameters to the Action Method of the controller.

In the action method of the controller class, you can use several methods to access the parameter values in the URL.

The controller base class presents available request and response objects. These objects have the same API structure as the httprequest/httpresponse objects you are familiar with in ASP. NET. An important difference is that these objects are now based on interfaces rather than closed classes. Specifically, the MVC Framework will release the system. Web. ihttprequest and System. Web. ihttpresponse interfaces. These objects are based on the interface. The advantage is that it is very easy to mock (mimic) them, so that you can easily test the unit of the controller class. I will discuss this in depth in my future blog posts.

The following is an example of how to use the request API in the detail action method of the productscontroller class to manually obtain the ID to query the string value:

The ASP. Net MVC framework also supports automatically ing the parameter values of included URLs into parameters of the Action method. By default, if your action method has a parameter, the MVC Framework checks the incoming request data to see if there is an HTTP request value with the same name. If yes, it will automatically pass it as a parameter to your action method.

For example, we can use this support to rewrite our detail action method and simplify it, as shown below:

In addition to ing parameter values from the query string/form set of the request, Asp. net MVC framework also allows you to use mvc url route to map the parameter values embedded in the core URL itself (for example, not/products/detail? Id = 3, but use/products/detail/3 ).

When you create a new MVC project, the declared default path ing rule has the format "/[controller]/[action]/[ID]". This means that if there is any sub-path after the Controller name and action name in the URL, it will be processed as a parameter named "ID" by default, the Controller action method is automatically passed as a method parameter.

This means that we can now use our detail method to obtain the ID parameter from the URL path (such as/products/detail/3:

I can use a similar method for List action, so that we can pass the category name as a part of the URL (for example,/products/LIST/beverages ). To make the code easy to read, I made a small change to the routing rule, instead of setting the parameter name as "ID". For this action, it is called "category ".

The following is a version of the productscontroller class that supports complete URL routing and parameter ing:

Note that the List action method above accepts a category parameter as part of the URL, and then a default webpage index parameter that is part of the URL query string (We will implement pagination on the server side, the parameter value is used to indicate which page of the corresponding category data should be displayed ).

The default parameters in our MVC Framework are processed by nullable type parameters in the Controller action method. Because the paging parameter of List action is an nullable int, which is an int in syntax? If this parameter exists in the URL, the MVC Framework will pass its value to the corresponding method. If this parameter does not exist, null is input. Refer to my previous questions about ?? Null coalescing operator post to learn how to operate a nullable type parameter like this.

Build Data Model Objects

So far, we have a productscontroller class that contains three action methods and is ready to process the incoming Web requests. The next step is to build some classes to help us operate the database and obtain the appropriate data needed to process these requests.

In the MVC world, "model" is an application component that maintains the status. In Web applications, this State generally persists in databases (for example, we may have a product object that represents the product data in the products table in our SQL database ).

The ASP. Net MVC framework allows you to use any data access mode or framework you want to obtain and manage your model. If you want to use ADO. Net datasets/datareaders (or the abstraction built on them), you can do that. If you prefer Object Relational mappers (ORM) such as Nhibernate, llblgen, wilsonormapper, and LINQ to SQL/LINQ to entities, you can do the same.

For our e-commerce routine, I would like to use built-in LINQ to SQL ORM released with. Net 3.5 and vs 2008. You can learn more about this in my blog series that is still writing a discussion about LINQ to SQL. In particular, you must read the first part, the second part, and the third part, and the fourth part of the post.

Right-click the "models" subdirectory of the MVC web project in Vs, select "Add new item", and add a LINQ to SQL model. In the LINQ to SQL orm designer, I will define three data model classes, which are mapped to the categories, products, and suppliers tables (read the second part of my LINQ to SQL series to learn how to do this ):

After defining the LINQ to SQL data model class, I will add a new northwinddatacontext section to our models directory:

In this class, I will define several helper methods to encapsulate some LINQ expressions. These expressions are used to obtain unique category objects from the database and obtain all product objects of the specified category, and obtain a separate product object based on the specified productid:

These auxiliary methods help us to obtain the required data model objects in the productscontroller class cleanly (instead of writing a LINQ expression in the Controller class ):

So far, we have all the data code and objects required to complete our productscontroller function.

Implement the productscontroller class

The Controller class in MVC-based applications is responsible for processing incoming requests and user input and interaction, execute appropriate application logic based on these inputs and interactions (obtain and update model data stored in the database, and so on ).

General ControllerNoGenerate a specific HTML response to the request. Tasks that generate HTML responses are owned by the "View" component in the application. These views are implemented through a separate class or template independent of the controller. The purpose of a view is to fully focus on the logic of the encapsulation presentation layer. It should not contain any application logic or database data acquisition code (all application logic should be processed by the Controller ).

In a typical MVC Web process, the Controller action method is responsible for processing incoming Web requests and executing appropriate application logic code using input parameter values, obtain or update the data model object from the database, and then select to use a "View" to display the interface response returned to the browser. As part of selecting an appropriate view to display, the Controller will explicitly input all the data and variables required by the view to the view in the form of parameters, to make the latter display the appropriate response:

You may be wondering, what are the advantages of separating the controller and view like this? Why not put them in the same class? The main motivation for splitting an application like this is to help you enhance the separation between the application/Data logic and the code generated on your interface. This allows you to isolate the display logic of your interface and greatly facilitate unit testing of your application/Data logic. It also helps your application maintain better, because it prevents you from accidentally adding the application/Data logic to your view template.

When implementing the three controller action methods of the productscontroller class, we will obtain the appropriate model object from the database based on the incoming URL parameter values, select a "View" component to display the appropriate HTML response. We will use a renderview () method of the controller base class to specify the view we want to use, and explicitly pass the specific data we want to use when the view is displayed.

The final result of our productscontroller implementation is as follows:

Note that the number of code lines in our action method is small (each method has only two lines ), this is partly because the URL parameter analysis logic is completely implemented by the MVC Framework (saving us a lot of lines of code ), this is partly because the product browsing scenario is quite simple from the business logic perspective (all the action methods involved are read-only display scenarios ).

But in general, you often find that some of you are sometimes referred to as "thin controller", that is, the Controller method is full of very short action methods (less than 10 lines of code ). This is often a good indication that you have encapsulated your data logic very cleanly and well separated your controller logic.

Unit Test productscontroller

You may be surprised that the next step we will take is to test our application logic and functions. You may ask, how is this possible? We have not implemented our view yet. Our application currently does not display an HTML Tag. In fact, part of the reason that the MVC method is attractive is that we can test the controller and model logic completely independently of the View/html generation logic. As you can see below, we can even unit test these objects before creating a view.

For the unit test, we will add a productscontrollertest class to the test project. This test project is used to create our ASP. net MVC applications are added to our solution by default:

Then we will define a simple unit test to test the detail Action Method of our productscontroller:

ASP. net mvc framework is specially designed to facilitate easy unit testing. All core APIs and contracts in the framework are interfaces, which provide a large number of extension points to facilitate easy object injection and customization (including using Windsor, structuremap, spring. net, and objectbuilder ). Developers will be able to use the built-in mock class, or use any. Net mock framework to simulate their own test versions of MVC-related objects.

In the unit test above, you can see how we injected a pseudo (dummy) into our productscontroller before calling the detail () Action method) "viewfactory. In this case, we will overwrite the default viewfactory. Otherwise, the default viewfactory will create and display our views. We can use this test viewfactory implementation for isolation, and only test the detail Action Behavior of our productcontroller (instead of calling the actual view for testing ). Note how we use three assert statements after the detail () Action method is called to verify that the correct behavior of this method has indeed occurred (specifically, this method obtains the correct product object and passes it to the appropriate view ).

Because we can mock and simulate any objects in the MVC framework (including ihttprequest and ihttpresponse objects), you no longer need to run unit tests in the Web service environment, we can create our productscontroller object in the regular class library and test it directly. This can greatly speed up unit testing and simplify their configuration and operation.

If we use Visual Studio 2008 IDE, we can easily track the results of our tests (this feature is now part of vs 2008 Professional Edition ):

I think you will find that the ASP. NET MVC framework greatly facilitates the compilation of tests and facilitates a very good TDD process.

Use the view display interface

We have completed the implementation and testing of the application + Data logic of the product browsing part of our e-commerce applications. Now we need to implement the relevant HTML interface.

We will implement the "View". These views will use the Action Method of productscontroller to provide the view-related data objects when calling the renderview () method, to display the appropriate interface:

In the preceding code example, the "categories" parameter of the renderview method indicates the name of the view to be displayed, the second parameter is to pass to the view object and display the list of classification objects on the appropriate HTML interface accordingly.

The ASP. net mvc Framework supports any template engine (such as nvelocity, Brail, and any template engine you want to write) to help generate interfaces. By default, the ASP. net mvc framework uses the existing ASP. NET pages (. aspx), master pages (. Master), and user controls (. ascx) in ASP. NET ).

We will use the built-in ASP. NET view engine to implement our e-commerce application interface.

Define the site. Master File

Because we will build many pages on the website, we will first define a master page to encapsulate the HTML layout/style common to the entire website. We will create a file named "site. Master" in the \ views \ shared directory of our project:

We can reference an external CSS style file to encapsulate all the styles of the entire website, and then use the master page to define the overall layout of the website, and specify the content placeholder area of the relevant content on the specific page. When doing this, we can also use all the cool functions of the new calculator in vs 2008, including the HTML split view designer, compiling CSS and nested master page support.

Understanding/views directory structure

By default, when you use Visual Studio to create a new ASP. net mvc project, it will generate a "shared" subdirectory under the "views" root directory. This is a recommended place for storing the master pages shared by multiple controllers in an application, user controls, and views.

When creating a view for a specific controller, the default ASP. Net MVC convention is to store them in the subdirectories of the \ views root directory. By default, the subdirectory name corresponds to the Controller name. For example, because the Controller class we are writing is called "productscontroller", by default, We will store a specific view related to it in the \ views \ products subdirectory:

When we call the renderview (string viewname) method in a specific controller, the MVC Framework automatically starts at \ views \ControllernameFind the corresponding. aspx or. ascx view template in the directory. If it cannot find the appropriate view template, it will find it in the \ views \ shared directory.

Create a Categories view

You can use the "Add new project" menu option in the products directory of Visual Studio, select the "MVC view webpage" item template, and create a "categories" view for our productscontroller. This will generate a new. ASPX page, we can link it with our site. the master page is associated to get the overall appearance (just like the master page, you will get the support of the WYSIWYG designer ):

When using the MVC mode to build an application, you need to keep your view code as concise as possible, and make sure that the view code is purely used to display the interface. The application and data retrieval logic should only be written in the Controller class. Then, the Controller class can choose to pass the required data object to the view when calling the renderview method. For example, in the categories action method of the productscontroller class below, we pass the list set of a category object to the Categories view:

By default, the MVC view page is from system. web. MVC. the viewpage base class is inherited. This base class provides many MVC-specific auxiliary methods and attributes that can be used to build the interface. One of the viewpage attributes is "viewdata". With this attribute, you can access the view-specific data object that the controller uses as a parameter to pass to the renderview () method.

From your view, you can later bind or access "viewdata" in a strong way ". If your view is inherited from viewpage, The viewdata attribute is a dictionary bound later. If your view is inherited from a generic viewpage <t>, where T indicates the type of the data object that the controller sends to the viewdata view, the viewdata attribute is strongly typed, match the Data Type passed in by your controller.

For example, the background class of my Categories view is inherited from viewpage <t>. I specify T as a list of category objects.

This means that when you operate the list <Category> viewdata provided by productscontroller. Categories () In my view code, I will get the complete type security, intelliisense and compile-time check:

Show Categories view:

If you still remember the previous one in this post, we will display the product category list in our Categories view:

In my Categories view implementation, I can write this HTML interface in two ways to generate code: 1) In. use line code in the aspx file, or 2) in. use server controls in the aspx file, and then use data binding in the background code.

Display Method 1: Use in-line code

Currently, for ASP. NET web pages, user controls and master pages support embedding display code in HTML identifiers using <%> and <% = %> syntaxes. We can use this technique in the categories view to easily compile a foreach loop to generate an HTML classification list:

Vs 2008 provides complete code intelliisense for VB and C # in the source code editor. This means that when you operate the category model object of the input view, we will get the intelliisense:

Vs 2008 also provides complete debugger support for in-line code (allowing us to set breakpoints on the code in the view in the debugger and dynamically check anything ):

Display Method 2: Use server-side controls

ASP. NET web pages, user controls, and master pages also provide support for using declarative server-side controls to encapsulate HTML interface generation. Instead of using in-line code as above, we can use the new <asp: listview> Control in. Net 3.5 to generate the list interface:

Note that the listview control encapsulates the display Value List, it is also responsible for processing nothing in the list (<emptydatatemplate> omits the trouble of writing if/else statements in the logo ). Then we can bind our category object to the listview control in the background Code as follows:

Important: In the MVC world, we only want to put the display code in the background code of our view, excluding any application or data logic. Note that we only need to assign the viewdata set of the strongly typed category object to the logic of the listview control. Our productscontroller controller class is the owner of the List of actually retrieved category objects from the database, not the view.

The listview Server Control version of our view template will then generate HTML with the same version as the code in the previous line. Because the <form runat = "server"> control, viewstate, id value, and other identifiers are not generated on the page, only pure CSS-friendly HTML:


Html. actionlink Method

One thing you may notice is the call to an HTML. actionlink method in the code snippets of the preceding view for the BOC code and server-side controls:

An HTML object is an auxiliary attribute of the viewpage base class. The actionlink method is an auxiliary method of the object. It allows you to dynamically generate HTML hyperlinks for the action method that is connected to the Controller. If you look at the HTML output diagram generated above, you can see some HTML output examples generated by this method:

<A href = ""> beverages </a>

The signature of the HTML. actionlink method I used is as follows:

String actionlink (string text, object values );

The first parameter indicates the content of the hyperlink to be displayed (for example, <A> text </a>), and the second parameter is an anonymous object, it represents a string of values used to generate the actual URL. You can think of it as a clean way to generate a dictionary. I will discuss the application of this parameter in my blog post on the URL routing engine in the future. But in short, you can use the URL routing system to process both the entered URL and generate the URL that you can output in the returned HTML. If our routing rules are like this:


When you write such code in the category view of productcontroller:

<% = Html. actionlink ("Click me to see beverages", new {Action = "list", Category = "beverages" }%>

The actionlink method will use the URL ing rules you have applied and feed your parameters to generate the following output:

<A href = ""> click me to see beverages </a>

This facilitates generating the URL in your application and the Ajax callback to your controller. It also means that you can update your url routing rules in one place, the code in your entire application will automatically adopt new changes in the process of processing incoming URLs and generating outgoing URLs.

Important Notes: To enhance testability, the current MVC Framework does not support PostBack events for server-side controls in your view. Instead, Asp. net MVC application generates hyperlinks and Ajax callback to the Controller action, and then only displays the output using the view (and any server-side controls. This helps ensure that your view logic is kept at a minimum, focusing only on display, and you can unit test your controller class, independent of your view, verify all application and data logical behaviors. I will discuss this in more depth in future posts.


This first post is very long, but I hope it will apply to the new ASP. how all the different components in the net MVC Framework are combined, and how to use it to create common real-world scenarios provides a wide overview. The first public preview of ASP. net mvc will be released in a few weeks, and you will be able to use it to do everything I described above.

Although many built-in MVC concepts (especially those focusing on separation) are relatively new to many readers of this post, I hope this post will show the ASP that we are developing. net MVC implementation is how to cleanly embed the existing ASP. net ,.. net, and in the Visual Studio framework. You can use the. aspx,. ascx,. Master files, and ASP. NET Ajax files to create your ASP. net mvc view. Today ASP. net non-interface functions, such as form authentication, Windows authentication, Member, role, URL Authorization, cache, session Status, user information, health monitoring, configuration, compilation, localization and httpmodules/httphandlers all fully support the MVC model.

If you do not like the MVC model or find it is not natural for your development style, you do not have to use it. It only provides options,NoReplaces the existing webforms page controller model. The webforms and MVC models will be fully supported and improved in the future. If you want to, you can even build an application, partially using webforms and partially using MVC.

If you like the content posted above (or want to learn more), pay attention to my blog during this period. I will further discuss the MVC concepts and use them to further build our e-commerce applications and demonstrate more MVC features.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.