久久久精品一区ed2k-女人被男人叉到高潮的视频-中文字幕乱码一区久久麻豆樱花-俄罗斯熟妇真实视频

ASP.NETWebAPI控制器創(chuàng)建過(guò)程(一)

ASP.NET Web API 控制器創(chuàng)建過(guò)程(一)

前言

在前面對(duì)管道、路由有了基礎(chǔ)的了解過(guò)后,本篇將帶大家一起學(xué)習(xí)一下在ASP.NET Web API中控制器的創(chuàng)建過(guò)程,這過(guò)程分為幾個(gè)部分下面的內(nèi)容會(huì)為大家講解第一個(gè)部分,也是ASP.NET Web API框架跟ASP.NET MVC框架實(shí)現(xiàn)上存在不同的一部分。

十載的潞州網(wǎng)站建設(shè)經(jīng)驗(yàn),針對(duì)設(shè)計(jì)、前端、開(kāi)發(fā)、售后、文案、推廣等六對(duì)一服務(wù),響應(yīng)快,48小時(shí)及時(shí)工作處理。營(yíng)銷(xiāo)型網(wǎng)站建設(shè)的優(yōu)勢(shì)是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動(dòng)調(diào)整潞州建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無(wú)論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計(jì),從而大程度地提升瀏覽體驗(yàn)。創(chuàng)新互聯(lián)建站從事“潞州網(wǎng)站設(shè)計(jì)”,“潞州網(wǎng)站推廣”以來(lái),每個(gè)客戶項(xiàng)目都認(rèn)真落實(shí)執(zhí)行。

 

ASP.NET Web API 控制器創(chuàng)建、激活過(guò)程

  • ASP.NET Web API控制器創(chuàng)建過(guò)程(一)

  • ASP.NET Web API控制器創(chuàng)建過(guò)程(二)

  • 未完待續(xù)

 

環(huán)境描述、問(wèn)題的發(fā)現(xiàn)

在項(xiàng)目運(yùn)用中,我們大多數(shù)會(huì)把控制器部分從主程序抽離出來(lái)放置單獨(dú)的項(xiàng)目中,這種情況下在使用ASP.NET MVC框架的項(xiàng)目環(huán)境中是不會(huì)有什么問(wèn)題的,因?yàn)镸VC框架在創(chuàng)建控制器的時(shí)候會(huì)加載當(dāng)前主程序引用的所有程序集并且按照?qǐng)?zhí)行的搜索規(guī)則(公共類(lèi)型、實(shí)現(xiàn)IController的)搜索出控制器類(lèi)型并且緩存到xml文件中。而這種方式如果在使用了默認(rèn)的ASP.NET Web API框架環(huán)境下就會(huì)有一點(diǎn)點(diǎn)的問(wèn)題,這里就涉及到了Web API框架的控制器創(chuàng)建過(guò)程中的知識(shí)。來(lái)看一下簡(jiǎn)單的示例。

(示例還是《ASP.NET Web API 開(kāi)篇介紹示例》中的示例,不過(guò)做了略微的修改,符合上述的情況。)

我們還是在SelfHost環(huán)境下做示例,來(lái)看SelfHost環(huán)境下服務(wù)端配置:

示例代碼1-1

   classProgram
   {
        staticvoidMain(string[] args)
        {
            HttpSelfHostConfigurationselfHostConfiguration=
                newHttpSelfHostConfiguration("http://localhost/selfhost");
            using (HttpSelfHostServerselfHostServer=newHttpSelfHostServer(selfHostConfiguration))
            {
                selfHostServer.Configuration.Routes.MapHttpRoute(
                    "DefaultApi", "api/{controller}/{id}", new { id=RouteParameter.Optional });
 
                selfHostServer.OpenAsync();
 
                Console.WriteLine("

代碼1-1就是引用《ASP.NET Web API 開(kāi)篇介紹示例》中的示例,在示例SelfHost項(xiàng)目中定義了API控制器,在這里我們需要把它注釋掉,并且創(chuàng)建新的類(lèi)庫(kù)項(xiàng)目命名為WebAPIController,并且引用System.Web.Http.dll程序集和Common程序集,然后再定義個(gè)API控制器,也就是把原先在SelfHost項(xiàng)目中的控制器移動(dòng)到新建的類(lèi)庫(kù)項(xiàng)目中。

示例代碼1-2

usingSystem.Web.Http;
usingCommon;
 
namespaceWebAPIController
{
   publicclassProductController : ApiController
   {
        privatestaticList<Product>products;
 
        staticProductController()
        {
            products=newList<Product>();
            products.AddRange(
                newProduct[] 
                {
                    newProduct(){ ProductID="001", ProductName="牙刷",ProductCategory="洗漱用品"},
                    newProduct(){ ProductID="002", ProductName="《.NET框架設(shè)計(jì)—大型企業(yè)級(jí)應(yīng)用框架設(shè)計(jì)藝術(shù)》", ProductCategory="書(shū)籍"}
                });
        }
        publicIEnumerable<Product>Get(stringid=null)
        {
            returnfromproductinproductswhereproduct.ProductID==id||string.IsNullOrEmpty(id) selectproduct;
        }
        publicvoidDelete(stringid)
        {
            products.Remove(products.First(product=>product.ProductID==id));
        }
        publicvoidPost(Productproduct)
        {
            products.Add(product);
        }
        publicvoidPut(Productproduct)
        {
            Delete(product.ProductID);
            Post(product);
        }
   }
}

這個(gè)時(shí)候還要記得把SelfHost項(xiàng)目添加WebAPIController項(xiàng)目的引用,要保持跟MVC項(xiàng)目的環(huán)境一樣,然后我們?cè)谶\(yùn)行SelfHost項(xiàng)目,等待監(jiān)聽(tīng)開(kāi)啟過(guò)后再使用瀏覽器請(qǐng)求服務(wù)會(huì)發(fā)現(xiàn)如下圖所示的結(jié)果。

圖1

ASP.NET Web API 控制器創(chuàng)建過(guò)程(一)

看到圖1中的顯示問(wèn)題了吧,未找到匹配的控制器類(lèi)型。如果是MVC項(xiàng)目則不會(huì)有這樣的問(wèn)題,那么問(wèn)題出在哪呢?實(shí)現(xiàn)方式的差異,下面就為大家來(lái)解釋一下。

 

解決問(wèn)題

在上一篇中我們最后的示意圖里可以清晰的看到ASP.NET Web API框架中的管道模型最后是通過(guò)HttpControllerDispatcher類(lèi)型的對(duì)象來(lái)“生成”的APIController。我們現(xiàn)在就來(lái)看一下HttpControllerDispatcher類(lèi)型的定義。

示例代碼1-3

   publicclassHttpControllerDispatcher : HttpMessageHandler
   {
        //Fields
        privatereadonlyHttpConfiguration_configuration;
        privateIHttpControllerSelector_controllerSelector;
 
        //Methods
        publicHttpControllerDispatcher(HttpConfigurationconfiguration);
        privatestaticHttpResponseMessageHandleException(HttpRequestMessagerequest, Exceptionexception);
        protectedoverrideTask<HttpResponseMessage>SendAsync(HttpRequestMessagerequest, CancellationTokencancellationToken);
        privateTask<HttpResponseMessage>SendAsyncInternal(HttpRequestMessagerequest, CancellationTokencancellationToken);
 
        //Properties
        publicHttpConfigurationConfiguration { get; }
        privateIHttpControllerSelectorControllerSelector { get; }
    }

從示例代碼1-3中可以看到HttpControllerDispatcher類(lèi)型繼承自HttpMessageHandler類(lèi)型,由此可見(jiàn),通過(guò)前面《ASP.NETWeb API 管道模型》篇幅的知識(shí)我們了解到在ASP.NET Web API管道的最后一個(gè)消息處理程序?qū)嶋H是HttpControllerDispatcher類(lèi)型,在Web API框架調(diào)用HttpControllerDispatcher類(lèi)型的SendAsync()方法時(shí)實(shí)際是調(diào)用了HttpControllerDispatcher類(lèi)型的一個(gè)私有方法SendAsyncInternal(),而APIController就是在這個(gè)私有方法中生成的,當(dāng)然不是由這個(gè)私有方法來(lái)生成它的。下面我們就來(lái)看一下SendAsyncInternal()的基礎(chǔ)實(shí)現(xiàn)。

示例代碼1-4

   privateTask<HttpResponseMessage>SendAsyncInternal(HttpRequestMessagerequest, CancellationTokencancellationToken)
   {
        IHttpRouteDatarouteData=request.GetRouteData();
        HttpControllerDescriptordescriptor=this.ControllerSelector.SelectController(request);
        IHttpControllercontroller=descriptor.CreateController(request);
   }

代碼1-4很清晰的說(shuō)明了APIController的生成過(guò)程,這只是片面的,這里的代碼并不是全部,我們現(xiàn)在只需關(guān)注APIController的生成過(guò)程,暫時(shí)不去關(guān)心它的執(zhí)行過(guò)程。

首先由HttpControllerDispatcher類(lèi)型中的一個(gè)類(lèi)型為IHttpControllerSelector的屬性ControllerSelector(實(shí)則是DefaultHttpControllerSelector類(lèi)型)根據(jù)HttpRequestMessage參數(shù)類(lèi)型來(lái)調(diào)用IHttpControllerSelector類(lèi)型里的SelectController()方法,由此獲取到HttpControllerDescriptor類(lèi)型的變量descriptor,然后由變量descriptor調(diào)用它的CreateController()方法來(lái)創(chuàng)建的控制器。

說(shuō)到這里看似一個(gè)簡(jiǎn)單的過(guò)程里面蘊(yùn)含的知識(shí)還是有一點(diǎn)的,我們首先來(lái)看ControllerSelector屬性

示例代碼1-5

   privateIHttpControllerSelectorControllerSelector
   {
        get
        {
            if (this._controllerSelector==null)
            {
                this._controllerSelector=this._configuration.Services.GetHttpControllerSelector();
            }
            returnthis._controllerSelector;
        }
    }

這里我們可以看到是由HttpConfiguration類(lèi)型的變量_configuration中的Servieces(服務(wù)容器)來(lái)獲取的IHttpControllerSelector類(lèi)型的對(duì)象。那我們獲取到的究竟實(shí)例是什么類(lèi)型的?

 

到這里先暫停,大家先不用記住上面的一堆廢話中的內(nèi)容,現(xiàn)在我們來(lái)看一下HttpConfiguration這個(gè)類(lèi)型,我們現(xiàn)在只看HttpConfiguration類(lèi)型,忘掉上面的一切。

示例代碼1-6

   publicclassHttpConfiguration : IDisposable
   {
        //Fields
        privateIDependencyResolver_dependencyResolver;
 
        //Methods
        publicHttpConfiguration();
        publicHttpConfiguration(HttpRouteCollectionroutes);
        privateHttpConfiguration(HttpConfigurationconfiguration, HttpControllerSettingssettings);
 
        publicIDependencyResolverDependencyResolver { get; set; }
        publicServicesContainerServices { get; internalset; }
 
   }

在這里我們看到有字段、構(gòu)造函數(shù)和屬性,對(duì)于_dependencyResolver字段和對(duì)應(yīng)的屬性我們下面會(huì)有講到這里就不說(shuō)了。這里主要就是說(shuō)明一下ServicesContainer 類(lèi)型的Services屬性。對(duì)于ServicesContainer類(lèi)型沒(méi)用的朋友可能不太清楚,實(shí)際上可以把ServicesContainer類(lèi)型想象成一個(gè)IoC容器,就和IDependencyResolver類(lèi)型的作用是一樣的,在前面的《C#編程模式之?dāng)U展命令》一文中有涉及到ServicesContainer類(lèi)型的使用,感興趣的朋友可以去看看。

回到主題,在構(gòu)造函數(shù)執(zhí)行時(shí)ServicesContainer類(lèi)型實(shí)例實(shí)際是由它的子類(lèi)DefaultServices類(lèi)型實(shí)例化而來(lái)的。而在DefaultServices類(lèi)型實(shí)例化的時(shí)候它的構(gòu)造函數(shù)中會(huì)將一些服務(wù)和具體實(shí)現(xiàn)的類(lèi)型添加到緩存里。

圖2

ASP.NET Web API 控制器創(chuàng)建過(guò)程(一)

在圖2中我們現(xiàn)在只需關(guān)注第二個(gè)紅框中的IHttpControllerSelector對(duì)應(yīng)的具體服務(wù)類(lèi)型是DefaultHttpControllerSelector類(lèi)型。

現(xiàn)在我們?cè)賮?lái)看代碼1-5中的GetHttpControllerSelector()方法,它是有ServicesExtensions擴(kuò)展方法類(lèi)型來(lái)實(shí)現(xiàn)的。

 

好了現(xiàn)在大家的思緒可以回到代碼1-4中,現(xiàn)在我們知道是由DefaultHttpControllerSelector類(lèi)型的SelectController()方法來(lái)生成HttpControllerDescriptor類(lèi)型的。暫時(shí)不用管HttpControllerDescriptor類(lèi)型,我們先來(lái)看SelectController()方法中的實(shí)現(xiàn)細(xì)節(jié)。

示例代碼1-7

publicvirtualHttpControllerDescriptorSelectController(HttpRequestMessagerequest)
   {
        HttpControllerDescriptordescriptor;
 
        stringcontrollerName=this.GetControllerName(request);
        if (this._controllerInfoCache.Value.TryGetValue(controllerName, outdescriptor))
        {
            returndescriptor;
        }
   }

這里可以看到controllerName是由路由數(shù)據(jù)對(duì)象RouteData來(lái)獲取的,然后由_controllerInfoCache變量根據(jù)控制器名稱(chēng)獲取到HttpControllerDescriptor實(shí)例,這里HttpControllerDescriptor實(shí)例我們暫且不管,后面的篇幅會(huì)有講到。

重點(diǎn)是我們看一下_controllerInfoCache變量中的值是怎么來(lái)的?是從HttpControllerTypeCache類(lèi)型的Cache屬性值而來(lái)。而Cache的值則是根據(jù)HttpControllerTypeCache類(lèi)型的中的InitializeCache()方法得來(lái)的,我們看下實(shí)現(xiàn)。

實(shí)例代碼1-8

 

   privateDictionary<string, ILookup<string, Type>>InitializeCache()
   {
        IAssembliesResolverassembliesResolver=this._configuration.Services.GetAssembliesResolver();
       returnthis._configuration.Services.GetHttpControllerTypeResolver().GetControllerTypes(assembliesResolver).GroupBy<Type, string>(t=>t.Name.Substring(0, t.Name.Length-DefaultHttpControllerSelector.ControllerSuffix.Length), StringComparer.OrdinalIgnoreCase).ToDictionary<IGrouping<string, Type>, string, ILookup<string, Type>>(g=>g.Key, g=>g.ToLookup<Type, string>(t=> (t.Namespace??string.Empty), StringComparer.OrdinalIgnoreCase), StringComparer.OrdinalIgnoreCase);
    }

還記得文章的主題嗎?回想一下,在本篇幅的內(nèi)容只涉及到代碼1-8的第一句代碼,后面篇幅會(huì)繼續(xù)往下講解,我們就來(lái)看一下第一句代碼。

第一句是獲取IAssembliesResolver類(lèi)型的實(shí)例assembliesResolver,而之對(duì)應(yīng)的服務(wù)則是在圖2中顯示出來(lái)了,就是DefaultAssembliesResolver類(lèi)型,DefaultAssembliesResolver類(lèi)型控制著框架搜尋的程序集范圍,罪魁禍?zhǔn)自谶@。

示例代碼1-9

   publicclassDefaultAssembliesResolver : IAssembliesResolver
   {
        //Methods
        publicvirtualICollection<Assembly>GetAssemblies()
        {
            returnAppDomain.CurrentDomain.GetAssemblies().ToList<Assembly>();
        }
   }

看到這里大家應(yīng)該明白了,在SelfHost環(huán)境下的服務(wù)端啟動(dòng)之后就沒(méi)有加載我們所想要的WebAPIController程序集,所以才會(huì)有圖1所示的問(wèn)題。這個(gè)我們可以來(lái)查看一下。

將1-1代碼修改如示例代碼1-10.

代碼1-10

   classProgram
   {
        staticvoidMain(string[] args)
        {
            HttpSelfHostConfigurationselfHostConfiguration=
                newHttpSelfHostConfiguration("http://localhost/selfhost");
            using (HttpSelfHostServerselfHostServer=newHttpSelfHostServer(selfHostConfiguration))
            {
                selfHostServer.Configuration.Routes.MapHttpRoute(
                    "DefaultApi", "api/{controller}/{id}", new { id=RouteParameter.Optional });
 
                selfHostServer.OpenAsync();
                foreach (AssemblyassemblyinAppDomain.CurrentDomain.GetAssemblies())
                {
                    Console.WriteLine(assembly.FullName.Substring(0,assembly.FullName.IndexOf("Version")));
                }
                Console.WriteLine("服務(wù)器端服務(wù)監(jiān)聽(tīng)已開(kāi)啟");
                Console.Read();
            }
            
        }
}

這個(gè)時(shí)候我們啟動(dòng)SelfHost項(xiàng)目,就可以查看到到底有沒(méi)有我們想要的程序集,如圖3。

圖3

ASP.NET Web API 控制器創(chuàng)建過(guò)程(一)

可以看一下,根本沒(méi)有我們所需的,那怎么樣才能正常的運(yùn)行起來(lái)如一開(kāi)始所說(shuō)的那樣呢?

示例代碼1-11

usingSystem.Web.Http.Dispatcher;
usingSystem.Reflection;
 
namespaceSelfHost.CustomAssembliesResolver
{
   publicclassLoadSpecifiedAssembliesResolver : IAssembliesResolver
   {
 
        publicICollection<Assembly>GetAssemblies()
        {
            AppDomain.CurrentDomain.Load("WebAPIController");
            returnAppDomain.CurrentDomain.GetAssemblies();
        }
   }
}

我們通過(guò)自定義AssembliesResolver來(lái)加載我們指定的程序集,并且最后要把我們實(shí)現(xiàn)的替換到Web API框架中,如下代碼。

示例代碼1-12

   classProgram
   {
        staticvoidMain(string[] args)
        {
            HttpSelfHostConfigurationselfHostConfiguration=
                newHttpSelfHostConfiguration("http://localhost/selfhost");
            using (HttpSelfHostServerselfHostServer=newHttpSelfHostServer(selfHostConfiguration))
            {
                selfHostServer.Configuration.Routes.MapHttpRoute(
                    "DefaultApi", "api/{controller}/{id}", new { id=RouteParameter.Optional });
 
                selfHostServer.Configuration.Services.Replace(typeof(IAssembliesResolver),
                    newCustomAssembliesResolver.LoadSpecifiedAssembliesResolver());
 
                selfHostServer.OpenAsync();
                Console.WriteLine("服務(wù)器端服務(wù)監(jiān)聽(tīng)已開(kāi)啟");
                Console.Read();
            }
            
        }
}

這個(gè)時(shí)候我們?cè)龠\(yùn)行SelfHost項(xiàng)目,并且使用瀏覽器來(lái)請(qǐng)求,最后結(jié)果如圖4.

圖4

ASP.NET Web API 控制器創(chuàng)建過(guò)程(一)

WebHost環(huán)境

在WebHost環(huán)境中則不會(huì)發(fā)生上述所描述的問(wèn)題,為什么?

示例代碼1-13

   publicclassGlobal : System.Web.HttpApplication
   {
        protectedvoidApplication_Start(objectsender, EventArgse)
        {
            GlobalConfiguration.Configuration.Routes.MapHttpRoute(
              "DefaultAPI", "api/{controller}/{id}", new { controller="product",id=RouteParameter.Optional });
            
        }
}

代碼1-13表示著WebHost環(huán)境下的路由注冊(cè),看起來(lái)比SelfHost環(huán)境要簡(jiǎn)便的多。因?yàn)椤昂?jiǎn)便”封裝在GlobalConfiguration類(lèi)型中了,前面的文章也對(duì)GlobalConfiguration類(lèi)型做過(guò)介紹,不過(guò)并沒(méi)有把重點(diǎn)放到IAssembliesResolver服務(wù)上?,F(xiàn)在我們來(lái)看一下實(shí)現(xiàn)。

示例代碼1-14

privatestaticLazy<HttpConfiguration>_configuration=newLazy<HttpConfiguration>(delegate {
            HttpConfigurationconfiguration=newHttpConfiguration(newHostedHttpRouteCollection(RouteTable.Routes));
            configuration.Services.Replace(typeof(IAssembliesResolver), newWebHostAssembliesResolver());
            configuration.Services.Replace(typeof(IHttpControllerTypeResolver), newWebHostHttpControllerTypeResolver());
            configuration.Services.Replace(typeof(IHostBufferPolicySelector), newWebHostBufferPolicySelector());
            returnconfiguration;
        });

我們可以清楚的看到DefaultAssembliesResolver類(lèi)型被替換成了WebHostAssembliesResolver類(lèi)型。為什么WebHost不會(huì)有這樣的問(wèn)題就都在WebHostAssembliesResolver類(lèi)型當(dāng)中了。

示例代碼1-15

   internalsealedclassWebHostAssembliesResolver : IAssembliesResolver
   {
        //Methods
        ICollection<Assembly>IAssembliesResolver.GetAssemblies()
        {
            returnBuildManager.GetReferencedAssemblies().OfType<Assembly>().ToList<Assembly>();
        }
}

把WebHost環(huán)境中的結(jié)構(gòu)修改的和SelfHost環(huán)境中的一樣,然后請(qǐng)求則會(huì)發(fā)現(xiàn)不會(huì)遇到什么問(wèn)題。

圖5

ASP.NET Web API 控制器創(chuàng)建過(guò)程(一)

 

下一篇將會(huì)講解一下APIController的生成過(guò)程,也就是代碼1-8的第二句代碼部分。

當(dāng)前標(biāo)題:ASP.NETWebAPI控制器創(chuàng)建過(guò)程(一)
本文路徑:http://sd-ha.com/article12/iedhdc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供面包屑導(dǎo)航品牌網(wǎng)站建設(shè)、手機(jī)網(wǎng)站建設(shè)、微信小程序、虛擬主機(jī)響應(yīng)式網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

網(wǎng)站建設(shè)網(wǎng)站維護(hù)公司