1.IOC(转:https://www.cnblogs.com/artech/p/inside-asp-net-core.html)html
IoC的全名Inverse of Control,翻译成中文就是“控制反转”或者“控制倒置”。控制反转也好,控制倒置也罢,它体现的意思是控制权的转移,即原来控制权在A手中,如今须要B来接管。那么具体对于软件设计来讲,IoC所谓的控制权的转移具备怎样的体现呢?要回答这个问题,就须要先了解IoC的C(Control)究竟指的是怎样一种控制。对于咱们所在的任何一件事,不论其大小,其实能够分解成相应的步骤,因此任何一件事都有其固有的流程,IoC涉及的所谓控制能够理解为“针对流程的控制jquery
咱们经过一个具体事例来讲明传统的设计在采用了IoC以后针对流程的控制是如何实现反转的。好比说如今设计一个针对Web的MVC类库,咱们不妨将其命名为MvcLib。简单起见,这个类库中只包含以下这个同名的静态类ajax
public static class MvcLib { public static Task ListenAsync(Uri address); public static Task<Request> ReceiveAsync(); public static Task<Controller> CreateControllerAsync(Request request); public static Task<View> ExecuteControllerAsync(Controller controller); public static Task RenderViewAsync(View view); }
MvcLib提供了如上5个方法帮助咱们完成整个HTTP请求流程中的5个核心任务。具体来讲,ListenAsync方法启动一个监听器并将其绑定到指定的地址进行HTTP请求的监听,抵达的请求经过ReceiveAsync方法进行接收,咱们将接收到的请求经过一个Request对象来表示。CreateControllerAsync方法根据接收到的请求解析并激活请求的目标Controller对象。ExecuteControllerAsync方法执行激活的Controller并返回一个表示视图的View对象。RenderViewAsync最终将View对象转换成HTML并做为当前请求响应的内容返回给请求的客户端。编程
如今咱们在这个MvcLib的基础上建立一个真正的MVC应用,那么除了按照MvcLib的规范自定义具体的Controller和View以外,咱们还须要自行控制从请求的监听与接收、Controller的激活与执行以及View的最终呈如今内的整个流程,这样一个执行流程反映在以下所示的代码中。json
class Program { static async Task Main() { while (true) { Uri address = new Uri("http://0.0.0.0:8080/mvcapp"); await MvcLib.ListenAsync(address); while (true) { var request = await MvcLib.ReceiveAsync(); var controller = await MvcLib.CreateControllerAsync(request); var view = await MvcLib.ExecuteControllerAsync(controller); await MvcLib.RenderViewAsync(view); } } } }
2.好莱坞法则设计模式
在好莱坞,把简历递交给演艺公司后就只有回家等待。由演艺公司对整个娱乐项目的彻底控制,演员只能被动式的接受电影公司的工做,在须要的环节中,完成本身的演出。“不要给咱们打电话,咱们会给你打电话(don‘t call us, we‘ll call you)”这是著名的好莱坞法则( Hollywood Principle或者 Hollywood Low),IoC完美地体现了这一法则。api
在IoC的应用语境中,框架就像是掌握整个电影制片流程的电影公司,因为它是整个工做流程的实际控制者,因此只有它知道哪一个环节须要哪些组件。应用程序就像是演员,它只须要按照框架定制的规则注册这些组件就能够了,由于框架会在适当的时机字典加载并执行注册的组件。跨域
以熟悉的ASP.NET Core MVC或者ASP.NET MVC应用开发来讲,咱们只须要按照约定规则(好比目录结构和命名等)定义相应的Controller类型和View文件就能够了。当ASP.NET (Core )MVC框架在进行处理请求的过程当中,它会根据解析生成的路由参数定义为对应的Controller类型,并按照预约义的规则找到咱们定义的Controller,而后自动建立并执行它。若是定义在当前Action方法须要呈现一个View,框架自身会根据预约义的目录约定找到咱们定义的View文件,并对它实施动态编译和执行。整个流程到处体现了“框架Call应用”的好莱坞法则。缓存
总的来讲,咱们在一个框架的基础上进行应用开发,就至关于在一条调试好的流水线上生成某种商品,咱们只须要在相应的环节准备对应的原材料,最终下线的就是咱们但愿获得的最终产品。IoC几乎是全部框架均具备的一个固有属性,从这个意义上讲,“IoC框架”的说法实际上是错误的,世界上并无什么IoC框架,或者说几乎全部的框架都是IoC框架。mvc
3.依赖注入(DI容器)
IoC主要体现了这样一种设计思想:经过将一组通用流程的控制权从应用转移到框架中以实现对流程的复用,并按照“好莱坞法则”实现应用程序的代码与框架之间的交互。咱们能够采用若干设计模式以不一样的方式实现IoC
DI是一种“对象提供型”的设计模式,在这里咱们将提供的对象统称为“服务”、“服务对象”或者“服务实例”。在一个采用DI的应用中,在定义某个服务类型的时候,咱们直接将依赖的服务采用相应的方式注入进来。按照“面向接口编程”的原则,被注入的最好是依赖服务的接口而非实现。
在应用启动的时候,咱们会对所需的服务进行全局注册。服务通常都是针对接口进行注册的,服务注册信息的核心目的是为了在后续消费过程当中可以根据接口建立或者提供对应的服务实例。按照“好莱坞法则”,应用只须要定义好所需的服务,服务实例的激活和调用则彻底交给框架来完成,而框架则会采用一个独立的“容器(Container)”来提供所需的每个服务实例。
咱们将这个被框架用来提供服务的容器称为“DI容器”,也由不少人将其称为“IoC容器”,根据咱们在《控制反转》针对IoC的介绍,我不认为后者是一个合理的称谓。DI容器之因此可以按照咱们但愿的方式来提供所需的服务是由于该容器是根据服务注册信息来建立的,服务注册了包含提供所需服务实例的全部信息。
以Autofac框架为列
框架特性
1,灵活的组件实例化:Autofac支持自动装配,给定的组件类型Autofac自动选择使用构造函数注入或者属性注入,Autofac还能够基于lambda表达式建立实例,这使得容器很是灵活,很容易和其余的组件集成。
2,资源管理的可视性:基于依赖注入容器构建的应用程序的动态性,意味着何时应该处理那些资源有点困难。Autofac经过容器来跟踪组件的资源管理。对于不须要清理的对象,例如Console.Out,咱们调用ExternallyOwned()方法告诉容器不用清理。细粒度的组件生命周期管理:应用程序中一般能够存在一个应用程序范围的容器实例,在应用程序中还存在大量的一个请求的范围的对象,例如一个HTTP请求,一个IIS工做者线程或者用户的会话结束时结束。经过嵌套的容器实例和对象的做用域使得资源的可视化。
3,Autofac的设计上很是务实,这方面更可能是为咱们这些容器的使用者考虑:
●组件侵入性为零:组件不须要去引用Autofac。
●灵活的模块化系统:经过模块化组织你的程序,应用程序不用纠缠于复杂的XML配置系统或者是配置参数。
●自动装配:能够是用lambda表达式注册你的组件,autofac会根据须要选择构造函数或者属性注入
●XML配置文件的支持:XML配置文件过分使用时很丑陋,可是在发布的时候一般很是有用
(1).属性注入
builder.Register(c => new A { B = c.Resolve<B>() });
为了支持循环依赖,使用激活的事件处理程序:
builder.Register(c => new A()).OnActivated(e => e.Instance.B = e.Context.Resolve<B>());
若是是一个反射组件,使用PropertiesAutowired()修改注册属性:
builder.RegisterType<A>().PropertiesAutowired();
若是你有一个特定的属性和值须要链接,你可使用WithProperty()修改:
builder.RegisterType<A>().WithProperty("PropertyName", propertyValue);
(2).方法注入
调用一个方法来设置一个组件的值的最简单的方法是,使用一个lambda表达式组件和正确的调用激活处理方法。
builder.Register(c => { var result = new MyObjectType(); var dep = c.Resolve<TheDependency>(); result.SetTheDependency(dep); return result; });
若是你不能使用一个lambda表达式注册,你能够添加一个激活事件处理程序(activating event handler)
builder .Register<MyObjectType>() .OnActivating(e => { var dep = e.Context.Resolve<TheDependency>(); e.Instance.SetTheDependency(dep); });
(3).构造函数注入
// 建立你的builder var builder = new ContainerBuilder(); // 一般你只关心这个接口的一个实现 builder.RegisterType<SomeType>().As<IService>(); // 固然,若是你想要所有的服务(不经常使用),能够这么写: builder.RegisterType<SomeType>().AsSelf().As<IService>();
生命周期
AutoFac中的生命周期概念很是重要,AutoFac也提供了强大的生命周期管理的能力。
AutoFac定义了三种生命周期:
Per Dependency Single Instance Per Lifetime Scope
Per Dependency为默认的生命周期,也被称为’transient’或’factory’,其实就是每次请求都建立一个新的对象
[Fact] public void per_dependency() { var builder = new ContainerBuilder(); builder.RegisterType<MyClass>().InstancePerDependency(); IContainer container = builder.Build(); var myClass1 = container.Resolve<MyClass>(); var myClass2 = container.Resolve<MyClass>(); Assert.NotEqual(myClass1,myClass2); }
Single Instance也很好理解,就是每次都用同一个对象
[Fact] public void single_instance() { var builder = new ContainerBuilder(); builder.RegisterType<MyClass>().SingleInstance(); IContainer container = builder.Build(); var myClass1 = container.Resolve<MyClass>(); var myClass2 = container.Resolve<MyClass>(); Assert.Equal(myClass1,myClass2); }
Per Lifetime Scope,同一个Lifetime生成的对象是同一个实例
[Fact] public void per_lifetime_scope() { var builder = new ContainerBuilder(); builder.RegisterType<MyClass>().InstancePerLifetimeScope(); IContainer container = builder.Build(); var myClass1 = container.Resolve<MyClass>(); var myClass2 = container.Resolve<MyClass>(); ILifetimeScope inner = container.BeginLifetimeScope(); var myClass3 = inner.Resolve<MyClass>(); var myClass4 = inner.Resolve<MyClass>(); Assert.Equal(myClass1,myClass2); Assert.NotEqual(myClass2,myClass3); Assert.Equal(myClass3,myClass4); }
[Fact] public void life_time_and_dispose() { var builder = new ContainerBuilder(); builder.RegisterType<Disposable>(); using (IContainer container = builder.Build()) { var outInstance = container.Resolve<Disposable>(new NamedParameter("name", "out")); using(var inner = container.BeginLifetimeScope()) { var inInstance = container.Resolve<Disposable>(new NamedParameter("name", "in")); }//inInstance dispose here }//out dispose here }
4.过滤器(转:http://www.javashuo.com/article/p-oxrrgmug-nt.html)
下图展现了Asp.Net Core MVC框架默认实现的过滤器的执行顺序:
Authorization Filters:身份验证过滤器,处在整个过滤器通道的最顶层。对应的类型为: AuthorizeAttribute.cs 对应的接口有同步和异步两个版本: IAuthorizationFilter.cs 、 IAsyncAuthorizationFilter.cs
Resource Filters:资源过滤器。由于全部的请求和响应都将通过这个过滤器,因此在这一层能够实现相似缓存的功能。对应的接口有同步和异步两个版本: IResourceFilter.cs 、 IAsyncResourceFilter.cs
Action Filters:方法过滤器。在控制器的Action方法执行以前和以后被调用,一个很经常使用的过滤器。对应的接口有同步和异步两个版本: IActionFilter.cs 、 IAsyncActionFilter.cs
Exception Filters:异常过滤器。当Action方法执行过程当中出现了未处理的异常,将会进入这个过滤器进行统一处理,也是一个很经常使用的过滤器。对应的接口有同步和异步两个版本: IExceptionFilter.cs 、 IAsyncExceptionFilter.cs
Result Filters:返回值过滤器。当Action方法执行完成的结果在组装或者序列化先后被调用。对应的接口有同步和异步两个版本: IResultFilter.cs 、 IAsyncResultFilter.cs
5.中间件(转http://www.javashuo.com/article/p-fyqdbkbe-ck.html)
Asp.Net Core,管道模型流程图
IHttpModule和IHttpHandler不复存在,取而代之的是一个个中间件(Middleware)。
Server将接收到的请求直接向后传递,依次通过每个中间件进行处理,而后由最后一个中间件处理并生成响应内容后回传,再反向依次通过每一个中间件,直到由Server发送出去。
中间件就像一层一层的“滤网”,过滤全部的请求和相应。这一设计很是适用于“请求-响应”这样的场景——消息从管道头流入最后反向流出。
接下来将演示在Asp.Net Core里如何实现中间件功能。
IHttpModule和IHttpHandler不复存在,取而代之的是一个个中间件(Middleware)。
Server将接收到的请求直接向后传递,依次通过每个中间件进行处理,而后由最后一个中间件处理并生成响应内容后回传,再反向依次通过每一个中间件,直到由Server发送出去。
中间件就像一层一层的“滤网”,过滤全部的请求和相应。这一设计很是适用于“请求-响应”这样的场景——消息从管道头流入最后反向流出。
接下来将演示在Asp.Net Core里如何实现中间件功能。
Middleware
Middleware支持Run、Use和Map三种方法进行注册,下面将展现每一种方法的使用方式。
Run方法
全部须要实现的自定义管道都要在 Startup.cs 的 Configure 方法里添加注册。
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory) { // 添加日志支持 loggerFactory.AddConsole(); loggerFactory.AddDebug(); // 添加NLog日志支持 loggerFactory.AddNLog(); // 添加自定义中间件 app.Run(async context => { await context.Response.WriteAsync("Hello World!"); }); // 添加MVC中间件 //app.UseMvc(); }
启动调试,访问地址 http://localhost:5000/ ,页面显示Hello World!字样
再次添加一个Run方法
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory) { // 添加日志支持 loggerFactory.AddConsole(); loggerFactory.AddDebug(); // 添加NLog日志支持 loggerFactory.AddNLog(); // 添加自定义中间件 app.Run(async context => { await context.Response.WriteAsync("Hello World!"); }); app.Run(async context => { await context.Response.WriteAsync("Hello World too!"); }); // 添加MVC中间件 //app.UseMvc(); }
启动调试,再次访问发现页面上只有Hello World!字样。
缘由是:Run的这种用法表示注册的此中间件为管道内的最后一个中间件,由它处理完请求后直接返回。
Use方法
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory) { // 添加日志支持 loggerFactory.AddConsole(); loggerFactory.AddDebug(); // 添加NLog日志支持 loggerFactory.AddNLog(); // 添加自定义中间件 app.Use(async (context, next) => { await context.Response.WriteAsync("Hello World!"); }); // 添加MVC中间件 //app.UseMvc(); }
启动调试,访问页面一样显示Hello World!字样。咱们发现使用Use方法替代Run方法,同样能够实现一样的功能。
再次添加一个Use方法,将原来的Use方法内容稍做调整,尝试实现页面显示两个Hello World!字样。
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory) { // 添加日志支持 loggerFactory.AddConsole(); loggerFactory.AddDebug(); // 添加NLog日志支持 loggerFactory.AddNLog(); // 添加自定义中间件 app.Use(async (context, next) => { await context.Response.WriteAsync("Hello World!"); await next(); }); app.Use(async (context, next) => { await context.Response.WriteAsync("Hello World too!"); }); // 添加MVC中间件 //app.UseMvc(); }
将两个Use方法换个顺序,稍微调整一下内容,再次启动调试,访问页面,发现字样输出顺序也发生了变化。
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory) { // 添加日志支持 loggerFactory.AddConsole(); loggerFactory.AddDebug(); // 添加NLog日志支持 loggerFactory.AddNLog(); HelloworldMiddleware.cs // 添加自定义中间件 app.Use(async (context, next) => { await context.Response.WriteAsync("Hello World too!"); await next(); }); app.Use(async (context, next) => { await context.Response.WriteAsync("Hello World!"); }); // 添加MVC中间件 //app.UseMvc(); }
从上面的例子能够发现,经过Use方法注册的中间件,若是不调用next方法,效果等同于Run方法。当调用next方法后,此中间件处理完后将请求传递下去,由后续的中间件继续处理。
当注册中间件顺序不同时,处理的顺序也不同,这一点很重要,当注册的自定义中间件数量较多时,须要考虑哪些中间件先处理请求,哪些中间件后处理请求。
另外,咱们能够将中间件单独写成独立的类,经过UseMiddleware方法一样能够完成注册。下面将经过独立的中间件类重写上面的演示功能。
新建两个中间件类: HelloworldMiddleware.cs 、 HelloworldTooMiddleware.cs
using System.Threading.Tasks; using Microsoft.AspNetCore.Http; namespace WebApiFrame.Core.Middlewares { public class HelloworldMiddleware { private readonly RequestDelegate _next; public HelloworldMiddleware(RequestDelegate next){ _next = next; } public async Task Invoke(HttpContext context){ await context.Response.WriteAsync("Hello World!"); await _next(context); } } } HelloworldMiddleware.cs
using System.Threading.Tasks; using Microsoft.AspNetCore.Http; namespace WebApiFrame.Core.Middlewares { public class HelloworldTooMiddleware { private readonly RequestDelegate _next; public HelloworldTooMiddleware(RequestDelegate next){ _next = next; } public async Task Invoke(HttpContext context){ await context.Response.WriteAsync("Hello World too!"); } } } HelloworldTooMiddleware.cs
修改 Startup.cs 的Configure方法内容
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory) { // 添加日志支持 loggerFactory.AddConsole(); loggerFactory.AddDebug(); // 添加NLog日志支持 loggerFactory.AddNLog(); // 添加自定义中间件 app.UseMiddleware<HelloworldMiddleware>(); app.UseMiddleware<HelloworldTooMiddleware>(); // 添加MVC中间件 //app.UseMvc(); }
启动调试,访问页面,能够看到一样的效果。
Map方法
Map方法主要经过请求路径和其余自定义条件过滤来指定注册的中间件,看起来更像一个路由。
修改 Startup.cs 的Configure方法内容,增长静态方法MapTest
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory) { // 添加日志支持 loggerFactory.AddConsole(); loggerFactory.AddDebug(); // 添加NLog日志支持 loggerFactory.AddNLog(); // 添加自定义中间件 app.Map("/test", MapTest); // 添加MVC中间件 //app.UseMvc(); } private static void MapTest(IApplicationBuilder app){ app.Run(async context => { await context.Response.WriteAsync("Url is " + context.Request.PathBase.ToString()); }); }
启动调试,访问路径 http://localhost:5000/test ,页面显示以下内容
可是访问其余路径时,页面没有内容显示。从这个能够看到,Map方法经过相似路由的机制,将特定的Url地址请求引导到固定的方法里,由特定的中间件处理。
另外,Map方法还能够实现多级Url“路由”,其实就是Map方法的嵌套使用
// 添加自定义中间件 app.Map("/level1", lv1App => { app.Map("/level1.1", lv11App => { // /level1/level1.1 }); app.Map("/level1.2", lv12App => { // /level1/level1.2 }); });
也能够经过MapWhen方法使用自定义条件进行“路由”
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory) { // 添加日志支持 loggerFactory.AddConsole(); loggerFactory.AddDebug(); // 添加NLog日志支持 loggerFactory.AddNLog(); // 添加自定义中间件 app.MapWhen(context => { return context.Request.Query.ContainsKey("a"); }, MapTest); // 添加MVC中间件 //app.UseMvc(); } private static void MapTest(IApplicationBuilder app) { app.Run(async context => { await context.Response.WriteAsync($"Url is {context.Request.Path.ToString()}{context.Request.QueryString.Value}"); }); }
启动调试,访问路径 http://localhost:5000/path?a=1&b=2 ,页面显示以下内容
只有当请求参数中含有a时,页面才正常显示内容。
其余内置的中间件
Asp.Net Core框架内置了几个中间件
6.路由(转http://www.javashuo.com/article/p-dbwvkkly-nt.html)
1.API定义
/* * API 定义以下 * GET api/menu 获取菜单列表 * POST api/menu 添加模块 * PUT api/menu 修改模块 * PATCH api/menu 修改菜单信息 * DELETE api/menu 删除模块 */
2.后台代码 :
MenuModelContext _Context = new MenuModelContext(); /// <summary> /// 获取列表 /// </summary> /// <returns></returns> [HttpGet] public IEnumerable<Menu> Get() { List<Menu> list = _Context.Menu.ToList(); return list; } /// <summary> /// 添加模块对象 /// </summary> /// <param name="m"></param> /// <returns></returns> [HttpPost] public bool Add(Model m) { try { m.AddTime = DateTime.Now; _Context.Model.Add(m); _Context.SaveChanges(); return true; } catch (Exception ex) { return false; } } /// <summary> /// 修改模块 /// </summary> /// <param name="m"></param> /// <returns></returns> [HttpPut] public bool Update(Model m) { try { Model oldModel = _Context.Model.Find(m.ModelId); oldModel.ModelName = m.ModelName; oldModel.SortNumber = m.SortNumber; _Context.SaveChanges(); return true; } catch (Exception ex) { return false; } } /// <summary> /// 修改菜单对象 /// </summary> /// <param name="m"></param> /// <returns></returns> [HttpPatch] public IActionResult Update(Menu m) { try { Menu oldMenu = _Context.Menu.Find(m.MenuId); if (oldMenu == null) return NotFound("你要访问的菜单不存在或已经删除"); oldMenu.MenuName = m.MenuName; oldMenu.SortNumber = m.SortNumber; oldMenu.ModelId = m.ModelId; _Context.SaveChanges(); return Ok(); } catch (Exception ex) { return Content(ex.Message); } } /// <summary> /// 删除模块 /// </summary> /// <param name="ids"></param> /// <returns></returns> [HttpDelete] public IActionResult Delete(string ids) { try { if (string.IsNullOrEmpty(ids)) throw new Exception("获取id参数失败"); List<int> idList = ids.Split(',').Select(q => Convert.ToInt32(q)).ToList(); List<Model> list = _Context.Model.Where(q => idList.Contains(q.ModelId)).ToList(); _Context.Model.RemoveRange(list); int count = _Context.SaveChanges(); //使用OkObjectResult 前台jquery自动解析为object对象,不须要进行反序列化处理 //返回的不是字符串 return Ok(new { msg = $"删除成功,总共删除{count}条数据" }); } catch (Exception ex) { //使用ContentResult返回字符串处理 return Content(ex.Message); } }
3.jQuery ajax代码
//Get获取列表数据 function testOne() { $.get(urlHelper.getApi('menu'), {}, function (data) { console.info(data); var menu1 = new Vue({ el: '#menu1', data: { result: data } }); }) } testOne(); //添加菜单 var example2 = new Vue({ el: '#example-2', data: { name:'添加菜单' }, //在 methods 对象中定义方法 methods: { addMenu: function (event) { //使用 Post提交添加菜单 var _this = this; this.name = '正在提交...'; $.post(urlHelper.getApi('menu'), { ModelName: '测试菜单5', SortNumber:5 }, function (data) { console.info(data); _this.name = '提交成功'; }); }, updateModel: function (event) { //使用put提交修改模块 var _this = this; $.ajax({ url: urlHelper.getApi('menu'), type: 'put', data: { ModelId: '4', ModelName: '模块abc', SortNumber: 4 }, success: function (data) { console.info(data); if (data == true) alert('修改为功'); else alert('修改失败'); } }); } } }); //修改菜单、删除模块 var btngroup1 = new Vue({ el: '#btngroup1', data: { name: '修改菜单', name1: '删除模块' }, methods: { updateMenu: function (e) { var _this = this; //使用patch 方式修改菜单 $.ajax({ url: urlHelper.getApi('menu'), type:'patch', data: { MenuID: 1, MenuName: '测试菜单One', SortNumber: 100, ModelID:2 }, success: function (data) { console.info(data); } }); }, deleteMenu: function (e) { //使用delete 提交方式删除模块 $.ajax({ url: urlHelper.getApi('menu'), type: 'delete', data: { ids:[1003] }, success: function (data) { console.info(data); }, error: function (data) { console.info(data); } }); } } });
根据HttpMethod的Template路由示例
1.API定义
/* * API 定义 * GET api/menu/{id} 获取指定ID的菜单对象 * GET api/menu/getmodel 获取模块列表内容 */
[HttpGet("{id}")] public IActionResult Get(int ID) { Menu m = _Context.Menu.Find(ID); if (m == null) return NotFound(); return Json(m); } //特别说明:路由中的Template的值不能够包含斜杠/ [HttpGet("getmodel")] public IActionResult GetModel() { List<Model> list = _Context.Model.ToList(); return Json(list); }
Jquery 的ajax代码
//其余Get方式测试 var btngroup2 = new Vue({ el: '#btngroup2', data: { name: '获取菜单对象', name1: '获取模块列表', item: {} //Vue的对象绑定,没有的状况下须要一个空对象,否则报错 }, methods: { getMenu: function (e) { var _this = this; //连接地址格式 :http://localhost:50000/api/menu/1/ $.get(urlHelper.getApi('menu','1'), { }, function (data) { console.info(data); _this.item = data; }); }, getModel: function (e) { var _this = this; $.get(urlHelper.getApi('menu', 'getmodel'), {}, function (data) { console.info(data); }) } } });
7.Startup
/// <summary> /// 此方法由运行时调用。使用此方法向容器添加服务。 /// </summary> /// <param name="services">For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940</param> /// <returns>DI容器</returns> public IServiceProvider ConfigureServices(IServiceCollection services) { //添加MVC services.AddMvc( // 配置异常过滤器 config => { config.Filters.Add(typeof(CustomExceptionFilter)); } ) // 设置json序列化方式 .AddJsonOptions(mvcJsonOptions => { //忽略循环引用 mvcJsonOptions.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; //不使用驼峰样式的key mvcJsonOptions.SerializerSettings.ContractResolver = new DefaultContractResolver(); //设置时间格式 mvcJsonOptions.SerializerSettings.DateFormatString = Const.yyyyMMddHHmmss; }) .SetCompatibilityVersion(CompatibilityVersion.Version_2_1); services.AddCors(options => { options.AddPolicy("AllowSpecificOrigins", builder => { builder.AllowAnyOrigin() .AllowAnyMethod() .AllowAnyHeader() .AllowCredentials(); }); }); // 注册服务而且实例化AutoFac替换默认容器 var containerBuilder = new ContainerBuilder(); //实例化 AutoFac 容器 // 注册用户服务 containerBuilder.RegisterType<UserService>().As<IUserService>(); containerBuilder.Populate(services); ApplicationContainer = containerBuilder.Build(); return new AutofacServiceProvider(ApplicationContainer); //第三方IOC接管 core内置DI容器 }
/// <summary> /// 此方法由运行时调用。使用此方法配置HTTP请求管道。 /// </summary> /// <param name="app">app</param> /// <param name="env">env</param> public void Configure(IApplicationBuilder app, IHostingEnvironment env) { //if (env.IsDevelopment()) //{ // app.UseDeveloperExceptionPage(); //} //app.UseExceptionHandler( // options => { // options.Run( // async context => // { // context.Response.StatusCode = (int)HttpStatusCode.OK; // context.Response.ContentType = "text/html"; // var ex = context.Features.Get<IExceptionHandlerFeature>(); // if (ex != null) // { // var err = $"<h1>Error: {ex.Error.Message}</h1>{ex.Error.StackTrace }"; // await context.Response.WriteAsync(err).ConfigureAwait(false); // } // }); // } //); //启动跨域 app.UseCors("AllowSpecificOrigins"); //注入MVC路由 app.UseMvc(); }