ASP.Net 4 all

Document Sample
ASP.Net 4 all
Description

Notes & tutorial for starting dev in ASP.Net MVC v1

Shared by: jackhv
Stats
views:
695
posted:
11/11/2009
language:
English
pages:
108
ASP.Net MVC 4 all - E J Hernández Valdelamar



ASP.Net MVC 4 all



Martial coding for rapid web development.



Eugenio Jacobo Hernández Valdelamar

México. Version 3. August, 2009



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar



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.



While you analyze and decide what is the best choice for your career, 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.1 About this document

This document started as a compilation of references to try to understand ASP.Net MVC framework and how to develop an application with it. 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. It's a "follow the breadcums" exercise and once I had a bunch of them, it was time to order all this jigsaw pieces to get the big picture. 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).



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar



1.2 About 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 that 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: jack_hv@yahoo.com



1.3 Licence

This work is licensed under the terms of the Creative Commons Attribution- Noncommercial-No Derivative Works 3.0 License.



1.4 Document versions

Version 3. August, 2009. Update on views realm. One more basic kata (sending e-mail), fixing tips and new PDF document format. Version 2. June, 2009. Format revision. File uploader sample. RSS sample. Basic techniques updated. Initial structure of intermediate techniques (app design & testing). Initial structure of the intermediate techniques chapter. Version 1. May, 2009. Basic document structure (key concepts, basic techniques and code katas) and initial content.



2 ASP.Net MVC: key concepts

2.1 Web pages are not enough

When you start dealing with web development, the basic thing you start playing with is HTML.



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

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.2 Web applications

See document: smli_tr-2007-166.pdf



So you want to make an application. Well, then you have to write some code to make a program. But where is this programs is going to live? In your PC (win or *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.1 Database 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)



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

* 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.2 Spaghetti 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.



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.



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

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 this 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.3 Separate 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 have a structure. Most often the ASP pages are HTML pages with embedded 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, certain 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 * Script code in 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.4 ASP.Net: web forms & code behind See document: what-is-asp-net.html



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

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.5 Layered 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 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.3 A 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.



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

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.1 The 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 range 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.2 The 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 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:



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar



* 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). 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.



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

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



This pattern is yet another variation on model-view-controller and model- view-presenter. 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.



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar



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.3 The 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.



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



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar



2.4 What 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.1 ASP.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.2 Contrasting ASP.NET and the MVC Framework See document: AnArchitecturalViewOfTheASPNETMVCFramework.aspx



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.



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

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.3 Routes 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



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.



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

* IIS 6.0 or below – You need to perform special configuration to use ASP.NET Routing.



2.5 ASP.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.1 Data 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.



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



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

LINQ to SQL is an O/RM (object relational mapping) implementation that ships in the .NET Framework "Orcas" release, and which allows you to model a relational database using .NET classes. You can then query the database using LINQ, as well as update/insert/delete data from it.



LINQ to SQL fully supports transactions, views, and 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. For each 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. The basic form of the Query Expression is: from [identifier] in [source collection] let [expression] where [boolean expression] order by [[expression](ascending/descending)], [optionally repeat] select [expression] group [expression] by [expression] into [expression] The queries return an IEnumerable



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar



3 ASP.Net MVC: basic techniques

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.1 Configure your development environment

The natural environment for ASP.Net MVC is MS Windows.



However, it is not the only playground where you can swing.



3.1.1 Windows environment

First, be patient. 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- 43bf-b6a635e00103cb4b&displaylang=en



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar



This is all that you need to start developing in your own machine.



3.1.2 Linux environment

According to some references, it is possible to do .Net development in Linux with Mono. And it was a surprise that ASP.Net MVC was supported in Mono so fast.



The setup checklist includes the following: - Mono SDK 2.4 (LINQ is expected to be integrated in version 2.6) - MonoDevelopIDE 2.0 - ASP.Net MVC add-in for MonoDevelop. That's all you need to work in a Linux environment.



3.2 Create 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 MVC Application"



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar



When you create a new 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.3 The Models realm

3.3.1 Hard coded models



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

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 properties as you may want or need.



This is a good exercise to understand how models work.



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 { get; set; } { get; set; } { get; set; } { get; set; } { get; set; } { get; set; }



public string SystemRequirements { get; set; } } The important thing here is to put this class on the Models folder.



3.3.2 The 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.



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar



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.



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

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.



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.3 The 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).



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar



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.



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar 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.



2. In the Choose Your Data Connection step, use the .mdf data connection and the name for the connection settings. Click Next.



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar



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.



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.



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar



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.4 The Controllers realm

3.4.1 Controller 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: + 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 types. + 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).



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

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.2 ViewData

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 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()



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

{ 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.3 CRUD

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.4 CRUD 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.



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.



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

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

- 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.



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

// 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);



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

}



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();



return RedirectToAction("Index"); } catch { return View(movie); } }



Define actions to create a new item 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.



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

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 public ActionResult Create() { return View(); } // POST: /Movies/Create [AcceptVerbs(HttpVerbs.Post)] public ActionResult Create(FormCollection collection) { try { Movie { Title = collection["Title"], = collection["Website"], v = new Movie



Website };



context.Movies.InsertOnSubmit(v); context.SubmitChanges(); return RedirectToAction("Index"); } catch { return View(); } }



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:



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

{"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.5 CRUD 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 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();



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar



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: - 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();



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

try { // add the item to the items set and save dbentities.AddToContactSet(contacto); dbentities.SaveChanges();



return RedirectToAction("Index"); } catch { return View(); } }



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 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.



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar



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(int id) { var contact2Edit = (from c in dbentities.ContactSet where(c.ID == id)select c).FirstOrDefault(); return View(contact2Edit); }



// // POST: /Contacts/Edit/5



[AcceptVerbs(HttpVerbs.Post)] public ActionResult Edit(Contact contact2Edit) { if(!ModelState.IsValid) return View(); try { // Get the original item, apply the changes and save it var originalContact = (from c in dbentities.ContactSet where(c.ID == contact2Edit.ID ) select c).FirstOrDefault(); dbentities.ApplyPropertyChanges(originalContact.EntityKey.EntitySetName, contact2Edit); dbentities.SaveChanges(); return RedirectToAction("Index"); }



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

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 publicActionResultDelete(intid) { varcontactToDelete = (fromc indbentities.ContactSet wherec.ID == id selectc).FirstOrDefault(); returnView(contactToDelete); } // POST: /Home/Delete/5 [AcceptVerbs(HttpVerbs.Post)] publicActionResultDelete(ContactcontactToDelete) { try { varoriginalContact = (fromc indbentities.ContactSet wherec.ID == contactToDelete.ID selectc).FirstOrDefault(); dbentities.DeleteObject(originalContact); dbentities.SaveChanges(); returnRedirectToAction("Index"); }



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

catch { returnView(); } }



3.5 The Views realm

3.5.1 New views for controllers See document: cc337884.aspx



The /Views Directory Structure See document: asp-net-mvc-framework-part-1.aspx



By default when you create a new ASP.NET MVC Project using Visual Studio, it will create a "Shared" sub-directory underneath the "Views" directory root. This is the recommended place to store Master Pages, User Controls, and Views that we want to share across multiple Controllers within the application.



When building views that are specific to an individual controller, the default ASP.NET MVC convention is to store them in sub-directories under the \Views root. By default the name of a sub- directory should correspond to the Controller name. For example, if the Controller class is called "ProductsController", we will by default store the Views specific to it within the \Views\Products sub- directory.



When we call the View(string viewName) method within a specific Controller, the MVC framework will automatically first look for a corresponding .aspx or .ascx view template underneath the \Views\ControllerName directory, and then if it can't find an appropriate view template there it will check the \Views\Shared directory for one



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.



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar Create a view

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).



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.5.2 CRUD 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



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

- 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.



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.



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



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

- 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.



|



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.



|



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 }) %>



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

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 " %>



Delete







Delete



Are you sure that you want to delete the entry for ?











3.5.3 Control your views, Luke



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

Yeah, I know. Wizards are nice way to get the work done, but a certain thing is that there are not wizards for every situation. If you want full control of your UI, then you must know how to deal with this in ASP.Net MVC.



The view header

Ok, so you create a view. What´s inside it?



At the top of each aspx page, there´s a header tag to identify the views.







Each @Page tag has the following properties: a. Page title b. Language used in the page logic. c. The masterpage used for the look and feel of the page. d. An Inherits property to specify that this page derives from the ViewPage MVC framework. This last property is very interesting. The views wizard adds some information here to specify the object types that are passed to the view.



Examples: 1. A header where is specified a Comment model is passed to the view. >"%> 2. A manually defined FileInfo objects list. >"%> 3. A header specifying an error handling object. "%>



To know this is very useful if not working with wizards or want to make manual changes.



HTML rendering

The most common use of view is to render HTML content that decorates your data for the output.



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

As with ASP.Net, you still have the support for using master pages to define the site pages layout, and then you can add the specific content to each page of your site using plain HTML and other tools.



Master and Content Pages See document: default.aspx



Defining a Master Page is just like defining a normal page. Master Pages can contain markup, controls, or code, or any combination of these elements. However, a Master Page can contain a special type of control, called a ContentPlaceHolder control.



A ContentPlaceHolder defines a region of the master page rendering that can be substituted with content from a page that derives from the master. A ContentPlaceHolder can also contain default content, just in case the derive page does not need to override this content.







To differentiate a Master Page from a normal page, a Master Page is saved under the .master file extension. A page can derive from a Master Page by defining a MasterPageFile attribute on its Page directive.







A Content Page can declare Content controls that specifically override content placeholder sections in the Master Page. A Content control is associated to a particular ContentPlaceHolder control through its ContentPlaceHolderID property. A Content Page may only contain markup and controls inside Content controls; it cannot have any toplevel content of its own. It can, however, have directives or code.



First content area for the TITLE.



Raw HTML tags



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

Inside content area, the most basic rendering can be made with raw HTML tags. Remember , , , and so on.



HTML helpers See document: dd410596.aspx



An HTML Helper, typically, is a method that generates a string. You can use HTML Helpers to generate standard HTML elements such as textboxes, links, dropdown lists, and list boxes.



TextBox Extension method: Html output:



CheckBox Extension method: Html output:



MVC introduces HTML Helpers that take the place of Server Controls and help you build out your HTML.



The ASP.NET MVC framework includes helper methods that provide an easy way to render HTML in a view.



The following list shows some of the currently available HTML helpers. The helpers listed with an asterisk (*) are demonstrated in this topic. ActionLink — Links to an action method. BeginForm — Marks the start of a form and links to the action method that renders the form. CheckBox — Renders a check box. DropDownList —Renders a drop-down list. Hidden — Embeds information in the form that is not rendered for the user to see. ListBox — Renders a list box. Password — Renders a text box for entering a password. RadioButton — Renders a radio button. TextArea — Renders a text area (multi-line text box). TextBox — Renders a text box.



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar BeginForm Helper

The BeginForm helper marks the start of an HTML form and renders as an HTML form element. The BeginForm helper method has several overrides.



The BeginForm helper implements the IDisposable interface, which enables you to use the using keyword (Using in Visual Basic), similar to ASP.NET AJAX usage.







RadioButton helper

The RadioButton helper method renders a radio button. In its simplest form, the method takes three parameters: the name of the control group, the option value, and a Boolean value that determines whether the radio button is selected initially.



Select your favorite color: Blue Purple Red Orange



TextBox helper

The TextBox helper method renders a text box that has the specified name.



Enter your name:



Html.ActionLink See document: chapter-6-understanding-html-helpers.aspx







August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

To learn more about this website, click the following link: In Listing, the first parameter passed to the Html.ActionLink() represents the link text and the second parameter represents the name of the controller action. This Html.ActionLink() helper renders the following HTML: About this Website The Html.ActionLink() helper has several overloads and supports several parameters: · linkText – The label for the link. · actionName – The action that is the target of the link. · routeValues – The set of values passed to the action. · controllerName – The controller that is the target of the link. · htmlAttributes – The set of HTML attributes to add to the link. · protocol – The protocol for the link (for example, https) · hostname – The host name for the link (for example, www.MyWebsite.com) · fragment – The fragment (anchor target) for the link. For example, to link to a div in a view with an id of news, you would specify news for the fragment. Notice that you can pass route values from an Html.ActionLink() to a controller action. For example, you might need to pass the Id of a database record that you want to edit. Here’s how you pass an Id parameter to the Edit() action: [C#]



Html.Encode See document: html-escaping-in-aspnet-mvc.html



HtmlEncode is only meant to encode characters for display in HTML. It specifically does not encode whitespace characters. HTML escaping is a key part of web site security, mainly to prevent Cross-Site Scripting (XSS) attacks. I’m no security expert, but I do know that everything the user types in must be HTML escaped before rendering it in the browser, otherwise bad people could do nasty things like write javascript which steals all the users cookies.



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

HTML escaping isn’t hard to do. You just convert But the tricky bit is remembering to do it every single time. If we forget in once place in the whole app, we’ve introduced a security hole.



ValidationSummary and ValidationMessage See document: dd410404.aspx



Validating user input to make sure that it matches the data model in an ASP.NET MVC application can help you protect the application data from user input mistakes and from users who have malicious intent. There are many ways to incorporate input validation in an MVC application.



At the top of the view, the ValidationSummary helper method renders a list of validation errors, if any are found. In addition, the ValidationMessage helper method renders a validation error message next to each form field for which an error is found.



Create











Fields Name: Required



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

Age: Required Street: City: State: Zipcode: Phone: Required Email:



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

Required











Create custom Html helper method See document: HtmlHelperMethod.aspx



Custom Html Helper method could we created in two ways



1. Using static method. 2. By extension method.



static method

The easiest way to create custom Html helper method is create static method and return a string. Here we are going to create a Html helper method, which will render a label element of Html.



Step 1:



Add a new folder called Helpers in Asp.Net MVC application.



Step 2:



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

Add a class in newly created Helpers folder. Right click at folder and then add class named LableHelper.cs



Step 3:



Now add static method in this class called Label. This method will return string and will take two string parameters named target and text. Code will be like below



using System; using System.Collections.Generic; using System.Linq; using System.Web;



namespace MvcApplication2.Helpers { public class LabelHelper { public static string Label(string target, string text) { return String.Format("{1}",target,text); } } }



Step 4:



Now, we are going to use Label Html helper in view or aspx page.



View\Home\Index.aspx







August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

Home Page



To learn more about ASP.NET MVC visit http://asp.net/mvc.











In above code couples of things are worth noticing.



1. 2. 3.



We have included Namespace for Html Handler method of Label. Html.BeginForm is inside using , such that after rendering form will get closed. LabelHelper.Label is preceded by {1}", target, text);



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

} }



In above code fact noticing are



1. First parameter to Html Helper method is this . In case of extension method always first parameter is class on which we are extending the method. 2. 3. 4. Extended method enables us to add new method in existing class. Here class is static class. We must define Extension method with static class. Extension method will be read be Intellisense like other method of the class.



Partial Views See document: dd942822.aspx



Another technique you can use to manage the complexity of views is partial views. Partial views in the Web forms view engine are user control files with a .ascx extension. Just like in ASP.NET Web forms, we can use partial views to encapsulate HTML and code that we might want to reuse across multiple views (like a login display). We can also use partials to break down a complicated view into smaller pieces. We can strongly type partial views by deriving from System.Web.Mvc.ViewUserControl. The add new view wizard in an MVC application allows you to select a checkbox to choose between a view and a partial view, and also allows you to select the strongly typed model. There is also an HTML helper available (RenderPartial) in the framework to make the job of using a partial view easy:







Render partial helper See document: tip-of-the-day-185-aspnet-mvc-html-helpers



Render Partial: Used to render partial views (ascx controls)



* void RenderPartial(this HtmlHelper htmlHelper, string partialViewName); * void RenderPartial(this HtmlHelper htmlHelper, string partialViewName, object model); * void RenderPartial(this HtmlHelper htmlHelper, string partialViewName, ViewDataDictionary viewData); * void RenderPartial(this HtmlHelper htmlHelper, string partialViewName, object model, ViewDataDictionary viewData);



Views can incarnate in other formats See document: asp-net-mvc-view-more-just-a-page-view-part-i.aspx August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar



At this point, anyone could say "views are HTML", but this is not necessarily true. Views can adopt other formats, so a view could be a XML. For example, suppose you need to expose an RSS Because it´s a MVC view, the file must have a header, as any other MVC view. The main difference is the XML header added. From this point you can specify you XML structure, and consume your model's data as usual, making the apropiate calls inside script tags (, ).



" %> 10 ]]> ]]>



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar



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 apps, to show how to apply the basic techniques discussed previously.



The examples are designed to integrate the basic techniques to solve common development scenarios.



These basic katas can be resumed as: know your data, get/set your data and view your data.



The main advantage of having a catalog of basic techniques is the description simplification of the procedures to develop each application.



4.1 Kata #1: Say Hello to

The problem: Develop a Hello world program with ASP- Net MVC. Procedure: - 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 ()



Public Class HelloController Inherits System.Web.Mvc.Controller ' ' GET: /Hello/SayHi2 Function SayHi2(ByVal name As String) As ActionResult ViewData("Name") = name



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

Return View() End Function - 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 This will display the greetings.



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar



4.2 Kata #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).



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar



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.



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar 4.2.1 Controller 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();



// // 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 );



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

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 { Title = collection["Title"], Website }; //create a new record context.Movies.InsertOnSubmit(v); context.SubmitChanges(); = collection["Website"], v = new Movie



return RedirectToAction("Index"); } catch {



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

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();



return RedirectToAction("Index"); } catch { return View(movie);



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

} } } }



4.3 Kata #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.1 The blog model

In this case we 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 (and 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.



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar



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.2 The blog controllers



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar



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, right?



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 visitors 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.



Code

using System; using System.Collections.Generic; using System.Linq;



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

using System.Web; using System.Web.Mvc; using System.Web.Mvc.Ajax; using MvcBlog.Models; namespace MvcBlog.Controllers { public class CategoriesController: Controller { BlogDBEntities dbentities =new BlogDBEntities();



// GET: /Category/DotNet public ActionResult Category(string catName) { //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(int id) { //get the posts related to this category var item = (from c in dbentities.CategorySet where(c.Id == id) select c).FirstOrDefault (); );



return View(item);



} // // GET: /Categories/Create



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

public ActionResult Create() { return View(); } // // POST: /Categories/Create [AcceptVerbs(HttpVerbs.Post)] public ActionResult Create([Bind(Exclude ="Id")]Category { if(!ModelState.IsValid) return View(); try { // add the item to the items set and save dbentities.AddToCategorySet (item); dbentities.SaveChanges(); return RedirectToAction("Index"); } catch { return View(); } } // // GET: /Categories/Edit/5 public ActionResult Edit(int id) { //get the post to edit var item = (from c in dbentities.CategorySet where(c.Id == id) select c).FirstOrDefault(); return View(item); } // // POST: /Categories/Edit/5 [AcceptVerbs(HttpVerbs.Post)] item)



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

public ActionResult Edit(Categoryitem2Edit) { if(!ModelState.IsValid) return View(); try { //apply the changes to the post and save it var originalItem = (from c in dbentities.CategorySet where(c.Id == item2Edit.Id) select c).FirstOrDefault(); dbentities.ApplyPropertyChanges(originalItem.EntityKey.EntitySetName, item2Edit); dbentities.SaveChanges(); return RedirectToAction("Index"); } catch { return View(); } } } }



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. int categoryID = (int)item.CategoriesReference.EntityKey.EntityKeyValues.First(k => k.Key == "Id").Value; //and then its name from the Category set



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

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. 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"] = new SelectList(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). 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 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"] = new SelectList(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 Category categ = (from c in dbentities.CategorySet where(c.Id == index)select c).First(); = categ;



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

//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; 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); }



//



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

// GET: /Post/3



public ActionResult Post(int id) { //return the datail from a post var item = (from c in dbentities.PostSet select c).FirstOrDefault(); return View(item); } where (c.Id == id)



// // GET: /Posts/Details/5



public ActionResult Details(int id) { //return the detail from a post 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-a4dd-54e1c08958d9 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); }



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar



// // 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) 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();



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

//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();



return RedirectToAction("Index"); } catch { return View(); } }



// // 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 this.ViewData["categories"] = new SelectList(dbentities.CategorySet.ToList(), "Id", "Title", item2Edit.Categories.EntityKey);



//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;



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

//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 = int.Parse(formItems["categories"]); //originalItem.CategoriesReference.EntityKey.EntityKeyValues.SetValue (int.Parse(formItems["categories"]),0);



//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-an-objectsforeign-key-value-with-linq-to- entities



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

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) ;



return View(recentPosts);



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar 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.



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

Comments are not in control of the post author. Users add comments related to a post, and there they stay.



To start:



- 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.



Code

using System; using System.Collections.Generic;



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Mvc.Ajax; using MvcBlog.Models; namespace MvcBlog.Controllers { public classCommentsController: Controller { //instance to access DB entities BlogDBEntities dbentities =new BlogDBEntities(); //show the form to add the comment public ActionResult Create(intid) { ViewData["postid"] = id; return View(); } //create the new comment [AcceptVerbs(HttpVerbs.Post)] public ActionResult Create([Bind(Exclude ="Id")]Comment item, FormCollection fc) { try { //set the published date item.PublishDate = DateTime.Now; //now get the selection list index int index = int.Parse ( fc["postid"]); //get the appropiate category Post p).First(); pos = (from p in dbentities.PostSet where(p.Id == index)select



//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();



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

return RedirectToAction("../Home"); } catch { return View(); } } //get the comments from a post public ActionResult Post(int id) { //get the post title and text to put at the beginning Post pos = (from p in dbentities.PostSet where(p.Id == id)select p).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 (); var comentarios = (from c in dbentities.CommentSet where(c.Posts.Id == id) select c).ToList(); return View(comentarios ); } } }



4.3.3 The 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.



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar 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. 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. Category: )ViewData["categories"], "Tech")%> 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.



Where is the post category?

Ah-ha!!! View generator wizard doesn´t add the category field of the post!!!!



And that includes the Create, details and Edit views.



As commented, you have to add labels or dropdown lists to show and edit this value. Is not simple, because Entities queries are quite obscure.



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar Home view

The home page is where the user is going to start his visit.



Recent blog entries

The home page view must display, as many blogs do, a list of the most recent post. The HomeController actually has an action method to do this, but I don´t want the Views wizard to generate a table with my entries. I prefer a format like Title ------------------------Message text .... Publish Date: 1/1/2009 Comments: N To do this, I can't depend on generated code, because it hasn't any style picker. Seems that its time to DIY but how? Instead of thinking about using server controls or any other thing, generate a view that shows a list. Then copy the loop that is inside of the aspx page, put it before the original loop, and start to play with the content format. You can accomplish something like this



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar



Then just erase the original table with its loop, and you are done. Recent entries







Comments:







Changes to the master page



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

To change the application title or to add some extra menu options, just edit the Site.Master file in folder Shared.



To change the title, change the text in the title div



My MVC Blog



To add more menu options add tags to the UL list:























Comments view Add a comment, please

To add comments. - Create a new view in the Comments folder, called Create. Only title and message field most be visible. - Add 2 links in the Home view to each comment with the text "View" and "Add new" - Set View link to URL ../Comments/Post/n to check the comments associated to that post - Set Add new link to URL ../Comments/Create/n to add the comment associated to that post



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar



- Generate the Create view to add comments. use the wizard to make a create view. Delete the Id and Date fields.



- Add a hidden field to hold the post id, so you can save the comment and associate to the post.



Now let´s view the comments

- Create the Post view in the Comments folder. With the wizard you can generate a List view.



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar



4.3.4 Comments

If you want to check the full code, I upload it to planetsourcecode.com Check it here. There's a lot to do with a blog. For instance: - Add paging to the posts list. - Add a post index. - Adding a better editor for messages like FCKEditor. - Add user roles and security. - Add this comments validations stuff (the one with the funny letters and numbers).



4.4 Kata #4: File upload

Let's take a break from DBs and do something with files.



A common need in many sites is to let the users upload their files (documents, images, videos). This functionality is the base for sites like Flickr, Scribd, YouTube and many others. To implement this, we need to create a folder where the files will be saved. http://towardsnext.wordpress.com/2009/04/17/file- upload-in-aspnet-mvc/



Three basic operations are needed:



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

1. Upload a file. 2. Consult a list of uploaded files. 3. View the file content



To make it visual, lets display images.



4.4.1 Upload controller



Procedure: 1. Create a new controller named FileUploadController. 2. Define the Index action method to show a list of the files uploaded. 3. Define the Upload action method to handle the file transfer and saving on the folder /Uploads. //transfer the files fron the client and save them on the uploads folder public ActionResult Upload() { foreach(string inputTagName in Request.Files) { HttpPostedFileBase file = Request.Files[inputTagName]; if(file.ContentLength > 0) { string filePath = Path.Combine(HttpContext.Server.MapPath("../Uploads") , Path.GetFileName(file.FileName)); file.SaveAs(filePath); } }



return RedirectToAction("FilesUploaded", "FileUpload"); } 4. Define the FilesUploaded action method to get a list of all files in the Uploads folder. The list will be send to a view to show all the files and give the chance of display a specific image. /// ///Get the list of uploaded files and launch a list view ///



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

/// public ActionResult FilesUploaded() { string path = HttpContext.Server.MapPath("../Uploads"); DirectoryInfo dirInfo = new DirectoryInfo(path); FileInfo[] files = dirInfo.GetFiles();



return View( files.ToList () ); } 5. Define the ViewImage(string fileName) action method to get and display an image; actually what is important is the image URL that will be composed from the base Uploads path and the name of the file selected. /// ///Constructs the image URL and send it to the view /// /// /// public ActionResult ViewImage(string fileName) { ViewData["imagen"] = "../Uploads/"+ fileName; return View(); }



4.4.2 Upload views

Procedure: 1. Create a new folder Views/FileUpload



Upload file view

Procedure: 1. Add a new view from the Index action method, with no options to get a clean view.



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar



2. In the aspx file, add a Html form with a textbox, a file input control to search and specify the name of the file to upload and a button to upload the file. Files uploaded to server ; The code call the Upload action method, that makes the magic of transfer and copy the file.



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar



Uploaded files list

Procedure: 1. Add a new view from the FilesUploaded action method, with no options to get a clean view. 2. This view receives the /Uploads directory file list as a parameter. This can be specified changing the Inherits property in the @Page tag, by adding the data type expected to do the processing (in this case, a List of FileInfo objects).



>"%>



3. In the second content tag, add a table to show the files list and a foreach loop to process the List received. FilesUploaded Files uploaded



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar





NOTE: be sure the variable name used in the new{} section of the ActionLink is the same that the parameter received by the action method.



View image



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

Procedure: 1. Add a new view from the ViewImage action method, with no options to get a clean view. 2. Add an img tag to display the image, and in the src property place the ViewData instance to specify the image path. ViewImage "/>



4.4.3 Comments

This file uploader don´t differ too much from its ASP or ASP.Net counterparts.



First interesting thing in here is that in this case, no model was needed. All data came from the .Net framework IO support (directory and file information).



Second interesting thing is the fact that you can define manually the object type from the parameter received by the view. In the precedent samples, all this was handled by the wizard, and we trust it for the job.



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

However, you may not need the wizard always, specially when no DB or model is part of your solution.



4.5 Kata #5: RSS feed reader

Now that we pass thru DBs and files, let´s try a standard online data source: RSS.



A very popular data source is the RSS channels that many blogs include as part of the data exchange services.



4.5.1 RSS controller



1. Create a new controller called RSSController



2. Define a new action method called RSSReader, where the RSS processing is taking place; the method will launch a view to display the results.



At this point, there are different options to process the content from the RSS:



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

a. Hard code the format to be sent to the view, and create a string with the Html. b. Process the content with a XSL template (more flexible if you need some changes).



Hard coded formatting

For the hard-coded formatting option: a.1 Define a RSSReaderHC action method a.2 Define a request-response HTTP pair (and define a proxy object if you have a proxy in your network) a.3 Get the response, assign it to a XMLDocument. a.4 Procces the XML document nodes and assign some HTML tags to format the output. Then pass this through the ViewData. //Read a feed and get its content //then format content with html tags public ActionResult RSSReaderHC() { string strRssUrl = "http://www.asp101.com/rss/"; //asp.net 101 news rss StringBuilder result=new StringBuilder(); //prepare the request HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(strRssUrl); //if you have a proxy, then fill this; otherwise comment it WebProxy proxy = new WebProxy("proxy.netdomain",8080); proxy.Credentials = new NetworkCredential("guest", "p4$$w0rd"); request.Proxy = proxy; //call for response HttpWebResponse response = (HttpWebResponse)request.GetResponse(); Stream rssStream = response.GetResponseStream(); //load content in a XML doc XmlDocument rssDoc=new XmlDocument(); rssDoc.Load(rssStream ); //get the node list from the rss XmlNodeList rssItems = rssDoc.SelectNodes("rss/channel/item"); //now process the nodes (link, title, description) //to add html tags result.Append ("");



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

foreach(XmlNode xnode in rssItems) { result.Append (""+ xnode.SelectSingleNode ("title").InnerText +""+" "); } result.Append (""); ViewData["rss"] = result.ToString(); return View( ); }



XSL formatting See document: 1479_Using_XSLT_to_Transform_XML_Using_ASPNET.5



XSL formatting is a more flexible way to define how data is going to be rendered in a page. The great advantage is that definition is kept outside the code, so any adjustment ain't imply code modification. A simple XSL file to format the RSS entries is the following:







August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar





For the XSL formatting option: b.1 Define a RSSReaderHC action method b.2 Define a request-response HTTP pair (and define a proxy object if you have a proxy in your network) b.3 Get the response, assign it to a XPath document. b.4 Load the XSLT file defined to format the data. b.5 Pass the XML document to the XSL document and process it. Get the resulting string and pass this through the ViewData. public ActionResult RSSReaderXSL() { string strRssUrl = "http://www.asp101.com/rss/"; //asp.net 101 news rss string resHTML; //prepare the request HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(strRssUrl); //if you have a proxy, then fill this WebProxy proxy = new WebProxy("proxy.mynet", 8080); proxy.Credentials = new NetworkCredential("guest", "p4$$w0rd"); request.Proxy = proxy; //call for response HttpWebResponse response = (HttpWebResponse)request.GetResponse(); //get the rss content Stream rssStream = response.GetResponseStream(); //load content in a XML doc // Load the XML



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

XPathDocument doc = new XPathDocument(rssStream); // Load the style sheet. XslCompiledTransform xslt =new XslCompiledTransform(); xslt.Load(Server.MapPath("../Views/RSS/RSS.xslt")); //apply the format to the content and put it //on a string to send it to the view MemoryStream ms = new MemoryStream(); XmlTextWriter writer = new XmlTextWriter(ms, Encoding.ASCII); StreamReader rd = new StreamReader(ms); xslt.Transform(doc, writer); ms.Position = 0; resHTML = rd.ReadToEnd(); rd.Close(); ms.Close(); ViewData["rssText"] = resHTML; return View(); }



4.5.2 Hard coded view

The resulting view is actually very simple, because all formating was made in the controller. All you have to do is add a tag to display the ViewData["rss"] content.







RSSReaderHC RSSReaderHC



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar



4.5.3 XSL view

Create a view called RSSReaderXSL and use the same approach: just show the DataView content.



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar



4.6 Kata #6: Sending e.mail

To finish with the "trivial" techniques, let's see one of the most useful rabbit in the hat. Sooner or later, you´ll need to send and e-mail. Because you want feedback about something, or want to send a message with a confirmation; there are many scenarios where this can be done. So, what do we need to send an e-mail via a web page? Sending an e-mail implies to use the SMTP (Simple Mail Transfer Protocol) protocol. The .NET Framework version 1.x included a number of classes in the System.Web.Mail class that allowed programmatically sending an email with a few lines of code. While this namespace and these classes still exist in the .NET Framework version 2.0, they have been deprecated in favor of new mail- related classes found in the System.Net.Mail namespace. When sending an email from a page you will, typically: 1. Create a MailMessage object 2. Assign its properties 3. Create an instance of the SmtpClient class 4. Specify details about the SMTP server to use 5. Send the MailMessage via the SmtpClient object's Send method Well, it sounds easy, isn´t it? As usual, create a new MVC project.



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar



NOTE: a few weeks ago I had to reinstall my VS 2k8. So, when I create this project, something looks wrong. No highlighting of MVC clases or attributes, and it seems that MVC reference it's gone. Solution: reinstall your ASP.Net MVC 1.0 and add the System.Web.Mvc reference to the project.



4.6.1 SendMail controller

1. Create a new controller called SendMailController



2.1 Define the index action method to show a blank page.



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

2.2 Define the EditEMail action method to show the mail edition UI.



3. Define a new action method called SendEMail, where the e-mail will be forged and transmitted ; the method will launch a view to display the results.



Code

namespace MvcSendMail.Controllers { public class SendMailController: Controller { public ActionResult Index() { returnView(); } /// ///Launch the email edit view /// public ActionResult EditEMail() { return View(); } /// ///When send is pushed, here is where the mail is prepared and launched /// public ActionResult SendEMail(string mailTo,string subject, string message) { MailMessage mm = new MailMessage("jacoboh@mywork.com.mx", mailTo); mm.Subject = subject; mm.Body = message; mm.IsBodyHtml = false; //specify the host address to the client SmtpClient smtp = new SmtpClient("200.0.2.7"); smtp.Send (mm);



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

return View("Index"); } } }



4.6.2 SendMail views

Procedure: 1. Create a new folder Views/SendMail



Edit e-mail view

Procedure: 1. Add a new view from the Index action method, with no options to get a clean view. 2. Add labels and textboxes to get the e-mail address, subject and message. Add a button to send the e-mail.



Problems with the EnterpriseServices DLL

I tried to run the app to see the UI in te browser and I get this error: "Compiler error message: System.EnterpriseServices.dll' could not be found"



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar



Fortunately, I found a post with the fix. I wrote a .bat with the following: rem Fix error "Could not load file or assembly System.EnterpriseServices" "C:\Archivos de programa\Microsoft SDKs\Windows\v6.0A\bin\gacutil.exe" /i Microsoft.NET/Framework/v2.0.50727/System.EnterpriseServices.dll pause But it seems that the file is not in my machine.



Ups!! the path dude, the PATH!!!! "C:\Archivos de programa\Microsoft SDKs\Windows\v6.0A\bin\gacutil.exe" /i C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\System.EnterpriseServices.dll



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar



Ufff. Everything back to normal. Well...almost.



Editing your view with HTML helpers

Because this time there is no good old wizard to generate my UI, I design the view with asp controls. The code looks like this: EditEMail



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

The error displayed in the browser was: Exception Details: System.Web.HttpException: Control 'ctl00_MainContent_txtMail' of type 'TextBox' must be placed inside a form tag with runat=server.



Looks like something messy happens with standard ASP controls



So, I decided to use HTML helpers instead, and it just works fine! (also it looks cleaner).



Edit email message Mail to: %> %>



Subject:



Message: %>



Just remember to assign the helpers the same name as the variables from method SendEMail.



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar



4.7 Final comments

As complexity grows, you can see for each case that the description level raise. This is necessary to communicate how to implement each case, trying to be as clear as possible.



To be honest, I ain't did any previous design for the samples (pure instinct). Having the problem stated I used the techniques in the previous chapter to develop the applications, so many decisions, specially in the blog, were made on the fly and I tried to leave them commented for you.



The last kata was very dramatic, because of certain unexpected results of reinstalling my VS 2k8, but I believe the experience and fixes can help you in an adverse scenario.



In the next set of katas I will include a more formal design phase, now that I have a better idea of an application structure.



Its clear that you may want to use ASP.net MVC to do something complex for you or for a client, and that implies additional techniques; but for the moment and to have that sense of accomplish, I feel these cases can put you on the right track.



5 ASP.Net MVC: intermediate techniques

tieekm mi



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

Once you have taste your first victories after making some examples, its time to get some order in your development process.



I think there are two things that we must do to put some quality in the new applications: design and test.



Design is basic to establish what you are going to do. In the basic katas the only design element that helps to get an idea of what is going on, is the Entity-Relationship diagram that we made for the database.



So its very important to draw a blueprint before write a simgle line of code.



After that, lets code, but before you reach the Views realm, its important to test the logic of your application, and this framework its a good chance to learn and do lots of unit testing.



So these to topics will be presented in this chapter.



5.1 The app design realm

A simple question: where do we go from here? I´m sure that after an idea shows, the next step is make this decision. And when you want to go from point A to B, a map is very useful.



I like to use diagrams, because they give you a panoramic vision of where to go and what to do. But the trick here is which diagrams to use.



My proposal is to use 4 artifacts: 1. Entity-relation diagram, for the data model design. 2. Class diagram, to state the MVC architecture and the components of the application, as well of the services the controller(s) will offer. 3. A navigation map to state the application navigation.



5.1.1 Navigation maps



5.2 Error handling



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar

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?



5.2.1 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.



5.2.2 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.



5.2.3 Action filters See document: dd695917.aspx



5.3 The 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.



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar 5.3.1 Unit testing See document: ASPNETMVCFrameworkPart2.aspx 5.3.2 Testing a controller See document: this-is-how-asp-net-mvc-controller-actions-should-be-unit-tested.aspx 5.3.3 Create a test project Test methods



6 References

Some references to articles, tutorials and projects related to ASP.Net MVC framework.



6.1 Articles

6.1.1 Web Applications - Spaghetti Code for the 21st Century See document: smli_tr-2007-166.pdf 6.1.2 Building Web Apps without Web Forms See document: cc337884.aspx 6.1.3 An Architectural View of the ASP.NET MVC Framework See document: AnArchitecturalViewOfTheASPNETMVCFramework.aspx 6.1.4 Hosting an entire ASP.NET MVC request for testing purposes See document: hosting-an-entire-asp-net-mvc-request-for-testing-purposes.aspx 6.1.5 ASP.NET MVC: Securing Your Controller Actions See document: aspnet-mvc-securing-your-controller-actions 6.1.6 Virtual Earth meets MVC See document: virtual-earth-meets-mvc.aspx 6.1.7 Partial Rendering & View Engines in ASP.NET MVC See document: partial-renderi.html



6.2 Tutorials

6.2.1 ASP.Net MVC tutorials See document: mvc 6.2.2 Contact manager in Asp.Net MVC See document: ASPNETMVCSampleProjects.aspx



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar 6.2.3 ASP.NET MVC Sample Applications - Open-Source Examples and Tutorials See document: ASPNETMVCSampleApplicationsOpenSourceExamplesTutorials 6.2.4 NerdDinner ASP.NET MVC Tutorial See document: aspnetmvc-nerdinner_v1.pdf 6.2.5 Scott Guthrie’s ASP.net MVC Tutorial Links See document: scott-guthries-aspnet-mvc-tutorial-links 6.2.6 ASP.NET MVC - Part 1 See document: aspnet_mvc.aspx 6.2.7 ASP.NET MVC Preview: Using The MVC UI Helpers See document: aspnet-mvc-preview-using-the-mvc-ui-helpers 6.2.8 Building a Simple Photo Gallery in ASP.NET MVC Framework See document: BuildingASimplePhotoGalleryInASPNETMVCFramework.aspx 6.2.9 25+ Best ASP.NET MVC Tutorials and Articles See document: 25-plus-best-asp-net-mvc-tutorials-and-articles 6.2.10 A Guide to Learning ASP.NET MVC Release Candidate 1 See document: a-guide-to-learning-asp.net-mvc-release-candidate-1.aspx 6.2.11 Creating a Tag Cloud using ASP.NET MVC and the Entity Framework See document: Creating-a-Tag-Cloud-using-ASP.NET-MVC-and-the-Entity-Framework



6.3 Projects

Some real world project.



6.3.1 Oxite See document: oxite



Blog engine built on ASP.NET MVC



6.3.2 MVC StoreFront See document: mvc-storefront-part-1



Rob Conery has been documenting the design and creation of a storefront using the MVC Framework along with Agile coding practices such as test- driven development and common patterns such as the Repository Pattern.



6.3.3 Blogging Engine See document: 1538_Building_a_Simple_Blog_Engine_with_ASPNET_MVC_and_LINQ__Part_1



August, 2009



ASP.Net MVC 4 all - E J Hernández Valdelamar



Keyvan Nayyeri has a multi-part series on building a Blog Engine with ASP.NET MVC. Blog Engine creation seems to be a popular way for people to demonstrate technology and it does it effectively.



6.3.4 Kigg - The Digg Clone See document: Kigg



This Digg clone is a very good implementation and use of the MVC Framework.



6.3.5 Yonkly See document: yonkly

Yonkly is an open source (well, not any more) twitter clone application built with ASP.net MVC. Yonkly provides the functionalities of twitter and some additional features such as threaded messages and also provides integration with twitter.



August, 2009




Share This Document


Related docs
Other docs by jackhv
ASP.Net 4 all
Views: 695  |  Downloads: 95
by registering with docstoc.com you agree to our
privacy policy

You are almost ready to download!

You are almost ready to download!