




版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、ASP.NET MVC In-Depth: The Life of an ASP.NET MVC Request The purpose of this blog entry is to describe, in painful detail, each step in the life of an ASP.NET MVC request from birth to death. I want to understand everything that happens when you type a URL in a browser and hit the enter key when req
2、uesting a page from an ASP.NET MVC website.Why do I care? There are two reasons. First, one of the promises of ASP.NET MVC is that it will be a very extensible framework. For example, youll be able to plug in different view engines to control how your website content is rendered. You also will be ab
3、le to manipulate how controllers get generated and assigned to particular requests. I want to walk through the steps involved in an ASP.NET MVC page request because I want to discover any and all of these extensibility points.Second, Im interested in Test-Driven Development. In order to write unit t
4、ests for controllers, I need to understand all of the controller dependencies. When writing my tests, I need to mock certain objects using a mocking framework such as Typemock Isolator or Rhino Mocks. If I dont understand the page request lifecycle, I wont be able to effectively mock it.Two Warnings
5、But first, two warnings.Here's the first warning: Im writing this blog entry a week after the ASP.NET MVC Preview 2 was publicly released. The ASP.NET MVC framework is still very much in Beta. Therefore, anything that I describe in this blog entry might be outdated and, therefore, wrong in a cou
6、ple of months. So, if you are reading this blog entry after May 2008, dont believe everything you read.Second, this blog entry is not meant as an overview of ASP.NET MVC. I describe the lifecycle of an ASP.NET MVC request in excruciating and difficult to read detail. Okay, you have been warned.Overv
7、iew of the Lifecycle StepsThere are five main steps that happen when you make a request from an ASP.NET MVC website:1. Step 1 The RouteTable is CreatedThis first step happens only once when an ASP.NET application first starts. The RouteTable maps URLs to handlers.2. Step 2 The UrlRoutingModule Inter
8、cepts the RequestThis second step happens whenever you make a request. The UrlRoutingModule intercepts every request and creates and executes the right handler.3. Step 3 The MvcHandler ExecutesThe MvcHandler creates a controller, passes the controller a ControllerContext, and executes the controller
9、.4. Step 4 The Controller ExecutesThe controller determines which controller method to execute, builds a list of parameters, and executes the method.5. Step 5 The RenderView Method is CalledTypically, a controller method calls RenderView() to render content back to the browser. The Controller.Render
10、View() method delegates its work to a particular ViewEngine.Lets examine each of these steps in detail.Step 1 : The RouteTable is CreatedWhen you request a page from a normal ASP.NET application, there is a page on disk that corresponds to each page request. For example, if you request a page named
11、SomePage.aspx then there better be a page named SomePage.aspx sitting on your web server. If not, you receive an error.Technically, an ASP.NET page represents a class. And, not just any class. An ASP.NET page is a handler. In other words, an ASP.NET page implements the IHttpHandler interface and has
12、 a ProcessRequest() method that gets called when you request the page. The ProcessRequest() method is responsible for generating the content that gets sent back to the browser.So, the way that a normal ASP.NET application works is simple and intuitive. You request a page, the page request correspond
13、s to a page on disk, the page executes its ProcessRequest() method and content gets sent back to the browser.An ASP.NET MVC application does not work like this. When you request a page from an ASP.NET MVC application, there is no page on disk that corresponds to the request. Instead, the request is
14、routed to a special class called a controller. The controller is responsible for generating the content that gets sent back to the browser.When you write a normal ASP.NET application, you build a bunch of pages. There is always a one-to-one mapping between URLs and pages. Corresponding to each page
15、request, there better be a page.When you build an ASP.NET MVC application, in contrast, you build a bunch of controllers. The advantage of using controllers is that you can have a many-to-one mapping between URLs and pages. For example, all of the following URLs can be mapped to the same controller:
16、The single controller mapped to these URLs can display product information for the right product by extracting the product Id from the URL. The controller approach is more flexible than the classic ASP.NET approach. The controller approach also results in more readable and intuitive URLs. So, how do
17、es a particular page request get routed to a particular controller? An ASP.NET MVC application has something called a Route Table. The Route Table maps particular URLs to particular controllers.An application has one and only one Route Table. This Route Table is setup in the Global.asax file. Listin
18、g 1 contains the default Global.asax file that you get when you create a new ASP.NET MVC Web Application project by using Visual Studio.An applications Route Table is represented by the static RouteTable.Routes property. This property represents a collection of Route objects. In the Global.asax file
19、 in Listing 1, two Route objects are added to the Route Table when the application first starts (The Application_Start() method is called only once when the very first page is requested from a website).A Route object is responsible for mapping URLs to handlers. In Listing 1, two Route objects are cr
20、eated. Both Route objects map URLs to the MvcRouteHandler. The first Route maps any URL that follows the pattern controller/action/id to the MvcRouteHandler. The second Route maps the particular URL Default.aspx to the MvcRouteHandler.By the way, this new routing infrastructure can be used independe
21、ntly of an ASP.NET MVC application. The Global.asax file maps URLs to the MvcRouteHandler. However, you have the option of routing URLs to a different type of handler. The routing infrastructure described in this section is contained in a distinct assembly named System.Web.Routing.dll. You can use t
22、he routing without using the MVC. Step 2 : The UrlRoutingModule Intercepts the RequestWhenever you make a request against an ASP.NET MVC application, the request is intercepted by the UrlRoutingModule HTTP Module. An HTTP Module is a special type of class that participates in each and every page req
23、uest. For example, classic ASP.NET includes a FormsAuthenticationModule HTTP Module that is used to implement page access security using Forms Authentication.When the UrlRoutingModule intercepts a request, the first thing the module does is to wrap up the current HttpContext in an HttpContextWrapper
24、2 object. The HttpContextWrapper2 class, unlike the normal HttpContext class, derives from the HttpContextBase class. Creating a wrapper for HttpContext makes it easier to mock the class when you are using a Mock Object Framework such as Typemock Isolator or Rhino Mocks. Next, the module passes the
25、wrapped HttpContext to the RouteTable that was setup in the previous step. The HttpContext includes the URL, form parameters, query string parameters, and cookies associated with the current request. If a match can be made between the current request and one of the Route objects in the Route Table,
26、then a RouteData object is returned. If the UrlRoutingModule successfully retrieves a RouteData object then the module next creates a RouteContext object that represents the current HttpContext and RouteData. The module then instantiates a new HttpHandler based on the RouteTable and passes the Route
27、Context to the new handlers constructor. In the case of an ASP.NET MVC application, the handler returned from the RouteTable will always be an MvcHandler (The MvcRouteHandler returns an MvcHandler). Whenever the UrlRoutingModule can match the current request against a Route in the Route Table, an Mv
28、cHandler is instantiated with the current RouteContext. The last step that the module performs is setting the MvcHandler as the current HTTP Handler. An ASP.NET application calls the ProcessRequest() method automatically on the current HTTP Handler which leads us to the next step.Step 3 : The MvcHan
29、dler ExecutesIn the previous step, an MvcHandler that represents a particular RouteContext was set as the current HTTP Handler. An ASP.NET application always fires off a certain series of events including Start, BeginRequest, PostResolveRequestCache, PostMapRequestHandler, PreRequestHandlerExecute,
30、and EndRequest events (there are a lot of application events for a complete list, lookup the HttpApplication class in the Microsoft Visual Studio 2008 Documentation).Everything described in the previous section happens during the PostResolveRequestCache and PostMapRequestHandler events. The ProcessR
31、equest() method is called on the current HTTP Handler right after the PreRequestHandlerExecute event.When ProcessRequest() is called on the MvcHandler object created in the previous section, a new controller is created. The controller is created from a ControllerFactory. This is an extensibility poi
32、nt since you can create your own ControllerFactory. The default ControllerFactory is named, appropriately enough, DefaultControllerFactory.The RequestContext and the name of the controller are passed to the ControllerFactory.CreateController() method to get a particular controller. Next, a Controlle
33、rContext object is constructed from the RequestContext and the controller. Finally, the Execute() method is called on the controller class. The ControllerContext is passed to the Execute() method when the Execute() method is called.Step 4 : The Controller ExecutesThe Execute() method starts by creat
34、ing the TempData object (called the Flash object in the Ruby on Rails world). The TempData can be used to store temporary data that must be used with the very next request (TempData is like Session State with no long-term memory).Next, the Execute() method builds a list of parameters from the reques
35、t. These parameters, extracted from the request parameters, will act as method parameters. The parameters will be passed to whatever controller method gets executed.The Execute() method finds a method of the controller to execute by using reflection on the controller class (.NET reflection and not n
36、avel gazing reflection). The controller class is something that you wrote. So the Execute() method finds one of the methods that you wrote for your controller class and executes it. The Execute() method will not execute any controller methods that are decorated with the NonAction attribute.At this p
37、oint in the lifecycle, weve entered your application code. Step 5 : The RenderView Method is CalledNormally, your controller methods end with a call to either the RenderView() or RedirectToAction() method. The RenderView() method is responsible for rendering a view (a page) to the browser.When you c
38、all a controllers RenderView() method, the call is delegated to the current ViewEngines RenderView() method. The ViewEngine is another extensibility point. The default ViewEngine is the WebFormViewEngine. However, you can use another ViewEngine such as the NHaml ViewEngine.The WebFormViewEngine.Rend
39、erView() method uses a class named the ViewLocator class to find the view. Next, it uses a BuildManager to create an instance of a ViewPage class from its path. Next, if the page has a master page, the location of the master page is set (again, using the ViewLocator class). If the page has ViewData,
40、 the ViewData is set. Finally, the RenderView() method is called on the ViewPage.The ViewPage class derives from the base System.Web.UI.Page class. This is the same class that is used for pages in classic ASP.NET. The final action that RenderView() method performs is to call ProcessRequest() on the
41、page class. Calling ProcessRequest() generates content from the view in the same way that content is generated from a normal ASP.NET page.Extensibility PointsThe ASP.NET MVC lifecycle was designed to include a number of extensibility points. These are points where you can customize the behavior of t
42、he framework by plugging in a custom class or overriding an existing class. Heres a summary of these extensibility points:1. Route objects When you build the Route Table, you call the RouteCollection.Add() method to add new Route objects. The Add() method accepts a RouteBase object. You can implemen
43、t your own Route objects that inherit from the base RouteBase class.2. MvcRouteHandler When building an MVC application, you map URLs to MvcRouteHandler objects. However, you can map a URL to any class that implements the IRouteHandler interface. The constructor for the Route class accepts any objec
44、t that implements the IRouteHandler interface.3. MvcRouteHandler.GetHttpHandler() The GetHttpHandler() method of the MvcRouteHandler class is a virtual method. By default, an MvcRouteHandler returns an MvcHandler. If you prefer, you can return a different handler by overriding the GetHttpHandler() m
45、ethod.4. ControllerFactory You can assign a custom class by calling the System.Web.MVC.ControllerBuilder.Current.SetControllerFactory() method to create a custom controller factory. The controller factory is responsible for returning controllers for a given controller name and RequestContext.5. Cont
46、roller You can implement a custom controller by implementing the IController interface. This interface has a single method: Execute(ControllerContext controllerContext).6. ViewEngine You can assign a custom ViewEngine to a controller. You assign a ViewEngine to a controller by assigning a ViewEngine
47、 to the public Controller.ViewEngine property. A ViewEngine must implement the IViewEngine interface which has a single method: RenderView(ViewContext viewContext). 7. ViewLocator The ViewLocator maps view names to the actual view files. You can assign a custom ViewLocator to the default WebFormView
48、Engine.ViewLocator property.If you can think of any other extensibility points that I overlooked, please add a comment to this blog post and I will update this entry.SummaryThe goal of this blog entry was to describe the entire life of an ASP.NET MVC request from birth to death. I examined the five
49、steps involved in processing an ASP.NET MVC request: Creating the RouteTable, Intercepting the request with the UrlRoutingModule, Generating a Controller, Executing an Action, and Rendering a View. Finally, I talked about the points at which the ASP.NET MVC Framework can be extended. 探究ASP.NET MVC:
50、ASP.NET MVC請(qǐng)求的生命周期本書(shū)詳細(xì)描述了ASP.NET MVC請(qǐng)求從開(kāi)始到結(jié)束的整個(gè)過(guò)程,當(dāng)你在瀏覽器上輸入U(xiǎn)RL地址并且在ASP.NET網(wǎng)站請(qǐng)求頁(yè)面敲擊回車(chē)時(shí),這個(gè)過(guò)程就產(chǎn)生了。我探究這個(gè)過(guò)程的原因有兩點(diǎn)。第一,ASP.NET MVC的功能之一在于它是一個(gè)擴(kuò)展性的類(lèi)庫(kù)。例如,你可以通過(guò)視圖引擎來(lái)控制網(wǎng)站頁(yè)面呈現(xiàn)的方式,也可以操作控制器的產(chǎn)生方式以及指派給特定的請(qǐng)求到控制器,之所以我粗略地解釋ASP.NET MVC頁(yè)面產(chǎn)生的過(guò)程,是因?yàn)槲蚁朐敿?xì)的講述它的擴(kuò)展性能。第二,我對(duì)頁(yè)面驅(qū)動(dòng)開(kāi)發(fā)方式非常感興趣。為了詳談控制器這塊,就必須了解和控制器相關(guān)的東西,本書(shū)采用模擬類(lèi)似于Typemock
51、,Isolator,Rhino特定對(duì)象的方式來(lái)講述,但是要有效的模擬它,必須理解請(qǐng)求頁(yè)面的整個(gè)生命周期。注意:注意一:由于本書(shū)寫(xiě)于ASP.NET MVC Preview 2發(fā)行一星期后,且ASP.NET MVC 類(lèi)庫(kù)處于第二測(cè)試階段,所以本書(shū)描述中可能會(huì)出現(xiàn)過(guò)時(shí)的內(nèi)容,敬請(qǐng)諒解!但是如果在2008年5月之前閱讀本書(shū),相信會(huì)有意想不到的好處。注意二:本書(shū)并不是對(duì)ASP.NET MVC的整個(gè)講述,而僅僅局限于對(duì)SP.NET MVC請(qǐng)求的生命周期。主要步驟:當(dāng)你在ASP.NET MVC網(wǎng)站發(fā)出一個(gè)頁(yè)面請(qǐng)求時(shí)主要會(huì)產(chǎn)生五個(gè)步驟:1. 創(chuàng)建RoutetTable當(dāng)你第一次運(yùn)行ASP.NET應(yīng)用程序時(shí)Ro
52、uteTable就被創(chuàng)建,RouteTable通過(guò)URL來(lái)繪制handler。2. UrlRoutingMoudule 截獲請(qǐng)求當(dāng)你發(fā)出一個(gè)請(qǐng)求時(shí),這個(gè)步驟就發(fā)生了,UrlRoutingModule截獲所有的請(qǐng)求,并且創(chuàng)建和執(zhí)行正確的handler.3. 執(zhí)行MvcHandlerMvcHandler創(chuàng)建一個(gè)控制器,將ControlContext傳遞給控制器,并且執(zhí)行控制器。4. 執(zhí)行控制器控制器將決定控制器執(zhí)行的方式,建立一個(gè)參數(shù)表,并且執(zhí)行這個(gè)方法。5. 調(diào)用RenderView一般來(lái)說(shuō),控制器調(diào)用RenderView將執(zhí)行結(jié)果返回給瀏覽器。之后控制器的RenderView方法將工作委托給專(zhuān)
53、門(mén)的引擎?,F(xiàn)在開(kāi)始詳細(xì)的講解這些步驟1.創(chuàng)建RouteTable當(dāng)你從ASP.NET應(yīng)用程序中發(fā)出一個(gè)請(qǐng)求時(shí),在磁盤(pán)上將相應(yīng)地生成一個(gè)頁(yè)面請(qǐng)求。例如,如果你請(qǐng)求了一個(gè)稱(chēng)SomePage.aspx的頁(yè)面,最好在Web服務(wù)器上也將這個(gè)頁(yè)面被命名為SomePage.aspx,否則的話(huà),將會(huì)發(fā)出一個(gè)錯(cuò)誤報(bào)告。從技術(shù)上來(lái)說(shuō),ASP.NET頁(yè)面相當(dāng)于一個(gè)類(lèi),同時(shí)也是個(gè)handler.換句話(huà)說(shuō),ASP.NET繼承了IHttpHandler接口,且當(dāng)獲得請(qǐng)求時(shí)會(huì)生成ProcessRequest()方法。這個(gè)方式是生成結(jié)果并將執(zhí)行結(jié)果返回到瀏覽器的。因此,ASP.NET程序的運(yùn)行方式是簡(jiǎn)單的,首先創(chuàng)建一個(gè)頁(yè)面,
54、相應(yīng)的在磁盤(pán)上也生成同樣的頁(yè)面,然后執(zhí)行ProcessRequest()方法,并將結(jié)果返回給瀏覽器。而ASP.NET MVC程序并不是這樣工作的。當(dāng)你在ASP.NET MVC網(wǎng)站上發(fā)出一個(gè)請(qǐng)求,并不會(huì)在磁盤(pán)上相應(yīng)地生成這個(gè)頁(yè)面,相反,這個(gè)請(qǐng)求被定位到成為控制器的類(lèi)中,這個(gè)控制器將生成執(zhí)行結(jié)果并將它返回給瀏覽器。在ASP.NET程序中,將會(huì)生成一系列的頁(yè)面,并總要將路徑和頁(yè)面一一對(duì)應(yīng)。但是在ASP.NET MVC程序中,相比之下,會(huì)產(chǎn)生一些控制器,使用控制器的好處就是可以使路徑和頁(yè)面形成多對(duì)一的關(guān)系。例如,下面的路徑將會(huì)好、放在同樣的控制器中:和這些路徑匹配的控制器能夠通過(guò)URL中的產(chǎn)品ID號(hào)來(lái)
55、準(zhǔn)確的顯示相應(yīng)的產(chǎn)品信息,這樣比較起來(lái),控制器比ASP.NET具有更多的靈活性和可讀性。但是,控制器是怎樣定位到指定頁(yè)面的呢?ASP.NET MVC具有Route Table ,這個(gè)可以將控制器和頁(yè)面的路徑想對(duì)應(yīng)起來(lái)。一個(gè)程序有且僅有一個(gè)Route Table,這個(gè)Route Table放置在Global.asax文件中,圖1是當(dāng)你在Visual Studio中建立ASP.NET MVC程序時(shí)默認(rèn)的Global.asax文件。 程序中的RouteTable可以用靜態(tài)的RouteTable屬性表示,這個(gè)屬性是由一系列的Route對(duì)象組成。在圖1中的Global.asax文件中,當(dāng)程序第一次運(yùn)行時(shí)
56、(頁(yè)面第一次在網(wǎng)站中生成時(shí)程序中的Start()方法才第一次運(yùn)行)兩個(gè)Route對(duì)象將被增加到RouteTable中。Route對(duì)象是用來(lái)處理URL和handler之間的匹配關(guān)系,在圖1中,當(dāng)兩個(gè)Route對(duì)象被創(chuàng)建時(shí),它們都用來(lái)匹配URL和MvcRouteHandler.第一個(gè)Route對(duì)象是將所有的URL和MvcRouteHandler進(jìn)行匹配。然而,你可以選擇將URL和不同類(lèi)型的handler想對(duì)應(yīng)。這個(gè)這個(gè)Route結(jié)構(gòu)的描述被包含在稱(chēng)之為System.web.routing.dll的程序集中,它是和程序想隔離開(kāi)的,所以,在沒(méi)有MVC的情況下也是可以使用Route對(duì)象的。2.UrlRo
57、utingModlue截獲請(qǐng)求當(dāng)你在ASP.NET MVC程序中發(fā)出一個(gè)請(qǐng)求時(shí),就將會(huì)被UrlRoutingModule截獲。在每一個(gè)頁(yè)面請(qǐng)求中,都會(huì)有個(gè)特定的HTTP單元,例如,在ASP.NET頁(yè)面中包含F(xiàn)ormsAuthenticationModule HTTP 模型,功能是在Forms權(quán)限下執(zhí)行頁(yè)面的。當(dāng)UrlRoutingModule截獲請(qǐng)求時(shí),這個(gè)模型首先要做的就是將當(dāng)前的HttpContext包裹在在HttpContextWrapper2對(duì)象中。HttpContextWrapper2和HttpContext不同,當(dāng)你在使用類(lèi)似于Typemock,Isolator,Rhino對(duì)象時(shí),
58、這個(gè)模型是非常容易模擬的。接下來(lái),這個(gè)模型將被包裹的HttpContext傳遞給先前講述的RouteTable中,HttpContext包括URL,C參數(shù)類(lèi)型,查詢(xún)字符串參數(shù),以及和請(qǐng)求相關(guān)的cookies.如果在RouteTable中找到與當(dāng)前請(qǐng)求想對(duì)應(yīng)的Route對(duì)象,這個(gè)RouteData將會(huì)被返回。如果UrlRoutingModule成功地獲取一個(gè)RouteData對(duì)象,并且創(chuàng)建了包含當(dāng)前HttpContext和RouteData的RouteContext對(duì)象,這個(gè)模型將會(huì)立即生成一個(gè)新的基于RouteTable的HttpHandler,并將RouteContext傳遞給新的handl
59、er的構(gòu)造器中。在ASP.NET MVC應(yīng)用程序中,從RouteTable返回的handler總是一個(gè)MvcHandler(MvcRouteHandler 返回一個(gè)MvcHandler).當(dāng)在RouteTable中的Route對(duì)象中UrlRoutingModule能匹配當(dāng)前請(qǐng)求的話(huà),MvcHandler將會(huì)立即執(zhí)行當(dāng)前的RouteContext,最后,這個(gè)模型將會(huì)執(zhí)行嵌入在當(dāng)前HTTP Handler中的MvcHandler.ASP.NET程序自動(dòng)地調(diào)用ProcessRequest()方法。然后轉(zhuǎn)入下一步驟。3.執(zhí)行MvcHandler在上一步驟中,MvcHandler代表了當(dāng)前HTTP Handler中的特定的RouteContext.而在ASP.NET應(yīng)用程序中,總是接二連三的提出一系列的事件,包括St
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年養(yǎng)殖市場(chǎng)分析:生豬價(jià)格與飼料成本博弈下的行業(yè)微利時(shí)代來(lái)臨
- 2025年衛(wèi)浴柜行業(yè)競(jìng)爭(zhēng)分析:衛(wèi)浴柜行業(yè)競(jìng)爭(zhēng)格局更加激烈
- 貴州省銅仁市2024-2025學(xué)年高三上學(xué)期1月期末考試英語(yǔ)試題【含答案】
- 2024-2025學(xué)年北京市朝陽(yáng)區(qū)高二(上)期末歷史試卷
- 2025年公共營(yíng)養(yǎng)師操作試題及答案
- 2025年醫(yī)院常見(jiàn)面試題及答案
- 居家老人測(cè)試題及答案
- 水土保護(hù)毯施工方案
- 5年級(jí)上冊(cè)所有文言文
- 4年級(jí)下冊(cè)英語(yǔ)書(shū)科普版
- 關(guān)于優(yōu)化員工溝通渠道的通知
- 工藝品加工合同6篇
- 2025年第六屆全國(guó)國(guó)家版圖網(wǎng)絡(luò)知識(shí)競(jìng)賽題庫(kù)及答案(中小學(xué)組)
- 2025年榆林市公共交通總公司招聘(57人)筆試參考題庫(kù)附帶答案詳解
- 醫(yī)院培訓(xùn)課件:《多發(fā)性骨髓瘤》
- 3《鴻門(mén)宴》課件 2024-2025學(xué)年統(tǒng)編版高一語(yǔ)文必修下冊(cè)
- 2025年遼寧石化職業(yè)技術(shù)學(xué)院?jiǎn)握新殬I(yè)傾向性測(cè)試題庫(kù)審定版
- 安徽省六校2024-2025學(xué)年高三下學(xué)期2月素質(zhì)檢測(cè)考試生物學(xué)試題(含解析)
- 2025年湖南省長(zhǎng)沙市單招職業(yè)傾向性測(cè)試題庫(kù)及參考答案
- 十八項(xiàng)核心制度培訓(xùn)課件
- 2024年遠(yuǎn)程教育行業(yè)市場(chǎng)運(yùn)營(yíng)現(xiàn)狀及行業(yè)發(fā)展趨勢(shì)報(bào)告
評(píng)論
0/150
提交評(píng)論