最详细的【微信小程序+阿里云Web服务】开发部署指引(五):实现服务端调用逻辑
前言
前面完成了服务端数据库表的创建。这篇文章,我们来继续服务端Web API和逻辑的实现,并把程序部署到主机网站空间。
一、开发环境
由于我们使用C#开发,可以使用Visual Studio开发环境进行程序开发和发布,版本从VS 2008到VS 2019均可。
二、开发步骤
1.创建项目
新建一个ASP. NET Web应用程序项目。
2.创建对象实体类
对应数据表结构,创建卡片大类、卡片小类、卡片实体类。
- 卡片大类:
public class B_Category
{
public B_Category()
{
Types = new List<B_Type>();
}
public int Id { get; set; }
public string Name { get; set; }
// 存放当前卡片大类下的卡片小类列表
public List<B_Type> Types { get; set; }
}
- 卡片小类:
public class B_Type
{
public int Id { get; set; }
public string Name { get; set; }
public int Sequential { get; set; }
public int ImageMode { get; set; }
public string ImageVer { get; set; }
}
- 卡片:
public class B_Card
{
public int Id { get; set; }
public string Name1 { get; set; }
public string Name2 { get; set; }
public string Name3 { get; set; }
public string ImageVer { get; set; }
}
3.创建数据库操作的工具类
public static class Dao
{
private static string connectionString = null;
static Dao()
{
connectionString = ConfigurationManager.ConnectionStrings[ConfigurationManager.AppSettings["DBConnection"]].ConnectionString;
}
public static string GetConnectionString()
{
return connectionString;
}
public static DataTable Fill(string sqlText, IDictionary<string, object> param)
{
DataTable result = new DataTable("Result");
using (SqlConnection sqlConnection = new SqlConnection(connectionString))
{
if (sqlConnection.State != ConnectionState.Open)
sqlConnection.Open();
SqlDataAdapter adapter = new SqlDataAdapter(sqlConnection.CreateCommand());
adapter.SelectCommand.CommandText = sqlText;
SetParameter(adapter.SelectCommand, param);
adapter.Fill(result);
}
return result;
}
public static DataTable FillByStoredProcedure(string sqlText, IDictionary<string, object> param, int timeout)
{
DataTable result = new DataTable("Result");
using (SqlConnection sqlConnection = new SqlConnection(connectionString))
{
if (sqlConnection.State != ConnectionState.Open)
sqlConnection.Open();
SqlDataAdapter adapter = new SqlDataAdapter(sqlConnection.CreateCommand());
adapter.SelectCommand.CommandType = CommandType.StoredProcedure;
adapter.SelectCommand.CommandTimeout = timeout;
adapter.SelectCommand.CommandText = sqlText;
SetParameter(adapter.SelectCommand, param);
adapter.Fill(result);
}
return result;
}
public static DataRow Get(string sqlText, IDictionary<string, object> param)
{
DataTable data = Fill(sqlText, param);
if (data.Rows.Count > 0)
return data.Rows[0];
else
return null;
}
public static int Execute(string sqlText, IDictionary<string, object> param)
{
int result;
using (SqlConnection sqlConnection = new SqlConnection(connectionString))
{
if (sqlConnection.State != ConnectionState.Open)
sqlConnection.Open();
SqlCommand sqlCommand = sqlConnection.CreateCommand();
sqlCommand.CommandText = sqlText;
SetParameter(sqlCommand, param);
result = sqlCommand.ExecuteNonQuery();
}
return result;
}
public static int Execute(string sqlText, List<IDictionary<string, object>> paramList)
{
List<string> sqlTextList = new List<string>();
for (int i = 0; i < paramList.Count; i++)
{
sqlTextList.Add(sqlText);
}
return Execute(sqlTextList, paramList);
}
public static int Execute(List<string> sqlTextList, List<IDictionary<string, object>> paramList)
{
int result = 0;
SqlTransaction sqlTransaction = null;
using (SqlConnection sqlConnection = new SqlConnection(connectionString))
{
if (sqlConnection.State != ConnectionState.Open)
sqlConnection.Open();
sqlTransaction = sqlConnection.BeginTransaction();
SqlCommand sqlCommand = sqlConnection.CreateCommand();
sqlCommand.Transaction = sqlTransaction;
for (int i = 0; i < sqlTextList.Count; i++)
{
sqlCommand.CommandText = sqlTextList[i];
SetParameter(sqlCommand, paramList[i]);
result += sqlCommand.ExecuteNonQuery();
}
sqlTransaction.Commit();
}
return result;
}
public static object ExecuteScalar(string sqlText, IDictionary<string, object> param)
{
object result;
using (SqlConnection sqlConnection = new SqlConnection(connectionString))
{
if (sqlConnection.State != ConnectionState.Open)
sqlConnection.Open();
SqlCommand sqlCommand = sqlConnection.CreateCommand();
sqlCommand.CommandText = sqlText;
SetParameter(sqlCommand, param);
result = sqlCommand.ExecuteScalar();
}
return result;
}
public static bool Exists(string sqlText, IDictionary<string, object> param)
{
DataTable data = Fill(sqlText, param);
return data.Rows.Count > 0;
}
public static int Count(string sqlText, IDictionary<string, object> param)
{
DataTable data = Fill(sqlText, param);
return data.Rows.Count;
}
private static void SetParameter(SqlCommand sqlCommand, IDictionary<string, object> param)
{
sqlCommand.Parameters.Clear();
if (param == null || param.Count == 0) return;
foreach (var item in param)
{
sqlCommand.Parameters.Add(new SqlParameter(item.Key, item.Value));
}
}
}
4.创建数据访问层
public class DataAccess
{
// 获取所有启用的卡片大类
public DataTable GetCategory()
{
string sqlText = @"select *from [Category] where [Status]=1 order by Rank,Id";
return Dao.Fill(sqlText, null);
}
// 根据卡片大类Id获取所有启用的卡片小类
public DataTable GetType(int CategoryId)
{
string sqlText = @"select *from [Type] where CategoryId=@CategoryId and [Status]=1 order by Rank,Id";
IDictionary<string, object> param = new Dictionary<string, object>()
{
{ "CategoryId" , CategoryId },
};
return Dao.Fill(sqlText, param);
}
// 获取相应卡片小类Id的信息
public DataTable GetType2(int TypeId)
{
string sqlText = @"select *from [Type] where Id=@TypeId";
IDictionary<string, object> param = new Dictionary<string, object>()
{
{ "TypeId" , TypeId },
};
return Dao.Fill(sqlText, param);
}
// 根据卡片小类Id获取所有启用的卡片大类,参数Sequential控制结果输出按照Rank定义顺序或是无序
public DataTable GetCard(int TypeId, int Sequential)
{
string order = "Rank,Id";
if (Sequential == 0) order = "NEWID()";
string sqlText = @"select *from [Card] where TypeId=@TypeId and [Status]=1 order by " + order;
IDictionary<string, object> param = new Dictionary<string, object>()
{
{ "TypeId" , TypeId },
};
return Dao.Fill(sqlText, param);
}
// 插入一条使用反馈信息
public int InsertFeedback(int Type, string Message, string Contacts)
{
string sqlText = @"insert into [Feedback](Type, Message, Contacts, Time)
select @Type, @Message, @Contacts, getdate()";
IDictionary<string, object> param = new Dictionary<string, object>()
{
{ "Type" , Type },
{ "Message" , Message },
{ "Contacts" , Contacts },
};
return Dao.Execute(sqlText, param);
}
}
5.定义API方法
从之前的功能分析,服务端我们需要至少提供以下3个API:
- 获取卡片大小类别:GetType
- 获取当前卡片类别的所有卡片明细:GetCard
- 保存使用反馈信息:InsertFeedback
我们为每个API方法创建一个.ashx文件,这样客户端就可以直接post数据到这个文件URL,进行数据交互。
所以我们分别创建了3个文件:
- GetType.ashx
public class GetType : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
// 获取所有卡片大类
List<B_Category> categories = new List<B_Category>();
DataTable data = new DataAccess().GetCategory();
// 遍历每个卡片大类,获取对应的卡片小类保存于大类里的Types列表
for (int i = 0; i < data.Rows.Count; i++)
{
Category category = new Category();
category.Id = Convert.ToInt32(data.Rows[i]["Id"]);
category.Name = data.Rows[i]["Name"].ToString();
DataTable data2 = new DataAccess().GetType(category.Id);
for (int j = 0; j < data2.Rows.Count; j++)
{
B_Type type = new B_Type();
type.Id = Convert.ToInt32(data2.Rows[j]["Id"]);
type.Name = data2.Rows[j]["Name"].ToString();
type.Sequential = Convert.ToInt32(data2.Rows[j]["Sequential"]);
type.ImageMode = Convert.ToInt32(data2.Rows[j]["ImageMode"]);
type.ImageVer = data2.Rows[j]["ImageVer"].ToString();
category.Types.Add(type);
}
categories.Add(category);
}
string res = JsonConvert.SerializeObject(categories);
context.Response.ContentType = "text/plain";
context.Response.Write(res);
context.Response.End();
}
public bool IsReusable
{
get
{
return false;
}
}
}
- GetCard.ashx
public class GetCard : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
// 获取当前卡片小类的信息
string TypeId = context.Request["TypeId"];
int Sequential = 1;
List<B_Card> cards = new List<B_Card>();
DataTable tdata = new DataAccess().GetType2(Convert.ToInt32(TypeId));
// 卡片小类的Sequential值,指示卡片是否按顺序输出
if (tdata.Rows.Count > 0) Sequential = Convert.ToInt32(tdata.Rows[0]["Sequential"]);
// 获取当前卡片小类的所有卡片
DataTable data = new DataAccess().GetCard(Convert.ToInt32(TypeId), Sequential);
for (int i = 0; i < data.Rows.Count; i++)
{
B_Card card = new B_Card();
card.Id = Convert.ToInt32(data.Rows[i]["Id"]);
card.Name1 = data.Rows[i]["Name1"].ToString();
card.Name2 = data.Rows[i]["Name2"].ToString();
card.Name3 = data.Rows[i]["Name3"].ToString();
card.ImageVer = data.Rows[i]["ImageVer"].ToString();
cards.Add(card);
}
string res = JsonConvert.SerializeObject(cards);
context.Response.ContentType = "text/plain";
context.Response.Write(res);
context.Response.End();
}
public bool IsReusable
{
get
{
return false;
}
}
}
- InsertFeedback.ashx
public class InsertFeedback : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
string Type = context.Request["Type"];
string Message = context.Request["Message"];
string Contacts = context.Request["Contacts"];
new DataAccess().InsertFeedback(Convert.ToInt32(Type), Message, Contacts);
context.Response.ContentType = "text/plain";
context.Response.Write("ok");
context.Response.End();
}
public bool IsReusable
{
get
{
return false;
}
}
}
三、部署程序
上述开发完成后,进行程序发布,发布后的文件,需要上传到主机网站空间。
上传方法,一般是通过FTP。之前我们已经申请拿到站点FTP登录信息(地址、账号和密码),这时可以通过FTP工具上传文件。当然,使用Windows文件资源管理器也可以进行上传,不过删除修改文件有时会比较麻烦,而且如果文件较大较多,容易出现连接断开。
专题文章链接
最详细的【微信小程序+阿里云Web服务】开发部署指引(一):准备开始
最详细的【微信小程序+阿里云Web服务】开发部署指引(二):注册微信小程序
最详细的【微信小程序+阿里云Web服务】开发部署指引(三):开通阿里云主机
最详细的【微信小程序+阿里云Web服务】开发部署指引(四):搭建服务端数据库
最详细的【微信小程序+阿里云Web服务】开发部署指引(五):实现服务端调用逻辑
最详细的【微信小程序+阿里云Web服务】开发部署指引(六):开发微信小程序的准备
最详细的【微信小程序+阿里云Web服务】开发部署指引(七):小程序项目中的文件资源
最详细的【微信小程序+阿里云Web服务】开发部署指引(八):开发小程序卡片类型呈现功能
最详细的【微信小程序+阿里云Web服务】开发部署指引(九):开发小程序卡片浏览功能
最详细的【微信小程序+阿里云Web服务】开发部署指引(十):实现发音朗读
最详细的【微信小程序+阿里云Web服务】开发部署指引(十一):开发小程序设置功能
最详细的【微信小程序+阿里云Web服务】开发部署指引(十二):开发小程序用户反馈功能
最详细的【微信小程序+阿里云Web服务】开发部署指引(十三):小程序底部菜单
最详细的【微信小程序+阿里云Web服务】开发部署指引(十四):发布小程序
最详细的【微信小程序+阿里云Web服务】开发部署指引(十五):结语
更多推荐

所有评论(0)