ASP.NET MVC2 第四章Ⅰ
时间:2010-10-15 来源:T.337(Canon in D)
Let name our first application with "SportsStore",so the online shopping have functions as follows: a product catalog that’s browsable by category and page index; a cart that visitors may add and remove quantities of products to and from ; a checkout screen onto which visitors may enter shipping details
Use the strong MVC and related technologies by doing the following:
- Following tidy MVC architecture principles, further enhanced by using Ninject as a dependency injection (DI—also known as inversion-of-control) container for
application components - Creating reusable UI pieces with partial views and the Html.RenderAction() helper
- Using the System.Web.Routing facilities to achieve clean, search engine–optimized URLs
- Using SQL Server, LINQ to SQL, and the repository design pattern to build a database-backed product catalog
- Creating a pluggable system for handling completed orders (the default implementation will e-mail order details to a site administrator)
- Using ASP.NET Forms Authentication for security
You’ll build the application in three parts:
- In this chapter, you’ll set up the core infrastructure, or skeleton, of the application. This will include a SQL database, a DI container, a rough-and-ready product catalog, and a quick CSS-based web design.
- In Chapter 5, you’ll fill in the bulk of the public-facing application features, including the catalog navigation, shopping cart, and checkout process.
- In Chapter 6, you’ll add administration features (i.e., CRUD for catalog management), authentication, and a login screen, plus a final enhancement: letting administrators upload product images.
Unit Testing and TDD
ASP.NET MVC is specifically architected to support unit testing. Throughout these three chapters, you’ll see |
§4.1 Getting Started
Creating Your Solutions and Projects
New project –>choose Blank Solution
Then you can the solution as follows:
You can delete both of the Class1.cs files that Visual Studio “helpfully” added.
§4.2 Starting Your Domain Model
The domain model is the heart of the application. Create a new folder called Entities inside the SportsStore.Domain project, and then add a new C# class called Product.
it is hard to know how to describe your product. let's started with some obvious one.
namespace SportsStore.Domain.Entities { public class Product { public int ProductID { get; set; } public string Name { get; set; } public string Description { get; set; } public decimal Price { get; set; } public string Category { get; set; } } }
§4.2.1 Creating an Abstract Repository
Create a new top-level folder inside SportsStore.Domain called Abstract, and add a new interface IProductsRepository:
namespace SportsStore.Domain.Abstract { public interface IProductsRepository { IQueryable<Product> Products { get; } } }
§4.2.1 Making a Fake Repository
Add another top-level folder to SportsStore.Domain called Concrete, and then add to it a C# class, FakeProductsRepository.cs
namespace SportsStore.Domain.Concrete { public class FakeProductsRepository:IProductsRepository { // Fake hard-coded list of products private static IQueryable<Product> fakeProducts = new List<Product> { new Product { Name = "Football", Price = 25 }, new Product { Name = "Surf board", Price = 179 }, new Product { Name = "Running shoes", Price = 95 } }.AsQueryable(); public IQueryable<Product> Products { get { return fakeProducts; } } } }
§4.3 Displaying a List of Products
In this section creating a controller class and action method that can display a list of the products in your repository (initially using FakeProductsRepository)
§4.3.1 Adding the First Controller
In Solution Explorer, right-click the Controllers folder (in the SportsStore.WebUI project), and then choose Add –> Controller. Into the prompt that appears, enter the name ProductsController. Don’t check “Add action methods for Create, Update, and Details scenarios,” because that option generates a large block of code that isn’t useful here.
namespace SportsStore.Controllers { public class ProductsController : Controller { } }
In order to display a list of products, ProductsController needs to access product data by using a reference to some IProductsRepository.add a project reference from SportsStore.WebUI to SportsStore.Domain.
namespace SportsStore.Controllers { public class ProductsController : Controller { private IProductsRepository productsRepository; public ProductsController() { // This is just temporary until we have more infrastructure in place productsRepository = new FakeProductsRepository(); } } }
At the moment, this controller has a hard-coded dependency on FakeProductsRepository. Later on, you’ll eliminate this dependency using a DI container
Next, add an action method, List(), that will render a view showing the complete list of products
§4.3.2 Setting Up the Default Route
There’s a routing system that determines how URLs map onto controllers and actions.Head on over to your Global.asax.cs file
As you can see , we change it into
public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( "Default", // Route name "{controller}/{action}/{id}", // URL with parameters new { controller = "ProductsController", action = "List", id = UrlParameter.Optional } // Parameter defaults ); }
You might already know that.no more expain.
§4.3.3 Adding the First View
The first step is to create a master page that will act as a site-wide template for all our public-facing views. Right-click the /Views/Shared folder in Solution Explorer and then choose Add –> New Item. Gave it the name Site.Master
We just need /Views/Shared/Site.Master to exist before creating the first view. Go back to your ProductsController.cs file, rightclick inside the List() method body, and choose Add View.
ProductsController’s List() method populates Model with an IEnumerable<Product> by passing productsRepository.Products.ToList() to View(), so you can fill in some basic view markup for displaying that sequence of products:
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<SportsStore.Domain.Entities.Product>>" %> <%@ Import Namespace="SportsStore.Domain.Entities" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> List </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <% foreach(var product in Model) { %> <div> <h3><%= product.Name %></h3> <%= product.Description %> <h4><%= product.Price.ToString("c") %></h4> </div> <% } %> </asp:Content>
Run the application then you will see the follow picture:
§4.4 Connecting to a Database
You can already display a list of products from an IProductsRepository, but it is just a hard-coded list. It’s time to create another implementation of IProductsRepository, but
this time one that connects to a SQL Server database
§4.4.1 Defining the Database Schema
We'll set up a new SQL database with a Products table and some test data
Create a new database called SportsStore,and the coloumns as follows:
and then fill the test data:
Here i generate the data code by Mygeneration:
--|-------------------------------------------------------------------------------- --| [Products] - Backs up all the data from a table into a SQL script. --|-------------------------------------------------------------------------------- BEGIN TRANSACTION SET IDENTITY_INSERT [Products] ON INSERT INTO [Products] ([ProductID], [Name], [Description], [Category], [Price]) VALUES (1, 'Kayak', 'A boat for one person', 'Watersports ', 275); INSERT INTO [Products] ([ProductID], [Name], [Description], [Category], [Price]) VALUES (2, 'Lifejacket', 'Protective and fashionable', 'Watersports ', 48); INSERT INTO [Products] ([ProductID], [Name], [Description], [Category], [Price]) VALUES (3, 'Soccer ball', 'FIFA-approved', 'Soccer ', 19); INSERT INTO [Products] ([ProductID], [Name], [Description], [Category], [Price]) VALUES (4, 'Corner flags', 'Give your playing field that professional touch', 'Soccer ', 34); INSERT INTO [Products] ([ProductID], [Name], [Description], [Category], [Price]) VALUES (5, 'Stadium', 'Flat-packed ', 'Soccer ', 79500); INSERT INTO [Products] ([ProductID], [Name], [Description], [Category], [Price]) VALUES (6, 'Thinking cap', 'Improve your brain', 'Chess ', 16); INSERT INTO [Products] ([ProductID], [Name], [Description], [Category], [Price]) VALUES (7, 'Unsteady chair', 'Secretly give your opponent a disadvantage', 'Chess ', 29); INSERT INTO [Products] ([ProductID], [Name], [Description], [Category], [Price]) VALUES (8, 'Human chess board', 'A fun game for the whole extended family', 'Chess ', 75); INSERT INTO [Products] ([ProductID], [Name], [Description], [Category], [Price]) VALUES (9, 'Bling-bling King', 'Gold plated', 'Chess ', 1200); SET IDENTITY_INSERT [Products] OFF IF @@ERROR <> 0 ROLLBACK TRANSACTION; ELSE COMMIT TRANSACTION; GO --|--------------------------------------------------------------------------------
§4.4.2 Setting Up LINQ to SQL
To avoid manual SQL queries or stored procedures, let’s set up and use LINQ to SQL. You’ve already defined a domain entity as a C# class (Product); now you can map it to the corresponding database table by adding a few new attributes.add an assembly reference from the SportsStore.Domain project to System.Data.Linq.dll.
Tip: Here, you have to specify an explicit name for the table, because it doesn’t match the name of the class ("Product" != "Products"), but you don’t have to do the same for the columns/properties, because their names do match. |
§4.4.3 Creating a Real Repository
Add a new class, SqlProductsRepository, to SportsStore.Domain’s /Concrete folder:
namespace SportsStore.Domain.Concrete { public class SqlProductsRepository : IProductsRepository { private Table<Product> productsTable; public SqlProductsRepository(string connectionString) { productsTable = (new DataContext(connectionString)).GetTable<Product>(); } public IQueryable<SportsStore.Domain.Entities.Product> Products { get { return productsTable; } } } }
Back in SportsStore.WebUI, make ProductsController reference SqlProductsRepository instead of FakeProductsRepository by updating ProductsController’s constructor:
public ProductsController() { string connString = "Data Source=(local)\\SQL2005; Initial Catalog=SportsStore;Integrated Security=True;"; productsRepository = new SqlProductsRepository(connString); }Run it ,and show
LET'S GO TO NEXT SECTION~!