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(); }