ASP.NET MVC2 第四章Ⅰ

Now it’s time to put the framework into action for real and see how those benefits work out in a realistic e-commerce application.

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
that in action, writing unit tests for many of SportsStore’s features and behaviors using the popular open
source testing tools NUnit and Moq.

 

 

§4.1  Getting Started

Creating Your Solutions and Projects

New project –>choose Blank Solution

1

Then you can the solution as follows:

2

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.

3

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

4

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.

5

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:

6

§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:

9

and then fill the test data:

10

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

11

LET'S GO TO  NEXT SECTION~!

原文地址:https://www.cnblogs.com/TivonStone/p/1852370.html