소스 오픈 - ASP를 읽어드릴게요.NET_MVC(4)

11328 단어 mvc.net개원asp.net
전편에서 ActionResult의 Execute Result 방법에 대해 이야기했는데, 오늘 계속하겠습니다.
우선 ActionResult의 정의(코드 세그먼트 1)를 살펴보자. 이것은 추상적인 클래스이고 추상적인 방법인 ExecuteResult만 있다.
    public abstract class ActionResult
    {
        public abstract voidExecuteResult(ControllerContext context);
    }

코드 세그먼트 1
ActionResult는 매우 중요한 화제이다. MVC는 Action에서 HTML 응답을 직접 생성하고 전송하지 않고 ActionResult를 되돌려주고, MVC 프레임워크에서 ExecuteResult 방법을 호출한다.이것은 디자인 모델의 응용, 즉'명령 모드'로 요청과 실행 요청을 분리하여 그것들 간의 결합을 해제한다.명령 모드에 관해서는 도랑 뇌보를 스스로 찾아보세요.
ActionResult에는 ViewResultBase,ContentResult,FileResult,HttpStatusCodeResult,JavaScriptResult,JsonResult,RedirectResult,RedirectToRouteResult,AtomEntryActionResult,AtomFeedActionResult,AtomServiceDocumentonResult,DataContractJsonactionResult,DatactionActionResult,ActionActionResult,ActionResult,ActionResultMultiFormatActionResult、ResourceErrorActionResult、ResourceRedirectToRouteResult.이러한 하위 클래스는 서로 다른 수요에 따라 정의된 것이고 가장 흔히 볼 수 있는 것은 ViewResultBase의 하위 클래스인 ViewResult이다. (물론 PartialViewResult도 ViewResultBase의 하위 클래스이기도 하다.)그러나 ViewResult는 ExecuteResult 방법을 다시 쓰는 것이 아니라 부류인 ViewResultBase에서 다시 쓰는 것입니다. 코드 세그먼트 2 참조.
        public override voidExecuteResult(ControllerContext context)
        {
            if (context == null)
            {
                throw newArgumentNullException("context");
            }
            if (String.IsNullOrEmpty(ViewName))
            {
                ViewName =context.RouteData.GetRequiredString("action");
            }
 
            ViewEngineResult result = null;
 
            if (View == null)
            {
                result = FindView(context);
                View = result.View;
            }
 
            TextWriter writer =context.HttpContext.Response.Output;
            ViewContext viewContext = newViewContext(context, View, ViewData, TempData, writer);
            View.Render(viewContext, writer);
 
            if (result != null)
            {
               result.ViewEngine.ReleaseView(context, View);
            }
        }

코드 세그먼트 2
코드 세그먼트 2의 문장 [View.Render(viewContext, writer)]는 HTML을 브라우저로 렌더링하고 보내는 핵심 코드입니다.여기서부터 만인이 존경하는 보기 엔진 메커니즘을 도입하기 시작했다. 우리는 문장[result=FindView(context)을 보고FindView의 정의를 추적한다. 오, 이것은 추상적인 방법이다. 그래, 그의 하위 클래스인 ViewResult에서 찾아 코드 세그먼트 3을 보자.
        protected override ViewEngineResultFindView(ControllerContext context)
        {
            ViewEngineResult result =ViewEngineCollection.FindView(context, ViewName, MasterName);
            if (result.View != null)
            {
                return result;
            }
 
            // we need to generate an exceptioncontaining all the locations we searched
            StringBuilder locationsText = newStringBuilder();
            foreach (string location inresult.SearchedLocations)
            {
                locationsText.AppendLine();
                locationsText.Append(location);
            }
            throw newInvalidOperationException(String.Format(CultureInfo.CurrentCulture,
                                                             MvcResources.Common_ViewNotFound, ViewName, locationsText));
        }

코드 세그먼트 3
FindView 방법의 역할은 지정한 보기 엔진을 찾고 코드 세그먼트 3에서 문장 [View Engine Result result = View Engine Collection. FindView(context, ViewName, Master Name)]을 찾아 View Engine Collection으로 추적하는 것입니다.FindView 정의(코드 세그먼트 4).
        public virtual ViewEngineResultFindView(ControllerContext controllerContext, string viewName, stringmasterName)
        {
            if (controllerContext == null)
            {
                throw newArgumentNullException("controllerContext");
            }
            if (String.IsNullOrEmpty(viewName))
            {
                throw newArgumentException(MvcResources.Common_NullOrEmpty, "viewName");
            }
 
            return Find(e =>e.FindView(controllerContext, viewName, masterName, true),
                        e =>e.FindView(controllerContext, viewName, masterName, false));
        }

코드 세그먼트 4
Find 방법(코드 세그먼트 5)에 들어가는 것을 추적합니다. 이 방법의 역할은 보기 엔진 집합에서Funclookup 의뢰로 현재 사용하고 있는 보기 엔진을 검색하는 것입니다.
 
       private ViewEngineResultFind(Func<IViewEngine, ViewEngineResult> lookup, bool trackSearchedPaths)
        {
            // Returns
            //    1st result
            // OR list of searched paths (iftrackSearchedPaths == true)
            // OR null
            ViewEngineResult result;
 
            List<string> searched = null;
            if (trackSearchedPaths)
            {
                searched = newList<string>();
            }
 
            foreach (IViewEngine engine inCombinedItems)
            {
                if (engine != null)
                {
                    result = lookup(engine);
 
                    if (result.View != null)
                    {
                        return result;
                    }
 
                    if (trackSearchedPaths)
                    {
                       searched.AddRange(result.SearchedLocations);
                    }
                }
            }
 
            if (trackSearchedPaths)
            {
                // Remove duplicate searchpaths since multiple view engines could have potentially looked at the samepath
                return newViewEngineResult(searched.Distinct().ToList());
            }
            else
            {
                return null;
            }
        }

코드 세그먼트 5
코드 세그먼트 5에는 보기 엔진 집합을 대표하는 CombinedItems가 있는데, 그 정의는 코드 세그먼트 6을 참조한다.
        internal IViewEngine[] CombinedItems
        {
            get
            {
                IViewEngine[] combinedItems =_combinedItems;
                if (combinedItems == null)
                {
                    combinedItems =MultiServiceResolver.GetCombined<IViewEngine>(Items, _dependencyResolver);
                    _combinedItems =combinedItems;
                }
                return combinedItems;
            }
        }

코드 세그먼트 6
CombinedItems는 실제로View Engine Collection의 내용 항목을 가리키는데 View Engine Collection의 내용은 어디에서 채워졌을까요?코드 세그먼트 3의 [View Engine Result result = View Engine Collection.FindView(context, ViewName, Master Name)]를 보십시오. 그 안에 View Engine Collection이 있습니다. 정의로 넘어가세요. 코드 세그먼트 7을 보십시오.
        [SuppressMessage("Microsoft.Usage","CA2227:CollectionPropertiesShouldBeReadOnly", Justification ="This entire type is meant to be mutable.")]
        public ViewEngineCollectionViewEngineCollection
        {
            get { return _viewEngineCollection?? ViewEngines.Engines; }
            set { _viewEngineCollection =value; }
        }

코드 세그먼트 7
표시되는 ViewEngineCollection은 ViewEngines에서 파생됩니다.Engines, ViewEngines로 이동합니다.Engines의 정의는 코드 세그먼트 8을 참조하십시오.봤지!원래 비밀은 여기에 있었다. View Engine Collection이라는 집합의 내용은 미리 설정된 WebForm View Engine과 Razor View Engine, 즉 우리가 잘 알고 있는 WebForm 보기 엔진과 Razor 보기 엔진이다.
    public static class ViewEngines
    {
        private static readonlyViewEngineCollection _engines = new ViewEngineCollection
        {
            new WebFormViewEngine(),
            new RazorViewEngine(),
        };
 
        public static ViewEngineCollectionEngines
        {
            get { return _engines; }
        }
}

코드 세그먼트 8
코드 세그먼트 4를 다시 한 번 살펴보면 [e=> e.FindView(controller Context,viewName,masterName,true)] 이 Lamda 표현식(본질은 의뢰)은Find 방법의 첫 번째 매개 변수인lookup으로 전달된다. 즉, 이 Lamda 표현식으로 어떤 보기 엔진이 현재 사용하고 있는 보기 엔진인지 판단하는 것이다.e.FindView를 계속해서 추적하고 정의(코드 세그먼트 9)에 들어가면 FindView가 인터페이스 IViewEngine의 한 방법임을 알 수 있습니다.IView Engine은 보기 엔진의 인터페이스입니다. 우리는 이미 보기 엔진의 핵심에 도달했습니다. 닭이 얼었죠?
    public interface IViewEngine
    {
        ViewEngineResultFindPartialView(ControllerContext controllerContext, string partialViewName,bool useCache);
        ViewEngineResultFindView(ControllerContext controllerContext, string viewName, stringmasterName, bool useCache);
        void ReleaseView(ControllerContextcontrollerContext, IView view);
}

코드 세그먼트 9
자, 누가 IView Engine 인터페이스를 실현했는지 살펴보자. 한참을 찾았는데 Virtual Path Provider View Engine만 IView Engine 인터페이스를 실현한 것을 발견했다. 코드 섹션 10 참조.
        public virtual ViewEngineResultFindView(ControllerContext controllerContext, string viewName, stringmasterName, bool useCache)
        {
            if (controllerContext == null)
            {
                throw newArgumentNullException("controllerContext");
            }
            if (String.IsNullOrEmpty(viewName))
            {
                throw newArgumentException(MvcResources.Common_NullOrEmpty, "viewName");
            }
 
            string[] viewLocationsSearched;
            string[] masterLocationsSearched;
 
            string controllerName =controllerContext.RouteData.GetRequiredString("controller");
            string viewPath =GetPath(controllerContext, ViewLocationFormats, AreaViewLocationFormats,"ViewLocationFormats", viewName, controllerName, CacheKeyPrefixView,useCache, out viewLocationsSearched);
            string masterPath =GetPath(controllerContext, MasterLocationFormats, AreaMasterLocationFormats,"MasterLocationFormats", masterName, controllerName,CacheKeyPrefixMaster, useCache, out masterLocationsSearched);
 
            if (String.IsNullOrEmpty(viewPath)|| (String.IsNullOrEmpty(masterPath) &&!String.IsNullOrEmpty(masterName)))
            {
                return newViewEngineResult(viewLocationsSearched.Union(masterLocationsSearched));
            }
 
            return newViewEngineResult(CreateView(controllerContext, viewPath, masterPath), this);
        }

코드 세그먼트 10
CreateView 방법을 추적하면 추상적인 방법인 것을 발견할 수 있습니다. 그래요.BuildManager View Engine이 VirtualPathProvider View Engine를 계승한 것을 발견했습니다.그러나 CreateView 방법을 다시 쓰지 않았습니다. 당황하지 마세요. 계속 모색해 보니 RazorView Engine와 WebForm View Engine(그를 상관하지 않음)가 BuildManager View Engine를 계승한 것을 발견했습니다.여기서 우리는 RazorView Engine의CreateView 방법만 보고 다시 쓴다. (코드 세그먼트 11)
        protected override IViewCreateView(ControllerContext controllerContext, string viewPath, stringmasterPath)
        {
            var view = new RazorView(controllerContext,viewPath,
                                    layoutPath: masterPath, runViewStartPages: true,viewStartFileExtensions: FileExtensions, viewPageActivator: ViewPageActivator)
            {
                DisplayModeProvider = DisplayModeProvider
            };
            return view;
        }

코드 세그먼트 11
코드 세그먼트 11은 IView 대상을 얻어서 코드 세그먼트 10은 View Engine Result를 얻게 하고 우리는 코드 세그먼트 2의 문장 [result =FindView(context), View =result. View;여기서 View 개체를 얻어 View를 호출합니다.Render(viewContext, writer) 방법은 무엇입니까?우리는 문장 [TextWriter writer =context.HttpContext.Response.output;]을 찾았다.확 트이지 않습니까?오랜만에 밤낮으로 생각했던Response가 드디어 나타났습니다. 이 Response가 있으면 HTML 응답을 브라우저로 렌더링할 수 있습니다. 이로써 브라우저에서HTTP 요청을 보내고 서버에서 HTML 응답을 보내며 완전한 회로를 구성하여 큰 성과를 거둘 수 있습니다.믿어, 피곤해 죽겠어!
미완성 미속...

좋은 웹페이지 즐겨찾기