Mvc项目实例 MvcMusicStore
原文链接:http://www.cnblogs.com/wenming205/archive/2010/08/08/1795341.html
文章不错,看完之后搭建项目就没什么问题了,其他很多就是经验问题了
做过webform的,其实也就需要知道怎么把页面和C#代码关联起来,看看这个不错
一、简介
此项目为.Net Mvc学习试例,原版的项目可从www.asp.net网站上下载;
在学习的过程中,我们将通过.net mvc2来创建一个音乐仓储系统。整个应用程序包括三个部分,分别为:选购、结帐和后台管理
二、预备知识
在学习此项目时,最好具用Linq知识。在这里推荐博客园里LoveCherry的一步一步学Linq to sql
http://www.cnblogs.com/lovecherry/archive/2007/08/13/853754.html
三、项目开始
第一节 搭建基本开发准备
项目开发环境
开发工具:vs2010旗舰版
使用迅雷可从此连接下载;
thunder://QUFlZDJrOi8vfGZpbGV8Y25fdmlzdWFsX3N0dWRpb18yMDEwX3VsdGltYXRlX3g4Nl9kdmRfNTMyMzQ3Lmlzb3wyN
jg1OTgyNzIwfDRhZTYyMjg5MzNkZGU0OWQ5YmZhNGMzNDY3YzgzMWMyfC9aWg==
数据库:sqlserver2000或更高,此项目中我采用的是sqlserver2005
第二节 新建MVC项目
打开vs2010 选中文件à新建à项目
将打一个新建项目对话框,
1. 选择.net framework4平台
2. 选择web模板中 Asp.net MVC2空web应用程序
3. 修改项目名称为MvcMusicStore ,然后点击确定
项目中默认新建了一些文件夹,它们的作用如下:
文件夹名称 |
作用 |
/Controllers |
存储控制器文件,处理页面传入的请求,和返回数据库处理文件 |
/Views |
界面或页面模板 |
/Models |
数据库业务实体类及数据类 |
/Content |
存储图片,样式表,或其它静态文件 |
/Scripts |
存放自定义javascript文件 |
/App_Data |
存放数据库文件 |
控制器(Controller)
添加一个HomeController
鼠标右击Controller文件夹,à添加à控制器 打开添加控制器对话框,把控制器名称修改为HomeController à点击添加.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MvcMusicStore.Controllers
{
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
return View();
}
}
}
为了更新简单的认识控制器,我们修改HomeController 让其返回一个字符串
1. 把Index函数返回的ActoinResult改为string
2. 修改return语句
修改后代码为:
// GET: /Home/
public string Index()
{
return "Hello from Home";
}
运行项目查看效果
注明:请不要录入上面的地址去浏览;在vs中自带的服务器会随机分配端口。
下面我们将为项目仓储控制器它有三个模块它们分别为
1. 仓储首页模块
2. 列表模块
3. 指定相册的详细模块
添加控制器和方法
代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MvcMusicStore.Controllers
{
public class StoreController : Controller
{
//
// GET: /Store/
public string Index()
{
return "Hello from Store.Index()";
}
//
// GET: /Store/Browse
public string Browse()
{
return "Hello from Store.Browse()";
}
//
// GET: /Store/Details
public string Details()
{
return "Hello from Store.Details()";
}
}
}
再次运行项目,浏览/Store/Detials
从上面页面中我们看到,仅仅传地址而不传参数是无法浏览特定相册信息的。下面我们修改控制器的Details方法
// GET: /Store/Details/5
public string Details(int id)
{
string message = "Store.Details,ID=" + id;
return Server.HtmlEncode(message);
}
运行效果如下
在传输入参数时,为什么不是/store/detals/?id=6呢? 这里我们看一下Global.asax文件
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace MvcMusicStore
{
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // 路由名称
"{controller}/{action}/{id}", // 带有iD参?数的URL
new { controller = "Home", action = "Index", id = UrlParameter.Optional } //参数默认值
);
}
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
}
}
}
其中这段
routes.MapRoute(
"Default", // 路由名称
"{controller}/{action}/{id}", // 带有iD参?数的URL
new { controller = "Home", action = "Index", id = UrlParameter.Optional } //参数默认值
);
说明地址栏中第二个/后面的值就是参数id的默认值,所以当我浏览store/details/6时,就说明参数id的值为6
那么,我们要传其它值时,怎么办呢?还好.net mvc框架中早已经考虑到,我们不必再去写相应的路由。 我们接着修改controller中的代码。
//
// GET: /Store/Browse
public string Browse()
{
string message = "Store.Browse, Genre=" +
Server.HtmlEncode(Request.QueryString["genre"]);
return Server.HtmlEncode(message);
}
运行效果如下:
说明:在程序中我们应用到Server.HtmlEncode 方法来处理Request.Querystring[“genre”] 是为了防止javascript注入和修改浏览地址
视图和视图模块
这里我们要引入一个概念视图模块;
在mvc项目中重点体现的是Model ,View 和Controller三个部分。这三个部分中View部分负责显示,一般是一些显示模板;
Controller控制器,类似于一个中间转化器,处理浏览器发过来的请求,传向指定的方法,调用Model 来和数据库交互信息;
Model模块层,处理数据库信息。
在这个过程中出现一个问题就是View 和Model数据通过谁传递,怎么传递?
在.net mvc中增加了两个数据类型,ViewData 和TempData
虽然ViewData和TempData都可以传递弱类型数据,但是两者的使用是有区别的:
ViewData的生命周期和View相同, 只对当前View有效.
TempData保存在Session中, Controller每次执行请求的时候会从Session中获取TempData并删除
Session, 获取完TempData数据后虽然保存在内部的字典对象中,但是TempData集合的每个条目访问一次后就从字典表中删除.
也就是说TempData的数据至多只能经过一次Controller传递.
为何TempData只能够在Controll中传递一次? 因为SessionStateTempDataProvider.LoadTempData方法(在TempDataDictionary.Load中调用)在从ControllerContext的Session中读取了TempData数据后, 会清空Session:
使用模板
使用mvc模板为程序公共元素设置信息
找到Views文件夹,选中Shared文件夹,右健单击à添加à新建项—>选中Mvc2视图母板
把文件名称设置为Site.master à添加
添加成功后,向母板页中添加样式表 然后添加一些html标记。代码如下:
<%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<link href="/Content/Site.css" rel="stylesheet" type="text/css" />
<title><asp:ContentPlaceHolder ID="TitleContent" runat="server" /></title>
</head>
<body>
<div>
<div id="header">
<h1>ASP.NET MVC Music Store</h1>
<ul id="navlist">
<li class="first"><a href="/" id="current">Home</a></li>
<li> <a href="/Store/">Store</a></li>
</ul>
</div>
<asp:ContentPlaceHolder ID="MainContent" runat="server">
</asp:ContentPlaceHolder>
</div>
</body>
</html>
添加一个视图模板
首先,我们要修改HomeController
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MvcMusicStore.Controllers
{
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
return View();
}
}
}
选中函数Index() ,然后右键单击Index 选择添加视图
修改添加Index视图代码如下:
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>This is the Homepage</h2>
</asp:Content>
再次运行项目
使用ViewModel向View传输入信息
为项目创建一个新的文件夹,将其命名为ViewModels
在信息传输入时分为两类一是简单信息另一个是复杂信息两类;通过绑定视力的强类型数据对应的类,来传递信息
1. 简单信息传输
选中ViewModels文件夹,右键à添加类 StoreIndexViewModel
代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace MvcMusicStore.ViewModels
{
public class StoreIndexViewModel
{
public int NumberOfGenres { get; set; }
public List<string> Genres { get; set; }
}
}
信息传输类改完之后,我们要修改Controller文件,使用Controller把数据传输入到视图中;
找到StoreController 修改其index方法如下
// GET: /Store/
public ActionResult Index()
{
var genres=new List<string>{"Rock","Jazz","Country","Pop","Disco"};
var viewModel=new StoreIndexViewModel{
NumberOfGenres=genres.Count,
Genres=genres
};
return View(viewModel);
}
重新编译整个项目
选中Index添加对应视图,选中“创建强类型视图“ 在“视图数据类”里选中创建的ViewModels.StoreIndexViewModel类 à添加
修改视图代码如下:
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<MvcMusicStore.ViewModels.StoreIndexViewModel>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Index
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Browse Genres</h2>
<p> select from <%:Model.NumberOfGenres %> Genres:</p>
<ul>
<%foreach (string genreName in Model.Genres)
{ %>
<li>
<%:genreName %>
</li>
<%} %>
</ul>
</asp:Content>
2. 复杂信息传输
首先我们在Models文件夹里添加两个类。一是Albums.cs 另一个是Genre.cs
代码分别如下:
Genre.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace MvcMusicStore.Models
{
public class Genre
{
public string Name { get; set; }
}
}
Album.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace MvcMusicStore.Models
{
public class Album
{
public string Title { get; set; }
public Genre Genre { get; set; }
}
}
向ViewModels文件里添加新类StoreBrowseViewModel,做为复杂信息传输的介质
引用类库
using MvcMusicStore.Models;
修改StoreBrowseViewModel类
public class StoreBrowseViewModel
{
public Genre Genre { get; set; }
public List<Album> Albums { get; set; }
}
、
修改StoreController类
// GET: /Store/Browse
public ActionResult Browse()
{
string genreName =
Server.HtmlEncode(Request.QueryString["genre"]);
var genre = new Genre
{
Name = genreName
};
var albums = new List<Album>();
albums.Add(new Album { Title = genreName + "Album1" });
albums.Add(new Album { Title = genreName + "Album2" });
var viewModel = new StoreBrowseViewModel
{
Genre = genre,
Albums = albums
};
return View(viewModel);
}
然后选中Browse方法,右键单击添加视图 à创建强类型视图à 选择类为MvcMusicStore.ViewModels.StoreBrowseViewModelà添加
修改视图代码如下:
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Browsing Genre: <%:Model.Genre.Name %></h2>
<ul>
<%foreach (var album in Model.Albums)
{ %>
<li><%:album.Title %></li>
<%} %>
</ul>
</asp:Content>
接着,我们再修改控制器StoreController里的Details方法
//
// GET: /Store/Details/5
public ActionResult Details(int id)
{
var album = new Album
{
Title = "Sample Album"
};
return View(album);
}
而后,选种Details方法,右键添加视图,选择强类型为Models.Album ,最后修改details视图的代码如下:
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Album <%:Model.Title%></h2>
</asp:Content>
至此我们把StoreController里的Index ,Browse和Details模块全部实现了。 可还有一个问题,就是页面间如何连接。
下面我们接着修改代码,为页面间信息添加链接
找到Views文件夹里的Browse文件里的Index修改代码如下:
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Browse Genres</h2>
<p> select from <%:Model.NumberOfGenres %> Genres:</p>
<ul>
<%foreach (string genreName in Model.Genres)
{ %>
<li>
<%:Html.ActionLink(genreName,"Browse","Store",new {genre=genreName},null) %>
</li>
<%} %>
</ul>
</asp:Content>
说明:如果想通过ActionLink传输更多参数。
<%:Html.ActionLink(genreName,"Browse","Store",new {genre=genreName,gen="aa"},null) %>
运行结果为:/Store/Browse?genre=Jazz&gen=aa
重新运行整个项目,查看效果.