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.pswp.cn/news/259348.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/259348.shtml
英文地址,請注明出處:http://en.pswp.cn/news/259348.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

文字轉語音+html5,JS實現文字轉語音并播放

html&#xff1a;div>audio>div>js&#xff1a;function doTTS() {var ttsDiv document.getElementById(bdtts_div_id);var ttsAudio document.getElementById(tts_autio_id);var ttsText document.getElementById(ttsText).value;// 文字轉語音ttsDiv.removeChild…

字符串的全排列和組合算法

全排列在筆試面試中很熱門&#xff0c;因為它難度適中&#xff0c;既可以考察遞歸實現&#xff0c;又能進一步考察非遞歸的實現&#xff0c;便于區分出考生的水平。所以在百度和迅雷的校園招聘以及程序員和軟件設計師的考試中都考到了&#xff0c;因此本文對全排列作下總結幫助…

設計模式基于C#的工程化實現及擴展

設計模式基于C#的工程化實現及擴展 轉載于:https://www.cnblogs.com/gzmg/p/3344833.html

Python實現atm機的功能

主要還是參考網上內容&#xff0c;自己做了修改。雖然代碼有小bug&#xff0c;但是不影響學習和測試。功能&#xff1a;1.額度&#xff1a;80002.可以提現&#xff0c;手續費5%3.每月最后一天出賬單&#xff0c;寫入文件4.記錄每月日常消費流水5.提供還款接口1.atm的腳本[rootp…

Direct ByteBuffer學習

ByteBuffer有兩種一種是heap ByteBuffer,該類對象分配在JVM的堆內存里面&#xff0c;直接由Java虛擬機負責垃圾回收&#xff0c;一種是direct ByteBuffer是通過jni在虛擬機外內存中分配的。通過jmap無法查看該快內存的使用情況。只能通過top來看它的內存使用情況。 JVM堆內存大…

魔獸爭霸Ⅲ運行時不能初始化directX的錯誤解決

運行魔獸爭霸3不能初始化DirectX錯誤這樣解決&#xff1a; 1&#xff1a;在運行中輸入(winr)&#xff1a;dxdiag&#xff0c;查看顯示欄&#xff0c;確定電腦已安裝好directx 8.1以上&#xff0c;且下面的三個加速都已開啟。 2&#xff1a;如果沒有安裝directx就下載安裝一個&a…

Android7.0占用空間,Android7.0 開發者注意事項

1、當設備處于充電狀態且屏幕已關閉一定時間后&#xff0c;設備會進入低電耗模式并應用第一部分限制&#xff1a;關閉應用網絡訪問、推遲作業和同步。如果進入低電耗模式后設備處于靜止狀態達到一定時間&#xff0c;系統則會對 PowerManager.WakeLock、AlarmManager 鬧鈴、GPS …

Android探索之旅 | 面向對象和Java基礎

-- 作者 謝恩銘 轉載請注明出處 上一篇 Android探索之旅 | Android簡介 中說到&#xff1a; "Android的默認開發語言是Java&#xff0c;入門簡單。而且&#xff0c;你的Java水平不需要多好就可以上手開發Android App了。" 不少朋友說看到后很是心安。 不過小編也不想…

DataGirdView 編輯項時的驗證

dgvConfig.DataSource CreateTable();dgvConfig.Columns["編號"].ReadOnly true; //只讀dgvConfig.AllowUserToAddRows false; //不允許添加新行dgvConfig.EditingControlShowing new DataGridViewEditingControlShowingEventHandler(dgvConfig_EditingControlS…

使用Vitamio打造自己的Android萬能播放器(7)——在線播放(下載視頻)

前言 本章將實現非常實用的功能——下載在線視頻。涉及到多線程、線程更新UI等技術&#xff0c;還需思考產品的設計&#xff0c;如何將新加的功能更好的融入到現有的產品中&#xff0c;并不是簡單的加一個界面就行了&#xff0c;歡迎大家交流產品設計和技術細節實現&#xff01…

生成0到1之間隨機數的C代碼

#include <stdlib.h>#include <stdio.h>#include <time.h>int main(){srand((unsigned)time(NULL));int i;double r;for(i0;i<50;i){r(float)rand()/RAND_MAX; printf("%f\n",r);}return 0;}

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…

《G檔案》中關于游戲程序設計的文章

剛拿到前導的《G檔案》&#xff0c;發現了主程劉剛的文章&#xff0c;是目前我所見 到的關于游戲編程的最好的一篇&#xff0c;與大家共享。轉載&#xff1a;http://www.360doc.cn/article/2778_53476.html PC游戲編程 目錄 1 游戲程序理論 1.1 技術基礎 1.2 游戲底層 1.3 編…

shell筆記

system 磁盤 磁盤空間使用情況df查看文件或目錄大小du掛載usb sudo fdisk -l # Find what the drive is called e.g. /dev/sdb1 sudo mkdir /media/usb sudo mount /dev/sdb1 /media/usb sudo umount /media/usb# umount sudo umount /media/usb utils awk 打印文件的第一列(域…

html5編輯文檔,HTML5帶各種趣味動畫的文本編輯器

CSS語言&#xff1a;CSSSCSS確定body {background-color: #eee;}html,body {margin: 0px;height: 100%;overflow: hidden;}.toolbar {width: 100%;background: #fff;padding: 4px 10px;}.characters {display: inline-block;margin-right: 20px;vertical-align: top;}.characte…

社會轉型

轉載&#xff0c;版權由作者所有。 常常在政府工作報告中看到關于“社會轉型期”的說法&#xff0c;不是太明白&#xff0c;在百度里找了找&#xff0c;果然有不少&#xff0c;摘抄下來&#xff0c;做為學習資料用&#xff1a; 一是指體制轉型&#xff0c;即從計劃經濟體制向市…

在WPF中處理Windows消息

在Winform中 處理Windows消息通過重寫WndProc方法 在WPF中 使用的是System.Windows. Sytem.Windows.Controls等名字空間&#xff0c;沒有WndProc函數 WPF中處理消息首先要獲取窗口句柄&#xff0c;創建HwndSource對象 通過HwndSource對象添加消息處理回調函數。 此外 WPF中沒有…