27

MEF를 사용하는 복합 ASP .NET MVC 3 면도기 애플리케이션이 있습니다. 응용 프로그램에서 일반 Views 폴더 아래에 DLL 파일 및보기 (CSHTML)로 플러그인을 배포하려면 모든 것이 잘됩니다. 하지만 이것은 매우 깨끗한 것은 아니며 컨트롤러 및 모델과 함께 DLL 파일 내에 임베디드 리소스로 뷰를 배치하지 않으면 실제 플러그인이되지 않습니다.MEF 및 Maz를 사용하는 면도기 뷰

많은 기사를 읽었습니다 (대부분은 구식입니다). 실제로 스택 오버플로에 하나가 있습니다. Controllers and Views inside a Class Library

도큐멘트를 VirtualPathProvider으로 확인했으며 어셈블리 내에서 파일을 찾고 완벽하게로드하는 사용자 정의 빌드를 만들었습니다. 적어도 스트림을 얻는다). 이를 위해 VirtualPathProviderdocumentation on MSDN을 따라갔습니다.

VirtualFile에 대한 구현도 있지만 VirtualDirectory에는 아직 적용되지 않습니다.

여기에 문제가 있습니다. 나는 면도기보기로 일하고 있습니다. Razor가 파일을 빌드하려면 web.config 파일의 구성 사양이 필요하다는 것을 알고 있습니다. 하지만 DLL에이 파일을 포함 시키면이 구성이 손실됩니다.

는 나는 내가 오류가 계속 왜 궁금 :

The view at '~/Plugins/CRM.Web.Views.CRM.Index.cshtml' must derive from WebViewPage, or WebViewPage.

어쩌면 난 그냥 작동하게하는 몇 가지 코드를 추가해야합니까? 어떤 아이디어?

+1

뭔가 생각해보아야 할 사항 : 모든 cshtml 파일에 "@inherits System.Web.Mvc.WebViewPage"를 추가하면 모든 것이 잘 진행됩니다. 그러나 나는 단순히 그것을 할 수는 없다. (그것은 이미 일반 뷰 파일을 사용하여 자동으로 진행되는 무언가에 막대한 노력을 기울일 것이다). 그래서, 어떤 아이디어? –

+0

이 게시물은 도움이 될 수도 있지만 지금 당장은 테스트 할 수 없습니다. 최대한 빨리 시도하고 결과/답변을 게시하십시오. http://stackoverflow.com/questions/6465855/a-plugin-framework-with-asp-net-mvc3-and-embedded-razor-views –

+0

이미 설정 파일을 적절한 가상 경로에 넣으려고 했습니까? 우리가 Mvc보기 폴더 아래에있는 "표준 정렬"시뮬레이션하는 그런 식으로? –

답변

3

following blog post을 살펴보십시오.

+0

흥미 롭습니다. 그러나 이것은 모든 뷰를 미리 컴파일해야합니다. 나는 그걸로 아니에요, 난 단순히 클래스 라이브러리 내부에 cshtml 파일을 추가하고 싶습니다. 그게 전부입니다 (임베디드 리소스뿐입니다). 당신이 전혀 볼 수 없었던 다른 점은 제가 건물을 짓고 있다는 것입니다! 내가 틀렸다고 정정 해 주지만, 플러그인이 존재하는지 여부를 알지 못하는 플러그인을 주 앱 참조로 보지 못했습니다! =) –

+0

@ LordALMM, 왜? 제공된 솔루션이 개별 어셈블리의 외부화 뷰에서 요구 사항을 어떻게 충족시키지 못합니까? –

+0

"흥미 롭습니다.하지만 모든 뷰를 미리 컴파일해야합니다. 저는 그 것이 아니므로 cshtml 파일을 클래스 라이브러리에 추가하기 만하면됩니다. 모든 것이 (임베디드 리소스뿐입니다)." (2 월 15 일). 작동합니까? 예. 그러나 그것은 최선의 방법은 아닙니다. 폭탄으로 개미를 죽일 수 있기 때문에 이것이 최선의 방법이되지는 않습니다. Razor와 어떤 종류의 공급자를 함께 사용하여 임베디드 리소스 (사전 컴파일 된 클래스가 아닌 일반 CSHTML 파일)를 사용할 수있는 방법을 찾고 있습니다. –

2

호삼,

당신이 말하는 포스트는 이미 다린이 제안한 것입니다. 이 방법의 주된 단점은 사용자 정의 MvcRazorClassGenerator 컴파일러를 사용하여 CSHTML보기 파일을 클래스 파일로 변환하는 것입니다. 그렇게하려면 프로젝트의 모든 CSHTML보기를 컨텐츠로 설정하고 사용자 정의 도구를 MvcRazorClassGenerator로 설정해야합니다.

LordALMaa에 대해 말할 수는 없지만 컴파일러 소스를 다운로드하고 샷을 주었고 정확히 내가 원하는 방식으로 작동하지 않습니다.

:

내 다른 방법은 파일의 원시 내용을 읽어 외부 DLL에서 임베디드 자원으로 CSHTML 파일을 포함하고 문자열로보기를 실행 (http://razorengine.codeplex.com/ 예는 CodeProject의에 RazorEngine 참조)했다

모든 면도기 구문과 얼마나 잘 호환되는지 모르기 때문에 기업용 응용 프로그램의 RazorEngine에 완전히 의존하고 싶지 않았습니다. 그래서 지금 당장 포기했습니다.

저는 멀티 - 테넌트 응용 프로그램 인 ASP.NET MVC 2.0에서 제작 한 프로토 타입에서 왔습니다. 서버 팜에서는 모든 클라이언트가 동일한 코드 기반을 공유하는 하나의 응용 프로그램 인스턴스를 실행합니다. 내 MVC 2.0 프로토 타입에서 요청한 "클라이언트"가 무엇인지 결정할 수 있었고 기본 (코어 코드 사용자 정의의 경우)을 오버라이드하는 사용자 지정 컨트롤러를 확인하고 사용자 지정보기를 확인할 수있었습니다 (사용자 지정의 경우). 핵심보기). 이것이하는 일은 우리가 각 클라이언트에 대해 말할 때마다 "플러그인"을 배포 할 수있게하는 것입니다. 소프트웨어는 클라이언트가 요청과 일치하는 사용자 정의 컨트롤러와 일치하는 사용자 정의 액션을 가지고 있는지 여부를 감지하고, 일치하는 경우 커스터마이징 된 컨트롤러/액션을 대신 사용합니다.

프로토 타입을 MVC 3으로 마이그레이션하기 시작했을 때 LordALMaa와 동일한 문제가 발생했습니다. "The view at '... Index.cshtml'은 WebViewPage 또는 WebViewPage에서 파생되어야합니다."내 CSHTML보기에 "@inherits System.Web.Mvc.WebViewPage"를 배치하는 방법을 살펴보고 그것이 작동하도록 점점 더 가까워 지는지 살펴 보겠습니다.

MVC 3을 사용하는 MVC 2.0 프로토 타입을 사용하고 있기 때문에 면도기는 최우선 순위가 아니며 시간을 낭비하지 않습니다. 4.0 프레임 워크를 활용해야한다면 WebForms 엔진을 사용하여 MVC 3.0을 MVC 3.0으로 이식 할 수 있습니다.

7

면도날 뷰를 클래스 라이브러리에 포함하는 기본 방법은 빌드 빌드 이벤트를 사용하여 MVC 웹 사이트의보기/영역 폴더에 복사하는 것입니다. ViewEngine 또는 VirtualPathProvider를 재정의하면 사용자 지정보기 위치를 지정할 수 있습니다.

나를위한 까다로운 부분은이 View Class 라이브러리에서 작동하도록 인텔리 센스를 얻고있었습니다. 먼저 Web.Config를 View 어셈블리에 추가해야합니다. 실제로 어셈블리에 포함 할 필요는 없습니다. 어셈블리 루트 디렉토리 (또는 views 폴더)에만 있어야합니다. 다음은 그 예입니다. 중요한 어셈블리/편집 섹션을 참조하십시오. 모든 OutputPath 요소 대신 '디버그 \ 빈 \'또는 '출시 \ 빈 \'의 '빈 \'를 가리 키도록

<?xml version="1.0"?> 
<configuration> 
    <configSections> 
    <sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"> 
     <section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" /> 
     <section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" /> 
    </sectionGroup> 
    </configSections> 

    <system.web.webPages.razor> 
    <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /> 
    <pages pageBaseType="System.Web.Mvc.WebViewPage"> 
     <namespaces> 
     <add namespace="System.Web.Mvc" /> 
     <add namespace="System.Web.Mvc.Ajax" /> 
     <add namespace="System.Web.Mvc.Html" /> 
     <add namespace="System.Web.Routing" /> 
     </namespaces> 
    </pages> 
    </system.web.webPages.razor> 

    <appSettings> 
    <add key="webpages:Enabled" value="false" /> 
    </appSettings> 

    <system.web> 
    <compilation targetFramework="4.0"> 
     <assemblies> 
     <add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/> 
     <add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/> 
     <add assembly="System.Data.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/> 
     <add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /> 
     <add assembly="System.Web.WebPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /> 
     </assemblies> 
    </compilation> 

    <httpHandlers> 
     <add path="*" verb="*" type="System.Web.HttpNotFoundHandler"/> 
    </httpHandlers> 

    <!-- 
     Enabling request validation in view pages would cause validation to occur 
     after the input has already been processed by the controller. By default 
     MVC performs request validation before a controller processes the input. 
     To change this behavior apply the ValidateInputAttribute to a 
     controller or action. 
    --> 
    <pages 
     validateRequest="false" 
     pageParserFilterType="System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" 
     pageBaseType="System.Web.Mvc.ViewPage, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" 
     userControlBaseType="System.Web.Mvc.ViewUserControl, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"> 
     <controls> 
     <add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" namespace="System.Web.Mvc" tagPrefix="mvc" /> 
     </controls> 
    </pages> 
    </system.web> 
    <system.webServer> 
    <validation validateIntegratedModeConfiguration="false" /> 
    <handlers> 
     <remove name="BlockViewHandler"/> 
     <add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler" /> 
    </handlers> 
    </system.webServer> 
</configuration> 

다음으로, 당신은 당신의 클래스 라이브러리의 vbproj 파일을 수정해야합니다. 이것은 클래스 라이브러리와 intellisense 버그를 일으킬 수있는 ASP.Net 웹 프로젝트 유형간에 발견 한 주요 차이점입니다.

여전히 상속해야하는 오류가 발생하는 경우보기에서 @Inherits System.Web.Mvc.WebViewPage를 사용하는 것이 좋습니다. 보기를 웹 사이트 프로젝트에 복사하지 않으면 사용자 정의 ViewEngine/VirtualPathProvider를 사용하여 포함 된 자원에서보기를로드 할 수 있습니다. 그렇다면 상속녀가 필요합니다. 면도기는 뷰 기반 클래스가 불행히도 무엇인지 알고 있습니다.

행운을 비네.

+0

흥미 롭습니다. 나는 이것을 시도하고 결과를 게시 할 것이다. –

0

안녕하세요, 저는 내부에 DLL보기를 원하는 좋은 이유가 있다고 생각합니다. 그러나 모든 것을 하나의 개체로 패키징하는 특별한 방법이라고 생각하십시오.

플러그인을 개발중인 경우 요즘 사람들은 NUGET 형식으로 패키지를 선택합니다. 이는 다른 것들 중에서도 문제를 해결합니다. 패키지와 라이브러리로 플러그인을 배포하는 한 가지 방법 인 .nupkg 구조를 가지고 있습니다.

지역 사회가 일반적으로 따르는 또 다른 해결책은 (만약 그들이 nuget처럼 정교한 것을 원하지 않는다면) 면도기 같은 뷰 엔진을 사용하지 않고 플러그인 DLL을 코딩하여 대신 old를 사용하여 HTML을 모두 출력한다는 것입니다 Response.Write의 원시적 인 방법으로 cshtml 파일과 독립적입니다. 그래도 cshtml을 사용하려면 - this blog entry을 참조하여 클래스로 사전 컴파일하십시오.

+0

흠 나는 그 질문에 대한 답이 아니라는 것을 알고 있습니다. 그러나 요점은 질문자가 포장의 더 깊은 문제를 해결하는이 길을 따르는 것을 방해하는 것입니다. – Zasz