1_MVC+EF+Autofac(dbfirst)轻型项目框架_core层(以登陆为例)

前言

  在上一篇0_MVC+EF+Autofac(dbfirst)轻型项目框架_基本框架中,我已经介绍了这个轻型框架的层次结构,在下面的这篇文章中,我将以教师登陆功能为例,具体来扩充下我的core层的代码。

  在这之前,我想先补充讨论下是否有必要添加server层,因为看过不少别人的框架都有这一层。首先,server层在不同地方有着不同的解释。有个常听的词叫MVSC,这里所指的S虽然也是server的意思,但实现的功能更有点类似于我框架中的core,主要存放也是业务逻辑。但我看了别人框架上的server层,有些甚至已经直接继承自Controller类,一开始很不解,这样做让web层中的Controller颜面何存。但在深入了解了mvc的一些机制后觉得这样做也有道理(mvc在注册控制器时是遍历文件夹中的dll来的),把视图和控制器存放在了不同的程序集里,便于团队开发。但有些server层的作用更像是单纯为了给web(view)和core解耦或者说是改变依赖关系。具体我还真的没能力来讨论这么做有没有必要,别人这么做必然有别人的出发点和目的,但在我的轻量架构中还是没有引入server这个层,因为在一定程度上它只会增加框架整体的复杂性,“轻”还是主基调。

  同样,文中有问题的地方欢迎批评指正!谢谢!

创建过程

  1.首先数据表结构如下图

  

  表中ID是教师的GUID,TID才是用来登陆的唯一标示,PID是权限的标示,接下去讲权限判断时将会提到它。

  2.根据数据库生成edmx在Model层的Entity中

  3.在ICore中创建教师类接口,在Core中创建教师类

  接口中很简单,就一句话,定义了教师类的接口。

public partial interface ITeacher{}

  在Core中创建一个类用来实现ITeacher接口

    public partial class Teacher : BaseCore<Entity.Teacher>, ICore.ITeacher{public Teacher(DbContext dbContext){db = dbContext;}}

  BaseCore是什么?不要惊慌。在上一篇中,我谈到了我将不引入DAL层来再次封装EF,但在EF中,有些操作比较复杂,例如修改删除等。如果每次使用时都要先查找再修改,要写很多重复代码,我的BaseCore是对这些方法的一些封装,虽然会造成一些代码的污染,但着实可以少写不少重复代码。也许会有人提出异议,这样的行为是否可以理解成是对EF的封装?我也不能完全否认,但我更愿意把它理解成业务层对于操作EF的帮助类:

    第一,相对于单独做一层来看,这样更“轻”

    第二,这样做放在业务上也更加合适,例如不需要去考虑“分页该不该放在DAL?”这类永远讨论不出正确答案的问题

    第三,维护更简单

    第四,既然是帮助类,那就提供了不用它的可能,觉得不爽不用它就是

  以下是BaseCore的代码,有点长。帮助类中借鉴了部分他人分享的代码,实在找不到出处了,这里表示感谢!

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Data.Entity;
  4 using System.Data.Entity.Infrastructure;
  5 using System.Linq;
  6 using System.Linq.Expressions;
  7 using System.Reflection;
  8 using System.Text;
  9 
 10 namespace EDUA_Core
 11 {
 12     /// <summary>
 13     /// 业务帮助父类
 14     /// </summary>
 15     /// <typeparam name="T">之类类型</typeparam>
 16     public class BaseCore<T> where T : class,new()
 17     {
 18         /// <summary>
 19         /// EF上下文对象
 20         /// </summary>
 21         protected DbContext db { get; set; }
 22 
 23         #region 1.0新增实体 + void Add(T model)
 24         /// <summary>
 25         /// 新增实体
 26         /// </summary>
 27         /// <param name="model">新增的实体</param>
 28         protected void Add(T model)
 29         {
 30             db.Set<T>().Add(model);
 31         }  
 32         #endregion
 33 
 34         #region 1.0.1新增实体并保存 + int AddAndSave(T model)
 35         /// <summary>
 36         /// 新增实体并保存
 37         /// </summary>
 38         /// <param name="model">新增的实体</param>
 39         /// <returns>受影响的行数</returns>
 40         protected int AddAndSave(T model)
 41         {
 42             Add(model);
 43             return db.SaveChanges();
 44         } 
 45         #endregion
 46 
 47         #region 2.0删除实体 + void Del(T model)
 48         /// <summary>
 49         /// 删除实体
 50         /// </summary>
 51         /// <param name="model">删除的实体</param>
 52         protected void Del(T model)
 53         {
 54             db.Set<T>().Attach(model);
 55             db.Set<T>().Remove(model);
 56         } 
 57         #endregion
 58 
 59         #region 2.0.1删除实体并保存 + int DelAndSave(T model)
 60         /// <summary>
 61         /// 删除实体并保存
 62         /// </summary>
 63         /// <param name="model">删除的实体</param>
 64         /// <returns>受影响的行数</returns>
 65         protected int DelAndSave(T model)
 66         {
 67             Del(model);
 68             return db.SaveChanges();
 69         } 
 70         #endregion
 71 
 72         #region 2.1根据条件删除 + void DelBy(Expression<Func<T, bool>> delWhere)
 73         /// <summary>
 74         /// 根据条件删除
 75         /// </summary>
 76         /// <param name="delWhere">条件</param>
 77         protected void DelBy(Expression<Func<T, bool>> delWhere)
 78         {
 79             //3.1查询要删除的数据
 80             List<T> listDeleting = db.Set<T>().Where(delWhere).ToList();
 81             //3.2将要删除的数据 用删除方法添加到 EF 容器中
 82             listDeleting.ForEach(u =>
 83             {
 84                 db.Set<T>().Attach(u);//先附加到 EF容器
 85                 db.Set<T>().Remove(u);//标识为 删除 状态
 86             });
 87         } 
 88         #endregion
 89 
 90         #region 2.1.1根据条件删除并保存 + int DelByAndSave(Expression<Func<T, bool>> delWhere)
 91         /// <summary>
 92         /// 根据条件删除并保存
 93         /// </summary>
 94         /// <param name="delWhere">条件</param>
 95         /// <returns>受影响的行数</returns>
 96         protected int DelByAndSave(Expression<Func<T, bool>> delWhere)
 97         {
 98             DelBy(delWhere);
 99             return db.SaveChanges();
100         } 
101         #endregion
102 
103         #region 3.0修改实体 + void Modify(T model, params string[] proNames)
104         /// <summary>
105         /// 修改,如:
106         /// T u = new T() { uId = 1, uLoginName = "asdfasdf" };
107         /// this.Modify(u, "uLoginName");
108         /// </summary>
109         /// <param name="model">要修改的实体对象</param>
110         /// <param name="proNames">要修改的 属性 名称</param>
111         protected void Modify(T model, params string[] proNames)
112         {
113             //4.1将 对象 添加到 EF中
114             DbEntityEntry entry = db.Entry<T>(model);
115             //4.2先设置 对象的包装 状态为 Unchanged
116             entry.State = (System.Data.Entity.EntityState)System.Data.EntityState.Unchanged;
117             //4.3循环 被修改的属性名 数组
118             foreach (string proName in proNames)
119             {
120                 //4.4将每个 被修改的属性的状态 设置为已修改状态;后面生成update语句时,就只为已修改的属性 更新
121                 entry.Property(proName).IsModified = true;
122             }
123         } 
124         #endregion
125 
126         #region 3.0.1修改和保存 + int ModifyAndSave(T model, params string[] proNames)
127         /// <summary>
128         /// 修改和保存,如:
129         /// T u = new T() { uId = 1, uLoginName = "asdfasdf" };
130         /// this.Modify(u, "uLoginName");
131         /// </summary>
132         /// <param name="model">要修改的实体对象</param>
133         /// <param name="proNames">要修改的 属性 名称</param>
134         /// <returns>受影响的行数</returns>
135         protected int ModifyAndSave(T model, params string[] proNames)
136         {
137             Modify(model, proNames);
138             return db.SaveChanges();
139         } 
140         #endregion
141 
142         #region 3.1批量修改 + void ModifyBy(T model, Expression<Func<T, bool>> whereLambda, params string[] modifiedProNames)
143         /// <summary>
144         /// 批量修改
145         /// </summary>
146         /// <param name="model">要修改的实体对象</param>
147         /// <param name="whereLambda">查询条件</param>
148         /// <param name="proNames">要修改的 属性 名称</param>
149         protected void ModifyBy(T model, Expression<Func<T, bool>> whereLambda, params string[] modifiedProNames)
150         {
151             //4.1查询要修改的数据
152             List<T> listModifing = db.Set<T>().Where(whereLambda).ToList();
153 
154             //获取 实体类 类型对象
155             Type t = typeof(T); // model.GetType();
156             //获取 实体类 所有的 公有属性
157             List<PropertyInfo> proInfos = t.GetProperties(BindingFlags.Instance | BindingFlags.Public).ToList();
158             //创建 实体属性 字典集合
159             Dictionary<string, PropertyInfo> dictPros = new Dictionary<string, PropertyInfo>();
160             //将 实体属性 中要修改的属性名 添加到 字典集合中 键:属性名  值:属性对象
161             proInfos.ForEach(p =>
162             {
163                 if (modifiedProNames.Contains(p.Name))
164                 {
165                     dictPros.Add(p.Name, p);
166                 }
167             });
168 
169             //4.3循环 要修改的属性名
170             foreach (string proName in modifiedProNames)
171             {
172                 //判断 要修改的属性名是否在 实体类的属性集合中存在
173                 if (dictPros.ContainsKey(proName))
174                 {
175                     //如果存在,则取出要修改的 属性对象
176                     PropertyInfo proInfo = dictPros[proName];
177                     //取出 要修改的值
178                     object newValue = proInfo.GetValue(model, null); //object newValue = model.uName;
179 
180                     //4.4批量设置 要修改 对象的 属性
181                     foreach (T usrO in listModifing)
182                     {
183                         //为 要修改的对象 的 要修改的属性 设置新的值
184                         proInfo.SetValue(usrO, newValue, null); //usrO.uName = newValue;
185                     }
186                 }
187             }
188         } 
189         #endregion
190 
191         #region 3.1.1批量修改并保存 + int ModifyByAndSave(T model, Expression<Func<T, bool>> whereLambda, params string[] modifiedProNames)
192         /// <summary>
193         /// 批量修改并保存
194         /// </summary>
195         /// <param name="model">要修改的实体对象</param>
196         /// <param name="whereLambda">查询条件</param>
197         /// <param name="proNames">要修改的 属性 名称</param>
198         /// <returns>受影响的行数</returns>
199         protected int ModifyByAndSave(T model, Expression<Func<T, bool>> whereLambda, params string[] modifiedProNames)
200         {
201             ModifyBy(model, whereLambda, modifiedProNames);
202             return db.SaveChanges();
203         } 
204         #endregion
205 
206         #region 4.0根据条件获取记录条数 + int GetCountBy(Expression<Func<T, bool>> whereLambda)
207         /// <summary>
208         /// 根据条件获取记录条数
209         /// </summary>
210         /// <returns>总记录条数</returns>
211         protected int GetCountBy(Expression<Func<T, bool>> whereLambda)
212         {
213             return db.Set<T>().Where(whereLambda).Count();
214         } 
215         #endregion
216 
217         #region 5.0获取所有记录 + List<T> GetAllList()
218         /// <summary>
219         /// 获取所有记录
220         /// </summary>
221         /// <returns>返回的集合</returns>
222         protected List<T> GetAllList()
223         {
224             return db.Set<T>().ToList();
225         } 
226         #endregion
227 
228         #region 5.1根据条件查询 + List<T> GetListBy(Expression<Func<T, bool>> whereLambda)
229         /// <summary>
230         /// 根据条件查询
231         /// </summary>
232         /// <param name="whereLambda">条件Lambda表达式</param>
233         /// <returns>返回的集合</returns>
234         protected List<T> GetListBy(Expression<Func<T, bool>> whereLambda)
235         {
236             return db.Set<T>().Where(whereLambda).ToList();
237         } 
238         #endregion
239 
240         #region 5.2根据条件 排序 和查询 + List<T> GetListBy<TKey>(Expression<Func<T, bool>> whereLambda, Expression<Func<T, TKey>> orderLambda, bool IsDes = false)
241         /// <summary>
242         /// 根据条件 排序 和查询
243         /// </summary>
244         /// <typeparam name="TKey">排序字段类型</typeparam>
245         /// <param name="whereLambda">查询条件 lambda表达式</param>
246         /// <param name="orderLambda">排序条件 lambda表达式</param>
247         /// // <param name="IsDes">是否逆序</param>
248         /// <returns>返回的集合</returns>
249         protected List<T> GetListBy<TKey>(Expression<Func<T, bool>> whereLambda, Expression<Func<T, TKey>> orderLambda, bool IsDes = false)
250         {
251             if(IsDes)
252                 return db.Set<T>().Where(whereLambda).OrderByDescending(orderLambda).ToList();
253             return db.Set<T>().Where(whereLambda).OrderBy(orderLambda).ToList();
254         } 
255         #endregion
256 
257         #region 5.3分页查询 + List<T> GetPagedList<TKey>(int pageIndex, int pageSize, Expression<Func<T, bool>> whereLambda, Expression<Func<T, TKey>> orderBy, bool IsDes = false)
258         /// <summary>
259         /// 分页查询
260         /// </summary>
261         /// <param name="pageIndex">页码</param>
262         /// <param name="pageSize">页容量</param>
263         /// <param name="whereLambda">条件 lambda表达式</param>
264         /// <param name="orderBy">排序 lambda表达式</param>
265         /// <param name="IsDes">是否逆序</param>
266         /// <returns>返回的集合</returns>
267         protected List<T> GetPagedList<TKey>(int pageIndex, int pageSize, Expression<Func<T, bool>> whereLambda, Expression<Func<T, TKey>> orderBy, bool IsDes = false)
268         {
269             if (IsDes)
270                 return db.Set<T>().Where(whereLambda).OrderByDescending(orderBy).Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
271             return db.Set<T>().Where(whereLambda).OrderBy(orderBy).Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
272         } 
273         #endregion
274 
275     }
276 }
View Code

   可以看出,在上面的代码中,我提供了增删改查的大部分方法,对于写入性的操作,我提供了是否立刻SaveChange的选择,如果立刻save,可以调用类似于AddAndSave()这样的方法,如果想多次调用后统一保存以提高性能,可以调用Add()这类方法,在所有操作结束后,再调用saveChange的方法。这个帮助类中存在一个DbContext类型的属性,它用来存放ef上下文,在teacher的实现类中,提供了它的构造方法,将dbcontext传入。帮助类中几乎所有的操作都依赖于这个DbContext。

  上面teacher的接口和实现都是有partial修饰,是一个部分类(接口),这样做的目的是为了便于管理,例如日后需要添加一个学生类时可以这样

 1     public partial class Student : BaseCore<Entity.Student>, ICore.IStudent
 2     {
 3         public Student(DbContext dbContext)
 4         {
 5             db = dbContext;
 6         }
 7     }
 8 
 9     public partial class Teacher : BaseCore<Entity.Teacher>, ICore.ITeacher
10     {
11         public Teacher(DbContext dbContext)
12         {
13             db = dbContext;
14         }
15     }

  这些代码是重复的,可将它们写在同一个cs中,如果有需要可以用T4模板自动生成,但事实上并不是每张表都需要生成对应的实体,所以我选择手动来添加它们。教师和学生具体的登陆的逻辑可能不同,将它们放在另一个partial类中会更加合理。

  4.创建教师的部分接口和部分类

  接口如下 

 1     public partial interface ITeacher
 2     {
 3         #region 教师登录 + ReturnVal Login(string tid, string pwd); 
 4         /// <summary>
 5         /// 教师登录
 6         /// </summary>
 7         /// <param name="tid">教师id</param>
 8         /// <param name="pwd">密码</param>
 9         /// <returns>约定返回类型</returns>
10         ReturnVal Login(string tid, string pwd); 
11         #endregion
12     }

  实现如下

 1 public partial class Teacher
 2     {
 3 
 4         #region 教师登录操作 + WebModel.ReturnVal Login(string tid, string pwd)
 5         /// <summary>
 6         /// 教师登录操作
 7         /// </summary>
 8         /// <param name="tid">教师登录名</param>
 9         /// <param name="pwd">密码</param>
10         /// <returns>约定返回类</returns>
11         public WebModel.ReturnVal Login(string tid, string pwd)
12         {
13             int iTID = Convert.ToInt32(tid);
14             Entity.Teacher teacher = this.GetListBy(t => (t.TID == iTID) && (t.IsDel == false)).ToList().FirstOrDefault();
15             if (teacher == null)
16             {
17                 return new ReturnVal(ReturnStatu.Failure, "用户不存在");
18             }
19             else
20             {
21                 if (EDUA_Util.EncrypHelper.MD5(pwd) == teacher.Password)
22                 {
23                     return new ReturnVal(ReturnStatu.Success, "登陆成功", WebModel.Teacher.ToWebModel(teacher));
24                 }
25                 else
26                 {
27                     return new ReturnVal(ReturnStatu.Failure, "密码错误");
28                 }
29             }
30         }  
31         #endregion
32     }

  很简单,首先判断用户是否存在,接下去判断密码是否正确。

  第13行,这里我使用了我的basecore里的方法,如果不想用也很简单。

  返回值类型为ReturnVal,这是我自己的类,原因是不能简单地用一个bool值来传递登陆成功与否,如果登陆成功了需要将对象返回保存在cookie,session中,以保证状态的维持。ReturnVal也会被用在其他core与web传递数据的过程中。ReturnVal类如下

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 
 7 namespace WebModel
 8 {
 9     /// <summary>
10     /// 返回值约定
11     /// 从core 到 web 返回内容的封装
12     /// </summary>
13     public class ReturnVal
14     {
15         #region 属性
16         /// <summary>
17         /// 返回的状态
18         /// </summary>
19         public ReturnStatu Statu { get; set; }
20         /// <summary>
21         /// 返回的消息
22         /// </summary>
23         public string Message { get; set; }
24         /// <summary>
25         /// 返回的数据
26         /// </summary>
27         public object Data { get; set; } 
28         #endregion
29 
30         #region 构造方法
31         /// <summary>
32         /// 构造方法
33         /// </summary>
34         /// <param name="statu">状态</param>
35         public ReturnVal(ReturnStatu statu)
36         {
37             this.Statu = statu;
38         }
39         /// <summary>
40         /// 构造方法
41         /// </summary>
42         /// <param name="statu">状态</param>
43         /// <param name="message">消息</param>
44         public ReturnVal(ReturnStatu statu, string message)
45             : this(statu)
46         {
47             this.Message = message;
48         }
49         /// <summary>
50         /// 构造方法
51         /// </summary>
52         /// <param name="statu">状态</param>
53         /// <param name="message">消息</param>
54         /// <param name="data">数据</param>
55         public ReturnVal(ReturnStatu statu, string message, object data)
56             : this(statu, message)
57         {
58             this.Data = data;
59         } 
60         #endregion
61     }
62 
63 
64     /// <summary>
65     /// 状态枚举
66     /// </summary>
67     public enum ReturnStatu
68     {
69         /// <summary>
70         /// 成功
71         /// </summary>
72         Success,
73         /// <summary>
74         /// 失败
75         /// </summary>
76         Failure,
77         /// <summary>
78         /// 错误
79         /// </summary>
80         Err
81     }
82 }
View Code

  ReturnVal在WebModel程序集下,同样在该程序集下的还有上面用到的WebModel.Teacher。按照常理,EF和View之间存在着Core层,故View不可直接依赖于EF,所以它们之间需要一层WebModel来传递。WebModel的存在类似于DTO,它可以剥离那些上层中用不到的字段,以下是我的WebModel中的Teacher类,为了方便,里面提供了将实体类转换为WebModel类的静态方法,也是上面所用到的。

 1 namespace WebModel
 2 {
 3     public class Teacher
 4     {
 5         #region 属性
 6         /// <summary>
 7         /// guid
 8         /// </summary>
 9         public System.Guid ID { get; set; }
10         /// <summary>
11         /// 学号
12         /// </summary>
13         public int TID { get; set; }
14         /// <summary>
15         /// 姓名
16         /// </summary>
17         public string Name { get; set; }
18         /// <summary>
19         /// 权限列表
20         /// </summary>
21         public List<Authority> AuthorityList { get; set; }
22         #endregion
23 
24         #region 转化为视图类的teacher + static Teacher ToWebModel(Entity.Teacher et)
25         /// <summary>
26         /// 转化为视图类的teacher
27         /// </summary>
28         /// <param name="es">实体类</param>
29         /// <returns>视图类</returns>
30         public static Teacher ToWebModel(Entity.Teacher et)
31         {
32             List<Entity.AuthorityToPower> Listatp = et.Power.AuthorityToPowers.ToList();
33             List<Authority> ListAut = new List<Authority>();
34             Listatp.ForEach(au => {
35                 ListAut.Add(Authority.ToWebModel(au.Authority));
36             });
37             return new Teacher()
38             {
39                 Name = et.Name,
40                 TID = et.TID,
41                 ID = et.ID,
42                 AuthorityList = ListAut
43             };
44         }
45         #endregion
46     }

 

  上面还用到了类似于EDUA_Util.EncrypHelper.MD5这类MD5加密算法,我将它们放到工具类中。它们在不同的项目中可以完全复用,类似这样的方法还有加密解密cookie,生随机数(封装过),生成验证码,导入导出Excel等等。将它们统统放到Util中还可以将很多第三方的引用添加到这个程序集中,保证上层程序集的整洁,它们是整个项目的Infrastructure(基础设施)。

  5.在ICoreSession,CoreSession中分别创建Teacher类

  上一篇中提到过,在web中的控制器中可以调用到iCoreSession,所以想要在web层调用core中teacher的login方法,就需要在ICoreSession中存在teacher对象。故接口中的代码如下

1     public interface ICoreSession
2     {
3         ITeacher ITeacher { get; }
4     }

  CoreSession中的代码如下,这样保证了在一次请求中teacher的单例,通过构造方法将db对象传入到teacher类中。

 1     public class CoreSession:EDUA_ICore.ICoreSession
 2     {
 3 
 4         #region 属性
 5         private DbContext db { get; set; }
 6         #endregion
 7 
 8         #region 构造方法
 9         public CoreSession()
10         {
11             db = new Entity.EDUAEntities();
12         }  
13         #endregion
14 
15         #region 保存 + int SaveChanges()
16         /// <summary>
17         /// 保存修改
18         /// </summary>
19         /// <returns>受影响的行数</returns>
20         public int SaveChanges()
21         {
22             return db.SaveChanges();
23         } 
24         #endregion
25 
26         ITeacher iTeacher;
27         public ITeacher ITeacher
28         {
29             get
30             {
31                 if (iTeacher == null)
32                 {
33                     iTeacher = new Teacher(db);
34                 }
35                 return iTeacher;
36             }
37         }
38     }

   6.创建Login页面

  控制器

#region 1.0 登陆界面
[HttpGet]
public ActionResult Login()
{return View();
} 
#endregion

  页面为强类型页面,使用了微软的数据验证,所以需要导入微软所提供的js @Scripts.Render("~/Scripts/mvcAjax")  使用App_Statr中的BundleConfig进行了绑定。

  

  视图中的类型类为WebModel.LoginUser,它同样放在webmodel程序集下的,我单独创建了ViewModel文件夹用来存放这些类,其实将它们放在web层也是合理的。对应的代码以及页面如下。

 1 using System;
 2 using System.Collections.Generic;
 3 using System.ComponentModel.DataAnnotations;
 4 using System.Linq;
 5 using System.Web;
 6 
 7 namespace WebModel
 8 {
 9 
10     /// <summary>
11     /// 登陆视图 模型
12     /// </summary>
13     public class LoginUser
14     {
15         /// <summary>
16         /// 用户名
17         /// </summary>
18         [Required(ErrorMessage = "用户名不能为空")]
19         public int LoginName { get; set; }
20         /// <summary>
21         /// 密码
22         /// </summary>
23         [Required(ErrorMessage = "密码不能为空")]
24         public string Pwd { get; set; }
25         /// <summary>
26         /// 验证码
27         /// </summary>
28         [Required(ErrorMessage = "请输入验证码")]
29         public string VCode { get; set; }
30         /// <summary>
31         /// 身份 1 为教师 0为学生
32         /// </summary>
33         [Required(ErrorMessage = "请输选择身份")]
34         public int Degree { get; set; }
35         /// <summary>
36         /// 是否记住
37         /// </summary>
38         public bool IsAlways { get; set; }
39     }
40 
41 }
@model WebModel.LoginUser
@{Layout = null;
}
<html>
<head><title>登陆</title><meta charset="utf-8" /><meta name="viewport" content="width=device-width" />@Scripts.Render("~/Scripts/mvcAjax")<style type="text/css">.p_main {margin-left: auto;margin-right: auto;width: 400px;margin-top: 45px;}.SingleLine {padding-top: 10px;}.alert {color: red;}#divMsg {display: none;}</style><script type="text/javascript">$(function () {$("#img_Vcode").click(function () {newVcode();});});//请求一个新的验证码function newVcode() {$("#img_Vcode").attr("src", "/helper/VCode/" + Math.round(Math.random() * 100000));}function Success(jsDate) {if (jsDate.Statu == "err") {$("#td_msg").html(jsDate.Msg);newVcode();}else if (jsDate.Statu == "ok") {window.location.href = jsDate.BackUrl;}}</script>
</head>
<body><div class="p_main"><div class="div_main">@using (Ajax.BeginForm(new AjaxOptions(){HttpMethod = "post",OnSuccess = "Success",LoadingElementId = "divMsg"})){<div class="SingleLine"><div style="float:left;width:80px;font-size:15px">登陆身份:</div><div><input type="radio" name="Degree" id="Degree0" value="0"><label for="Degree0">学生</label><input type="radio" name="Degree" id="Degree1" value="1" checked="checked"><label for="Degree1">教师</label></div></div><div style="clear:both"></div><div class="SingleLine"><div style="float:left;width:80px;font-size:15px">用户名:</div><div style="float:left">@Html.TextBoxFor(u => u.LoginName)</div><div style="float:left" class="alert">@Html.ValidationMessageFor(u => u.LoginName)</div></div><div style="clear:both"></div><div class="SingleLine"><div style="float:left;width:80px;font-size:15px">密码:</div><div style="float:left">@Html.PasswordFor(u => u.Pwd)</div><div style="float:left" class="alert">@Html.ValidationMessageFor(u => u.Pwd)</div></div><div style="clear:both"></div><div class="SingleLine"><div style="float:left;width:80px;font-size:15px">验证码:</div><div style="float:left">@Html.TextBoxFor(u => u.VCode)</div><div style="float:left"><img id="img_Vcode" src="/helper/VCode"></div><div style="float:left" class="alert">@Html.ValidationMessageFor(u => u.VCode)</div></div><div style="clear:both"></div><div class="SingleLine"><div style="float:left;padding-right:100px;">@Html.CheckBoxFor(u => u.IsAlways) <span>两小时内免登陆</span></div><div style="float:left"><input type="submit" value="登陆" /><div id="divMsg">登陆中~~~</div></div> <div id="td_msg" class="alert"></div>                    </div>}</div></div>
</body>
</html>

 

  实际的项目中,在登录时选择登陆身份,有教师或学生可选,它们公用一个登陆入口,在控制器中根据页面传回来的信息选择调用teacher的login方法或者是student的login方法。前台我用了EasyUI。

  7.控制器中的登陆处理

  在控制器中,通过调用ICoreSession中teacher的login方法来进行。

    a.判断验证码是否正确,如果错误直接返回验证码错误的json给页面

    b.判断用户所选择的登陆身份(学生的没有写)

    c.调用core中teacher的登陆方法,传入用户名和密码

    d.根据返回的ReturnVal判断登陆的状态,如果成功写入Session

    e.判断是否需要写入cookie,如有需要,则写入

    f.跳转到对应的页面

 1         #region 1.1 登录操作
 2         [HttpPost]
 3         public ActionResult Login(WebModel.LoginUser userInfo)
 4         {
 5             //判断验证码 为方便测试用0可跳过
 6             OperateHelper.BussinessHelper h = new OperateHelper.BussinessHelper(iCoreSession);
 7             if (((h.Vcode).ToLower() != (userInfo.VCode).ToLower()) && (userInfo.VCode != "0"))
 8             {
 9                 return WebModel.JsonModel.AjaxMsgModel.RedirectAjax("err", "验证码错误", "", "");
10             }
11             else
12             {
13                 //学生
14                 if (userInfo.Degree == 0)
15                 {
16                    //里面是对应学生的登陆操作
17                 }
18                 //教师
19                 else if (userInfo.Degree == 1)
20                 {
21                     ReturnVal rv = iCoreSession.ITeacher.Login(userInfo.LoginName.ToString(), userInfo.Pwd);
22                     if (rv.Statu == ReturnStatu.Success)
23                     {
24                         h.TeacherSession = rv.Data as WebModel.Teacher;
25                         //保存cookie
26                         if (userInfo.IsAlways)
27                         {
28                             h.TeacherTIDCookie = (rv.Data as WebModel.Teacher).ID.ToString();
29                         }
30                         else
31                         {
32                             h.TeacherTIDCookie = "";
33                         }
34                         return WebModel.JsonModel.AjaxMsgModel.RedirectAjax("ok", rv.Message, "", "/teacher/teacherhome/index");
35                     }
36                     else
37                     {
38                         return WebModel.JsonModel.AjaxMsgModel.RedirectAjax("err", rv.Message, "", "");
39                     }
40                 }
41                 else
42                 {
43                     return null;
44                 }
45             } 
46         #endregion

写在最后

  至此,登陆功能算是完成了,但没有对用户访问权限的过滤,登陆操作就没有任何意义。所以在下一篇中,我将会通过AuthorizeAttribute来实现用户权限的过滤。这样,一个最基本的架构才算形成。

 

转载请注明出处 huhuhuo的博客园

地址:http://www.cnblogs.com/linhan/p/4298971.html

转载于:https://www.cnblogs.com/linhan/p/4298971.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/259348.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python实现atm机的功能

主要还是参考网上内容&#xff0c;自己做了修改。虽然代码有小bug&#xff0c;但是不影响学习和测试。功能&#xff1a;1.额度&#xff1a;80002.可以提现&#xff0c;手续费5%3.每月最后一天出账单&#xff0c;写入文件4.记录每月日常消费流水5.提供还款接口1.atm的脚本[rootp…

使用Vitamio打造自己的Android万能播放器(7)——在线播放(下载视频)

前言 本章将实现非常实用的功能——下载在线视频。涉及到多线程、线程更新UI等技术&#xff0c;还需思考产品的设计&#xff0c;如何将新加的功能更好的融入到现有的产品中&#xff0c;并不是简单的加一个界面就行了&#xff0c;欢迎大家交流产品设计和技术细节实现&#xff01…

HTML声明文档类型后样式出错,doctype如何声明

如何doctype声明&#xff0c;新增的结构元素和功能元素HTML5已形成了最终的标准&#xff0c;概括来讲&#xff0c;它主要是关于图像&#xff0c;位置&#xff0c;存储&#xff0c;多任务等功能的增加。 新增的元素有绘画 canvas &#xff0c;用于媒介回放的 video 和 audio 元素…

Error-Project facet Java version 1.8 is not supported

最近导入最新的Strtus2.5.10.1 Demo时出现了这个错误 解决方案如下&#xff1a; 选中工程——右键——Properties 然后依次展开找到如图所示内容&#xff0c;将1.8改成1.7即可。 原因&#xff1a;工程默认配置是1.8&#xff0c;而本地环境JDK版本为1.7&#xff0c;两则不匹配造…

6.2

转载于:https://www.cnblogs.com/tutuaixiaomei/p/3354356.html

Tomcat全攻略

内容&#xff1a; 一&#xff1a;简单介绍二&#xff1a;安装及配置三&#xff1a;应用四&#xff1a;综述參考资料关于作者宗 锋西北大学计算机系硕士2001 年 12 月 随着java的流行&#xff0c;其在web上的应用也越来越广&#xff0c;tomcat作为一个开源的servlet容器&#xf…

Android Material风格的应用(三)--DrawerLayout

添加抽屉导航 Android Material风格的应用(一)--AppBar TabLayoutAndroid Material风格的应用(二)--RecyclerViewAndroid Material风格的应用(三)--DrawerLayoutAndroid Material风格的应用(四)--FloatActionButtonAndroid Material风格的应用(五)--CollapsingToolbar DrawerLa…

html5 数据缓存,HTML5: 本地缓存

HTML5 提供了两种在客户端存储数据的新对象&#xff1a;localStorage&#xff1a;没有时间限制的数据存储&#xff0c;在同一个浏览器中&#xff0c;只要没被手动清理&#xff0c;第二天、第二周或下一年之后&#xff0c;数据依然可用。sessionStorage&#xff1a;针对一个 ses…

上传Text文档并转换为PDF

今天在ASP.NET MVC环境中学习一些PDF相关的知识&#xff0c;想法是上传文件成功时&#xff0c;并把文件转换为PDF文档。 打开你的专案&#xff0c;运行NuGet包管理器&#xff0c;下载一个叫iTextSharp的东东&#xff1a;点击Install&#xff0c;按钮提示确认安装&#xff0c;成…

递归函数(九):最小不动点定理

递归函数&#xff08;一&#xff09;&#xff1a;开篇递归函数&#xff08;二&#xff09;&#xff1a;编写递归函数的思路和技巧递归函数&#xff08;三&#xff09;&#xff1a;归纳原理递归函数&#xff08;四&#xff09;&#xff1a;全函数与计算的可终止性递归函数&#…

html中单选框颜色怎么改,如何更改单选按钮的颜色?

侃侃无极一种快速的解决方法是使用来覆盖单选按钮的输入样式:after&#xff0c;但是创建自己的自定义工具箱可能是更好的做法。 input[typeradio]:after { width: 15px; height: 15px; border-radius: 15px; top: -2px; left: -1px; …

如何先执行input (checkbox,radio)再执行函数

2019独角兽企业重金招聘Python工程师标准>>> 遇到一个问题&#xff0c;当input type"checkbox"点击时&#xff0c;没有立即执行勾选或去勾&#xff0c;而是先执行函数&#xff0c;如下代码 $(".sidebar_cart .cart_list ul").on("click&qu…

Linux服务器上监控网络带宽的18个常用命令

本文介绍了一些可以用来监控网络使用情况的Linux命令行工具。这些工具可以监控通过网络接口传输的数据&#xff0c;并测量目前哪些数据所传输的速度。入站流量和出站流量分开来显示。 作者&#xff1a;布加迪编译来源&#xff1a;51CTO.com|2014-04-11 10:10移动端收藏分享【51…

[转]Windows Phone 7程序设计”完全版电子书可以免费下载了

本文转自&#xff1a;http://www.cnblogs.com/salam/archive/2010/10/29/1864246.html 现在学习Windows Phone 7开发资料十分有限&#xff0c;除了MSDN的官方开发文档外和一些博客外&#xff0c;几无其他的学习渠道。幸运地是美国的资深程序员兼作家Charles Petzold为大家免费放…

linux-redhat替换yum网络源为centos网络源

2019独角兽企业重金招聘Python工程师标准>>> 1.为什么要替换 redhat系统使用yum命令安装软件时会出现This system is not registered with RHN. RHN support will be disabled. 原因是redhat的yum安装软件需要注册&#xff0c;是收费的。而centos的yum源是免费的。这…

计算机如何打开无线网络适配器,win7系统下网络适配器打不开怎么解决

通常情况下我们的电脑中都会有一个网络适配器&#xff0c;这是计算机联网的设备&#xff0c;不过最近有深度技术win7旗舰版系统用户却遇到了网络适配器打不开的情况&#xff0c;该怎么办呢&#xff0c;接下来系统城小编就给大家分享一下win7系统下网络适配器打不开的具体解决方…

【Intellij Idea】设置JDK

1&#xff0c;File-->Project Structure 说明&#xff1a;可以设置整个工程的JDK&#xff0c;也设置每个modules的JDK,但是一般整个工程的JDK. 2&#xff0c;或者通过快捷键&#xff1a;ctrlaltshifts 转载于:https://www.cnblogs.com/august-shi/p/6655469.html

绘图用计算机配置要求,绘图笔记本电脑基本配置要求 绘图笔记本推荐

现在很多工业图、工程图都需要用电脑来话&#xff0c;比如CAD、PS、三维画图这些软件对电脑的配置要求还是比较高的&#xff0c;还有一些对色彩要求高的动画软件&#xff0c;那就更加需要配置了&#xff0c;下面小编就来简单说说绘图笔记本电脑最基本的配置要求以及绘图笔记本推…

计算机无法正常更新,无法完成更新正在撤销更改请不要关闭你的计算机如何修复...

我们电脑开机的时候可能会遇到各种问题&#xff0c;比如就有用户发现电脑开机的时候&#xff0c;一直提示无法完成更新正在撤销更改请不要关闭你的计算机&#xff0c;等待了很长时间也进不去系统&#xff0c;遇到这样的问题该怎么办呢&#xff1f;不用担心小编给大家支招&#…

自媒体和计算机相关吗,做自媒体,台式电脑跟笔记本电脑用哪个好呢?

四阿哥fly回答数&#xff1a;143 | 被采纳数&#xff1a;162019-06-29 12:16:21作为去年折腾了一年自媒体&#xff0c;各种情况遇到过&#xff0c;分享下台式电脑和笔记本到底哪个好&#xff1f;好在哪里&#xff1f;如果真的要选择&#xff0c;个人还是推荐用台式比较好。工…