【ASP.NET基础】简单企业产品展示网站--产品编辑CRUD
摘要:本文记录创建一个小的、简单的产品网站的步骤。
一,搭建一个简单的产品展示网站,熟悉以下知识点:NVelocity模板引擎、Ajax无刷新页面请求,文件上传,Row_Number实现分页,ckEditor使用,Bootstrap的简单使用。【点击查看网站效果】
二,网站基本框架:新建项目ProductWeb ,并完成基本框架的搭建(SQLHelper,ckEditor,Common_Nvelocity,Bootstrap等添加到项目中)。并创建ProductWebDB 。【下载基本模板框架】
三,在基本模板的基础上,添加后台 产品列表页面(ProductList_Admin.html)
A,新增数据库: ProduceWebDB 并新建表ProCategories、Products
USE [ProduceWebDB]
GO
/****** Object: Table [dbo].[ProCategories] Script Date: 2015/6/2 15:54:49 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[ProCategories](
[CateID] [decimal](, ) IDENTITY(,) NOT NULL,
[CateName] [varchar]() NOT NULL
) ON [PRIMARY] GO
SET ANSI_PADDING OFF
GO
/****** Object: Table [dbo].[Products] Script Date: 2015/6/2 15:54:50 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Products](
[ProID] [decimal](, ) IDENTITY(,) NOT NULL,
[ProName] [nvarchar]() NOT NULL,
[ProImagePath] [nvarchar](max) NOT NULL,
[ProIntroduce] [text] NOT NULL,
[ProCateID] [bigint] NOT NULL,
[AddTime] [datetime] NULL,
[AddIP] [nchar]() NULL,
[IsDelete] [bit] NOT NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] GO
ALTER TABLE [dbo].[Products] ADD CONSTRAINT [DF_Products_CreateTime] DEFAULT (getdate()) FOR [AddTime]
GO
ALTER TABLE [dbo].[Products] ADD CONSTRAINT [DF_Products_IsDelete] DEFAULT (()) FOR [IsDelete]
GO
B,项目新增ProductList_Admin.ashx一般处理程序 , 在Templates/Admin下添加对应的 ProductList_Admin.html 页面 ,在后台显示产品列表。
Templates/Admin/Head.html: 相当于模板页的页头部分,用Bootstrap导航组件 其他页面通过#parse("Head.html")调用
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html;" charset="gb2312" />
<!-- 这个属性主要是设置浏览器优先使用什么模式来渲染页面的-->
<!-- #下面的meta标签告诉IE浏览器,IE8/9及以后的版本都会以最高版本IE来渲染页面。 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge" /> <!--移动设备都是这Viewport里面打开,width=device-width表示打开页面默认和设备一致,initial-scale=1表示页面不进行缩放 -->
<meta name="viewport" content="width=device-width, initial-scale=1" />
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>后台管理</title> <!-- Bootstrap -->
<!--<link href="css/bootstrap.min.css" rel="stylesheet"/>-->
<!-- 新 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="http://cdn.bootcss.com/bootstrap/3.3.4/css/bootstrap.min.css" /> <!--低版本浏览器如果支持HTML5需要添加以下js-->
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE ]>
<script src="http://cdn.bootcss.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="http://cdn.bootcss .com/respond.js/1.4.2/respond.min.js"></script>
<![endif]--> <!--鼠标悬停弹出下拉菜单-->
<style type="text/css">
.navbar .nav > li .dropdown-menu {
margin: ;
} .navbar .nav > li:hover .dropdown-menu {
display: block;
} .navbar .nav > li .dropdown-menu > li:hover {
font-size: larger;
}
</style> </head>
<body> <!-- --导航条 默认高度50px, 固定在顶部 -->
<nav class="navbar navbar-default .navbar-fixed-top">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<!--当浏览器宽度变窄的时候会显示这个Button按钮,并且会把data-target中的div中ul收缩导航到Button下方-->
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<!--定义小按钮的样式-->
<span class="sr-only">Toggle navigation</span>
<!-- 页面变窄时 , 按钮的3条横线 -->
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<!--Logo位置-->
<a class="navbar-brand" href="http://www.cnblogs.com/chengzish/">后台管理</a> </div> <!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<!--导航条内容-->
<li class="active"><a href="#">首页 <span class="sr-only">(current)</span></a></li> <li><a href="#">成功案例编辑</a></li>
<li><a href="#">新闻活动编辑</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">服务编辑<span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li><a href="#">软件定制编辑</a></li>
<li class="divider"></li>
<li><a href="#">外包服务编辑</a></li>
<li class="divider"></li>
<li><a href="#">咨询服务编辑</a></li>
</ul>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">OA系统解决方案编辑<span class="caret"></span></a>
<ul class="dropdown-menu" role="menu"> <li><a href="#">员工考勤系统编辑</a></li>
<li class="divider"></li>
<li><a href="#">薪资结算系统编辑</a></li>
<li class="divider"></li>
<li><a href="#">门禁管理系统编辑</a></li>
<li class="divider"></li>
<li><a href="#">APP开发编辑</a></li> </ul>
</li>
</ul>
<!--搜索表单-->
<form class="navbar-form navbar-left" role="search">
<div class="form-group">
<input type="text" class="form-control" placeholder="Search" />
</div>
<button type="submit" class="btn btn-default">搜索</button>
</form>
<ul class="nav navbar-nav navbar-right">
<li><a href="#">Git Fork</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">联系我们编辑<span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li><a href="#">地址</a></li>
<li><a href="#">电话</a></li>
<li><a href="#">邮箱</a></li>
<li class="divider"></li>
<li><a href="#">微信</a></li>
</ul>
</li>
</ul>
</div>
<!-- /.navbar-collapse -->
</div>
<!-- /.container-fluid -->
</nav>
Templates/Admin/Foot.html: 相当于模板页的页头部分,标注版权信息,其他页面通过#parse("Foot.html")
<div id="footer" class="container"> <nav class="navbar navbar-default navbar-fixed-bottom"> <div class="navbar-inner navbar-content-center"> <p class="text-muted credit" style="padding: 10px; text-align: center">
Copyright @- By 橙子科技 All Rights Reserved. </p> </div> </nav>
</div> <!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="http://cdn.bootcss.com/jquery/1.11.2/jquery.min.js"></script> <!-- Bootstrap核心js依赖于jQuery,所以要先引用jQuery-->
<!-- Include all compiled plugins (below), or include individual files as needed -->
<!-- <script src="js/bootstrap.min.js"></script>--> <!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
<script src="http://cdn.bootcss.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
</body>
</html>
Templates/Admin/ProductList_Admin.html: 产品列表展示页面,遍历显示产品数据
#parse("Admin/Head.html")
<h2>产品列表维护</h2> <div style="width: 70%; text-align: center; margin-left: 15%;">
<table class="table table-striped table-bordered table-hover">
<tr>
<td>产品名称</td>
<td>产品类别</td>
<td>编辑</td>
<td>删除</td>
</tr>
#foreach($Pro in $data.Products)
<tr>
<td>$Pro.ProName</td>
<td>$Pro.CateName />
</td>
<td><a href="ProductEdit.html?action=edit&id=$Pro.ProID">编辑</a></td>
<td><a href="ProductEdit.html?action=delete&id=$Pro.ProID">删除</a></td>
</tr>
#end
</table>
</div> #parse("Admin/Foot.html")
ProductList_Admin.ashx: 从数据库中读取产品信息
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data; namespace ProductWeb
{
/// <summary>
/// ProductList_Admin 后台显示产品列表
/// </summary>
public class ProductList_Admin : IHttpHandler
{ public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/html";
//从DB中选出产品信息
string sql = "SELECT [ProID],[ProName],[ProImagePath],[ProIntroduce],b.[CateName] as CateName FROM [dbo].[Products] as a left join [dbo].[ProCategories] as b on a.ProCateID=b.CateID ";
SQLHelper sqlH = new SQLHelper();
DataTable dt = sqlH.ExecuteQuery(sql, CommandType.Text); var data = new { PageTitle = "产品列表", Products = dt.Rows }; string strHtml = Common_Nvelocity.RenderHTML("Admin/ProductList_Admin.html", data);
context.Response.Write(strHtml);
} public bool IsReusable
{
get
{
return false;
}
}
}
}
C,Ctrl+F5运行程序,查看 ProductList_Admin.ashx 读出了DB中的数据:
四,添加产品编辑页面(ProductEdit.html)点击ProductList_Admin.html中的“编辑”跳转到ProductEdit.html编辑页面.
PorductEdit.ashx根据传递过来的Action(edit,delete,addnew)进行编辑、删除、新增操作。
A, 更新webconfig允许写入 html 标签
<system.web>
<compilation debug="true" targetFramework="4.0" />
<httpRuntime requestValidationMode="2.0"/>
</system.web>
B, 添加ProductEdit.html 页面 (1,三个隐藏控件分别记录当前页面是否是首次加载,点击“保存”按钮需要执行的操作,传递过来的id的值 2, 注意下拉列表的实现)
#parse("Admin/Head.html") <script src="../../ckeditor/ckeditor.js"></script> <div style="width: 70%; text-align: left; margin-left: 15%;">
#if($data.ActionEdit=="edit")
<h2 class="text-center">产品编辑</h2>
#elseif ($data.ActionEdit=="delete")
<h2 class="text-center">产品删除 </h2>
#elseif ($data.ActionEdit=="addnew")
<h2 class="text-center">产品新增</h2>
#end
<form method="post" action="ProductEdit.ashx">
<!--三个隐藏,IspostBack 记录页面是否首次加载,action 记录提交按钮后是需要新增还是编辑,txtProIDHiddden 隐藏当前编辑的id -->
<input type="hidden" name="IsPostBack" value="true" />
<input type="hidden" name="txtaction" value="$data.ActionEdit" />
<input type="hidden" name="txtProIDHiddden" value="$data.Product.ProID" /> <table class="table table-striped table-bordered"> <tr>
<td>产品名称:</td>
<td>
<input type="text" name="txtProName" value="$data.Product.ProName" /></td>
</tr> <tr>
<td>产品分类:</td>
<td>
<select name="txtProCateID">
#foreach($cate in $data.Categories)
#if($cate.CateID==$data.Product.ProCateID)
<option value="$cate.CateID" selected="selected">$cate.CateName</option>
#else
<option value="$cate.CateID">$cate.CateName</option>
#end
#end
</select>
</td>
</tr> <tr>
<td>产品图片:</td>
<td>
<img id="ProImg" src="$data.Product.ProImagePath" class="img-rounded" /></td>
</tr>
<tr>
<td>产品介绍:</td>
<td>
<textarea id="idProIntroduce" name="txtProIntroduce">$data.Product.ProIntroduce </textarea>
</td>
</tr>
<tr>
<td colspan="" style="text-align: center">
<input type="submit" value="保存" class="btn btn-primary" />
<a href="ProductList_Admin.ashx" class="btn btn-default">返回</a>
</td>
</tr>
</table> </form>
<div style="width: 70%; text-align: center; margin-left: 15%;">
<script type="text/javascript">
var txtIntro = document.getElementById("idProIntroduce");
CKEDITOR.replace(txtIntro); </script>
#parse("Admin/Foot.html")
C, 添加ProductEdit.ashx 处理新增、编辑、删除操作,并把数据交给Nvelocity模板从而加载到前台页面
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using System.Data.SqlClient; namespace ProductWeb
{
/// <summary>
/// ProductEdit Product编辑页面
/// </summary>
public class ProductEdit : IHttpHandler
{ public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/html";
string strHtml = "";
string sqlCates = "SELECT [CateID],[CateName] FROM [dbo].[ProCategories]";
SQLHelper sqlH = new SQLHelper();
DataTable dtCates = sqlH.ExecuteQuery(sqlCates, CommandType.Text); //[ProID],[ProName],[ProImagePath],[ProIntroduce],[ProCateID],b.[CateName] as CateName,b.[CateID] as CateID FROM [Products] as a left join [ProCategories] as b on a.ProCateID=b.CateID and a.ProID=@strProID "; //
////定义Product,并给一个默认的控制
var ProductOriginal = new { ProID = , ProName = "", ProImagePath = "", ProIntroduce = "", CateName = "", CateID = "" }; //页面首次加载 , 显示Product信息
if (string.IsNullOrEmpty(context.Request.Form["IsPostBack"]) == true)
{
string strProID = context.Request.QueryString["id"]; // 点击 编辑 按钮,传递过来 action 和 id值
string strAction = context.Request.QueryString["action"] == null ? "" : context.Request.QueryString["action"].ToString().ToLower(); // 点击保存后,具体是 edit、 delte还是 add, 保存在页面的隐藏控件中
string strPageTitle = "产品操作"; //default if (!string.IsNullOrEmpty(strProID)) // id 存在
{
//从DB中选出 id 对应的Product 信息
SqlParameter[] sqlParas = new SqlParameter[] {
new SqlParameter("@strProID",strProID)
}; if (strAction == "edit")
{
strPageTitle = "产品编辑";
}
else if (strAction == "delete")
{
strPageTitle = "产品删除";
}
else if (strAction == "addnew")
{
strPageTitle = "产品新增";
}
//选择出ID对应的Product
DataTable dtPro = dtGetProductByID(strProID);
int numExist = ;
numExist = dtPro.Rows.Count; if (numExist > )
{
// 产品存在,显示产品信息
var data = new { PageTitle = strPageTitle, Categories = dtCates.Rows, Product = dtPro.Rows[], ActionEdit = strAction };
strHtml = Common_Nvelocity.RenderHTML("Admin/ProductEdit.html", data);
}
else
{
// 不存在,显示编辑页面
var data = new { PageTitle = strPageTitle, Categories = dtCates.Rows, Product = ProductOriginal, ActionEdit = strAction };
strHtml = Common_Nvelocity.RenderHTML("Admin/ProductEdit.html", data);
}
}
else
{
//显示编辑页面
var data = new { PageTitle = strPageTitle, Categories = dtCates.Rows, Product = ProductOriginal, ActionEdit = strAction };
strHtml = Common_Nvelocity.RenderHTML("Admin/ProductEdit.html", data);
} }
//点击了 submit 按钮,根据传递过来的action进行操作 update/delete
else
{
string strAction = context.Request.Form["txtaction"];
if (!string.IsNullOrEmpty(strAction))
{
string strInfo = "";
if (strAction == "edit")
{ string strProID = context.Request.Form["txtProIDHiddden"];
string strProName = context.Request.Form["txtProName"];
string strProCateID = context.Request.Form["txtProCateID"];
//string strProImagePath = context.Request.Form["strProImgPath"];
string strProIntroduce = context.Request.Form["txtProIntroduce"]; //选择出ID对应的Product
DataTable dtPro = dtGetProductByID(strProID);
int numExist = ;
numExist = dtPro.Rows.Count;
if (numExist > )
{
//update
string sqlUpdate = "update [Products] set [ProName]=@ProName,[ProIntroduce]=@ProIntroduce,[ProCateID]=@ProCateID where [IsDelete]=0 and [ProID]=@ProID ";
SqlParameter[] sqlParas = new SqlParameter[] {
new SqlParameter("@ProName",strProName),
new SqlParameter("@ProCateID",strProCateID),
new SqlParameter("@ProIntroduce",strProIntroduce),
new SqlParameter("@ProID",strProID)
};
int numSuccUpd = ;
numSuccUpd = sqlH.ExecuteNonQuery(sqlUpdate, sqlParas, CommandType.Text); if (numSuccUpd > )
{
strInfo = "更新成功";
DataTable dtProNew = dtGetProductByID(strProID);
var data = new { PageTitle = "产品编辑", Categories = dtCates.Rows, Product = dtProNew.Rows[], ActionEdit = strAction, InfoMeg = strInfo };
strHtml = Common_Nvelocity.RenderHTML("Admin/ProductEdit.html", data);
}
else
{
strInfo = "更新失败";
DataTable dtProNew = dtGetProductByID(strProID);
var data = new { PageTitle = "产品编辑", Categories = dtCates.Rows, Product = dtProNew.Rows[], ActionEdit = strAction, InfoMeg = strInfo };
strHtml = Common_Nvelocity.RenderHTML("Admin/ProductEdit.html", data);
}
}
}
else if (strAction == "delete")
{
string strProID = context.Request.Form["txtProIDHiddden"];
//选择出ID对应的Product
DataTable dtPro = dtGetProductByID(strProID);
int numExist = ;
numExist = dtPro.Rows.Count;
if (numExist > )
{
string sqlUpdate = "update [Products] set [IsDelete]=1 where [ProID]=@ProID ";
SqlParameter[] sqlParas = new SqlParameter[] {
new SqlParameter("@ProID",strProID)
};
int numSuccUpd = ;
numSuccUpd = sqlH.ExecuteNonQuery(sqlUpdate, sqlParas, CommandType.Text);
if (numSuccUpd > )
{
strInfo = "删除成功";
context.Response.Redirect("productlist_admin.ashx");
}
else
{
DataTable dtProNew = dtGetProductByID(strProID);
var data = new { PageTitle = "产品删除", Categories = dtCates.Rows, Product = dtProNew.Rows[], ActionEdit = strAction, InfoMeg = strInfo };
strHtml = Common_Nvelocity.RenderHTML("Admin/ProductEdit.html", data);
}
} }
else if (strAction == "addnew")
{
//写入数据库 string strProName = context.Request.Form["txtProName"];
string strProCateID = context.Request.Form["txtProCateID"];
string strProImagePath = "updloadFiles/3.jpg";
string strProIntroduce = context.Request.Form["txtProIntroduce"];
if (string.IsNullOrEmpty(strProName) || string.IsNullOrEmpty(strProCateID) || string.IsNullOrEmpty(strProIntroduce))
{
strInfo = "不允许为空";
var data = new { PageTitle = "产品新增", Categories = dtCates.Rows, Product = ProductOriginal, MesgInfo = strInfo };
strHtml = Common_Nvelocity.RenderHTML("Admin/ProductEdit.html", data);
}
else
{
string sqlInsert = " insert into [Products]([ProName],[ProCateID],[ProIntroduce],[ProImagePath]) values(@ProName,@ProCateID,@ProIntroduce,@ProImagePath) ";
SqlParameter[] sqlParas = new SqlParameter[] {
new SqlParameter("@ProName",strProName),
new SqlParameter("@ProCateID",strProCateID),
new SqlParameter("@ProIntroduce",strProIntroduce),
new SqlParameter("@ProImagePath",strProImagePath)
};
int numSucc = sqlH.ExecuteNonQuery(sqlInsert, sqlParas, CommandType.Text);
if (numSucc == )
{
strInfo = "添加成功";
context.Response.Redirect("productlist_admin.ashx");
}
else
{
strInfo = "添加失败";
var data = new { PageTitle = "产品新增", Categories = dtCates.Rows, Product = ProductOriginal, MesgInfo = strInfo };
strHtml = Common_Nvelocity.RenderHTML("Admin/ProductEdit.html", data);
}
} }
}
else
{
var data = new { PageTitle = "产品编辑", Categories = dtCates.Rows, Product = ProductOriginal, MesgInfo = "" };
strHtml = Common_Nvelocity.RenderHTML("Admin/ProductEdit.html", data);
} }
context.Response.Write(strHtml);
} public DataTable dtGetProductByID(string strProID)
{
SQLHelper sqlH = new SQLHelper();
//选择出ID对应的Product
string sqlPro = "SELECT [ProID],[ProName],[ProImagePath],[ProIntroduce],[ProCateID],b.[CateName] as CateName,b.[CateID] as CateID FROM [Products] as a left join [ProCategories] as b on a.ProCateID=b.CateID where [IsDelete]=0 and a.ProID=@ProID ";
SqlParameter[] sqlParas = new SqlParameter[] {
new SqlParameter("@ProID", strProID)
}; DataTable dtPro = sqlH.ExecuteQuery(sqlPro, sqlParas, CommandType.Text);
return dtPro;
} public bool IsReusable
{
get
{
return false;
}
}
}
}
---------------------------------------------------实现效果: 新增 AddNew---------------------------------------------------
----------------------------------------------------实现效果: 编辑 Edit-------------------------------------------------------
----------------------------------------------------实现效果: 删除 Delete-----------------------------------------------------
五,实现图片上传和分页 (知识点:1,From表单设置enctype属性 2,文件上传并SaveAs到Server.MapPath 3,Row_Number()进行分页)
A,分别更新ProductEdit.html和ProductEdit.ashx 实现图片的上传和更新(图片存储在服务器,图片名称存储DB)
Templates/Admin/ProductEdit.html: Form表单添加enctype="multipart/form-data"属性 ,图片src读取图片路径
#parse("Admin/Head.html") <script src="../../ckeditor/ckeditor.js"></script> <div style="width: 70%; text-align: left; margin-left: 15%;">
#if($data.ActionEdit=="edit")
<h2 class="text-center">产品编辑</h2>
#elseif ($data.ActionEdit=="delete")
<h2 class="text-center">产品删除 </h2>
#elseif ($data.ActionEdit=="addnew")
<h2 class="text-center">产品新增</h2>
#end
<form method="post" action="ProductEdit.ashx" enctype="multipart/form-data">
<!--三个隐藏,IspostBack 记录页面是否首次加载,action 记录提交按钮后是需要新增还是编辑,txtProIDHiddden 隐藏当前编辑的id -->
<input type="hidden" name="IsPostBack" value="true" />
<input type="hidden" name="txtaction" value="$data.ActionEdit" />
<input type="hidden" name="txtProIDHiddden" value="$data.Product.ProID" /> <table class="table table-striped table-bordered"> <tr>
<td>产品名称:</td>
<td>
<input type="text" name="txtProName" value="$data.Product.ProName" /></td>
</tr> <tr>
<td>产品分类:</td>
<td>
<select name="txtProCateID">
#foreach($cate in $data.Categories)
#if($cate.CateID==$data.Product.ProCateID)
<option value="$cate.CateID" selected="selected">$cate.CateName</option>
#else
<option value="$cate.CateID">$cate.CateName</option>
#end
#end
</select>
</td>
</tr> <tr>
<td>产品图片:</td>
<td>#if ($data.ActionEdit=="addnew")
<input type="file" name="ProductImage" value="上传图片" />
#else
<img id="ProImg" src="../../uploadFiels/$data.Product.ProImagePath" class="img-rounded" style="width: 40px; height: 40px" />
<input type="file" name="ProductImage" value="更新图片" />
#end </td>
</tr>
<tr>
<td>产品介绍:</td>
<td>
<textarea id="idProIntroduce" name="txtProIntroduce">$data.Product.ProIntroduce </textarea>
</td>
</tr>
<tr>
<td colspan="" style="text-align: center">
<input type="submit" value="保存" class="btn btn-primary" />
<a href="ProductList_Admin.ashx" class="btn btn-default">返回</a>
</td>
</tr>
</table>
</form> <br />
<br />
<br />
<script type="text/javascript">
var txtIntro = document.getElementById("idProIntroduce");
CKEDITOR.replace(txtIntro);
</script>
#parse("Admin/Foot.html")
ProductEdit.ashx: 实现图片保存到uploadfiles文件夹,图片名称保存到DB
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using System.Data.SqlClient;
using System.IO; namespace ProductWeb
{
/// <summary>
/// ProductEdit Product编辑页面
/// </summary>
public class ProductEdit : IHttpHandler
{ public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/html";
string strHtml = "";
string sqlCates = "SELECT [CateID],[CateName] FROM [dbo].[ProCategories]";
SQLHelper sqlH = new SQLHelper();
DataTable dtCates = sqlH.ExecuteQuery(sqlCates, CommandType.Text); //[ProID],[ProName],[ProImagePath],[ProIntroduce],[ProCateID],b.[CateName] as CateName,b.[CateID] as CateID FROM [Products] as a left join [ProCategories] as b on a.ProCateID=b.CateID and a.ProID=@strProID "; //
////定义Product,并给一个默认的控制
var ProductOriginal = new { ProID = , ProName = "", ProImagePath = "", ProIntroduce = "", CateName = "", CateID = "" }; //页面首次加载 , 显示Product信息
if (string.IsNullOrEmpty(context.Request.Form["IsPostBack"]) == true)
{
string strProID = context.Request.QueryString["id"]; // 点击 编辑 按钮,传递过来 action 和 id值
string strAction = context.Request.QueryString["action"] == null ? "" : context.Request.QueryString["action"].ToString().ToLower(); // 点击保存后,具体是 edit、 delte还是 add, 保存在页面的隐藏控件中
string strPageTitle = "产品操作"; //default if (!string.IsNullOrEmpty(strProID)) // id 存在
{
//从DB中选出 id 对应的Product 信息
SqlParameter[] sqlParas = new SqlParameter[] {
new SqlParameter("@strProID",strProID)
}; if (strAction == "edit")
{
strPageTitle = "产品编辑";
}
else if (strAction == "delete")
{
strPageTitle = "产品删除";
}
else if (strAction == "addnew")
{
strPageTitle = "产品新增";
}
//选择出ID对应的Product
DataTable dtPro = dtGetProductByID(strProID);
int numExist = ;
numExist = dtPro.Rows.Count; if (numExist > )
{
// 产品存在,显示产品信息
var data = new { PageTitle = strPageTitle, Categories = dtCates.Rows, Product = dtPro.Rows[], ActionEdit = strAction };
strHtml = Common_Nvelocity.RenderHTML("Admin/ProductEdit.html", data);
}
else
{
// 不存在,显示编辑页面
var data = new { PageTitle = strPageTitle, Categories = dtCates.Rows, Product = ProductOriginal, ActionEdit = strAction };
strHtml = Common_Nvelocity.RenderHTML("Admin/ProductEdit.html", data);
}
}
else
{
//显示编辑页面
var data = new { PageTitle = strPageTitle, Categories = dtCates.Rows, Product = ProductOriginal, ActionEdit = strAction };
strHtml = Common_Nvelocity.RenderHTML("Admin/ProductEdit.html", data);
} }
//点击了 submit 按钮,根据传递过来的action进行操作 update/delete
else
{
string strAction = context.Request.Form["txtaction"];
if (!string.IsNullOrEmpty(strAction))
{
string strInfo = "";
if (strAction == "edit")
{ string strProID = context.Request.Form["txtProIDHiddden"];
string strProName = context.Request.Form["txtProName"];
string strProCateID = context.Request.Form["txtProCateID"];
string strProImageName = ""; //文件名
string strProIntroduce = context.Request.Form["txtProIntroduce"]; //选择出ID对应的Product
DataTable dtPro = dtGetProductByID(strProID);
int numExist = ;
numExist = dtPro.Rows.Count;
if (numExist > )
{ //上传文件
HttpPostedFile proImg = context.Request.Files["ProductImage"]; //获得客户端上传图片信息
string imgServerPath = context.Server.MapPath("~/uploadFiels/"); //项目中 uploadFiles路径
string strTimeNow = DateTime.Now.ToString("yyyyMMddHHmmssfff");
strProImageName = strTimeNow + Path.GetExtension(proImg.FileName);
if ((Path.GetExtension(proImg.FileName) == ".jpg" || Path.GetExtension(proImg.FileName) == ".png") && proImg.ContentLength < )
{
proImg.SaveAs(imgServerPath + strProImageName); //上传
}
//update DB
string sqlUpdate = "update [Products] set [ProName]=@ProName,[ProIntroduce]=@ProIntroduce,[ProCateID]=@ProCateID,[ProImagePath]=@ProImagePath where [IsDelete]=0 and [ProID]=@ProID ";
SqlParameter[] sqlParas = new SqlParameter[] {
new SqlParameter("@ProName",strProName),
new SqlParameter("@ProCateID",strProCateID),
new SqlParameter("@ProIntroduce",strProIntroduce),
new SqlParameter("@ProID",strProID),
new SqlParameter("@ProImagePath",strProImageName)
};
int numSuccUpd = ;
numSuccUpd = sqlH.ExecuteNonQuery(sqlUpdate, sqlParas, CommandType.Text); if (numSuccUpd > )
{
strInfo = "更新成功";
DataTable dtProNew = dtGetProductByID(strProID);
var data = new { PageTitle = "产品编辑", Categories = dtCates.Rows, Product = dtProNew.Rows[], ActionEdit = strAction, InfoMeg = strInfo };
strHtml = Common_Nvelocity.RenderHTML("Admin/ProductEdit.html", data);
}
else
{
strInfo = "更新失败";
DataTable dtProNew = dtGetProductByID(strProID);
var data = new { PageTitle = "产品编辑", Categories = dtCates.Rows, Product = dtProNew.Rows[], ActionEdit = strAction, InfoMeg = strInfo };
strHtml = Common_Nvelocity.RenderHTML("Admin/ProductEdit.html", data);
}
}
}
else if (strAction == "delete")
{
string strProID = context.Request.Form["txtProIDHiddden"];
//选择出ID对应的Product
DataTable dtPro = dtGetProductByID(strProID);
int numExist = ;
numExist = dtPro.Rows.Count;
if (numExist > )
{
string sqlUpdate = "update [Products] set [IsDelete]=1 where [ProID]=@ProID ";
SqlParameter[] sqlParas = new SqlParameter[] {
new SqlParameter("@ProID",strProID)
};
int numSuccUpd = ;
numSuccUpd = sqlH.ExecuteNonQuery(sqlUpdate, sqlParas, CommandType.Text);
if (numSuccUpd > )
{
strInfo = "删除成功";
context.Response.Redirect("productlist_admin.ashx");
}
else
{
DataTable dtProNew = dtGetProductByID(strProID);
var data = new { PageTitle = "产品删除", Categories = dtCates.Rows, Product = dtProNew.Rows[], ActionEdit = strAction, InfoMeg = strInfo };
strHtml = Common_Nvelocity.RenderHTML("Admin/ProductEdit.html", data);
}
} }
else if (strAction == "addnew")
{
//写入数据库 string strProName = context.Request.Form["txtProName"];
string strProCateID = context.Request.Form["txtProCateID"];
string strProImageName = "";
string strProIntroduce = context.Request.Form["txtProIntroduce"]; if (string.IsNullOrEmpty(strProName) || string.IsNullOrEmpty(strProCateID) || string.IsNullOrEmpty(strProIntroduce))
{
strInfo = "不允许为空";
var data = new { PageTitle = "产品新增", Categories = dtCates.Rows, Product = ProductOriginal, MesgInfo = strInfo };
strHtml = Common_Nvelocity.RenderHTML("Admin/ProductEdit.html", data);
}
else
{
//上传文件
HttpPostedFile proImg = context.Request.Files["ProductImage"]; //获得客户端上传图片信息
string imgServerPath = context.Server.MapPath("~/uploadFiels/"); //项目中 uploadFiles路径
string strTimeNow = DateTime.Now.ToString("yyyyMMddHHmmssfff");
strProImageName = strTimeNow + Path.GetExtension(proImg.FileName);
if ((Path.GetExtension(proImg.FileName) == ".jpg" || Path.GetExtension(proImg.FileName) == ".png") && proImg.ContentLength < )
{
proImg.SaveAs(imgServerPath + strProImageName); //上传
}
// Insert DB
string sqlInsert = " insert into [Products]([ProName],[ProCateID],[ProIntroduce],[ProImagePath]) values(@ProName,@ProCateID,@ProIntroduce,@ProImagePath) ";
SqlParameter[] sqlParas = new SqlParameter[] {
new SqlParameter("@ProName",strProName),
new SqlParameter("@ProCateID",strProCateID),
new SqlParameter("@ProIntroduce",strProIntroduce),
new SqlParameter("@ProImagePath",strProImageName)
};
int numSucc = sqlH.ExecuteNonQuery(sqlInsert, sqlParas, CommandType.Text);
if (numSucc == )
{
strInfo = "添加成功";
context.Response.Redirect("productlist_admin.ashx");
}
else
{
strInfo = "添加失败";
var data = new { PageTitle = "产品新增", Categories = dtCates.Rows, Product = ProductOriginal, MesgInfo = strInfo };
strHtml = Common_Nvelocity.RenderHTML("Admin/ProductEdit.html", data);
}
} }
}
else
{
var data = new { PageTitle = "产品编辑", Categories = dtCates.Rows, Product = ProductOriginal, MesgInfo = "" };
strHtml = Common_Nvelocity.RenderHTML("Admin/ProductEdit.html", data);
} }
context.Response.Write(strHtml);
}
// Query Product By ID
public DataTable dtGetProductByID(string strProID)
{
SQLHelper sqlH = new SQLHelper();
//选择出ID对应的Product
string sqlPro = "SELECT [ProID],[ProName],[ProImagePath],[ProIntroduce],[ProCateID],b.[CateName] as CateName,b.[CateID] as CateID FROM [Products] as a left join [ProCategories] as b on a.ProCateID=b.CateID where [IsDelete]=0 and a.ProID=@ProID ";
SqlParameter[] sqlParas = new SqlParameter[] {
new SqlParameter("@ProID", strProID)
}; DataTable dtPro = sqlH.ExecuteQuery(sqlPro, sqlParas, CommandType.Text);
return dtPro;
} public bool IsReusable
{
get
{
return false;
}
}
}
}
--------------------------图片上传-效果--------------------------------------------
B,借助SQL的Row_Number方法进行分页, 前台页面传入页码到后台,然后查询对应页码的数据。(1,Row_Number 2,页码计算 3,根据当前页面把上一页、下一页禁用)
分别更新ProductList_Admin.html 和 ProductList_Admin.ashx页面:
Templates/Admin/ProductList_Admin.html 调用Bootstrap分页组件
#parse("Admin/Head.html") <h2 class="text-center">产品列表维护</h2> <div style="width: 70%; text-align: center; margin-left: 15%;">
<table class="table table-striped table-bordered table-hover">
<tr style="font-weight: bolder"> <td>产品名称</td>
<td>产品类别</td>
<td>编辑</td>
<td>删除</td>
</tr>
#foreach($Pro in $data.Products)
<tr>
<td>$Pro.ProName</td>
<td>$Pro.CateName</td> <td><a href="ProductEdit.ashx?action=edit&id=$Pro.ProID">编辑</a></td>
<td><a href="ProductEdit.ashx?action=delete&id=$Pro.ProID">删除</a></td> </tr>
#end
<tr>
<td colspan="" class="text-center">
<nav>
<ul class="pagination">
#if($data.PageBeforeNext.PageBefore==0)
<li class="disabled">
#else
<li>#end
<a href="Productlist_admin.ashx?Page=$data.PageBeforeNext.PageBefore" aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
</li> #foreach($pageHref in $data.PageData)
<li><a href="$pageHref.Href">$pageHref.Title</a></li>
#end #if($data.PageBeforeNext.PageNext>=$data.PageNums)
<li class="disabled">
#else
<li>#end
<a href="Productlist_admin.ashx?Page=$data.PageBeforeNext.PageNext" aria-label="Next">
<span aria-hidden="true">»</span>
</a>
</li>
<li><a>共$data.PageNums页</a></li>
</ul>
</nav>
</td>
</tr>
<tr>
<td colspan="" class="text-center">
<a href="ProductEdit.ashx?action=AddNew" class="btn btn-default">新增</a></td>
</tr>
</table>
</div> #parse("Admin/Foot.html")
ProductList_Admin.ashx: 1,页数计算,理解Row_Number分页 2,生成对应的href链接传递给前台页面 3, 当前页码、页面总数、上页、下页
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using System.Data.SqlClient; namespace ProductWeb
{
/// <summary>
/// ProductList_Admin 后台显示产品列表
/// </summary>
public class ProductList_Admin : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/html"; //从DB中选出产品信息
SQLHelper sqlH = new SQLHelper();
//DataTable是把数据读取出来以后放入内存中,如果数据量大的话 一次性都读出来的话就很吃内存造成系统性能很差
//这时候我们就要从DB中只读取我们需要的数据就好了 , 把数据进行分页处理,只读取需要页数的数据 // 一,页数计算。查询出来Product总数numAllProducts. 总页数numPages=Celling(numAllProducts/10.0) . 天花板函数的结果是 >=这个数的最小整数
int numAllProducts = Convert.ToInt32(sqlH.ExecuteScalar("select count(*) from [Products] where [IsDelete]=0", CommandType.Text));
int numPages = (int)Math.Ceiling(numAllProducts / 10.0); // 5/10→1 10/10→1 11/10→2 //二,生成前台页面 a 的链接地址 href
object[] objPageData = new object[numPages];
for (int i = ; i < numPages; i++)
{
objPageData[i] = new { Href = "ProductList_Admin.ashx?Page=" + (i + ).ToString(), Title = (i + ).ToString() };
} //三,根据前台传递过来的页码,查询对应页面的数据
int intRowNumber = ; //默认为第1页 1-10条数据,第2页: 11~20条数据 (intRowNumber-1)*10+1~intRowNumber*10
string strPageNumber = context.Request.QueryString["Page"];
if (!string.IsNullOrEmpty(strPageNumber))
{
intRowNumber = Convert.ToInt32(strPageNumber); //获取传递过来的页面
} //选择对应页面的数据
string sql = @"select * from
(SELECT [ProID],[ProName],[ProImagePath],[ProIntroduce],[ProCateID],b.[CateName] as CateName,b.[CateID] as CateID,ROW_NUMBER() over (order by ProID) as RowNum
FROM [Products] as a left join [ProCategories] as b on a.ProCateID=b.CateID where [IsDelete]=0 ) as s
where s.RowNum between (@IntRowNumber-1)*10+1 and @IntRowNumber*10 "; SqlParameter[] sqlParas = new SqlParameter[] {
new SqlParameter("@IntRowNumber",intRowNumber)
};
//string sql = "SELECT [ProID],[ProName],[ProImagePath],[ProIntroduce],b.[CateName] as CateName FROM [dbo].[Products] as a left join [dbo].[ProCategories] as b on a.ProCateID=b.CateID where [IsDelete]=0 ";
DataTable dt = sqlH.ExecuteQuery(sql, sqlParas, CommandType.Text); //四,根据当天页码和总页面数,设置前一页和后一页
var varPageBeforeNext = new { PageBefore = intRowNumber - , PageNext = intRowNumber + }; var data = new { PageTitle = "产品列表", Products = dt.Rows, PageData = objPageData, PageNums = numPages, PageBeforeNext = varPageBeforeNext }; string strHtml = Common_Nvelocity.RenderHTML("Admin/ProductList_Admin.html", data);
context.Response.Write(strHtml);
} public bool IsReusable
{
get
{
return false;
}
}
}
}
--------------------------------------------------分页实现效果------------------------------------------------------
总结:本文实现了产品编辑的增删查改功能,了解图片上传、分页实现等。 【Demo下载 】
参考:
NVelocity 语法: http://www.cnblogs.com/hxling/archive/2011/10/23/2221918.html
Row_Number()使用: http://www.cnblogs.com/gy51Testing/archive/2012/07/26/2609832.html
【ASP.NET基础】简单企业产品展示网站--产品编辑CRUD的更多相关文章
- 精致3D图片切换效果,最适合企业产品展示
这是一个精致的立体图片切换效果,特别适合企业产品展示,可立即用于实际项目中.支持导航和自动播放功能, 基于 CSS3 实现,推荐使用最新的 Chrome,Firefox 和 Safari 浏览器浏览效 ...
- 使用jQuery简单实现产品展示的图片左右滚动功能
今天要做一个产品展示功能,由于产品比较多,一屏展示不完,所以想要做一个通过点击进行翻页的效果,在网上找了几个都不大好用,最后只能自己动手写了. 效果如下所示: 原理比较简单:将要滚动显示的区域的CSS ...
- WPF基础到企业应用系列6——布局全接触
本文转自:http://knightswarrior.blog.51cto.com/1792698/365351 一. 摘要 首先很高兴这个系列能得到大家的关注和支持,这段时间一直在研究Windows ...
- ASP.NET基础之HttpHandler学习
ASP.NET基础之HttpHandler学习 经过前两篇[ASP.NET基础之HttpModule学习]和[ASP.NET基础之HttpContext学习]文章的学习我们对ASP.NET的基础内容有 ...
- Kano模型告诉你“是不是只要企业努力的提高产品或服务质量,顾客满意度就一定会提高吗?”
在 PO在敏捷需求下要遵守哪6条重要原则? 中讲到探索和交付两大阶段的6个原则 其中在原则[做有价值的需求]中讲了两个方法:BSA分析和产品Backlog 其中BSA分析是我在产品规划阶段常使用的 ...
- (转)ASP.NET基础之HttpHandler学习
原文地址:http://www.cnblogs.com/wujy/archive/2013/08/18/3266009.html 经过前两篇[ASP.NET基础之HttpModule学习]和[ASP. ...
- 从产品展示页面谈谈Hybris的特有概念和设计结构
今天这篇文章来自我的同事,SAP成都研究院Hybris开发团队的开发人员Zhang Jonathan(张健).需要特别介绍的是,张健和成都研究院的其他开发同事不同,张健毕业于电子科技大学,读的专业是英 ...
- 【转】asp.net mvc3 简单缓存实现sql依赖
asp.net mvc3 简单缓存实现sql依赖 议题 随 着网站的发展,大量用户访问流行内容和动态内容,这两个方面的因素会增加平均的载入时间,给Web服务器和数据库服务器造成大量的请求压力.而大 ...
- (转)asp.net基础-HttpModule
HttpModule是向实现类提供模块初始化和处置事件.当一个HTTP请求到达HttpModule时,整个ASP.NET Framework系统还并没有对这个HTTP请求做任何处理,也就是说此时对于H ...
随机推荐
- 微信get post请求到微信服务器 模版 素材操作
1:素材管理 官方文档 package org.konghao.weixin.media; import java.io.File; import java.io.IOException; impor ...
- 学习tolua#·20多个例子
初始项目搭建 clone官方库 新建unity工程 依次把官方库里的Assets和Unity5.x/Assets拷贝到项目Assets里 打开unity工程, 开始逐个学习例子,例子目录: 1. he ...
- HttpRuntime.Cache 失效
最近做一个报纸内容类网站,为了提高响应速度,将首页各栏目以及二级栏目中Part文献列表存储在HttpRuntime.Cache缓存中,发布后发现问题,刚插入的缓存很快就失效,本机调试没有问题. 由于H ...
- addClass 函数
javascript: function addClass(id,new_class){ var i,n=0; new_class=new_class.split(","); fo ...
- Java组待开发的任务
周枫: A.将digital,xylinkWeb修改为支持oracle版,并完成测试工作.准备好实施安装的步骤和每步需要的文件,比如发布的项目,tomcat,jdk,memcached,数据库等,在单 ...
- cdoj 1131 男神的礼物 区间dp
男神的礼物 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/problem/show/1131 Descr ...
- C# 6与VB 12即将加入模式匹配
又有一种源自于函数式编程语言中的概念加入了C#和VB的阵营,这就是被称为模式匹配(Pattern Matching)的特性.初看上去,模式匹配的作用类似于一段switch/select语句块,但它的功 ...
- LFS7.4编译笔记(1)
由于第一次编译,花了不少时间,也不知道能不能成功,所以就没有记笔记,现在重新编译一次,这次不装U盘而是装到我的移动硬盘上面.步骤差不多,因为我感觉硬盘的速度会比U盘快. 至于LFS的优点,我就不多说了 ...
- 【JavaScript】AJAX总结(异步JavaScript和XML)
AJAX介绍 通过 AJAX,你可以创建更好.更快以及更友好的 WEB 应用程序. AJAX 基于 JavaScript 和 JavaScript的XMLHttpRequest对象. AJAX 应用程 ...
- 【译文】漫谈ASP.NET中的Session
最近这两天被一个Web Farm环境下的Session处理问题虐得很痛苦,网上到处找解决方案,在无意中翻看到这篇文章,感觉很不错,顺手查了一下,貌似没有现成的译文,于是一咬牙一跺脚把这篇文章翻译出来了 ...