大家好,本篇是接上一篇 ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(零) 前言 ASP.NET SignalR WebIM系列第二篇。本篇会带领大家将 LayIM界面中的数据动态化。当然还不涉及即时消息通讯,如果你已经搞定了数据界面,那么本文您可以简单的看一下,或者略过。
进入正题,layim帮我们定义好了数据规则,我们只要写一个接口实现那个json规范就可以了,剩下的事情就交给layim去做,看一下json格式。(对应文件夹:demo/json/getList/.json,demo/json/getMembers.json)
另外,大家可以参考官方文档:http://www.layui.com/doc/layim.html
{ "code": 0 ,"msg": "" ,"data": { "mine": { "username": "纸飞机" ,"id": "100000" ,"status": "online" ,"sign": "在深邃的编码世界,做一枚轻盈的纸飞机" ,"avatar": "http://cdn.firstlinkapp.com/upload/2016_6/1465575923433_33812.jpg" } ,"friend": [{ "groupname": "前端码屌" ,"id": 1 ,"online": 2 ,"list": [{ "username": "贤心" ,"id": "100001" ,"avatar": "http://tp1.sinaimg.cn/1571889140/180/40030060651/1" ,"sign": "这些都是测试数据,实际使用请严格按照该格式返回" },{ "username": "Z_子晴" ,"id": "108101" ,"avatar": "http://tva3.sinaimg.cn/crop.0.0.512.512.180/8693225ajw8f2rt20ptykj20e80e8weu.jpg" ,"sign": "微电商达人" },{ "username": "Lemon_CC" ,"id": "102101" ,"avatar": "http://tp2.sinaimg.cn/1833062053/180/5643591594/0" ,"sign": "" },{ "username": "马小云" ,"id": "168168" ,"avatar": "http://tp4.sinaimg.cn/2145291155/180/5601307179/1" ,"sign": "让天下没有难写的代码" },{ "username": "徐小峥" ,"id": "666666" ,"avatar": "http://tp2.sinaimg.cn/1783286485/180/5677568891/1" ,"sign": "代码在囧途,也要写到底" }] },{ "groupname": "网红" ,"id": 2 ,"online": 3 ,"list": [{ "username": "罗玉凤" ,"id": "121286" ,"avatar": "http://tp1.sinaimg.cn/1241679004/180/5743814375/0" ,"sign": "在自己实力不济的时候,不要去相信什么媒体和记者。他们不是善良的人,有时候候他们的采访对当事人而言就是陷阱" },{ "username": "长泽梓Azusa" ,"id": "100001222" ,"sign": "我是日本女艺人长泽あずさ" ,"avatar": "http://tva1.sinaimg.cn/crop.0.0.180.180.180/86b15b6cjw1e8qgp5bmzyj2050050aa8.jpg" },{ "username": "大鱼_MsYuyu" ,"id": "12123454" ,"avatar": "http://tp1.sinaimg.cn/5286730964/50/5745125631/0" ,"sign": "我瘋了!這也太準了吧 超級笑點低" },{ "username": "谢楠" ,"id": "10034001" ,"avatar": "http://tp4.sinaimg.cn/1665074831/180/5617130952/0" ,"sign": "" },{ "username": "柏雪近在它香" ,"id": "3435343" ,"avatar": "http://tp2.sinaimg.cn/2518326245/180/5636099025/0" ,"sign": "" }] },{ "groupname": "我心中的女神" ,"id": 3 ,"online": 1 ,"list": [{ "username": "林心如" ,"id": "76543" ,"avatar": "http://tp3.sinaimg.cn/1223762662/180/5741707953/0" ,"sign": "我爱贤心" },{ "username": "佟丽娅" ,"id": "4803920" ,"avatar": "http://tp4.sinaimg.cn/1345566427/180/5730976522/0" ,"sign": "我也爱贤心吖吖啊" }] }] ,"group": [{ "groupname": "前端群" ,"id": "101" ,"avatar": "http://tp2.sinaimg.cn/2211874245/180/40050524279/0" },{ "groupname": "Fly社区官方群" ,"id": "102" ,"avatar": "http://tp2.sinaimg.cn/5488749285/50/5719808192/1" }] } }
有的同学可能觉得这个json太复杂,不知道如何下手,其实很简单,我们先分析第一层
{"code":0,"msg":"","data":null}
是不是很简单,code就是数据是否合法,0 代表成功 1 或其他代表数据有异常,msg 就是程序上的信息,比如获取失败,或者参数不正确等等。data 最重要的一部分,就是我们下一步要分析的数据了。可以看到 data的格式如下:
{
mine: {
//当前登录用户的个人信息,头像,昵称等
},
friend: [
//friend 第一层 是group,代表好友分组,好友分组中又包含若干好友,所以,有一个list属性,list中的每个元素肯定就是好友了,同mine一样,也包含头像,昵称等信息
],
group: [
//群组比friend相对来说简单一点,就一层,就是群组信息,至于获取群成员就要看另外一个json了。(,demo/json/getMembers.json)
]
}
数据分析就做到这里,.NET当中有自带的序列化方法,也有第三方序列化组件,这里我们完全不用担心,用MVC中的JsonResult就可以了。下面我们就要开始代码阶段了,打开LayIM.Model的项目。
好,先把最外层的写上,命名呢大致表达意思即可,在新建Model的时候要注意提取公共的字段,比如,每个对象,user 或者group都有id,那么我们就可以把id提取出来,然后写其他得类继承它就可以了。代码参考如下:
1 /// <summary> 2 /// 返回结果 3 /// </summary> 4 public class JsonResultModel 5 { 6 public JsonResultType code { get; set; } 7 public object data { get; set; } 8 public string msg { get; set; } 9 } 10 11 /// <summary> 12 /// 成功失败 13 /// </summary> 14 public enum JsonResultType 15 { 16 Success = 0, 17 Failed = 1 18 }
1 /// <summary> 2 /// 基础信息json 3 /// </summary> 4 public class BaseListResult 5 { 6 public BaseListResult() 7 { 8 //friend = new List<FriendGroupEntity>(); 9 //group = new List<GroupEntity>(); 10 } 11 public IEnumerable<FriendGroupEntity> friend { get; set; } 12 public IEnumerable<GroupEntity> group { get; set; } 13 public UserEntity mine { get; set; } 14 }
/// <summary> /// 群员信息json /// </summary> public class MembersListResult { /// <summary> /// 群主 /// </summary> public UserEntity owner { get; set; } /// <summary> /// 群成员列表 /// </summary> public IEnumerable<GroupUserEntity> list { get; set; } }
其中FriendGroupEntity代表好友分组信息,GroupEntity代表群组信息,UserEntity就是用户基础信息了,这里要注意,如果增加自己的业务,比如,用户好友备注昵称,可以加字段,但是不要少了layim中规定的字段。下面贴出 UserEntity的代码,当然,也可以不用继承来实现,定义若干个类,然后每个类对应相应的对象即可。
1 /// <summary> 2 /// 基类 3 /// </summary> 4 public class BaseEntity 5 { 6 public int id { get; set; } 7 } 8 9 /// <summary> 10 /// 基类 11 /// </summary> 12 public class AvatarEntity : BaseEntity 13 { 14 public string avatar { get; set; } 15 } 16 17 /// <summary> 18 /// 用户 19 /// </summary> 20 public class UserEntity : AvatarEntity 21 { 22 public string status { get; set; } 23 public string username { get; set; } 24 public string sign { get; set; } 25 }
好了,现在对象模型已经建好了,下一步我们该干嘛呢?没错,既然数据是活的,那么就要用到数据库了,当然这里的数据库你可以用mysql,sqlserver,mongodb等都可以。至于数据库设计就不多讲了,每个人有每个人的想法.我把表介绍一下:
- 用户表 (包含用户基本信息,账号信息等,主键 用户id)
- 用户好友分组表(每个用户有自己的好友分组,如果想让业务复杂一点,就加上系统分组,类似我的好友,黑名单等,这些都是不可删除的,主键 好友分组id)
- 好友分组关系表(每个用户好友分组里面对应多个好友,外键关联 分组id,用户id)
- 用户群表(用户加入的群或者创建的群信息,包含群主,群介绍等等,主键 群id)
- 用户群关系表(每个群都有若干个用户,外键关联 群id,用户id)
以上五个表我们用来对接layim基本没什么大问题了。如果有些同学确实不会设计,可以在评论区留下你的邮箱,我把脚本发给你。(这里贴图太麻烦,所以具体的设计就不在做介绍了)
数据库设计完之后,就是很枯燥的CRUD了,这个不用我多说了吧,不理解的同学呢可以稍微学习一下,也不算太难。项目中我就引用了Macrosoft官方的SqlHelper,然后自己写了些帮助类。官方的sqlhelper如下:
using System; using System.Data; using System.Xml; using System.Data.SqlClient; using System.Collections; namespace Microsoft.ApplicationBlocks.Data { /// <summary> /// The SqlHelper class is intended to encapsulate high performance, scalable best practices for /// common uses of SqlClient /// </summary> public sealed class SqlHelper { #region private utility methods & constructors // Since this class provides only static methods, make the default constructor private to prevent // instances from being created with "new SqlHelper()" private SqlHelper() { } /// <summary> /// This method is used to attach array of SqlParameters to a SqlCommand. /// /// This method will assign a value of DbNull to any parameter with a direction of /// InputOutput and a value of null. /// /// This behavior will prevent default values from being used, but /// this will be the less common case than an intended pure output parameter (derived as InputOutput) /// where the user provided no input value. /// </summary> /// <param name="command">The command to which the parameters will be added</param> /// <param name="commandParameters">An array of SqlParameters to be added to command</param> private static void AttachParameters(SqlCommand command, SqlParameter[] commandParameters) { if (command == null) throw new ArgumentNullException("command"); if (commandParameters != null) { foreach (SqlParameter p in commandParameters) { if (p != null) { // Check for derived output value with no value assigned if ((p.Direction == ParameterDirection.InputOutput || p.Direction == ParameterDirection.Input) && (p.Value == null)) { p.Value = DBNull.Value; } command.Parameters.Add(p); } } } } /// <summary> /// This method assigns dataRow column values to an array of SqlParameters /// </summary> /// <param name="commandParameters">Array of SqlParameters to be assigned values</param> /// <param name="dataRow">The dataRow used to hold the stored procedure\'s parameter values</param> private static void AssignParameterValues(SqlParameter[] commandParameters, DataRow dataRow) { if ((commandParameters == null) || (dataRow == null)) { // Do nothing if we get no data return; } int i = 0; // Set the parameters values foreach (SqlParameter commandParameter in commandParameters) { // Check the parameter name if (commandParameter.ParameterName == null || commandParameter.ParameterName.Length <= 1) throw new Exception( string.Format( "Please provide a valid parameter name on the parameter #{0}, the ParameterName property has the following value: \'{1}\'.", i, commandParameter.ParameterName)); if (dataRow.Table.Columns.IndexOf(commandParameter.ParameterName.Substring(1)) != -1) commandParameter.Value = dataRow[commandParameter.ParameterName.Substring(1)]; i++; } } /// <summary> /// This method assigns an array of values to an array of SqlParameters /// </summary> /// <param name="commandParameters">Array of SqlParameters to be assigned values</param> /// <param name="parameterValues">Array of objects holding the values to be assigned</param> private static void AssignParameterValues(SqlParameter[] commandParameters, object[] parameterValues) { if ((commandParameters == null) || (parameterValues == null)) { // Do nothing if we get no data return; } // We must have the same number of values as we pave parameters to put them in if (commandParameters.Length != parameterValues.Length) { throw new ArgumentException("Parameter count does not match Parameter Value count."); } // Iterate through the SqlParameters, assigning the values from the corresponding position in the // value array for (int i = 0, j = commandParameters.Length; i < j; i++) { // If the current array value derives from IDbDataParameter, then assign its Value property if (parameterValues[i] is IDbDataParameter) { IDbDataParameter paramInstance = (IDbDataParameter)parameterValues[i]; if (paramInstance.Value == null) { commandParameters[i].Value = DBNull.Value; } else { commandParameters[i].Value = paramInstance.Value; } } else if (parameterValues[i] == null) { commandParameters[i].Value = DBNull.Value; } else { commandParameters[i].Value = parameterValues[i]; } } } /// <summary> /// This method opens (if necessary) and assigns a connection, transaction, command type and parameters /// to the provided command /// </summary> /// <param name="command">The SqlCommand to be prepared</param> /// <param name="connection">A valid SqlConnection, on which to execute this command</param> /// <param name="transaction">A valid SqlTransaction, or \'null\'</param> /// <param name="commandType">The CommandType (stored procedure, text, etc.)</param> /// <param name="commandText">The stored procedure name or T-SQL command</param> /// <param name="commandParameters">An array of SqlParameters to be associated with the command or \'null\' if no parameters are required</param> /// <param name="mustCloseConnection"><c>true</c> if the connection was opened by the method, otherwose is false.</param> private static void PrepareCommand(SqlCommand command, SqlConnection connection, SqlTransaction transaction, CommandType commandType, string commandText, SqlParameter[] commandParameters, out bool mustCloseConnection) { if (command == null) throw new ArgumentNullException("command"); if (commandText == null || commandText.Length == 0) throw new ArgumentNullException("commandText"); // If the provided connection is not open, we will open it if (connection.State != ConnectionState.Open) { mustCloseConnection = true; connection.Open(); } else { mustCloseConnection = false; } // Associate the connection with the command command.Connection = connection; // Set the command text (stored procedure name or SQL statement) command.CommandText = commandText; // If we were provided a transaction, assign it if (transaction != null) { if (transaction.Connection == null) throw new ArgumentException("The transaction was rollbacked or commited, please provide an open transaction.", "transaction"); command.Transaction = transaction; } // Set the command type command.CommandType = commandType; // Attach the command parameters if they are provided if (commandParameters != null) { AttachParameters(command, commandParameters); } return; } #endregion private utility methods & constructors #region ExecuteNonQuery /// <summary> /// Execute a SqlCommand (that returns no resultset and takes no parameters) against the database specified in /// the connection string /// </summary> /// <remarks> /// e.g.: /// int result = ExecuteNonQuery(connString, CommandType.StoredProcedure, "PublishOrders"); /// </remarks> /// <param name="connectionString">A valid connection string for a SqlConnection</param> /// <param name="commandType">The CommandType (stored procedure, text, etc.)</param> /// <param name="commandText">The stored procedure name or T-SQL command</param> /// <returns>An int representing the number of rows affected by the command</returns> public static int ExecuteNonQuery(string connectionString, CommandType commandType, string commandText) { // Pass through the call providing null for the set of SqlParameters return ExecuteNonQuery(connectionString, commandType, commandText, (SqlParameter[])null); } /// <summary> /// Execute a SqlCommand (that returns no resultset) against the database specified in the connection string /// using the provided parameters /// </summary> /// <remarks> /// e.g.: /// int result = ExecuteNonQuery(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24)); /// </remarks> /// <param name="connectionString">A valid connection string for a SqlConnection</param> /// <param name="commandType">The CommandType (stored procedure, text, etc.)</param> /// <param name="commandText">The stored procedure name or T-SQL command</param> /// <param name="commandParameters">An array of SqlParamters used to execute the command</param> /// <returns>An int representing the number of rows affected by the command</returns> public static int ExecuteNonQuery(string connectionString, CommandType commandType, string commandText, params SqlParameter[] commandParameters) { if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString"); // Create & open a SqlConnection, and dispose of it after we are done using (SqlConnection connection = new SqlConnection(connectionString)) { connection.Open(); // Call the overload that takes a connection in place of the connection string return ExecuteNonQuery(connection, commandType, commandText, commandParameters); } } /// <summary> /// Execute a stored procedure via a SqlCommand (that returns no resultset) against the database specified in /// the connection string using the provided parameter values. This method will query the database to discover the parameters for the /// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order. /// </summary> /// <remarks> /// This method provides no access to output parameters or the stored procedure\'s return value parameter. /// /// e.g.: /// int result = ExecuteNonQuery(connString, "PublishOrders", 24, 36); /// </remarks> /// <param name="connectionString">A valid connection string for a SqlConnection</param> /// <param name="spName">The name of the stored prcedure</param> /// <param name="parameterValues">An array of objects to be assigned as the input values of the stored procedure</param> /// <returns>An int representing the number of rows affected by the command</returns> public static int ExecuteNonQuery(string connectionString, string spName, params object[] parameterValues) { if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString"); if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName"); // If we receive parameter values, we need to figure out where they go if ((parameterValues != null) && (parameterValues.Length > 0)) { // Pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache) SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connectionString, spName); // Assign the provided values to these parameters based on parameter order AssignParameterValues(commandParameters, parameterValues); // Call the overload that takes an array of SqlParameters return ExecuteNonQuery(connectionString, CommandType.StoredProcedure, spName, commandParameters); } else { // Otherwise we can just call the SP without params return ExecuteNonQuery(connectionString, CommandType.StoredProcedure, spName); } } /// <summary> /// Execute a SqlCommand (that returns no resultset and takes no parameters) against the provided SqlConnection. /// </summary> /// <remarks> /// e.g.: /// int result = ExecuteNonQuery(conn, CommandType.StoredProcedure, "PublishOrders"); /// </remarks> /// <param name="connection">A valid SqlConnection</param> /// <param name="commandType">The CommandType (stored procedure, text, etc.)</param> /// <param name="commandText">The stored procedure name or T-SQL command</param> /// <returns>An int representing the number of rows affected by the command</returns> public static int ExecuteNonQuery(SqlConnection connection, CommandType commandType, string commandText) { // Pass through the call providing null for the set of SqlParameters return ExecuteNonQuery(connection, commandType, commandText, (SqlParameter[])null); } <
请发表评论