Eugenio Jacobo Hernández Valdelamar México. Version 1 May, 2009
1
1 Introduction.............. Introduction........................ ..................... ..................... ..................... ..................... ..................... ......................... ....................6 ......6 1.1 About this document................ document........................... ..................... ..................... ...................... .......................... ..................6 ...6 1.2 About the author..................... author............................... ..................... ..................... ..................... ..................... ....................7 ..........7 1.3 Licence............... Licence.......................... ..................... ..................... ..................... ..................... ...................... ........................... ...................7 ...7 1.4 Document versions................ versions........................... ..................... ..................... ...................... ...............................7 ....................7 2 ASP ASP.Net .Net MVC: key concepts................ concepts.......................... ..................... ..................... ................................. ..........................7 ...7 2.1 Web pages are not enough........................ enough................................... .......................... ................................7 .................7 2.2 Web applications................... applications............................. ..................... ..................... ..................... .............................. ......................8 ...8 2.2.1 Database driven Web sites.................... sites................................................... .........................................8 ..........8 2.2.2 Spaghetti a la Web.......... Web..................... ..................... ..................... ...................... ................................9 .....................9 2.2.3 Separate the code, please.................... please............................... .................... .............................10 ....................10 2.2.4 ASP.Net: ASP.Net: web forms & code behind...............................................10 behind...............................................10 2.2.5 Layered development............ development....................... ..................... ...................................... ..................................11 ......11 2.3 A little solar system............ system....................... ..................... ..................... ..................... ..................... ..................... ............ .11 2.3.1 The raise of web application frameworks.............. frameworks......................... ........................11 .............11 2.3.2 The Model-View-Controller Model-View-Controller pattern................ pattern.......................... ..................... ......................12 ...........12 MVC components............... components.......................... ..................... ..................... ..................... ........................... .......................12 ......12 Basic control flow................. flow............................ ...................... ..................... ..................... ..................... ............ ..........13 ........13 MVC passive model.................. model............................. ..................... ..................... ..................... ...........................13 .................13 MVC active model................. model............................ ..................... ..................... ...................... ............. ..................13 Passive Passive view: view: Model2.................. Model2............................. ...................... .................................... ..................................14 .........14 2.3.3 The REST pattern.................. pattern............................ ..................... ..................... ...................... .........................15 .............15 2.4 What is ASP ASP.NET .NET MVC?.......................... MVC?..................................... ....................... ................................. .......................15 ..15 2.4.1 ASP ASP.MVC .MVC application's structure.............. structure........................ ..................... ............................15 .................15 2.4.2 Contrasting ASP ASP.NET .NET and the MVC Framework....... Framework..............................16 .......................16 2.4.3 Routes............ Routes...................... ..................... ..................... ..................... ..................... ..................... .................. ................16 .........16 ASP.NET Routing..................................................................................17 2.5 ASP ASP.Net .Net inside.................. inside............................. ..................... ..................... .......................... ...................................17 ....................17 2.5.1 Data access................ access........................... ..................... .......................................... .............................................17 .............17 LINQ to SQL................. SQL............................ ..................... ..................... ..................... ..................... ..................... ................. .........18 ..18 DataContext class.................. class............................. ..................... ..................... ..................... ..........................18 ................18 LINQ query syntax................. syntax........................... ..................... ..................... ................. ...........................18 ....................18 3 ASP ASP.Net .Net MVC: basic techniques............... techniques.......................... ..................... .......................... .............................19 .............19 3.1 Configure your development environment................ environment........................... ..........................19 ...............19 3.2 Create an ASP ASP.Net .Net MVC application project............... project.........................................19 ..........................19 3.3 The Models realm.................. realm............................ ..................... ...................... ..................... ..............................20 ....................20 3.3.1 Hard coded models................ models........................... ...................... ..................... .................... .......................20 .............20 Create a model class......................... class................................... ............................. .......................................21 ....................21 2
1 Introduction.............. Introduction........................ ..................... ..................... ..................... ..................... ..................... ......................... ....................6 ......6 1.1 About this document................ document........................... ..................... ..................... ...................... .......................... ..................6 ...6 1.2 About the author..................... author............................... ..................... ..................... ..................... ..................... ....................7 ..........7 1.3 Licence............... Licence.......................... ..................... ..................... ..................... ..................... ...................... ........................... ...................7 ...7 1.4 Document versions................ versions........................... ..................... ..................... ...................... ...............................7 ....................7 2 ASP ASP.Net .Net MVC: key concepts................ concepts.......................... ..................... ..................... ................................. ..........................7 ...7 2.1 Web pages are not enough........................ enough................................... .......................... ................................7 .................7 2.2 Web applications................... applications............................. ..................... ..................... ..................... .............................. ......................8 ...8 2.2.1 Database driven Web sites.................... sites................................................... .........................................8 ..........8 2.2.2 Spaghetti a la Web.......... Web..................... ..................... ..................... ...................... ................................9 .....................9 2.2.3 Separate the code, please.................... please............................... .................... .............................10 ....................10 2.2.4 ASP.Net: ASP.Net: web forms & code behind...............................................10 behind...............................................10 2.2.5 Layered development............ development....................... ..................... ...................................... ..................................11 ......11 2.3 A little solar system............ system....................... ..................... ..................... ..................... ..................... ..................... ............ .11 2.3.1 The raise of web application frameworks.............. frameworks......................... ........................11 .............11 2.3.2 The Model-View-Controller Model-View-Controller pattern................ pattern.......................... ..................... ......................12 ...........12 MVC components............... components.......................... ..................... ..................... ..................... ........................... .......................12 ......12 Basic control flow................. flow............................ ...................... ..................... ..................... ..................... ............ ..........13 ........13 MVC passive model.................. model............................. ..................... ..................... ..................... ...........................13 .................13 MVC active model................. model............................ ..................... ..................... ...................... ............. ..................13 Passive Passive view: view: Model2.................. Model2............................. ...................... .................................... ..................................14 .........14 2.3.3 The REST pattern.................. pattern............................ ..................... ..................... ...................... .........................15 .............15 2.4 What is ASP ASP.NET .NET MVC?.......................... MVC?..................................... ....................... ................................. .......................15 ..15 2.4.1 ASP ASP.MVC .MVC application's structure.............. structure........................ ..................... ............................15 .................15 2.4.2 Contrasting ASP ASP.NET .NET and the MVC Framework....... Framework..............................16 .......................16 2.4.3 Routes............ Routes...................... ..................... ..................... ..................... ..................... ..................... .................. ................16 .........16 ASP.NET Routing..................................................................................17 2.5 ASP ASP.Net .Net inside.................. inside............................. ..................... ..................... .......................... ...................................17 ....................17 2.5.1 Data access................ access........................... ..................... .......................................... .............................................17 .............17 LINQ to SQL................. SQL............................ ..................... ..................... ..................... ..................... ..................... ................. .........18 ..18 DataContext class.................. class............................. ..................... ..................... ..................... ..........................18 ................18 LINQ query syntax................. syntax........................... ..................... ..................... ................. ...........................18 ....................18 3 ASP ASP.Net .Net MVC: basic techniques............... techniques.......................... ..................... .......................... .............................19 .............19 3.1 Configure your development environment................ environment........................... ..........................19 ...............19 3.2 Create an ASP ASP.Net .Net MVC application project............... project.........................................19 ..........................19 3.3 The Models realm.................. realm............................ ..................... ...................... ..................... ..............................20 ....................20 3.3.1 Hard coded models................ models........................... ...................... ..................... .................... .......................20 .............20 Create a model class......................... class................................... ............................. .......................................21 ....................21 2
3.3.2 The database................. database........................... ..................... ..................... ................................. ................................21 .........21 Create a database................ database........................... ..................... ............................... .........................................21 ....................21 Design the database on the fly......................... fly................................... ...............................22 .....................22 Design the DB model and create the database..................................23 Using an existing database.................. database............................. ..................... ..................... ........................ ...............23 ..23 3.3.3 The database model classes................ classes........................... ..................... ..................... ....................23 .........23 LINQ to SQL style................ style........................... ...................... ..................... ..................... ................ .....................23 ................23 Create a MVC data model................. model........................... ..................... .....................................23 ..........................23 Create Entity Classes From From a Database............... Database...........................................24 ............................24 Entity Framework style................. style........................... ..................... ............................ .................................24 ................24 Create a MVC data model................. model........................... ..................... .....................................24 ..........................24 Generate model from DB................. DB........................... ..................... ..................... .............. .................24 .............24 3.4 The Controllers realm.............. realm......................... ..................... ..................... ..................... ............................26 ..................26 3.4.1 Controller class and actions......................... actions.................................... .................... ......................26 .............26 Create a MVC Controller............... Controller.......................... ..................... ..................... ..................... ..................... ............. .26 Define an action ac tion method......................... method................................... ................ ........................... ...........................27 ......27 Specify the model object instance in the controller............................27 controller............................27 3.4.2 ViewData.............. ViewData......................... ..................... ..................... ..................... ..................... ..................... .................. ..........27 ..27 Define a controller's c ontroller's action to pass data.................. data............................. ...................... ................27 .....27 3.4.3 CRUD................. CRUD............................ ..................... ..................... .................................. ...........................................28 ....................28 3.4.4 CRUD controller (LINQ to SQL style)............... style).......................... ..................... ....................28 ..........28 Create an instance of the model database context........................... .29 Define an action to get the list of items from the database................29 Define an action to display details from a specific item.................. item......................29 ....29 Define actions to edit an item.................. item............................. ..................... ..................... ......................30 ...........30 Get the details of the item to display.......................... display..............................................30 ....................30 Define save action..................... action............................... ..................... ..................... ........................ .......................30 .........30 Define actions to create a new item...... i tem................ .............................................31 ...................................31 Error in edit and create operations....................... operations............................................ ..............................32 .........32 3.4.5 Error handling................... handling.............................. ..................... ..................... ................ .......................... .......................32 ..32 No error handling effects............... effects......................... ..................... .................................. ................................33 .........33 What's that [HandleError] attribute?......................... attribute?................................... ..........................33 ................33 Action filters................... filters............................. ..................... ...................... ..................... ..................... ..................... ............ ......33 ....33 3.4.6 CRUD controller (Entity framework style)............................... style).....................................33 ......33 Create an instance of the data model................. model............................ ..................... .....................33 ...........33 Define an action to list items from the DB..........................................34 DB..........................................34 Define an action to create a new item.................... item.............................. .......................... ..................35 ..35 Define an action to display details from a specific item.................. item......................36 ....36 Define actions to edit an item.................. item............................. ..................... ..................... ......................36 ...........36 3
Define an action to delete an item.....................................................37 3.5 The Testing realm................................................................................38 3.6 The Views realm..................................................................................39 3.6.1 New views for controllers..............................................................39 Create a new folder with controller's prefix name..............................39 Create a view......................................................................................39 3.6.2 CRUD views...................................................................................39 Create a view to list items..................................................................40 Create a view to display item details..................................................40 Create a view to edit item...................................................................41 Create a view to create a new item....................................................41 Create a view to delete an item..........................................................42 4 ASP.Net MVC: basic code katas.................................................................43 4.1 Kata #1: Say Hello to ...........................................................43 4.2 Kata #2: Basic CRUD with simple DB..................................................45 4.2.1 Controller code..............................................................................46 4.3 Kata #3: a blog engine.......................................................................49 4.3.1 The blog model.............................................................................49 4.3.2 The blog controllers......................................................................51 Categories Controller..........................................................................51 Code................................................................................................52 Posts controller...................................................................................55 Code................................................................................................56 Home controller..................................................................................61 Code................................................................................................62 Comments controller..........................................................................63 Add comment..................................................................................63 View comments...............................................................................63 Code................................................................................................64 4.3.3 The blog views..............................................................................66 Categories views.................................................................................66 Posts views.........................................................................................66 Where is the post category?............................................................67 Home view..........................................................................................67 Recent blog entries..........................................................................67 Changes to the master page...........................................................68 Comments view..................................................................................69 Add a comment, please...................................................................69 Now let´s view the comments.........................................................70 4
4.3.4 Comments.....................................................................................71 4.4 Final comments...................................................................................71 5 References................................................................................................72 5.1 Articles................................................................................................72 5.1.1 Web Applications - Spaghetti Code for the 21st Century..............72 5.1.2 Building Web Apps without Web Forms.........................................72 5.1.3 An Architectural View of the ASP.NET MVC Framework.................72 5.2 Tutorials...............................................................................................72 5.2.1 ASP.Net MVC tutorials...................................................................72 5.2.2 Contact manager in Asp.Net MVC.................................................72 5.2.3 ASP.NET MVC Sample Applications - Open-Source Examples and Tutorials.................................................................................................72 5.2.4 NerdDinner ASP.NET MVC Tutorial.................................................72 5.2.5 Scott Guthrie’s ASP.net MVC Tutorial Links....................................72 5.2.6 ASP.NET MVC - Part 1....................................................................72 5.2.7 ASP.NET MVC Preview: Using The MVC UI Helpers.........................72 5.3 Projects...............................................................................................72 5.3.1 Oxite.............................................................................................72 5.3.2 MVC StoreFront.............................................................................73 5.3.3 Blogging Engine............................................................................73 5.3.4 Kigg - The Digg Clone...................................................................73
1 Introduction So you want to make a Web application. Well, there are tons of information around the Internet and so many languages and tools. However, when you choose one, there is a learning curve to climb, so this decision is crucial for the next weeks, months or years of your pro life. But, what do you have to consider? Language must be something known to you or easy to learn if it´s something new. Maybe, you don't want to pay for a tool because you want to evaluate it. Web infrastructure must be at hand, so your computer must be able to host a web server. Maybe you read some articles and top 10 lists to make sure you are on the right track or just because you want to be part "on the right side" according to statistics.
5
While you analyze and decide what the best choice for your career is, I pick Microsoft web platform. I know VB.Net for a while (desktop flavor), I have the tool (Visual Studio 2008) and the environment (virtual machine server with Internet information server), and because I don´t want to start with 1990's ASP, I want to start with the most recent incarnation of MS Web development alternatives: ASP.Net MVC framework. In this document I´m planning to expose the main concepts and techniques to develop a Web application using this platform. So let´s start.
1.1About this document This document started as a compilation of references to try to understand ASP.Net MVC framework and how to develop an application. However there were lots of details about web applications, the ASP.Net framework and design criteria that I wanted to unify to have a clear vision about this technology. Another reason is that many articles in the web (some dated from 2007 or earlier) show code snipplets that don´t apply to the current release of the framework; decorating action methods with attributes or changing views code behind are deprecated, so its important to have an actual version of this code. That's how these notes began to grow, and some readings about martial arts gave me the idea of organizing the contents: theory, techniques and applied sets of techniques to solve problems (katas).
1.2About the author Well, I've been teaching since 1993 and programming since 1990. I started with Turbo Pascal, then Turbo C++, had some courses of mystic languages (Smalltalk, Prolog), had a taste of Java in the server side and I met Visual Basic in 1996. Since then I've been developing solutions with MS technologies, most for desktop and C/S. Even when today I am more involved in software processes and methods, I like to be aware of technology evolution, and I really think th at web applications are about to make a great leap. I still enjoy a lot programming and learning something new, and I believe this is a good opportunity to share the experience. Please, send any comment and suggestion that help me improve this work to: [email protected]
1.3Licence
6
This work is licensed under the terms of the Creative Commons AttributionNoncommercial-No Derivative Works 3.0 License.
1.4Document versions Version 1. May, 2009. Basic document structure (key concepts, basic techniques and code katas) and initial content.
2 ASP.Net MVC: key concepts 2.1Web pages are not enough When you start dealing with web development, the basic thing you start playing with is HTML. All you have to do is creating a file with .html extension, write some tags and the result in a browser will be a web page. Lets put something clear: writing HTML is NOT programming. HTML is a way to format content that will be displayed on a browser. You can be a masochist and write your pages in a text editor like Note Pad, or have a life and use a Web page editor. Even you can use Office Word and then export the document to a Web page. Of course, this is only about contents; the aesthetic part still remains in the graphic artists realm, and because I don´t want to mess with color theory I'll keep it as Spartan as possible. As long as your content remains static, this is the way to go. But if you want to add some notes every day, display a calendar, have a list of your visitors or any functionality that implies new data, making it by hand is a bad idea (unless you want to be buried alive in a server farm). Interaction, nice look & feel and fresh data implies programming and something to put the text, numbers or images you want to use.
2.2Web applications See document: smli_tr-2007-166.pdf So you want to make an application. Well, then you h ave to write some code to make a program. But where is this programs is going to live? In your PC (win or
7
*nix), in a big machine, in your cell phone? Well the answer tends to be everywhere, and that means that your environment is the World Wide Web. Current web applications rely extensively on a number of technologies that are fundamental components of the web browser. These include the HTML markup language, Cascading Style Sheets (CSS), the JavaScript scripting language, and the Document Object Model (DOM). In a way, these technologies serve as the logical equivalent of “binary code” of traditional software applications, and are intended for execution in any web browser regardless of the underlying hardware or operating system.
2.2.1Database driven Web sites A data-driven Web site draws its content from external dynamic data sources. The data sources may come from: * Files (text or XML) * Database (SQL Server, Access, Oracle) * XML Web services * Other websites When you have a data-driven site, you are collecting data on the fly and then building the pages from that data. A well-architected, data-driven Web site is much easier to maintain than a static Web site because most content changes require no change to the HTML behind the Web site. Instead, changes are made to the data source that drives the Web site, and the Web site automatically adjusts to reflect those changes. With a data-driven Web site, you connect to and present live data from a variety of data sources. Now the question is: how to do it?
2.2.2Spaghetti a la Web See document: Spaghetti_code
Many applications on the web today have a complex and tangled structure – just like spaghetti programs in the 1960s and 1970s. Spaghetti code is a pejorative term for source code that has a complex and tangled control structure, especially one using many gotos, exceptions, threads, global variables, or other "unstructured" constructs.
8
It is also used in pejorative sense to imply that a given piece of work is difficult to understand. So, where can you find spaghetti on the Web apps? Well, there are 3 primary scenarios: 1. Mixed code to the browser. Usually, HTML definitions, style sheets, and JavaScript code are not represented separately. Rather, in most web sites, HTML definitions, style sheets and JavaScript functions are interspersed and mixed in no specific order – other than the order that was established by the tools that were used to generate the web page. The source code of the web documents is not very easy to read and the actual behavior of the document is even harder to understand. This is because the typical user interaction model of the web is such that a new web page is generated and sent to the browser each time the user clicks on a link or a button on a page. 2. Creative freedom over software engineering. As long as the primary purpose of web development was the creation of web sites consisting of documents, pages and forms, there was little reason to apply established software engineering principles to web development. The web browser, with its original design dating back to 1990, is quite well-suited to displaying documents and supporting simple navigation from page to page. 3. Zero structure programming models. The old "spaghetti" code model of web developing platforms as ASP, where actual code with application logic (VBScript, Jscript or whatever) was mixed with markup UI elements (HTML) is a good example. Trying to maintain these applications today is really complicated because of a simple question: where is it? So, it seems that we need to ´put some order in here, but where to start?
2.2.3Separate the code, please See document: 112916.aspx
The most simple way to put some order to this mess is to separate. Let's put the put code in a separate script block element and let the markup in the rest of the page. Even when the organization unit is still the page, the page now has a structure. Most often the ASP pages are HTML pages with embedd ed VBScript or JScript, but there is no problem to implement ASP pages that generate plain text, XML or any other textual content. It is possible, of course, c ertain ASP page to contain only script and no static non-script content at all. This is especially useful when the application implements techniques such as page templates and all the content is dynamically generated, or when the generated content is not textual. So, to separate code from markup ASP provides: * Script code in <% %> and <%= %> tags
9
* Script code in <SCRIPT RUNAT=SERVER ... > tags * File include statement * OBJECT RUNAT=SERVER tags To separate code in a file with markup, script code tags are very useful. But a better practice is to have a real separation of the code, so you can thing in terms of libraries; then you can use a file include statement to consume them. These are some ways to get some separation; however, execution can become messy because of the fact of loading things that you maybe won´t use. Are we done? Mmmm...No.
2.2.4ASP.Net: web forms & code behind See document: what-is-asp-net.html
ASP.NET is a web application framework to allow programmers to build dynamic web sites, web applications and web services. In ASP.NET, Microsoft introduces the concept of a Web Form, much akin to a Windows Forms for Windows programming. Using Web Forms, an ASP.NET developer can develop web applications by dragging and dropping controls onto a design pane. Believe me. There's a difference between imagine where the content is going to be, and actually see it on its place. Another concept that Microsoft introduced in ASP.NET was the use of code behinds. Using code behinds, you can have a clean separation of the UI code and the application logic. In theory, this would allow a web designer, for example, to focus on the design markup with less potential for disturbing the programming code that drives it.
2.2.5Layered development See document: QuickDocId.aspx
Layered development or multi-layer development refers to a development model where presentation, business logic and data are separated. The application, like a web site or a Windows Forms application is usually called the Presentation layer. Then in the middle, you find the Business Logic Layer, or the BLL that is the bridge between the Presentation layer and the next layer: the Data Access Layer or the DAL. This DAL then talks to the database to perform selects, inserts, updates and deletes. One of the ideas of this design is that you can replace one or more of the layers without affecting the others. The design concept sounds good, but the problem is when it's time to code it. Many developers can argue that they are doing a layered application, but they are writing all the logic in the code behind file of a form. Maybe they'll try to separate the business and data layers, but everyone has different ideas and experiences about doing this. Some people will try to get the
10
data directly from the DB instead of creating a business object with that responsibility. So even when layers have a defined responsibility its necessary to restrict the way the application is actually coded. And the only way to do that is applying a design that affects the code structure.
2.3A little solar system It's been stated that layering is not enough to achieve structure and behavior in our applications. The programming model and language's flexibility let us code the way we want it. But in order to achieve code reuse, better applications structure, its necessary to limit this freedom. One way to limit the way applications structure is by design, but the other one is by the programming model used as the foundation to build the application. For example, ASP.Net is a framework that forces us to use object orientation, and in the case of web forms, to separate logic from presentation. In this section the concepts of web application framework and design patterns is explored in order to create our little solar system inside this ever growing universe called WWW.
2.3.1The raise of web application frameworks Web application frameworks are software tools that are commonly used to aid in the creation and management of various types of online applications. A web application framework can involve designing and launching pages for a website or provisioning various applications to provide a wide ran ge of web services to consumers. The framework tends to include all the elements needed to accomplish the desired tasks, thus eliminating the need to secure the necessary tools from different sources. One of the key elements of any web application framework is the software library. As the name implies, software libraries are a central repository for all types of software that may be utilized in the creation and ongoing function of online activities. A typical library will include software to help manage the creation and maintenance of online databases, provide security to the web pages, and also help with mapping the pages so there is a sense of continuity and order.
2.3.2The Model-View-Controller pattern Model–view–controller (MVC) is an architectural pattern used in software engineering. Successful use of the pattern isolates business logic from user interface considerations, resulting in an application where it is easier to modify
11
either the visual appearance of the application or the underlying business rules without affecting the other.
MVC components The MVC pattern, separates an application in three components: Model, View and Controller:
* Model: this is where all the business logic of the application resides: it can range from a simple static class that returns a dataset to a complex multi-assembly Business Logic Layer that uses an assembly specific to the Data Access Layer. * View: at the other end of the application is the View, which displays the application's user interface and contains the representation of the data that have been retrieved by the Model. This doesn't have logic, other than the one strictly related to the presentation of data. * Controller: between the two components stands the Controller. It acts as the orchestrator of all the interactions among the other components and the users: it handles the requests, reads the form values, passes them to the Model, decides which View to render and finally sends the data to be rendered to the View.
Basic control flow
See document: Model-view-controller MVC is often seen in web applications, where the view is the actual HTML or XHTML page, and the controller is the code that gathers dynamic data and generates the content within the HTML or XHTML. Finally, the model is represented by the actual content, which is often stored in a database or in XML nodes, and the business rules that transform that content based on user actions. Though MVC comes in different flavors, control flow is generally as follows: 1. The user interacts with the user interface in some way (for example, presses a mouse button).
12
2. The controller handles the input event from the user interface, often via a registered handler or callback. 3. The controller notifies the model of the user action, possibly resulting in a change in the model's state. (for example, the controller updates the user's shopping cart).[4] 4. A view uses the model indirectly to generate an appropriate user interface (for example, the view lists the shopping cart's contents). The view gets its own data from the model. The model and controller have no direct knowledge of the view. 5. The user interface waits for further user interactions, which restarts the cycle.
MVC passive model The passive model is employed when one controller manipulates the model exclusively. The controller modifies the model and then informs the view that the model has changed and should be refreshed. The model in this scenario is completely independent of the view and the controller, which means that there is no means for the model to report changes in its state.
MVC active model
See document: ms978748.aspx The active model is used when the model changes state without the controller's involvement. This can happen when other sources are changing the data and the changes must be reflected in the views. Consider a stock-ticker display. You receive stock data from an external source and want to update the views (for example, a ticker band and an alert window) when the stock data changes. Because only the model detects changes to its internal state when they occur, the model must notify the views to refresh the display.
However, one of the motivations of using the MVC pattern is to make the model independent from of the views. If the model had to notify the views of changes, you would reintroduce the dependency you were looking to avoid. Fortunately, the Observer pattern [Gamma95] provides a mechanism to alert other objects of state changes without introducing dependencies on them.
Passive view: Model2
See document: PassiveScreen.html 13
This pattern is yet another variation on model-view-controller and model- viewpresenter. As with these the UI is split between a view that handles display and a controller that responds to user gestures. The significant change with Passive View is that the view is made completely passive and is no longer responsible for updating itself from the model. As a result all of the view logic is in the controller.
As a result, there is no dependencies in either direction between the view and the model. In a Model2 application, requests flow from the browser directly to the controller (via a HTTP handler). The user interface of a Model2 application offers HTML input elements and all of them cause a link to be followed and a HTTP post. On the Web server the request is captured and transformed into a method call on the selected controller. As the controller’s method returns, the controller orders the view to render out to HTML. The view receives fresh data for its response directly from the controller. The output of the view is delivered to the front controller and sent back to the browser. In Model2, we can really say that the controller is the entry point in the flow and the view is extremely thin and passive—except for some JavaScript you may insert. The driving reason to use Passive View is to enhance testability. With the view reduced to a dumb slave of the controller, you run little risk by not testing the view. The controller can run and be tested outside of the UI environment
2.3.3The REST pattern The Representational State Transfer (REST) style is an abstraction of the architectural elements within a distributed hypermedia system. REST ignores the details of component implementation and protocol syntax in order to focus on the roles of components, the constraints upon their interaction with other components, and their interpretation of significant data elements. It encompasses the fundamental constraints upon components, connectors, and data that define the basis of the Web architecture, and thus the essence of its behavior as a network-based application.
14
REST is an architectural pattern that defines how network resources should be defined and addressed in order to gain shorter response times, clear separation of concerns between the front-end and back- end of a networked system. REST is based on three following principles: * An application expresses its state and implements its functionality by acting on logical resources * Each resource is addressed using a specific URL syntax * All addressable resources feature a contracted set of operations
2.4What is ASP.NET MVC? ASP.NET MVC is a framework that allows developers to apply the MVC pattern in the development of an ASP.NET application, thus allowing a better separation of concerns, which results in better reusability and easier testing. Now its easier to state that in this specific implementation of the MVC pattern the Passive View flavor is used: the View is not responsible of updating itself but everything is performed by the Controller. Like ASP.NET Web Forms, ASP.NET MVC is built on the ASP.NET framework.
2.4.1ASP.MVC application's structure See document: ASP.NET_MVC_Framework
ASP.Net MVC allows software developers to build a Web application as a composition of three roles: Model, View and Controller. A Model represents the state of a particular aspect of the application. Frequently, a model maps to a database table with the entries in the table representing the state of the table. A Controller handles interactions and updates the model to reflect a change in state of the application. A View extracts necessary information from a model and renders a user interface to display that.
2.4.2Contrasting ASP.NET and the MVC Framework See document: AnArchitecturalViewOfTheASPNETMVCFramework.aspx
15
So here's an alternate way of looking at the MVC Framework. It is an ASP.NET framework that performs data exchange by using a REST model versus the postback model of classic ASP.NET. Each page is split into two distinct components -controller and view - that operate over the same model of data. This is opposed to the classic code-behind model where no barrier is set that forces you to think in terms of separation of concerns and controllers and views. However, by keeping the code- behind class as thin as possible, and designing the business layer appropriately, a good developer could achieve separation of concerns even without adopting MVC and its overhead. MVC, however, is a model superior to a properly-done code-behind for its inherent support for test-driven development.
2.4.3Routes See document: 10925_3788416_2
ASP.NET MVC applications handle the web requests thru controller classes, and the request from the browser is directed to a particular controller via routes. Routes are a new feature in .NET 3.5 SP1, and ASP.NET MVC uses this feature to give controller classes the capability to respond to requests. ASP.NET MVC uses REST-like URLs (Representational State Transfer) that are cleaner than regular ASP.NET web application URLs. Here are examples of such URLs: /products/show/881 /customers/list /login/register As you can see, REST-like URLs tend to be clean, simple, and don't expose .aspx files directly on the server. Although you can have directly addressed .aspx pages in ASP.NET MVC applications, this is not the main idea.
ASP.NET Routing
See document: tutorial-08-cs.aspx
16
The ASP.NET MVC framework depends on ASP.NET Routing to route browser requests to controller actions. In order to take advantage of ASP.NET Routing, you might have to perform additional configuration steps on your web server. It all depends on the version of Internet Information Services (IIS) and the request processing mode for your application. Here’s a summary of the different versions of IIS: * IIS 7.0 (integrated mode) – No special configuration necessary to use ASP.NET Routing. * IIS 7.0 (classic mode) – You need to perform special configuration to use ASP.NET Routing. * IIS 6.0 or below – You need to perform special configuration to use ASP.NET Routing.
2.5ASP.Net inside ASP.Net MVC is a proposal for the structural problem of web applications. However, ASP.Net framework is the one that provides support to other important capabilities exploted in the new framework. The most important
2.5.1Data access If we want a data driven application, the fact is that we need to create a set of classes to represent (and access) our database. And the alternatives are: do it your own way or use something that does it for you. To access the database, you can choose one of the available options in the .Net framework: + ADO.NET’s classes. All that you need to connect to DBs, execute queries, read data or get a disconnected copy. The control is in your hands, so you need to know how to use it. In fact, this all mighty power implies that you must code all the data layer of your app. Just you, alone. So the question is: do you know how to do it? + Data source controls. The .NET framework offers five data source controls: SqlDataSource, AccessDataSource, ObjectDataSource, XmlDataSource, and SiteMapDataSource; these objects enable automatic connection to various data sources, and provide capabilities to read or modify your database using data-bound controls. The problem with this alternative is that you need to attach these controls to each page where you need to use data access, so there´s a strong cohesion issue.
17
Lucky you. In the last years MS has develop 2 new toys that create database models. The LINQ to SQL and the MS Entity Framework.
LINQ to SQL
See document: using-linq-to-sql-part-1.aspx LINQ to SQL is an O/RM (object relational mapping) implementation that ships in the .NET Framework "Orcas" "Orcas" release, and which allows you to model a relational database using .NET classes. You You can then query the database using LINQ, as well as update/insert/delete data from it. LINQ to SQL fully supports transactions, transactions, views, and stored stored procedures. It also provides an easy way to integrate data validation and business logic rules into your data model.
DataContext class When you press the "save" button within the LINQ to SQL designer surface, Visual Studio will persist out .NET classes that represent the entities and database relationships that we modeled. modeled. For each LINQ LINQ to SQL designer file added to our solution, a custom DataContext class will also be generated. This DataContext class is the main conduit by which we'll query entities from the database as well as apply changes. The DataContext class created will have properties that represent each Table we modeled within the database, as well as methods for each Stored Procedure we added.
LINQ query syntax See document: QueryExpressionSyntax.ashx The query expression syntax is much gentler than the Expression Method syntax and simplifies writing LINQ queries by removing Lambda Expressions and by using a familiar SQL like representation. One initial stumbling block to learning the LINQ syntax is that it reverses the Select- From-Where SQL structure and introduces FromWhere-Select. There is good reason for this switch in keyword ordering; it allows better intellisense support where Visual Studio can offer assistance by displaying collection and properties whilst the developer is creating the query. query. The basic form of the Query Expression Ex pression is:
18
from [identifier] in [source collection] let [expression] [expression] where [boolean expression] order by [[expression](ascending/descending)], [[expression](ascending/descending)], [optionally repeat] select [expression] [expression] group [expression] by [expression] into [expression] [expression] The queries return an IEnumerable
3 ASP.Net MVC: basic techn techniques iques As anything in life, you must first walk before you run. Climbing the learning curve implies to take one step at a time, so it´s important that steps are clear. In this chapter, the goal is to explore the most common basic techniques to make small and precise things with ASP.Net MVC. Each technique will be a recipe and you can identify it because the name of each technique starts with a verb ;) The best reason to do this, is to have a common set of imperative sentences that allow us to clearly follow a set of instructions in order to make something more complex. But for that, first read this and then you can move on to the next chapter.
3.1Configure your development environment First, be patient. p atient. You'll You'll need at least an hour to setup your dev environment. The setup checklist includes the following: + Install on your machine Visual Studio 2008 + Install Visual Studio 2008 Service Pack 1 (contains .Net framework 3.5 SP1) + Install ASP.NET MVC 1.0 http://www.microsoft.com/downloads/details.aspx?FamilyID=53289097-73ce- 43bfb6a6- 35e00103cb4b&displaylang=en 35e00103cb4b&displaylang=en This is all that you need to start developing in your own machine.
3.2Create an ASP.Net MVC application project See document: 3788416
Visual Studio's New Project dialog box should now have a new icon for "ASP.NET "ASP.NET MVC Application"
19
When you create a new ASP.NET ASP.NET MVC project, you will have several folders under the solution: namely Controllers, Models, and Views. When you write code to implement your application, you should store each of the different code files into their correct folders. Otherwise, the system might not work as designed.
3.3The Models realm 3.3.1Hard coded models Before dealing with DBs and sophisticated DAL models and code generators, the most basic and easy way to make models is by defining classes with as many ma ny properties as you may want or need. This is a good exercise to understand how models work.
20
Create a model class By using a model class, you can specify that a view should directly understand the properties of the model class; this means you do not need to use the ViewData object nearly as often. For instance, you might have a class like this to represent product information: public class Product { public int Id public string Name public string Description public float ListPrice public float CostPrice public string WebPage
public string SystemRequirements { get; set; } } The important thing here is to put this class on the Models folder.
3.3.2The database A relational database is a common persistence layer in software applications.
Create a database To create a new database: 1. Right-click the App_Data folder in the Solution Explorer window and select the menu option Add, New Item. 2. Select the Data category and select the SQL Server Database template. 3. Name your new database .mdf and click the Add button.
21
After you create your database, you can connect to the database by double- clicking the .mdf file located in the App_Data folder. Double-clicking the file opens the Server Explorer window.
Design the database on the fly If your data model is crystal clear inside your head (ja-ja) or if you want to fool around with a couple of tables, then you can use the Server explorer editing capabilities to create the tables and fields of your database.
Even you can populate your DB with data. This is a common practice when you try to remake an example from a tutorial or when you are working on a prototype or when making your first steps in the database world. Otherwise, if your system is complex enough (that is when relations between tables appear), maybe you need to consider a specific tool for the job.
22
NOTE: remember to set the table primary key.
Design the DB model and create the database Using an existing database Lets suppose that you did a desktop application that you want to migrate to Web. The database model is the same, so you want to use the actual database. All that you need to do is copy the DB file to your project (assuming you are using Access or SQL Server, attach the DB, and you are done.
3.3.3The database model classes In several seminars, tutorials and samples, there are 2 technologies preferred when you have to create the DB model classes: + LINQ to SQL + MS Entity Framework Their advantage is that generate the DB model is very easy and straight forward. To let everyone choose its favorite, I'll try of maintain a description for each technology.
LINQ to SQL style
Create a MVC data model In LINQ to SQL, the object relational designer analyzes a SQL Server database and presents the data tables and stored procedures to code as objects. 1. Add a LINQ to SQL Classes file .dbml to the project (File->New File->LINQ to SQL Classes- >Add).
23
Create Entity Classes From a Database If you already have a database schema defined, you can use it to quickly create LINQ to SQL entity classes modeled off of it. The easiest way to accomplish this is to open up a database in the Server Explorer within Visual Studio, select the Tables and Views you want to model in it, and drag/drop them onto the LINQ to SQL designer surface. 1. From Server Explorer, expand the Tables node. 2. Drag table names from the Server Explorer and drop them on the left- hand (larger) design surface.
The designer creates objects based on the table names.
Entity Framework style
Create a MVC data model See document: tutorial-26-cs.aspx Microsoft Entity Framework to generate the classes for our database model automatically. 1. Right-click the Models folder in the Solution Explorer window and the select the menu option Add, New Item. 2. Select the Data category and select the ADO.NET Entity Data Model template. 3. Give your data model the name .edmx and click the Add button. The Entity Data Model Wizard appears.
Generate model from DB In the Entity data model wizard: 1. In the Choose Model Contents step, select the Generate from database option.
24
2. In the Choose Your Data Connection step, use the .mdf data connection and the name for the connection settings. Click Next.
3. In the Choose Your Database Objects step, mark the Tables node to select all the tables or expand the node, and select the tables you need. Enter the namespace Models and click the Finish button.
25
After you complete the Entity Data Model Wizard, the Entity Data Model Designer appears. The designer displays a class that corresponds to each table being modeled.
The Entity Data Model wizard generates class names based on database table names. You almost always need to change the name of the class generated by the wizard. Change the name of the class from (plural) to (singular).
3.4The Controllers realm 3.4.1Controller class and actions A controller class is a lot lighter weight than a page. As a matter of fact, the only things that are truly necessary are to derive from System.Web.Mvc.Controller. An action is a method that's called in response to a request to a particular URL. Actions are responsible for doing whatever processing is required and then rendering a view.
Create a MVC Controller To create a new ASP.NET MVC Controller:
26
+ Select the menu option Add, Controller. + In the Add Controller dialog, enter the name. Remember, this has to end in Controller as there are some conventions we use to find these typ es. + Check the checkbox labeled Add action methods for Create, Update, and Details scenarios + Click add to create the new controller.
When add action methods for CRUD is selected, several method stubs are defined in the controller class (index, details, create and edit). If this option is not selected, only the index action method stub will be generated.
Define an action method MVC framework that enables us to define "action methods" on our controller, and then have the Controller base class automatically invoke the appropriate action method to execute based on the URL routing rules in use for our application. To define a new action: + Define a new public method that returns an ActionResult. + Name the method
In earlier versions, it was needed to put the [ControllerAction] attribute on your action methods, but that is now deprecated.
Specify the model object instance in the controller To specify the model object instance in the controller, you would modify the return statement slightly: Models.Product product = new Models.Product(); product.Id = 123; // ... return View(product);
3.4.2ViewData The controller often needs to specify what data to display on the view, such as choosing the correct product. To better enable this communication between the
27
view and the controller, the ASP.NET MVC framework contains a class called ViewData. This is a dictionary of name and value pairs, and it is accessible from both the controller class and the view's .aspx page.
Define a controller's action to pass data
See document: 10925_3788416_4 public ActionResult Index() { ViewData["Title"]
= "Home Page";
ViewData["Message"] = "Welcome to ASP.NET MVC!"; return View(); }
The Index method uses the ViewData object two times, to set a "Title" and a "Message". Because the ViewData is a collection object, you can freely choose any unique string value you prefer. The third statement in the method returns a View object.
3.4.3CRUD The acronym CRUD refers to all of the major functions that need to be implemented in a relational database application to consider it complete. Each letter in the acronym can be mapped to a standard SQL statement: Operation Create
SQL INSERT
Read (Retrieve) SELECT Update
UPDATE
Delete (Destroy) DELETE Although a relational database is a common persistence layer in software applications, there are numerous others. CRUD can be implemented with an object database, an XML database, flat text files, custom file format.
3.4.4CRUD controller (LINQ to SQL style) One of the most common things that you will want to do is to get data from the models you create. Maybe you want to get all the registers from a table, or just a few. Maybe you need to insert new records or edit and update some existing or maybe you want to delete some.
28
Create, read, update and delete (CRUD) are the four basic functions of persistent storage, a major part of nearly all computer software. With the model created, you will need the actions needed to specify how this operations do their job. In this section is shown how to define action methods consuming a LINQ to SQL model.
Create an instance of the model database context - Add a reference to the models using MyMvcApplication.Models Create a class member variable of type DataContext in the controller. We will use this context to access the database. private MoviesDataClassesDataContext dbcontext = new MoviesDataClassesDataContext ();
Define an action to get the list of items from the database
See document: article.aspx
- Define a new controller action method (you can add this in Index method or make a List method) and inside of it: - Define a LINQ query: * The var keyword tells the compiler to infer the type returned by a query. When a LINQ to Objects query is deferred, the sequence returned from a query expression is of type IEnumerable and is called a computation or result sequence. * The individual lines in a properly formatted query are called clauses. * The select clause at the end of the query helps define the type returned of the query. A select clause is said to project a result. // GET: /Movies/ public ActionResult Index() { var list = from item in dbcontext.Movies orderby item.Title select item;
return View(list.ToList()); }
Define an action to display details from a specific item
29
- Define a new controller action method or use the Details action method stub and inside of it: - Define a LINQ query that retrieves the item that match with the primary key value. For this, use the Single method of the context object, and state the condition to match. // GET: /Movies/Details/5 Public ActionResult Details(intid) { Movie
movie= dbcontext.Movies.Single(m=>m.ID ==id );
Return View(movie); }
The action method parameter must match the field type in the context model.
Define actions to edit an item
See document: create-a-strongly-typed-crud-ui-with-asp-net-mvc-rc.aspx Notice that the controller has 2 overloads of the Edit action: // GET: /Vehicles/Edit/5 public ActionResult Edit(int id) { ... } // POST: /Vehicles/Edit/5 [AcceptVerbs(HttpVerbs.Post)] public ActionResult Edit(int id, FormCollection collection) { ... }
The first one is for getting the item details in order to display then in the View. When the user clicks the submit button, a POST message will call the second overload with the form data.
Get the details of the item to display This implementation is identical to the Display action implementation. // GET: /Movies/Edit/5 public ActionResult Edit(int id) { Movie movieToEdit = dbcontext.Movies.Single(m => m.ID == id);
return View(movieToEdit); }
30
Define save action In the second overload of the Edit method, get the data out of the FormCollection instance, and apply it the item. Then save the changes to the DB, and display the list. // POST: /Movies/Edit/5 [AcceptVerbs(HttpVerbs.Post)] public ActionResult Edit(int id, FormCollection collection) {
//get the movie to save Movie movie = dbcontext.Movies.Single(m => m.ID == id);
try { // Assign the new values movie.Title = collection [ "Title"]; movie.Website = collection["Website"]; // Save changes context.SubmitChanges();
See document: create-a-strongly-typed-crud-ui-with-asp-net-mvc-rc.aspx Create method has 2 overloads as well. Again, one is to do any work before the Create View is shown and the other is to respond to the POST message and insert the data to the database. To Implement the second overload of the Create method, extract the data from the FormCollection instance, and build a new instance of Vehicle. Then, add it to the database, and return to the list. // GET: /Movies/Create publicActionResult Create() { returnView(); }
31
// POST: /Movies/Create [AcceptVerbs(HttpVerbs.Post)] publicActionResult Create(FormCollectioncollection) { try { Movie
Error in edit and create operations It's important to check if the tables of your data models have primary keys defined. Otherwise, edit and create operations can´t be performed. If you forgot to set the table primary key, you will have to copy the table to the LINQ designer in order to set the changes. The actual error is: {"Can't perform Create, Update or Delete operations on 'Table(Movie)' because it has no primary key."} If you don´t implement error handling, you can notice the error because no new records or changes are applied to the DB. However is a good idea to see how to implement error handling in controllers.
3.4.5Error handling When there´s an error in your code, the effect can be unpredictable. From a display error to a complete system's crash. So to avoid that scenarios its important to detect the error, show it or store it and, in the best case, fix it. In .Net we have the all mighty try..catch ...finally structure to do this. But, how you can use it on our controllers?
32
No error handling effects When an error occurs on an action method, and no error handling is implemented, the application will return you to the IDE and will highlight and display the error in your code. However, not everybody have the Visual Studio to get this level of detail.
What's that [HandleError] attribute? When you create an MVC application, there is a HomeController created by default, in your Controllers folder. Check it, and you will find a [HandleError] attribute decorating the controller's class. If you play for a while, and an error occurs, you will see a page displayed in the browser with all the error information for debugging porpouses. So, in theory, if you add this attribute to your new controllers, you can have the same level of verbose when an error occurs.
Action filters
See document: dd695917.aspx 3.4.6CRUD controller (Entity framework style) See document: tutorial-26-cs.aspx
Now that we know how to define action methods and use the LINQ to SQL, I think that is important to explore the use of Entity framework for 2 reasons: + Comparison. If you want to know which is better or fits better to your requirements or coding style. + Coding differences. There are slightly differences between both models, so its important to be aware of them. In this section I expose the same techniques for CRUD operations, so you can have the best of both worlds.
Create an instance of the data model - Add a reference to the models using MyMvcApplication.Models
33
Define a class member variable of the type you define when the model was generated (with suffix Entities) using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Mvc.Ajax; using MvcAgenda.Models;
namespace MvcAgenda.Controllers { public class ContactsController : Controller { ContactsDBEntities dbentities = new ContactsDBEntities ();
We will use this context to access the database.
Define an action to list items from the DB - Define a new controller action method (you can add this in Index method or make a List method) - Inside of the method, in the parenthesis of the View(), add a call to the data model entities to return a set of items and convert them to a list. ContactsDBEntities dbentities = new ContactsDBEntities ();
// GET: /Contacts/
public ActionResult Index() { return View(dbentities.ContactSet.ToList ()
);
}
Its interesting to note that entities has an ItemSet ready to consume.
Define an action to create a new item To enable users to create new items, we need to add two Create() actions to the controller. We need to create one Create() action that returns an HTML form for creating a new item. We need to create a second Create() action that performs the actual database insert of the new item. In the second Create method:
34
- Modify entry parameter to accept an instance of the Item class. - Decorate parameter with a [Bind] attribute. The [Bind] attribute is used to exclude the Id property from binding. Because the Id property represents an Identity property, we don’t want to set the Id property. - Add a new Item to the existing set of Contacts and call the SaveChanges() method to push these changes back to the underlying database. // POST: /Contacts/Create
[AcceptVerbs(HttpVerbs.Post)] Public ActionResult Create([Bind(Exclude ="Id")]Contact contacto) { if(!ModelState.IsValid) return View(); try { // add the item to the items set and save dbentities.AddToContactSet(contacto); dbentities.SaveChanges();
Shortcut discovery: You can generate an HTML form for creating new Contacts by right-clicking either of the two Create() methods and selecting the menu option Add View
Define an action to display details from a specific item - Define a new controller action method or use the Details action method stub and inside of it: - Define a variable and assign it the result of a LINQ query that retrieves the item that match with the primary key value. - Pass the variable to the View. // GET: /Contacts/Details/5
35
public ActionResult Details(int id) { var item = (from c in dbentities.ContactSet where (c.ID == id) select c).FirstOrDefault(); return View(item); }
Define actions to edit an item The first Edit() method is invoked by an HTTP GET operation. An Id parameter is passed to this method which represents the Id of the contact record being edited. The Entity Framework is used to retrieve a contact that matches the Id. A view that contains an HTML form for editing a record is returned. The second Edit() method performs the actual update to the database. This method accepts an instance of the Contact class as a parameter. The ASP.NET MVC framework binds the form fields from the Edit form to this class automatically. Notice that you don’t include the[Bind] attribute when editing a Contact (we need the value of the Id property). The Entity Framework is used to save the modified Contact to the database. The original Contact must be retrieved from the database first. Next, the Entity Framework ApplyPropertyChanges() method is called to record the changes to the Contact. Finally, the Entity Framework SaveChanges() method is called to persist the changes to the underlying database. // GET: /Contacts/Edit/5 public ActionResult Edit(intid) { var contact2Edit = (fromc indbentities.ContactSet where(c.ID == id)selectc).FirstOrDefault(); returnView(contact2Edit); }
// // POST: /Contacts/Edit/5
[AcceptVerbs(HttpVerbs.Post)] Public ActionResult Edit(Contactcontact2Edit) { if(!ModelState.IsValid) returnView(); try {
36
// Get the original item, apply the changes and save it var originalContact = (from c indbentities.ContactSet where(c.ID == contact2Edit.ID ) selectc).FirstOrDefault(); dbentities.ApplyPropertyChanges(originalContact.EntityKey.EntitySetNam e, contact2Edit); dbentities.SaveChanges(); returnRedirectToAction("Index"); } catch { Return View(); } }
Define an action to delete an item If you want to delete contacts then you need to add two Delete() actions to the controller class. The first Delete() action displays a delete confirmation form. The second Delete() action performs the actual delete. The first Delete() method returns a confirmation form for deleting a record from the database. The second Delete() method performs the actual delete operation against the database. After the original item has been retrieved from the database, the Entity Framework DeleteObject() and SaveChanges() methods are called to perform the database delete. // // GET: /Home/Delete/5
public ActionResult Delete(int id) { var contactToDelete = ( from c in dbentities.ContactSet where c.ID == id select c).FirstOrDefault();
return View(contactToDelete); }
// // POST: /Home/Delete/5
37
[AcceptVerbs(HttpVerbs.Post)] public ActionResult Delete(Contact contactToDelete) { try { var originalContact = ( from c in dbentities.ContactSet where c.ID == contactToDelete.ID select c).FirstOrDefault();
3.5The Testing realm In fact, a controller can be instantiated directly, and action methods called, without any additional infrastructure. You don't need an HTTP context, and you don't need a server, just a test harness.
3.6The Views realm 3.6.1New views for controllers See document: cc337884.aspx
Create a new folder with controller's prefix name To do this, first create a new folder in the solution under the Views folder. By default, the controller will look for a view in the Views\ folder (the controller prefix is the name of the controller class minus the word "Controller"). So if your controller's name is HelloController, the new folder's name will be Hello.
Create a view
38
Inside the new folder create a new view. The name of the ASPX file must match the name of one of the methods of the controller (for example, Index). There are no runat="server" tags. There's no form tag. There are no control declarations. In fact, this looks a lot more like classic ASP than ASP.NET. Note that MVC views are only responsible for generating output, so they don't need any of the event handling or complex controls that Web Forms pages do. The MVC Framework does borrow the .aspx file format as a useful text templating language.
3.6.2CRUD views See document: Create,_read,_update_and_delete
CRUD is also relevant at the user interface level of most applications. For example, in address book software, the basic storage unit is an individual contact entry. As a bare minimum, the software must allow the user to: * Create or add new entries * Read, retrieve, search, or view existing entries * Update or edit existing entries * Delete existing entries Without at least these four operations, the software cannot be considered complete. Because these operations are so fundamental, they are often documented and described under one comprehensive heading, such as "contact management" or "contact maintenance" (or "document management" in general, depending on the basic storage unit for the particular application). The following techniques show how to generate views using the Add View wizard. With this, new pages are created with all the fields required to match de DB model.
Create a view to list items Inside the Views folder, in the folder that match the desired controller: - Right click the folder and select Add/View - Write the name for the new View - Select the create a strong-typed view option - select the view data class MyMVCApp.Models.MyDB - Select the view content option as List - Select the site's master page. - Click the Add button. This will generate a new aspx page with all the fields returned by the DB model, to be displayed on a table.
39
Create a view to display item details Inside the Views folder, in the folder that match the desired controller: - Right click the folder and select Add/View - Write the name for the new View - Select the create a strong-typed view option - select the view data class MyMVCApp.Models.MyDB - Select the view content option as Details - Select the site's master page. - Click the Add button. This will generate a new aspx page with all the fields returned by the DB model, to show the detail of one item. This page can be accessed from the list page, that has a Detail option. All you have to do is un comment the id reference in the Details action link, and adjust the proper primary key field name. <%=Html.ActionLink( "Details", "Details", new{ id=item.ID
})%>
NOTE: When using Entity framework, this changes are not necessary.
Create a view to edit item
The Edit() action return an HTML form that can be used to edit a DB record. Inside the Views folder, in the folder that match the desired controller: - Right click the folder and select Add/View - Write the name for the new View - Select the create a strong-typed view option - select the view data class MyMVCApp.Models.MyDB - Select the view content option as Details - Select the site's master page. - Click the Add button. This will generate a new aspx page with all the fields returned by the DB model, to show the detail of one item. This page can be accessed from the list page, that has a Detail option. All you have to do is un comment the id reference in the Edit action link, and adjust the proper primary key field name. <%= Html.ActionLink( "Edit", "Edit", new {
40
id=item.ID }) %> |
Edit page can be access too from the details page. All you have to do is un comment the id reference in the Edit action link, and adjust the proper primary key field name. <%=Html.ActionLink( "Edit", "Edit", new { id=Model.ID }) %> |
Create a view to create a new item Inside the Views folder, in the folder that match the desired controller: - Right click the folder and select Add/View - Write the name for the new View (Create) - Select the create a strong-typed view option - select the view data class MyMVCApp.Models.MyDB - Select the view content option as Create - Select the site's master page. - Click the Add button. This will generate a new aspx page with all the fields needed by the DB model, to define a new item. This page can be accessed from the list page, that has a Create new option.
Create a view to delete an item Modify the Index view so that it contains a link for deleting contact records . You need to add the following code to the same table cell that contains the Edit link: Html.ActionLink( { id=item.Id }) %> Create the delete confirmation view. Right-click the Delete() method in the controller class and select the menu option Add View. The Add View dialog appears. Unlike in the case of the List, Create, and Edit views, the Add View dialog does not contain an option to create a Delete view. Instead, select the ContactManager.Models.Contact data class and the Empty view content. Selecting the Empty view content option will require us to create the view ourselves. This view contains a form that confirms whether or not a particular contact should be deleted <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage"
%>
Delete
41
Delete
Are you sure that you want to delete the entry for <%= Model.Name %> ?
<% using (Html.BeginForm(new { Id = Model.ID })) { %>
<% } %>
<%=Html.ActionLink("Back to List", "Index") %>
4 ASP.Net MVC: basic code katas The word Kata comes from the Japanese meaning formal exercise. In martial arts, a kata is a series of movements and techniques that are practiced in a pattern. Each kata is designed to teach a central principle or a set of common technique. These defensive and offensive movements will serve you to response to one or more attackers (imaginary or real clients, or just you and a crazy idea). In this chapter, the goal is to define and code some simple systems, to show how to apply the basic techniques discussed previously. The examples are designed to integrate the basic techniques to solve common development scenarios. The main advantage of having a catalog of basic techniques is the description simplification of the procedures to develop each application.
4.1Kata #1: Say Hello to The problem: Develop a Hello world program with ASP-Net MVC. Procedure:
42
- Create a new MVC project called HelloMVC - Create a new controller called HelloController - Define a controller's action called SayHi2(string name) - Send the name via the ViewData to the view PublicClassHelloController InheritsSystem.Web.Mvc.Controller ' ' GET: /Hello/SayHi2 Function SayHi2(ByValname AsString) As ActionResult ViewData("Name") = name Return View() EndFunction
- Create a new folder called Hello - Create a new view called SayHi2.aspx (an option is the views wizard, that will assign a master page to the view)
- Add the "Hi there" legend in the h2 tag and a reference to ViewData("Name") to display any name you want using a script code tag <%= %>
- Execute the project and go to URL http://localhost:1926/hello/sayhi2?name=Pepe
43
This will display the greetings.
4.2Kata #2: Basic CRUD with simple DB Lets play with a database and make some create, read, update and delete (CRUD). The problem: Develop an application capable of maintain a simple movie database (one table).
44
Procedure: Create a new MVC project called MVCMovieDemo. 1. Create a DB called MoviesDB.mdf 2. Create a table called Movies with 3 fields: id, title and web site. Set ID as primary key. 3. Create LINQ to SQL Data classes, and rename table Movies to Movie in design surface. 4. Create a controller called MoviesController. 4.1 Create an member instance of the DB data context to access the DB. 5. Define Index action method to retrieve a list of all the movies in the DB. 6. Define Details action method to retrieve the details of a movie, passing the id of the record. 7. Define Edit action methods to display item details and apply changes. 8. Define Create action method to create a new item, assign the values passed and insert a new record in the DB. 9. Create a new view called Index to show a List. Edit action links to allow details and edit operations. 10. Create a new view called Details to show an item. Edit action link to allow edit operation. 11. Create a new view called Edit to edit an item. 12, Create a new view called Create to create new movie item. Controller's code is provided to see details of each operation. in fact, is the only class you need to edit to define the app behavior.
4.2.1Controller code using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Mvc.Ajax; using MvcSample1.Models;
namespace MvcSample1.Controllers { public class MoviesController : Controller {
MoviesDataClassesDataContext context = new MoviesDataClassesDataContext ();
45
// // GET: /Movies/
public ActionResult Index() { //get the list of items in the DB var list = from item in context.Movies orderby item.Title select item; return View(list.ToList()); }
// // GET: /Movies/Details/5
public ActionResult Details(int id) { //show details from an item Movie movie= context.Movies.Single(m=>m.ID ==id ); return View(movie); }
// // GET: /Movies/Create
public ActionResult Create() { return View(); }
// // POST: /Movies/Create
[AcceptVerbs(HttpVerbs.Post)] public ActionResult Create(FormCollection collection) { try { //Create new instance and add the data Movie
v = new Movie
{
46
Title = collection[ "Title"], Website
= collection["Website"],
}; //create a new record context.Movies.InsertOnSubmit(v); context.SubmitChanges();
return RedirectToAction("Index"); } catch {
return View(); } }
// // GET: /Movies/Edit/5 public ActionResult Edit(int id) { //show details of item to update Movie movieToEdit = context.Movies.Single(m => m.ID == id); return View(movieToEdit); }
// // POST: /Movies/Edit/5
[AcceptVerbs(HttpVerbs.Post)] public ActionResult Edit(int id, FormCollection collection) {
Movie movie = context.Movies.Single(m => m.ID == id);
try { // apply changes to item and update movie.Title = collection[ "Title"]; movie.Website = collection["Website"]; context.SubmitChanges();
4.3Kata #3: a blog engine Can we do something more than ABCD as usual? Yes, please!!!!! Even when basic CRUD is important to get your hands dirty, nothing like take something a little more complicated to explore how far we can go. Blogs are simple applications to publish messages and receive comments; but if you have a business plan, maybe you can do something like Blogger. The problem: Develop a blogging engine supports blog posts, comments and categories. A blog post can have only one category and as many comments as possible. Because a blog is a little more complex than a basic CRUD, this time 10 or 15 lines will not be enough to tell how to do one. So I divide the procedure for each MVC modules.
4.3.1The blog model In this case I will use the Entity framework to show and explore its capabilities, and apply the techniques previously exposed. Procedure: 1. Create a new MVC project called MvcBlog 2. Create a new SQL database called BlogDB 2.1 Create 3 tables in the DB: Categories, Posts and Comments. Remember to set the primary key in each table. 2.2 Create a new DB diagram and add the db objects (tables) to edit the relationships of the tables 8and to have an ER diagram too). 2.3 Define the relationships between the tables. - One or more posts must belong to a category. - One or more comments must be related to a post.
48
3. In the models folder create a new Entity Data Model called BlogModel.edmx. Select the BlogDB to generate the model and the 3 tables you created in the DB.
3.1 Rename entities from plural to singular.
4.3.2The blog controllers
49
In kata #2 we only create one controller. Why? Well, just because we have only ONE table in our DB. In this case we have 3 tables in the DB, so if we follow the 1:1 relation logic, we will need 3 controllers. But a blog is not just a set of CRUD views. Its a fact that we will need complete CRUD for administration of Categories and Posts, if we stand in the blog author's role. But from a user perspective, when you enter a blog, generally the home page expose the most recent posts. From there, you can select a post and show its details and there you can add a comment or see the comments associated to that post. Another nice thing to do is to retrieve a list of posts related to one category. All these capabilities are not exactly CRUD operations, so it seems we'll need 4 controllers: •
CategoriesController, initially for the categories CRUD operations.
•
PostsController, initially for the posts CRUD operations.
•
HomeController, for visitors.
•
CommentsController, for edit and retrieve comments.
Categories Controller Procedure: 1. Create a new controller named CategoriesController. 2. Define the Index action method to get a list of all the categories. 3. Define the Details action method to get the details from an item. 4. Define the Edit action methods to edit one item. 5. Define the Create action method to create a new item.
{ Public class CategoriesController : Controller {
BlogDBEntities dbentities =new BlogDBEntities ();
// // GET: /Category/DotNet
Public ActionResult Category(stringcatName) { //get the posts related to this category //var categoryPosts = from p in dbentities.PostSet where (p.Categories.Title == catName) select p; //return View( categoryPosts
);
Return View(); }
Public ActionResult Index() { return View(dbentities.CategorySet.ToList ()); }
// // GET: /Categories/Details/5
Public ActionResult Details(intid) { //get the posts related to this category Var item = (fromc indbentities.CategorySet where(c.Id id) selectc).FirstOrDefault ();
try { //apply the changes to the post and save it varoriginalItem = (fromc indbentities.CategorySet where(c.Id == item2Edit.Id) selectc).FirstOrDefault(); dbentities.ApplyPropertyChanges(originalItem.EntityKey.EntitySetName, item2Edit); dbentities.SaveChanges();
Posts controller Procedure: 1. Create a new controller named PostsController. 2. Define the Index action method to get a list of all the posts. 3. Define the Details action method to get the details from an item. 3.1 To get the category from the item, you must make a LINQ to Entities query to get the value of the foreign key (index). 3.2 With the index value, search the CategoriesSet to get the category name. 3.3 Assign the value to the ViewData to consume it later on the view. intcategoryID = (int)item.CategoriesReference.EntityKey.EntityKeyValues.First(k
=>
k.Key == "Id").Value; //and then its name from the Category set string categoryName =(string) dbentities.CategorySet.First (v=>v.Id ==categoryID ).Title ; //return the category name in the ViewData ViewData["category"] = categoryName;
4. Define the Edit action methods to edit one item.
53
4.1 In the first edit method, pass the categories as a selectList to the ViewData["categories"] to populate a dropdown list in the view, to allow changing the category. this.ViewData["categories" ] = newSelectList (dbentities.CategorySet.ToList(), "Id", "Title");
4.2 in the second edit method, where changes are applied, apply the changes from the edited to the original item. All fields are saved, except the categoryId foreign Key. To save the category you must get the category from its set searching it using the formcollection value and then assign the category to the category reference of the post (what a mess). intindex = int.Parse(formItems[ "CategoryId" ]); Categorycateg = (fromc indbentities.CategorySet where(c.Id == index)selectc).First(); //and then assign it to the reference of the post originalItem.CategoriesReference.Value
= categ;
Now your item is editable.
5. Define the Create action methods to create a new item. 5.1 In the first create method, pass the categories as a selectList to the ViewData["categories"] to populate a dropdown list in the view, to allow changing the category. this.ViewData["categories" ] = newSelectList (dbentities.CategorySet.ToList(), "Id", "Title");
5.2 In the second create method, you must change the method parameters, adding a FromsCollection to get the values from input elements. 5.3 Solution is similar to edit, where you get the index of the list, get the item from Categories and then assign it to the new item. //add the Now date/time to the item item.PublishDate = DateTime.Now; //validate if a category is selected; if not pick the first if(formItems["CategoryId" ].Length == 0) formItems[ "CategoryId"] = "1"; //now get the selection list index intindex = int.Parse(formItems[ "CategoryId" ]); //get the appropiate category Categorycateg = (fromc indbentities.CategorySet where(c.Id == index)selectc).First(); //and assign it to the new item item.CategoriesReference.Value = categ;
// add the item to the items set and save dbentities.AddToPostSet (item); dbentities.SaveChanges();
Code using System;
54
using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Mvc.Ajax; using MvcBlog.Models;
namespace MvcBlog.Controllers { [HandleError ] public class PostsController : Controller { //instance to access DB entities BlogDBEntities dbentities = new BlogDBEntities();
public ActionResult Index() { //get all items to list 'em ordered by date var allPosts = from p in dbentities.PostSet orderby p.PublishDate descending select p ;
return View(allPosts); }
// // GET: /Post/3
public ActionResult Post(int id) { //return the datail from a post var item = (from c in dbentities.PostSet id) select c).FirstOrDefault(); return View(item); }
// // GET: /Posts/Details/5
public ActionResult Details(int id) { //return the detail from a post
55
where (c.Id
==
var item = (from c in dbentities.PostSet where (c.Id == id) select c).FirstOrDefault();
//get the category index from the item Entity key //code snippet from : //http://social.msdn.microsoft.com/Forums/enUS/adodotnetentityframework/thread/131edf35-0171-4376-a4dd54e1c08958d9 int categoryID = (int)item.CategoriesReference.EntityKey.EntityKeyValues.First(k
=>
k.Key == "Id").Value;
//and then its name from the Category set string categoryName =(string) dbentities.CategorySet.First (v=>v.Id ==categoryID ).Title ;
//return the category name in the ViewData ViewData["category"] = categoryName;
return View(item); }
// // GET: /Posts/Create
public ActionResult Create() { //to populate the categories dropdown list lets pass //the categories in the ViewData this.ViewData["categories" ] = new SelectList(dbentities.CategorySet.ToList(),
"Id", "Title");
//this.ViewData["categoryid"] = new Category(); return View(); }
// // POST: /Posts/Create
[AcceptVerbs(HttpVerbs.Post)] public ActionResult Create([Bind(Exclude = "Id")]Post item, FormCollection formItems) { if (!ModelState.IsValid)
56
return View();
try { //add the Now date/time to the item item.PublishDate = DateTime.Now; //validate if a category is selected; if not pick the first if (formItems["CategoryId" ].Length == 0) formItems["CategoryId" ] = "1"; //now get the selection list index int index = int.Parse(formItems["CategoryId"]); //get the appropiate category Category categ = (from c in dbentities.CategorySet where (c.Id == index) select c).First(); //and assign it to the new item item.CategoriesReference.Value = categ;
// add the item to the items set and save dbentities.AddToPostSet (item); dbentities.SaveChanges();
// // GET: /Posts/Edit/5 public ActionResult Edit(int id) { //return the item to edit var item2Edit = (from c in dbentities.PostSet where (c.Id == id) select c).FirstOrDefault();
//to populate the categories dropdown list lets pass //the categories in the ViewData
57
this.ViewData["categories" ] = new SelectList(dbentities.CategorySet.ToList(), item2Edit.Categories.EntityKey);
"Id", "Title",
//get the category index from the item Entity key int categoryID = (int)item2Edit.CategoriesReference.EntityKey.EntityKeyValues.First(k => k.Key == "Id").Value; //and then its name from the Category set string categoryName = (string)dbentities.CategorySet.First(v => v.Id == categoryID).Title;
//return the category name in the ViewData ViewData["category"] = categoryName;
return View(item2Edit); }
// // POST: /Posts/Edit/5
[AcceptVerbs(HttpVerbs.Post)] public ActionResult Edit(Post item2Edit,FormCollection formItems) { if (!ModelState.IsValid) return View();
try { //get the original item, var originalItem = (from c in dbentities.PostSet where(c.Id == item2Edit.Id ) select c).FirstOrDefault();
//change category id //try to change value in this way produce an Invalid op error //item2Edit.CategoriesReference.EntityKey.EntityKeyValues[0].Value
//apply the changes to the original item dbentities.ApplyPropertyChanges(originalItem.EntityKey.EntitySetName, item2Edit);
//now change the category (5 hours to find out how to do it) //first get it from the category set //http://stackoverflow.com/questions/826537/how-do-i-update-anobjects- foreign-key-value-with-linq-to- entities int index = int.Parse(formItems["CategoryId"]); Category
categ = (from c in dbentities.CategorySet
where (c.Id == index) select c).First(); //and then assign it to the reference of the post originalItem.CategoriesReference.Value
= categ;
//save changes to the item dbentities.SaveChanges();
return RedirectToAction("Index"); } catch(Exception e) { //if View(), the page have a null Model ViewData["edit error"] = e.Message + e.StackTrace ; return View( ); } } } }
Home controller Procedure: - Create a new controller named HomeController. - Create an instance of the data model. - Show a list with the last 3 most recent posts. 1. Modify Index action method adding a variable named recentPosts that will receive the result from a LINQ to Entities query to retrieve the top 5 records in the DB. 2. Pass the recentPosts variable to the return View. //get the 3 most recent posts and order them by date var recentPosts= (from p in dbentities.PostSet.Top("3") orderby p.PublishDate descending selectp) ;
59
return View(recentPosts);
Code using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using MvcBlog.Models;
namespace MvcBlog.Controllers { [HandleError ] public class HomeController : Controller { BlogDBEntities dbentities = new BlogDBEntities();
public ActionResult Index() { //get the 3 most recent posts and order them by date var recentPosts= (from p in dbentities.PostSet.Top("3") orderby p.PublishDate descending select p) ;
return View(recentPosts); }
public ActionResult About() { return View(); } } }
Comments controller Well, it´s time for comments. Comments are not in control of the post author. Users add comments related to a post, and there they stay. To start:
60
- Create a new controller named CommentsController. - Create an instance of the data model.
Add comment A blog's add comments page looks like this:
So what we need is: - create the Create action methods. The first to catch the id of the post to associate the comment. The second to save the comment data.
View comments
- Create the Post(id) action method to retrieve the comment associated to a post. - Make a LINQ to entities query to retrieve all comments associated to the post. - Assign to dataView the id, title and text of the post to show it at the beginning.
//instance to access DB entities BlogDBEntities dbentities =newBlogDBEntities ();
//show the form to add the comment publicActionResult Create(intid) { ViewData["postid"] = id; returnView(); }
//create the new comment [AcceptVerbs(HttpVerbs.Post)] publicActionResult Create([Bind(Exclude ="Id")]Commentitem, FormCollectionfc) {
try { //set the published date item.PublishDate = DateTime.Now; //now get the selection list index intindex = int.Parse ( fc["postid"]); //get the appropiate category Post pos = (fromp indbentities.PostSet index)selectp).First();
where(p.Id ==
//and assign it to the new item item.PostsReference.Value = pos;
// add the item to the items set and save dbentities.AddToCommentSet(item); dbentities.SaveChanges(); returnRedirectToAction("../Home"); } catch { returnView(); } }
//get the comments from a post publicActionResult Post(intid) {
62
//get the post title and text to put at the beginning Postpos = (fromp indbentities.PostSet where(p.Id == id)selectp).First(); ViewData["postid"] = pos.Id ; ViewData["postTitle" ]=pos.Title ; ViewData["postText" ] = pos.Message ;
//get all comments associated to the post //var comentarios = (from c in dbentities.CommentSet where ((int)(c.PostsReference.EntityKey.EntityKeyValues.GetValue (0) ) == id) select c).ToList (); varcomentarios = (fromc indbentities.CommentSet where(c.Posts.Id
== id) selectc).ToList();
returnView(comentarios ); }
} }
4.3.3The blog views Categories views Procedure: - Create a new folder called Categories. - Create a view called Index to retrieve the list of all items. - Create a view called Details to display the fields of an item. -Create a view to edit an item. Be sure to delete the Id field in the aspx page, cause it is not needed. - Create a view called Create to make a new item.
Posts views Procedure: - Create a new folder called Posts. - Create a view called Index to retrieve the list of all items. - Create a view called Details to display the fields of an item. -Create a view to edit an item. Be sure to delete the Id and PublicDate fields in the page.
63
1. Add a drop down list to display categories. Use the ViewData["categories"] to populate the list. - Create a view called Create to create a new item. Be sure to delete the Id and PublishDate fields in the aspx page, cause they are not needed. 1. Add a drop down list to display categories. Use the ViewData["categories"] to populate the list.
The problem with this comes when you want to save the new item, because the following error is shown: There is no ViewData item with the key 'Category' of type 'IEnumerable'. This happens because no item in the drop down list is selected. And because no Category is assigned to the new item (remember is the foreign key). This is fixed in the Create method of the controller.