實戰Angular2+web api增刪改查 (二)
webapi配置
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
//SwaggerConfig.Register();
GlobalConfiguration.Configure(WebApiConfig.Register);
//Nhibernate及日誌初始化
LoggingConfig.Register();
//依賴注入初始化
IocConfig.Register();
}
在Global.asax的啟動方法中加入依賴注入的配置,NHibernate配置,以及webapi配置,區域路由配置等,如果使用安全策略也許要在此加入,本例目前還沒進行身份認證處理,後面將會重點介紹。
AutoFac依賴注入配置
public static void Register()
{
ContainerBuilder builder = new ContainerBuilder();
Type baseType = typeof(IDependency);
varassemblies = AppDomain.CurrentDomain.GetAssemblies();
// 獲取所有相關類庫的程式集
builder.RegisterAssemblyTypes(assemblies)
.Where(type => baseType.IsAssignableFrom(type) && !type.IsAbstract)
.AsImplementedInterfaces()
.InstancePerLifetimeScope();
var config = GlobalConfiguration.Configuration;
builder.RegisterWebApiFilterProvider(config);
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
//builder.RegisterType<GroupListController>().InstancePerRequest();
var container = builder.Build();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
}
這個配置可以看出是利用反射技術獲取當前應用下的所有assemblies ,通過Type baseType = typeof(IDependency)指定凡是繼承該介面的例項都將注入到ContainerBuilder 容器中。
除此之外,要在wabapi中使用依賴注入還需處理webapi的注入,這就需要使用另一個工具Autofac.WebApi,使用PM > Install-Package Autofac.WebApi獲取。然後使用config.DependencyResolver = new AutofacWebApiDependencyResolver(container)就可將webapi的controller注入到容器中。
NHibernate配置
public class LoggingConfig
{
public static void Register()
{
SessionBuilder.Instance("web");
string logfile = CachedConfigContext.Current.ConfigService.GetFilePath("log4net");
var ms = new MemoryStream(Encoding.Default.GetBytes(logfile));
log4net.Config.XmlConfigurator.ConfigureAndWatch(new FileInfo(logfile));
}
}
這裡我還是用了log4net加入了log功能,這裡注意SessionBuilder.Instance("web");由於我們開發的是webapi應用所以這裡例項話是選擇為web。這裡的SessionBuilder是前面封裝的對Nhibernate的ISession管理的類。
Web Api跨域訪問配置
Web api跨越訪問需要使用另外一個工具
PM>install-package Microsoft.AspNet.WebApi.Cors
在global中的webapi register中增加
var cors = newEnableCorsAttribute(
origins: "*",
headers: "*",
methods: "*");
config.EnableCors(cors);
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API 跨域訪問
var cors = new EnableCorsAttribute(
origins: "*",
headers: "*",
methods: "*");
config.EnableCors(cors);
// Web API 路由
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Web api Controller
[EnableCors("*", "*", "*")]
public class GroupListController : ApiController
{
private IGroupService _groupService;
public GroupListController(IGroupService groupService)
{
_groupService = groupService;
}
public IList<GroupBaseDto> GetAll()
{
var list = _groupService.GetAll();
List<GroupBaseDto> groupList =AutoMapperHelper.MapToList<GroupBaseDto>(list);
return groupList;
}
public GroupBaseDto GetByID(string id)
{
var item = _groupService.GetByID(id);
GroupBaseDto groupdto = AutoMapperHelper.MapTo<GroupBaseDto>(item);
return groupdto;
}
public HttpResponseMessage PostGroup(GroupBaseDto group)
{
try
{
group.ID = Guid.NewGuid().ToString();
TGroup entity = AutoMapperHelper.MapTo<TGroup>(group);
_groupService.Add(entity);
return new HttpResponseMessage(HttpStatusCode.NoContent);
}
catch
{
throw new HttpResponseException(HttpStatusCode.InternalServerError);
}
}
public HttpResponseMessage PutGroup(string id, GroupBaseDto group)
{
try
{
group.ID = id;
TGroup entity = AutoMapperHelper.MapTo<TGroup>(group);
_groupService.Update(entity);
return new HttpResponseMessage(HttpStatusCode.NoContent);
}
catch(Exception se)
{
throw new HttpResponseException(HttpStatusCode.InternalServerError);
}
}
public HttpResponseMessage DeleteGroup(string id)
{
try
{
_groupService.Delete(id);
return new HttpResponseMessage(HttpStatusCode.NoContent);
}
catch
{
throw new HttpResponseException(HttpStatusCode.InternalServerError);
}
}
}
這裡看到通過使用了前面webapi的依賴注入配置,我們在controller的建構函式中就可以使用構造注入Iservice了。這裡也可以看到我們的資料傳遞使用了DTO,一方面是為了效率只傳輸與業務有關的資料,另一方面業務為了不暴露我們的資料屬性。
public class GroupBaseDto
{
public virtual string ID { get; set; }
public virtual string GROUPNAME { get; set; }
public virtual decimal? NORDER { get; set; }
public virtual string PARENTID { get; set; }
public virtual string GROUPTYPE { get; set; }
public virtual string GROUPCODE { get; set; }
}
為了簡單,這個例項我所使用DTO與我所在的領域模型一致,這裡還是用了一個AutoMapper工具,Automapper能夠讓我們在DTO與DO的轉換過程更簡單了,下面是對AutoMapper的一個封裝類,用於處理常用轉換。
///<summary>
/// AutoMapper擴充套件幫助類
///</summary>
public static class AutoMapperHelper
{
///<summary>
///型別對映
///</summary>
public static T MapTo<T>(this object obj)
{
if (obj == null) return default(T);
Mapper.Initialize(cfg=>cfg.CreateMap(obj.GetType(),typeof(T)));
return Mapper.Map<T>(obj);
}
///<summary>
///集合列表型別對映
///</summary>
public static List<TDestination> MapToList<TDestination>(this IEnumerable source)
{
foreach (var first in source)
{
var type = first.GetType();
Mapper.Initialize(cfg => cfg.CreateMap(type, typeof(TDestination)));
break;
}
return Mapper.Map<List<TDestination>>(source);
}
///<summary>
///集合列表型別對映
///</summary>
public static List<TDestination> MapToList<TSource, TDestination>(this IEnumerable<TSource> source)
{
//IEnumerable<T> 型別需要建立元素的對映
Mapper.Initialize(cfg => cfg.CreateMap(typeof(TSource), typeof(TDestination)));
return Mapper.Map<List<TDestination>>(source);
}
///<summary>
///型別對映
///</summary>
public static TDestination MapTo<TSource, TDestination>(this TSource source, TDestination destination)
where TSource : class
where TDestination : class
{
if (source == null) return destination;
Mapper.Initialize(cfg => cfg.CreateMap(typeof(TSource), typeof(TDestination)));
return Mapper.Map(source, destination);
}
}
到此我們一個簡單的api就已經完成了,可以通過Swashbuckle 進行測試,安裝PM> Install-Package Swashbuckle,使用時只需在路徑後加入swagger,如http://localhost:6611/swagger/ui/index