ASP net MVC5中怎么实现asp framesett 的效果

您的位置: >
> 阅读资讯:ASP.NET MVC5网站开发框架模型、数据、存储、业务逻辑(三)
ASP.NET MVC5网站开发框架模型、数据、存储、业务逻辑(三)
ASP.NET MVC5网站开发框架模型、数据、存储、业务逻辑(三)
前面项目的层次和调用关系都说明了,关系如下图
采用三层架构的时候,研究过BLL层的必要性,觉得业务逻辑完全可以在controller里实现,没有必要单独做一个项目,另一个分层多了会影响性能。后来我还是把业务逻辑独立出来,原因如下:
业务逻辑写进controller里代码看着比较混乱,时间久了代码容易理不清。
在controller里直接写逻辑重复代码会不较多,开发效率低。
分项目有利于代码重用,有时候可以直接拿到其他项目中稍作修改就可以用。
对于性能我觉得分层多了肯定会有影响,但是不会很大。现在硬件的更新速度远大于软件,对业务逻辑处理起来很轻松,多实例化几个类对性能影响不大。一般来说网站运行基本上是一个存数据库和取数据库的过程,业务逻辑还是比较少,只不过现在的网站使用的图片、动画更多,效果更加绚丽。我觉得网站的效率瓶颈主要出现在服务器的带宽、IO性能和存取数据库上。在代码方面能做的就是优化数据库的存龋对了一般项目来说,为了百分之几的运行效率远不如提高开发效率和更加容易的代码管理重要,能实现需求就好,运行效率是哪是大牛要做的事。
对IDAL、DAL、IBLL 、BLL这四个项目:
IDAL写一个Base接口,接口中固定几个数据库操作方法,其他接口都继承自这个接口;
DAL项目做个base类实现这个IDAL的base接口,其他类都继承自base类。
同样IBLL中也写一个Base接口,固定几个基本的操作方法,同样其他接口也继承自这个base接口
IBLL中也写一个base类来实现IBLL中的base接口,其他类继承自这个base类。
这里以对用户的操作来构建代码的基本模式:
这里写三个模型类。打开Ninesk.Models分别添加User、UserGroup、UserConfig三个模型类。
1、用户模型&User类
用户模型或者叫账户模型,为什么这么说看下面代码
ponentModel.DataA
namespace Ninesky.Models
/// &summary&
/// 用户模型
/// &remarks&
/// 创建:&br /&
/// 修改:
/// &/remarks&
/// &/summary&
public class User
public int UserID { }
/// &summary&
/// 用户名
/// &/summary&
[Required(ErrorMessage=&必填&)]
[StringLength(20,MinimumLength=4,ErrorMessage=&{1}到{0}个字符&)]
[Display(Name=&用户名&)]
public string UserName { }
/// &summary&
/// 用户组ID
/// &/summary&
[Required(ErrorMessage = &必填&)]
[Display(Name = &用户组ID&)]
public int GroupID { }
/// &summary&
/// 显示名
/// &/summary&
[Required(ErrorMessage = &必填&)]
[StringLength(20, MinimumLength = 2, ErrorMessage = &{1}到{0}个字符&)]
[Display(Name = &显示名&)]
public string DisplayName { }
/// &summary&
/// &/summary&
[Required(ErrorMessage = &必填&)]
[Display(Name = &密码&)]
[DataType(DataType.Password)]
public string Password { }
/// &summary&
/// &/summary&
[Required(ErrorMessage = &必填&)]
[Display(Name = &邮箱&)]
[DataType(DataType.EmailAddress)]
public string Email { }
/// &summary&
/// 用户状态&br /&
/// 0正常,1锁定,2未通过邮件验证,3未通过管理员
/// &/summary&
public int Status { }
/// &summary&
/// 注册时间
/// &/summary&
public DateTime RegistrationTime { }
/// &summary&
/// 上次登陆时间
/// &/summary&
public DateTime LoginTime { }
/// &summary&
/// 上次登陆IP
/// &/summary&
public DateTime LoginIP { }
public virtual UserGroup Group { }
这个模型类中只包含用户名、密码、用户组、显示名、邮箱等属性,纯粹是基本的账户信息,目的是让用户注册的时候尽可能的少填信息。其他信息如果需要可以再写新类与账户进行关联,用户需要的时候登录后再进行补填(如:资本资料、个人信息、联系方式等。这里先不考虑这些)。这里的显示名根据需要可以做昵称、真实姓名等来使用。
2、用户组模型&UserGroup类
这个类注意下GroupType,这个用来对用户组进行一下分类的,方便管理,其实没什么特别的意义。我的想法是普通类型就放普通的注册用户的组,如果大的网站允许用户升级的话,限定在这个类型的用户组内。特权组可以放一些vip之类的用户组,需要管理员给予,区别普通用户组,但又没有管理权。管理类型的用户组需要后台管理员给予,可以对文章、评论、咨询进行管理。
ponentModel.DataA
namespace Ninesky.Models
/// &summary&
/// 用户组
/// &remarks&
/// 创建:
/// 修改:
/// &/remarks&
/// &/summary&
public class UserGroup
public int GroupID { }
/// &summary&
/// &/summary&
[Required(ErrorMessage=&必填&)]
[StringLength(20, MinimumLength = 2, ErrorMessage = &{1}到{0}个字&)]
[Display(Name=&名称&)]
public string Name { }
/// &summary&
/// 用户组类型&br /&
/// 0普通类型(普通注册用户),1特权类型(像VIP之类的类型),3管理类型(管理权限的类型)
/// &/summary&
[Required(ErrorMessage = &必填&)]
[Display(Name = &用户组类型&)]
public int GroupType { }
/// &summary&
/// &/summary&
[Required(ErrorMessage = &必填&)]
[StringLength(50, ErrorMessage = &少于{0}个字&)]
[Display(Name = &说明&)]
public string Description { }
3、用户配置模型类&UserConfig类
这个类是一些用户配置信息(暂时只考虑了注册设置),在后台管理员处进行设置。
ponentModel.DataA
namespace Ninesky.Models
/// &summary&
/// 用户配置
/// &remarks&
/// &/remarks&
/// &/summary&
public class UserConfig
public int ConfigID { }
/// &summary&
/// 启用注册
/// &/summary&
[Display(Name = &启用注册&)]
[Required(ErrorMessage=&必填&)]
public bool Enabled { }
/// &summary&
/// 禁止使用的用户名&br /&
/// 用户名之间用&|&隔开
/// &/summary&
[Display(Name = &禁止使用的用户名&)]
public string ProhibitUserName { }
/// &summary&
/// 启用管理员验证
/// &/summary&
[Display(Name = &启用管理员验证&)]
[Required(ErrorMessage = &必填&)]
public bool EnableAdminVerify { }
/// &summary&
/// 启用邮件验证
/// &/summary&
[Display(Name = &启用邮件验证&)]
[Required(ErrorMessage = &必填&)]
public bool EnableEmailVerify { }
/// &summary&
/// 默认用户组Id
/// &/summary&
[Display(Name = &默认用户组Id&)]
[Required(ErrorMessage = &必填&)]
public int DefaultGroupId { }
二、数据存储层
数据存储层负责与数据库打交道,由于使用了接口产生了两个项目DAL和IDAL。IDAL是接口项目,DAL是接口的实现项目。
在与数据库的方便有一些共同的操作,像添加、修改、删除、查询等。不想在实际写代码的时候在用户类写一遍这些东西,用户组类再写一遍、以后文章、评论都再重复写这些代码。怎么办,弄个基类。以后其他类从基类继承就把这些公共方法继承过来了。
1、IDAL项目
首先打开IDAL项目,添加类InterfaceBaseRepository,代码如下。
using System.L
using System.Linq.E
namespace Ninesky.IDAL
/// &summary&
/// 接口基类
/// &remarks&创建: &br /&
/// 修改:&/remarks&
/// &/summary&
/// &typeparam name=&T&&类型&/typeparam&
public interface InterfaceBaseRepository&T&
/// &summary&
/// &/summary&
/// &param name=&entity&&数据实体&/param&
/// &returns&添加后的数据实体&/returns&
T Add(T entity);
/// &summary&
/// 查询记录数
/// &/summary&
/// &param name=&predicate&&条件表达式&/param&
/// &returns&记录数&/returns&
int Count(Expression&Func&T, bool&& predicate);
/// &summary&
/// &/summary&
/// &param name=&entity&&数据实体&/param&
/// &returns&是否成功&/returns&
bool Update(T entity);
/// &summary&
/// &/summary&
/// &param name=&entity&&数据实体&/param&
/// &returns&是否成功&/returns&
bool Delete(T entity);
/// &summary&
/// 是否存在
/// &/summary&
/// &param name=&anyLambda&&查询表达式&/param&
/// &returns&布尔值&/returns&
bool Exist(Expression&Func&T, bool&& anyLambda);
/// &summary&
/// 查询数据
/// &/summary&
/// &param name=&whereLambda&&查询表达式&/param&
/// &returns&实体&/returns&
T Find(Expression&Func&T, bool&& whereLambda);
/// &summary&
/// 查找数据列表
/// &/summary&
/// &typeparam name=&S&&排序&/typeparam&
/// &param name=&whereLamdba&&查询表达式&/param&
/// &param name=&isAsc&&是否升序&/param&
/// &param name=&orderLamdba&&排序表达式&/param&
/// &returns&&/returns&
IQueryable&T& FindList&S&(Expression&Func&T, bool&& whereLamdba, bool isAsc, Expression&Func&T, S&& orderLamdba);
/// &summary&
/// 查找分页数据列表
/// &/summary&
/// &typeparam name=&S&&排序&/typeparam&
/// &param name=&pageIndex&&当前页&/param&
/// &param name=&pageSize&&每页记录数&/param&
/// &param name=&totalRecord&&总记录数&/param&
/// &param name=&whereLamdba&&查询表达式&/param&
/// &param name=&isAsc&&是否升序&/param&
/// &param name=&orderLamdba&&排序表达式&/param&
/// &returns&&/returns&
IQueryable&T& FindPageList&S&(int pageIndex, int pageSize, out int totalRecord, Expression&Func&T, bool&& whereLamdba, bool isAsc, Expression&Func&T, S&& orderLamdba);
这里定义了增、删、改、判断存在、返回模型的查询、返回集合的查询,返回分页集合的查询7个公共方法。这几个方法基本满足一般需要,特殊的方法在继承的时候再添加。
还使用了泛型,在继承的时候传入实体类型就可以直接继承这些方法了。具体看下InterfaceUserRepository接口就清楚了。
using Ninesky.M
namespace Ninesky.IDAL
/// &summary&
/// 用户接口
/// &remarks&创建:&/remarks&
/// &/summary&
public interface InterfaceUserRepository:InterfaceBaseRepository&User&
简单吧,继承自InterfaceBaseRepository接口并传入实体类User就行了。我们在类视图中看下,是不是继承了基类的接口。
2、DAL项目
DAL项目是对IDAL项目接口的实现,项目中要创建DbContext类,对于DbContext类很多人讨论过它对数据库存取的效率,MSDN中说其是轻量的, 创建不需要很大开销,它也不是线程安全的对象,并且具有数据容器的性质(跟踪),因此很多人认为不应该将其静态化、单例化。但是对用户的单次请求来说实现DbContext唯一是合理的。 先看代码吧,非常简单。
using Ninesky.M
using System.Data.E
namespace Ninesky.DAL
/// &summary&
/// 数据上下文
/// &remarks&创建:&/remarks&
/// &/summary&
public class NineskyDbContext:DbContext
public DbSet&User& Users { }
public DbSet&UserGroup& UserGroups { }
public DbSet&UserConfig& UserConfig { }
public NineskyDbContext()
: base(&DefaultConnection&)
下面创建一个BaseRepository类,继承自InterfaceBaseRepository并实现类其接口的方法。
using Ninesky.IDAL;
using System.L
using System.Linq.E
namespace Ninesky.DAL
/// &summary&
/// 仓储基类
/// &remarks&创建:&/remarks&
/// &/summary&
public class BaseRepository&T&: InterfaceBaseRepository&T& where T : class
protected NineskyDbContext nContext = ContextFactory.GetCurrentContext();
public T Add(T entity)
nContext.Entry&T&(entity).State = System.Data.Entity.EntityState.A
nContext.SaveChanges();
public int Count(Expression&Func&T, bool&& predicate)
return nContext.Set&T&().Count(predicate);
public bool Update(T entity)
nContext.Set&T&().Attach(entity);
nContext.Entry&T&(entity).State = System.Data.Entity.EntityState.M
return nContext.SaveChanges() & 0;
public bool Delete(T entity)
nContext.Set&T&().Attach(entity);
nContext.Entry&T&(entity).State = System.Data.Entity.EntityState.D
return nContext.SaveChanges() & 0;
public bool Exist(Expression&Func&T, bool&& anyLambda)
return nContext.Set&T&().Any(anyLambda);
public T Find(Expression&Func&T, bool&& whereLambda)
T _entity = nContext.Set&T&().FirstOrDefault&T&(whereLambda);
public IQueryable&T& FindList&S&(Expression&Func&T, bool&& whereLamdba, bool isAsc, Expression&Func&T, S&& orderLamdba)
var _list = nContext.Set&T&().Where&T&(whereLamdba);
if (isAsc) _list = _list.OrderBy&T, S&(orderLamdba);
else _list = _list.OrderByDescending&T, S&(orderLamdba);
public IQueryable&T& FindPageList&S&(int pageIndex, int pageSize, out int totalRecord, Expression&Func&T, bool&& whereLamdba, bool isAsc, Expression&Func&T, S&& orderLamdba)
var _list = nContext.Set&T&().Where&T&(whereLamdba);
totalRecord = _list.Count();
if (isAsc) _list = _list.OrderBy&T, S&(orderLamdba).Skip&T&((pageIndex - 1) * pageSize).Take&T&(pageSize);
else _list = _list.OrderByDescending&T, S&(orderLamdba).Skip&T&((pageIndex - 1) * pageSize).Take&T&(pageSize);
代码中都是对数据库的操作。比较有看头的是这句protected NineskyDbContext nContext = ContextFactory.GetCurrentContext();
ContextFactory是一个简单工厂类,GetCurrentContext()是一个静态函数。利用简单工厂获取请求内的当前DbContext,也就是请求内的DbContext单例。先添加一个工厂类ContextFactory
using System.Data.E
using System.Runtime.Remoting.M
namespace Ninesky.DAL
/// &summary&
/// 上下文简单工厂
/// &remarks&
/// 创建:
/// &/remarks&
/// &/summary&
public class ContextFactory
/// &summary&
/// 获取当前数据上下文
/// &/summary&
/// &returns&&/returns&
public static NineskyDbContext GetCurrentContext()
NineskyDbContext _nContext = CallContext.GetData(&NineskyContext&) as NineskyDbC
if (_nContext == null)
_nContext = new NineskyDbContext();
CallContext.SetData(&NineskyContext&, _nContext);
return _nC
这里是先在CallContext中获取NineskyContext,如果为空则初始化一个NineskyContext,如果存在则直接返回。看CallContext,MSDN中讲CallContext提供对每个逻辑执行线程都唯一的数据槽,而在WEB程序里,每一个请求恰巧就是一个逻辑线程所以可以使用CallContext来实现单个请求之内的DbContext单例。
下面添加具体的仓储代码。
在DAL中再添加一个UserRepository类,继承自BaseRepository和InterfaceUserRepository。目的是继承自BaseRepository类,实现InterfaceUserRepositor接口。
using Ninesky.IDAL;
using Ninesky.M
using System.L
namespace Ninesky.DAL
/// &summary&
/// 用户仓库
/// &remarks&创建:&/remarks&
/// &/summary&
class UserRepository: BaseRepository&User&, InterfaceUserRepository
UserRepository就直接继承了基类中的方法,基类中的方法能满足绝大部分需要,UserRepository就不用再增加函数了,其他Repository类都类似,不在贴代码了。
这里我们在建一个Repository工厂,用来返回项目中的所有Repository类。
using Ninesky.IDAL;
namespace Ninesky.DAL
/// &summary&
/// 简单工厂?
/// &remarks&创建:&/remarks&
/// &/summary&
public static class RepositoryFactory
/// &summary&
/// 用户仓储
/// &/summary&
public static InterfaceUserRepository UserRepository { get { return new UserRepository(); } }
以后在BLL中调用的时候就不用每次都写InterfaceUserRepository _iUserRsy = new UserRepository()了,直接写成InterfaceUserRepository _iUserRsy = RepositoryFactory.UserRepository这个东西的好处就是,以后在DAL项目中实现InterfaceUserRepository接口的类需要修改时我们可以直接创建个新类,然后RepositoryFactory类中让UserRepository属性返回新类就行了。
3、IBLL项目
IBLL是业务逻辑层的接口,业务逻辑层对数据库的操作上基本还是增、删、改。同样写一个基接口把这三个操作写进去,这里与IDAL思路类似。
namespace Ninesky.IBLL
/// &summary&
/// 接口基类
/// &remarks&创建:&/remarks&
/// &/summary&
public interface InterfaceBaseService&T& where T : class
/// &summary&
/// &/summary&
/// &param name=&entity&&数据实体&/param&
/// &returns&添加后的数据实体&/returns&
T Add(T entity);
/// &summary&
/// &/summary&
/// &param name=&entity&&数据实体&/param&
/// &returns&是否成功&/returns&
bool Update(T entity);
/// &summary&
/// &/summary&
/// &param name=&entity&&数据实体&/param&
/// &returns&是否成功&/returns&
bool Delete(T entity);
在添加一个InterfaceUserService接口,继承自InterfaceBaseService。根据需要在接口中又添加了几个方法。在这里对Find方法的名称进行统一,凡是返回实体类的名称为Find()或FindByXXX(),返回一组数据的方法名称为FindList()或FindXXXList,分页的名称格式为FindPageList()或FindxxxPageList()
using Ninesky.M
using System.L
namespace Ninesky.IBLL
/// &summary&
/// 用户相关接口
/// &remarks&
/// 创建:
/// &/remarks&
/// &/summary&
public interface InterfaceUserService:InterfaceBaseService&User&
/// &summary&
/// 用户是否存在
/// &/summary&
/// &param name=&userName&&用户名&/param&
/// &returns&布尔值&/returns&
bool Exist(string userName);
/// &summary&
/// 查找用户
/// &/summary&
/// &param name=&userID&&用户ID&/param&
/// &returns&&/returns&
User Find(int userID);
/// &summary&
/// 查找用户
/// &/summary&
/// &param name=&userName&&用户名&/param&
/// &returns&&/returns&
User Find(string userName);
/// &summary&
/// 用户列表
/// &/summary&
/// &param name=&pageIndex&&页码数&/param&
/// &param name=&pageSize&&每页记录数&/param&
/// &param name=&totalRecord&&总记录数&/param&
/// &param name=&order&&排序:0-ID升序(默认),1ID降序,2注册时间升序,3注册时间降序,4登录时间升序,5登录时间降序&/param&
/// &returns&&/returns&
IQueryable&User& FindPageList(int pageIndex, int pageSize, out int totalRecord,int order);
4、BLL项目
BLL项目中要实现InterfaceUserService接口的方法,先添加BaseService的
using Ninesky.IBLL;
using Ninesky.IDAL;
namespace Ninesky.BLL
/// &summary&
/// 服务基类
/// &remarks&创建:&/remarks&
/// &/summary&
public abstract class BaseService&T& : InterfaceBaseService&T& where T : class
protected InterfaceBaseRepository&T& CurrentRepository { }
public BaseService(InterfaceBaseRepository&T& currentRepository) { CurrentRepository = currentR }
public T Add(T entity) { return CurrentRepository.Add(entity); }
public bool Update(T entity) { return CurrentRepository.Update(entity); }
public bool Delete(T entity) { return CurrentRepository.Delete(entity); }
这个类的构造函数中要传入一个参数就是currentRepository 这个在继承的时候进行传入。这里还是看用户类。
using Ninesky.DAL;
using Ninesky.IBLL;
using Ninesky.M
using System.L
namespace Ninesky.BLL
/// &summary&
/// 用户服务类
/// &remarks&
/// 创建:
/// &/remarks&
/// &/summary&
public class UserService:BaseService&User&,InterfaceUserService
public UserService() : base(RepositoryFactory.UserRepository) { }
public bool Exist(string userName) { return CurrentRepository.Exist(u =& u.UserName == userName);}
public User Find(int userID) { return CurrentRepository.Find(u =& u.UserID == userID); }
public User Find(string userName) { return CurrentRepository.Find(u =& u.UserName == userName); }
public IQueryable&User& FindPageList(int pageIndex, int pageSize, out int totalRecord, int order)
switch(order)
case 0: return CurrentRepository.FindPageList(pageIndex, pageSize, out totalRecord, u =& true, true, u =& u.UserID);
case 1: return CurrentRepository.FindPageList(pageIndex, pageSize, out totalRecord, u =& true, false, u =& u.UserID);
case 2: return CurrentRepository.FindPageList(pageIndex, pageSize, out totalRecord, u =& true, true, u =& u.RegistrationTime);
case 3: return CurrentRepository.FindPageList(pageIndex, pageSize, out totalRecord, u =& true, false, u =& u.RegistrationTime);
case 4: return CurrentRepository.FindPageList(pageIndex, pageSize, out totalRecord, u =& true, true, u =& u.LoginTime);
case 5: return CurrentRepository.FindPageList(pageIndex, pageSize, out totalRecord, u =& true, false, u =& u.LoginTime);
default: return CurrentRepository.FindPageList(pageIndex, pageSize, out totalRecord, u =& true, true, u =& u.UserID);
上面这个FindPageList代码太累赘了,一时还没想到好方法。
今天写到这里还是在想项目间的调用实现,写了两个base接口、两个base类,以后其他的类都从它们继承,写法都很类似。下次可以开始做界面了,在Ninesky.Web项目中基本上是通过IBLL,BLL跟数据进行打交道了。
===================================================
FindPageList() 这个排序的方法确实不太通用,代码修改如下:
1、接口 InterfaceBaseRepository
修改两个接口方法如图红框部分。
2、BaseRepository类
添加OrderBy方法,代码如下:
/// &summary&
/// &/summary&
/// &typeparam name=&T&&类型&/typeparam&
/// &param name=&source&&原IQueryable&/param&
/// &param name=&propertyName&&排序属性名&/param&
/// &param name=&isAsc&&是否正序&/param&
/// &returns&排序后的IQueryable&T&&/returns&
private IQueryable&T& OrderBy(IQueryable&T& source, string propertyName, bool isAsc)
if (source == null) throw new ArgumentNullException(&source&, &不能为空&);
if (string.IsNullOrEmpty(propertyName))
var _parameter = Expression.Parameter(source.ElementType);
var _property = Expression.Property(_parameter, propertyName);
if (_property == null) throw new ArgumentNullException(&propertyName&, &属性不存在&);
var _lambda = Expression.Lambda(_property, _parameter);
var _methodName = isAsc ? &OrderBy& : &OrderByDescending&;
var _resultExpression = Expression.Call(typeof(Queryable), _methodName, new Type[] { source.ElementType, _property.Type }, source.Expression, Expression.Quote(_lambda));
return source.Provider.CreateQuery&T&(_resultExpression);
修改FindList和FindPageList方法,修改下图
3、修改UserService的FindPageList方法
修改后的代码如下:
public IQueryable&User& FindPageList(int pageIndex, int pageSize, out int totalRecord, int order)
bool _isAsc =
string _orderName = string.E
switch(order)
_orderName = &UserID&;
_orderName = &UserID&;
_orderName = &RegistrationTime&;
_orderName = &RegistrationTime&;
_orderName = &LoginTime&;
case 5: _isAsc =
_orderName = &LoginTime&;
_orderName = &UserID&;
return CurrentRepository.FindPageList(pageIndex, pageSize, out totalRecord, u =& true, _orderName, _isAsc);
以上就是ASP.NET MVC5 网站开发框架模型、数据存储以及业务逻辑的相关介绍,比之前两节的内容是不是更加丰富了,希望本文可以对大家的学习有所帮助。
本文地址:
相关文章列表您所在的位置: &
VS2013:Web开发人员必须了解的一切
VS2013:Web开发人员必须了解的一切
核子可乐译
Visual Studio 2013已经发布,我们准备了下面这份以ASP.NET及Web工具为重点的Visual Studio 2013版本总结...
【51CTO独家译文】Visual Studio 2013已经发布,我们准备了下面这份以ASP.NET及Web工具为重点的Visual Studio 2013版本总结:
&Visual Studio 2013现在已经可通过进行下载,MSDN订阅用户则可下载。
&Visual Studio 2013需要与Visual Studio 2012配合安装,且允许用户在不同Visual
Studio版本之间随意切换&&因此大家完全不必存在顾虑。
&Visual Studio 2013带来新的ASP.NET版本,其中包括ASP.NET MVC 5、ASP.NET Web API 2、Razor
3、Entity Framework 6以及SignalR 2.0。
&ASP.NET新版本的关注重点在于&One
ASP.NET&,因此其核心功能及网络工作能够在不同平台之上实现同样的效果(例如将ASP.NET控制器添加到Web Forms应用当中)。
&新增核心功能包括基于Bootstrap的新模板、新的支架系统以及新的身份识别系统。
&Visual Studio
2013是一款极为出色的编辑器,能够打理各种Web文件,包括HTML、CSS、JavaScript、Markdown、LESS、Coffeescript、Handlebars、Angular、Ember、Knockdown等。
&ASP.NET网站标准新版本区中的Visual Studio 2013相关内容:
&.NET Web开发与工具官方博客中的博文
.提供很多关于新版本的优秀博客
&Scott Guthrie的博客:
&Scott Hanselman在ASP.NET网站上发布了一系列功能概述视频。它们做得非常好,能够带来理想的指导作用。大家可以通过以下地址进行观看:
Web开发指导:Visual Studio 2013的下载与安装
我发现Visual Studio 2013的安装过程相当快。根据Brian Harry发布的博文来看,直接安装并覆盖Visual
Studio预发布版也是完全可行的。
如果大家打算利用Visual Studio 2013单纯进行Web开发,那么完全可以通过勾选&Web Developer
Tools&选项来进一步缩短安装流程。
当然,我肯定还得介绍介绍其它能帮助用户完成任务的功能,例如针对Windows 8系统的Store应用以及Windows Phone 8.0
SDK&&不过它们会下载并安装大量其它组件(举例来说,Windows Phone
SDK会设置Hyper-V并下载几GB虚拟机数据)。因此,如果大家的本意仅仅是为了进行Web开发,那么只选择Web Developer
Tools即可&&其它组件可以稍后再进行安装。
如果各位手头的互联网连接比较给力,我建议大家直接使用网络安装工具而不必下载整个ISO。ISO文件当中包含全部功能,但网络安装工具则只会下载被选中的对应组件。
Visual Studio 2013开发设置与色彩主题
当大家首次启动Visual
Studio时,它会提示我们选择一些默认设置。具体如何选择完全取决于大家的喜好&&只要符合具体开发习惯即可&&各位也可以在稍后的使用中对其进行修改。
正如刚刚所说,具体设置完全取决于个人喜好。我建议大家在Web开发与Web开发(纯代码)之间进行选择。二者的惟一实质性区别在于纯代码模式会隐藏工具栏,大家可以利用Tools/Import与Export
Settings/Reset在两种模式之间切换。
Web开发设置
Web开发(纯代码)设置
通常情况下,我更倾向于使用Web开发(纯代码)模式,这是因为我希望能把注意力集中在代码身上&&当然,标准工具栏能够更轻松地切换为默认网络浏览器视图。我们稍后再进一步探讨。
每个人都可以任意选择自己喜欢的色彩主题,我个人会根据自己的心情选择Light或者Dark色调&&此外,我个人很喜欢在低对比度窗口显示方案,这能让自己的注意力更集中在代码本身而非标签或工具栏身上。我知道有些朋友对这种设定极为不满,希望蓝色主题能马上回归。我倒是对蓝色主题没啥好感&&它让我感觉自己仍然置身于远古时代的Visual
Studio版本当中&&好了,我一秒钟也不打算再多想。
因此,目前的情况是:如果大家安装Visual
Studio旗舰版,那么主题默认为Blue,其它版本则默认采用Light。如果各位坚持使用Blue方案,我也不会妄加品评。主题变更非常简单,按照Tools/Options/Environment/General的顺序一路点下去即可;或者选择更聪明的办法:按下Ctrl+Q组合键快速激活,然后输入主题名称并按回车确认。
在第一次使用时,Visual Studio
2013会提醒我们登录。其实不登录也,大家可以点击对话框下方的&暂时不登陆,以后再说&链接。不过我个人建议大家登录。这套登录机制并不会与授权许可挂钩,也不会追踪大家的使用情况并推送功能组件购买推荐。可以说登录只会带来好处,例如在不同计算机之间同步Visual
Studio设置等。总之,可以不登录,但登录之后回报多多。
ASP.NET全新内容概述
ASP.NET中的新鲜好东东也不少。我会在接下来的文章中介绍一部分,但更多内容推荐大家访问ASP.NET官方网站。
One ASP.NET
关于这个话题我们已经进行过多次讨论,最终的结论是&&有选择是好的,但选择本身也属于一种负担。哪大家着手创建一个全新ASP.NET项目,为什么还要做出一个个艰难的选择(且会造成长期影响)来决定应用程序该如何运作?我们为什么就不能先使用ASP.NET
Web Forms,并在未来需要的时候添加ASP.NET MVC&&这真有那么难吗?毕竟这手心手背都是ASP.NET,对吧?
在理想状态下,我们只需在项目起步时决定采用ASP.NET作为网站及服务的创建基础,并在其后的实际开发过程中根据需要添加其它工具(即下图中的绿色方块)。
好的,现在美梦终于成真。
当大家创建一个全新ASP.NET应用程序时,只需点击对应选项即可。
接下来,大家可以从现有模板当中选择一种作为起步&&不过模板之间的区别可不小。这并不是那种会让大家左右为难、不知如何取舍的模板,而只是一些首发选项。最重要的是,大家可以对其进行混合及匹配。举例来说,我们可以在选择使用Web
Forms模板中大部分设定的同时,另行借用MVC及Web API文件夹与核心。
大家过去可能也尝试过混合及匹配方案&&没错,虽然能够生效,但使用过程并不愉快。原先的ASP.NET项目文件当中包含各种特殊的项目类型GUID,因此如果大家希望手动编辑csproj文件、则只能在Web
Forms项目当中获得控制器支持。同一堆栈中的功能无法作用于其它堆栈,因此选择项目模板让人头痛不已。现在情况不同了,让我们尽情欢呼吧!
我曾在上周的演示环节中拿出一套开发demo&&一个由Web Forms加MVC再加Web API创建的网站,内置模块化支架式MVC以及由EF Code
First实现的Web API控制器;数据被添加到MVC视图当中,在Web API内进行查看,而后再向Web Forms
Default.aspx页面添加一套GridView并与Model绑定。整个过程大约耗时五分钟。当然,这只是个简单的实例,但确实能够在跨ASP.NET家族间进行数据共享方面发挥出色作用。
过去,验证机制被内置在模板当中。举例来说,大家需要利用ASP.NET MVC 4 Intranet Project模板来创建新的ASP.NET MVC
4应用程序,其中将预置Windows验证机制。因为关于验证的一切都被内置在每套模板当中,因此它们之间处于不同堆栈范畴,大家无法对其进行重复使用。有鉴于此,关于验证的选项并不多,因为它们涉及一大堆项目模板且需要做出大量改动。
现在,新项目对话框中包含一套通用的验证机制。当大家点击&Change
Authentication&(变更验证)按钮时,即可获得通用选项&&其起效机制完全相同,不再需要考虑具体模板或者用户的个人设置。这些选项都以ASP.NET框架为基础,且适用于全部托管环境(包括IIS、IIS
Express或者OWIN)。
默认情况下使用的是个人用户账户:
这是一套标准的&创建本地账户、使用用户名/密码或者OAuth&机制;不过这一切都以新型验证系统为基础。我们稍后再进一步讨论。
这里只有组织账户这一项需要进行额外配置,包括Active Directory、Windows Azure Active Directory或者Office
365的验证配置。
Visual Studio 2013采用新的身份认证系统。在继承了原先ASP.NET Membership以及Simple
Identity系统的优势之外,新版本还采纳了大量反馈意见从而为开发人员带来理想的支持力度,包括单元测试以及扩展能力。
我曾经就ASP.NET的身份认证机制撰写了几篇长博文,在今后的文章中我还将旧事重提。概括来说,我认为我们终于获得了一套恰到好处的身份认证系统,其中最出色的功能包括:
&默认项目简单、合理且效果突出&&大家可以按照File/New/Run/Register/Login的顺序设置自己的认证机制,而且肯定能正常起效。
&它支持标准的用户名/密码模式,同时也可采用外部验证机制(例如OAuth等)。
&定制工作容易实现且无需对全盘进行重新实施。它采用内置插接式组件,无需涉及大型独立系统。
&它采用IUser及IRole等作为内置接口,从而实现单元测试、关联性注入等功能。
&大家可以轻松添加用户配置数据(例如URL、Twitter引用、出生日期)。大家只需将属性添加到ApplicationUser模块当中,它们就会自动得到保存。
&对身份认证数据进行持续全面控制。在默认情况下,都由Entity Framework Code
First负责打理,但它也能够直接支持由小(修改架构)到大(使用其它ORM或者在文档数据库、云环境、XML、桌面后台EXIF数据或者其它机制中保存数据)的各类变更。
&配置工作通过OWIN实现,稍后Katana也将加入进来。利用OWIN打造意味着它具备便携性。
大家可以在ASP.NET网站上参阅更多与验证及身份认证相关的章节(稍后还将发布更多消息)。
项目模板基于新型Bootstrap
前面提到的各种新型项目模板由Bootstrap 3创建。Bootstrap(即原先的Twitter
Bootstrap)是一套前端框架,它带来的优势包括:
&采用响应式设计,因此项目能够自动利用CSS媒体查询与设备宽度相匹配。举例来说,菜单会在桌面浏览器中以全尺寸显示;但在移动设备的小型屏幕上,大家会自动获得符合移动使用习惯的菜单方案。
&内置Bootstrap风格将使大家的标准页面元素(包括标题、页脚、按钮、表单输入以及列表等)外观更漂亮、更具现代感。
&Bootstrap支持主题设置,因此大家可以在下拉菜单的新Bootstrap主题选项中重新装扮自己的网站。由于Bootstrap在Web开发行业中的人气很高,因此各类模板数量庞大、品种丰富&&付费版本与免费版本皆有,任君随意选择。
&Bootstrap还包含大量极具实用性的其它内容:组件(例如进度条及标记)、glyphicons、用于工具提示的jQuery插件、下拉菜单以及carousel等。
下面我们来看响应式部分是如何工作的。在页面处于全屏模式下时,菜单与标题会针对宽屏显示进行优化:&
在缩小页面尺寸之后(完全取决于页面宽度,与useragent检测无关),菜单会调整为更适合在移动设备上观看的纵向模式:
举例来说,我从网站上找到一套新的免费主题。对于简单主题来说,大家只需要下载其bootstrap.css文件并将其覆盖项目中的/content/bootstrap.css文件即可。
现在只需刷新当前页面,新主题就会自动生效:
支架系统的最大变化在于可以在整套ASP.NET体系下发挥作用。大家可以创建一个新的空白Web项目或者Web
Forms项目,其中将直接提供Scaffold相关菜单。
在目前的RTM版本中,我们拥有MVC 5与Web API 2两套控制器。我们曾在预览版本中对Web
Forms支架进行过评测,但在RTM版本中该系统又经过了重新调整。我们期待着在即将推出的正式版本中它能迎来更多改进。
这套支架系统不仅能够作用于全局ASP.NET框架,而且还在未来可扩展性方面留下很多可能性。虽然目前的版本还不完整,但最终效果应该很快就会揭晓。
项目自述页面
自述并不是什么重要组件,但我对Visual Studio
2013的对应页面表示赞赏。在创建新项目时,项目的根目录中会自动出现一个Project_Readme.html页面,可通过Visual
Studio的内置浏览器打开。
我真心喜欢这项设定。
很久很久以前,当大家打算创建新项目时,Visual Studio只是把整套平台甩给用户、然后坐看开发者挠着脑袋不知该如何下手。这样不好。
后来我们向新项目模板中加入了大量入门指导信息,用于提示大家该接下来该做什么;不过用户必须手动将这部分引导内容从网站中删掉。这些提示信息的内容并不属于页面固有内容,所以也不太理想。
最新的自述机制借助HTML文件实现,不会对项目代码产生任何影响。如果不喜欢,大家可以随时将其删除。不过请别太过草率&&它提供大量非常有用的链接,而且能够以特定格式创建自述文档、通过具体信息描述我们在项目中使用的另类设定。
备注:我很喜欢在Visual
Studio内部浏览器上阅读自述信息这个主意&&这比通过默认浏览器打开HTML页面酷得多也便利得多,毕竟额外弹出新窗口以及随之而来的启动时间让人烦躁。如果大家还在采用那种传统方式,最好尽快投入新方案的怀抱。理由很简单&&如果某些不知名的&活雷锋&事先在浏览器里已经打开了好几十个标签页,载入过程会活活把人逼疯。等到&感谢您安装我们的Visual
Studio扩展!&页面顺利打开,我一定已经在墙上撞死好几回了。总而言之,请优先利用Visual Studio中自带的浏览器打开自述页面。
ASP.NET MVC 5
ASP.NET MVC 5中的最大改动在于它不再作为独立项目类型。现在它可以与其它ASP.NET组件完美集成。
除了前面已经提到的这些常见功能(Bootstrap、模板、身份认证以及验证),我们再聊聊ASP.NET MVC中的其它新内容。
ASP.NET MVC现在支持属性路由功能,这要归功于Tim
McCall(网站的创始人)做出的卓越贡献。在属性路由功能的辅助下,用户可以通过为操作及控制器添加注解的方式指定路由机制。该功能支持多种复杂的定制化路由情况,而且允许大家保存自己的路由信息以及控制器操作。
控制器中包含的一项方法名为Hiding的操作,但我已经利用AttributeRouting在/spaghetti/with-nesting/where-is-wald中对其进行了配置:
public class SampleController : Controller
[Route(&spaghetti/with-nesting/where-is-waldo&)]
public string Hiding()
return &You found me!&;
我在自己的RouteConfig.cs文件中添加了上述代码,并通过以下方式将其注入到其它MVC路由当中:
public class RouteConfig
public static void RegisterRoutes(RouteCollection routes)
routes.IgnoreRoute(&{resource}.axd/{*pathInfo}&);
routes.MapMvcAttributeRoutes();
routes.MapRoute(
name: &Default&,
url: &{controller}/{action}/{id}&,
defaults: new { controller = &Home&, action = &Index&, id =
UrlParameter.Optional }
大家可以阅读更多关于ASP.NET MVC 5中属性路由的相关信息。
过滤器强化
过滤器新增两种类型,分别为Authentication Filters与Filter Overrides。
Authentication过滤器是ASP.NET MVC中的全新过滤器类型在ASP.NET
MVC流程中优先运行,从而允许用户为每项操作、每套控制器或者全局控制器指定验证逻辑。Authentication过滤器处理请求中的证书并提供对应主体。Authentication过滤器还可以为未经授权的请求添加验证质询。
Override过滤器允许大家改变特定方法或者控制器所应用的过滤器。Override过滤器能够为特定范围(例如操作或者控制器)设定不适用的过滤器类型。这一特性允许大家在全局范围配置过滤器的同时,排除特定操作或者控制器。
ASP.NET Web API 2
ASP.NET Web API 2当中包含大量新功能。
ASP.NET Web API支持ASP.NET MVC 5中的属性路由系统。大家可以阅读更多关于Web API中属性路由机制的介绍。
ASP.NET Web API具备OAuth
2.0支持能力,这是由于其借助了运行在OWIN中的安全中间件(下面将进一步介绍)。这一点对于已验证单页面应用等功能来说非常重要。
ASP.NET Web API现在全面支持OData。为了实现这一点,Web
API纳入大量最强大的执行机制:$select、$expand、$batch以及$value。大家可以阅读由Mike
Wasson撰写的OData执行机制支持评论。
想要囊括全部功能需要一份相当庞大的列表,其中包括CORS(即跨域请求共享)、IHttpACtionResult、IHttpRequestContext等等。我想大家最好在发行说明中对它们进行进一步了解。
OWIN与Katana
我最近刚刚撰写过一篇关于OWIN与Katana的文章,我也是这两套方案的坚定拥护者。
OWIN是一款开放Web接口,专门针对.NET。我们可以将其看作类似于HTML或者HTTP的规范,因此大家无法安装OWIN。OWIN带来的好处在于,它是一套业界通行规范,因此任何采纳这套方案的组件都可以由此接入ASP.NET堆栈&&无论是中间件还是主机。
Katana是微软推出的OWIN衍生方案。它利用OWIN将验证、处理、模块、IIS托管等元素串连起来,从而使ASP.NET能够托管OWIN组件与Katana组件,并使其运行在其它OWIN衍生方案当中。
Dierking在MSDN杂志中撰写了一篇精彩的文章,从深层次围绕Katana展开探讨&&文章题为《Katana项目入门指南》。他通过一个有趣的例子展示了以OWIN为基础且在单一堆栈中使用SignalR、ASP.NET
Web API以及NancyFx组件的实施途径。
如果这样的处理方式对于大家有意义,那当然最好。如果暂时没有也别担心,但请各位务必对此保持关注。随着ASP.NET对插件容纳能力的不断提升,将有越来越酷的使用方式逐步出现。
Visual Studio Web工具
好吧,这东西相当疯狂。Visual Studio在过去几年来不断迎来多种出色的Web开发功能,但微软最终将其整理并构建起新版本仍然令人激动。
Studio是我目前在Web文件领域最喜爱的代码编辑器:CSS、HTML、JavaScript以及大量流行库,一切都能打理得妥妥当当。
不要再把Visual
Studio当作是一种只能用来编写后端代码的大型编辑器了。不要再利用Notepad(或者Sublime、Notepad++等)编辑HTML以及CSS。Visual
Studio在配备SSD的现代计算机上只需两秒就能完成启动。在HTML属性、CSS类、jQuery或者Angular语法方面出现拼写错误实在是太愚蠢了。这不会让你成为更优秀的开发人员,只会让你变成浪费时间的傻瓜。
Browser Link
Browser Link是一种存在于Visual
Studio与全部网络浏览器之间的实时、双向连接。它只在我们以本地方式进行调试时才能发挥作用,但却适用于任何一款网络浏览器,包括模拟器。
大家可能已经在一些演示中看到过如何在编辑器内部做出修改以刷新浏览器,我也承认这种方式很酷。但这真的仅仅只是开始。这是一种双向连接,而且专门为扩展性而打造。这意味着大家可以通过编写扩展将信息由正在运行的应用程序(可以在IE、Chrome甚至是移动模拟器当中)返还至Visual
Studio。Mads及其技术团队展示了他们如何在浏览器的编辑模式下将源HTML返还至浏览器。我们甚至可以在演示中看到他们如何呈现HTML执行过程、检查兼容性问题以及检查无用的CSS类等等&&总之,没有做不到只有想不到。
新型HTML编辑器
早期版本中的HTML编辑器中存在大量陈旧代码,给我们的改进带来极大束缚。技术团队重新编写了HTML编辑器,从而让Visual
Studio中的新型扩展功能发挥作用&&这样的处理方式使他们得以将全部功能添加进来,包括CSS类与ID智能感知(只需输入style=&&即可获得一份关于当前项目的类与ID列表)、文档格式智能化排版以及自动同步JavaScript引用等等。
这是一段来自Mads Kristensen的视频教程,时长为三分钟。
集成化Windows Azure网站创建与发布
Azure门户机制运作良好、与普通网站的使用方式无异,但我们必须通过额外的步骤才能通过这套门户创建新网站、而后下载并发布配置文件、最后才能将其导入至自己的站点。这就像连续进行十次点击&&实在是让人感到疲劳,每次进行这项工作之后我都觉得需要睡一觉。
这一切在Visual Studio 2013的Server Explorer中都得到了更新,因此我可以直接右键点击Windows
Azure节点以创建新网站。在后续的发布过程中,我可以直接将站点分布配置文件导入进来并立刻执行。这意味着我能够利用免费的20MB
SQL数据库建立起新的Windows Azure网站并将其直接在Windows Azure中发布&&整个过程完全不涉及Visual
Studio。这真的很棒,我很喜欢。
大家可以阅读《利用Visual Studio 2013 RC创建全新Windows Azure网站》一文,相信会给您带来帮助。
更多Visual Studio Web开发功能
这篇文章仅仅算是概述,没有介绍到的卓越功能还有很多,其中包括JavaScript编辑、CSS编辑、发布以及Page Inspector(用于在Visual
Studio内部实时呈现您的页面)等等。可以观看更多功能演示视频。
一切只是开始,广泛的世界正等待我们探索。
好了,我们的这篇总结文章到这里就要迎来尾声了。请大家到http://asp.net/vnext中了解更多信息,并尽快下载Visual Studio
2013开始属于自己的新旅程。
原文链接:
原文标题:Top things web developers should know about the Visual Studio 2013
【编辑推荐】
【责任编辑: TEL:(010)】
关于&&&&的更多文章
2013年的11月13日,微软举办了Visual Studio 2013全球发布会,大
180天的Windows Server 2012试用版下载(标准版或数据中心版)
2月28日下午,微软在中国正式发布Office 365企业版,
IT行业当中还没有几个领域能够获得像云计算这样的迅猛
Microsoft TechEd China 2012,万名 IT 精英、智慧开
本书以轻松幽默的笔调向读者论述了高质量软件开发方法与C++/C编程规范。它是作者多年从事软件开发工作的经验总结。本书共17章,
51CTO旗下网站}

我要回帖

更多关于 asp.net mvc5实现登录 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信