인스턴스 만들기 페이지의 Ascx 제어에서 다시 끝없는 클래스 로드 FilePath

StackOverflow https://stackoverflow.com/questions/1325101

  •  19-09-2019
  •  | 
  •  

문제

질문: 그것은 다시 끝 코드 (지에서 뒤에 코드 하지만 실제 백 end class) 을 로드하고 렌더링하기 위해 페이지 또는 통제에 정의된다.aspx 또는.ascx 사용하지 않고 로드(경로)그리고 대신 인스턴스를 만듭 페이지의/제어 클래스?

내가 원하는 것 이것을 할 수 있(에서 다시 끝에스지 않는 코드):

MyControl myCtl = new MyApp.Views.Shared.MyControl();
String html = Util.ControlToString(myCtl); //I get an empty string & hidden errors

대신 이

public static string ControlToString(string path)
{
    Page pageHolder = new Page();
    MyControl myCtl = (MyControl)pageHolder.LoadControl(path);
    pageHolder.Controls.Add(myCtl);
    StringWriter output = new StringWriter();
    HttpContext.Current.Server.Execute(pageHolder, output, false);
    return output.ToString();
}

상세정보: 에 Asp.net 웹 애플리케이션 내가 때때로 필요하 렌더링에 사용자 정의 컨트롤(.ascx)또는 페이지는(.aspx)HTML 문자열입니다.페이지 또는 통제에서 상속 코드,뒤에 해당 클래스에 표시 intellisense 에 다시 끝 코드가 인스턴스를 만들 수 있고 속성을 설정 없이 컴파일시 혹은 실행시 오류가 있습니다.그러나려고 할 때 페이지를 렌더링하거나 제어 나는 언제나 빈 문자열에 따라 검사 페이지나 컨트롤의 보 억제 내 오류를 렌더링하지 않는 한 나는 페이지를 로드하거나 제어를 사용하여 실제 파일 경로.

내가 생각하는 중요한 문제와 함께 할 때&하는 방법.aspx/.ascx 파일은 런타임을 컴파일합니다.나는 원하지 않을 만들 미리 컴파일 클래스 라이브러리의 사용자 정의 컨트롤는 것이기 때문에 디자인을 만들 어색한 프로세스와 정말 좋아한 디자이너 기능을 제공.aspx/.ascx 페이지와 그래서 나는 사랑을 만들 수 있는 방법을 찾아 페이지에서 컴파일하도록 솔루션들은 사용 가능한과 같은 다른 어떤 다시 end class 지만 여전히 수 있을 사용하여 만든 디자이너입니다.내가 원하는 두 세계의 최고의(1)할 수 있는 페이지를 편집하고 컨트롤 디자이너 그리고(2)인스턴스를 만들고 속성을 설정합니다 다시 사용하여 종료됩니다.

도움이 되었습니까?

해결책

여기에 접근 방식에 도움이 될 수 있는 상황은 이렇습니다.

"Back-end"코드가 어디 있는지 알 수 없습니다 사용자 정의 컨트롤에 위치하고 있지만,사용자 정의 컨트롤가 알고있는 곳입니다.

그래서,사용자 정의 컨트롤 추가 정적 방법을 다음과 같다:

public partial class MyControl : UserControl
{
  ...
  public static MyControl LoadControl(CustomDto initialData)
  {
    var myControl = 
        (MyControl) 
        ((Page) HttpContext.Current.Handler)
        .LoadControl("~\\UserControlsSecretPath\\MyControl.ascx");
    myControl._initialData = initialData;
    return myControl;
  }
  ...
  private CustomDto _initialData;
}

(의 CustomDto 이 포함되어 있는 방법을 설명하기 위해 초기 데이터를 전달할 수 있는 사용자가 제어할 수 있습니다.당신이 할 필요가 없는 것,그것을 밖으로!)

이와 함께,로드하는 코드 사용자 컨트롤 을 알 필요가있는 경로를 사용자 정의 컨트롤 물리적 위치.는 경우에는 위치도 변경,그 후 업데이트나 위치에 있습니다.다른 모든 코드를 사용하는 이 정렬은 변경되지 않습니다.

에서 당신의 뒤쪽 끝 코드,또는 다른 곳에서,당신이 무언가를 할 수 있다:

var control = MyControl.LoadControl(customDto);
PlaceHolder1.Controls.Add(control);

다른 팁

일반적으로 말하기 : 아니요.

내가 아는 한, ASP.net은 상속합니다 수업에서 .aspx/.ascx 템플릿을 코드와 결합합니다. 이것이 컨트롤이 비어있는 이유입니다. 템플릿을 코드와 결합하는 코드가 누락되었습니다. 이는 일반적으로 ASP.NET에 의해 페이지 나 사용자 컨트롤에 처음 액세스 할 때 수행됩니다 (정확히 첫 번째 히트가 약간 느린 이유입니다. 실제로 훅 업 코드를 생성하고 컴파일하는 것입니다).

사전 컴파일 된 웹 사이트의 경우 ASP.NET은 사전 컴파일 된 웹 사이트의 .dll의 일부로이 코드를 생성하므로 이러한 사이트가 더 빠르게로드됩니다. 그러나 IIRC는 여전히 인스턴스화해야합니다 생성 원래 수업이 아닌 수업.

그것은 매우 일반적인 요청이지만 지금까지 MS는이를 수행 할 도구를 제공하지 않았습니다.

편집하다: 왜 당신이 메모리 내 문자열에 컨트롤을 렌더링하고 싶은지 알지 못하지만 빌드 문제에 대한 해결책이있을 수 있습니다.

비 컴파일 된 .ASCX 파일 (웹 응용 프로그램 모델이 아닌 웹 사이트 모델 사용)을 고수하는 경우 실제로 주요 프로젝트의 하위 폴더에 물리적으로 배치하여 별도로이를 개별적으로 개발하고 컨텐츠 파일로만 취급 할 수 있습니다. 그런 다음이 하위 폴더를 루트 폴더로 별도의 프로젝트를 만들 수 있습니다. 이 하위 폴더의 파일을 웹 사이트 파일로만 처리하면 기본 프로젝트는 여전히 웹 응용 프로그램 일 수 있습니다. (실제로 추천, '주 프로젝트에 포함 된 .csproj 파일을 원하지 않기 때문입니다.)

그러나 공유 코드 (즉, 컨트롤 프로젝트와 기본 프로젝트간에 공유)는 별도의 라이브러리 프로젝트에 넣어야하므로 상호 의존성없이 각 프로젝트를 별도로 컴파일 할 수 있습니다.

사용 LoadControl 메인 프로젝트 내에서는이를 즉석에서 컴파일 할 것입니다 (뒤의 코드가 가능). 속성을 설정 해야하는 경우 공유 프로젝트에서 인터페이스를 정의하고 적절한 사용자 컨트롤에서 구현하고 LoadControl 적절한 인터페이스에.

2008 년 vs에서 내 문제를 해결하는 솔루션을 개발했습니다.

  1. 주요 사이트 솔루션 작성 : VS 2008에서 MVC 1 웹 사이트 솔루션을 만듭니다
  2. 모델 클래스 라이브러리 만들기 : 모델 코드에 대한 클래스 라이브러리를 추가하십시오
  3. 보기 코드 작성 : .ASCX 페이지를 보유하려면 "빈 웹 사이트"를 추가하고 모델 라이브러리를 참조하십시오.
  4. 배포 사이트 작성 : "빈 웹 사이트"를 컴파일하는 배포 프로젝트 추가 "Properties Page"및 확인하다: "모든 출력을 단일 어셈블리로 병합"및 "라이브러리 구성 요소로 처리"하고 확실히 선택 취소: "이 사전 컴파일 된 사이트를 업데이트 할 수 있도록"
  5. 참조 배포 출력 : 메인 프로젝트에서는 배포 사이트의 출력에 대한 참조를 추가하십시오.
  6. ASP. - 컴파일 된 컨트롤 : ASP 아래에 컨트롤이 나타납니다. 네임 스페이스와 두 가지 방식으로 명명되었습니다. A.ASCX / ASPX 페이지가 "클래스 이름"을 선언하지 않은 경우 폴더와 파일 이름을 밑줄과 함께 사용하여 명명됩니다. < %@ control language = "c#"classname = "admin_index" %> B. 클래스 이름을 선언 한 경우 그 이름입니다.

  7. 목록 항목

용법: 예제 코드는 다음과 같습니다

다음은 예제 사용법입니다

public ActionResult Index()
{
    var ctl = new ASP.Directory_FirmProfile();  //create an instance
    ctl.Setup(new MyDataModel);                 //assign data

    //string test = CompiledControl.Render(ctl); //output to string
    return new HtmlCtl.StrongView(ctl);         //output to response
}    



   public class CompiledControl
    {
        public static string Render(Control c)
        {
            Page pageHolder = new Page();
            pageHolder.Controls.Add(c);
            StringWriter output = new StringWriter();
            HttpContext.Current.Server.Execute(pageHolder, output, false);
            return output.ToString();
        }

        public static void Render(Control c, StringWriter output)
        {
            Page pageHolder = new Page();
            pageHolder.Controls.Add(c);
            HttpContext.Current.Server.Execute(pageHolder, output, false);
        }

        public static void Render(Control c, HttpResponseBase r)
        {
            Page pageHolder = new Page();
            pageHolder.Controls.Add(c);
            HttpContext.Current.Server.Execute(pageHolder, r.Output, false);
        }


    }


    public class StrongView : ActionResult
    {
        private Control ctl;
        public StrongView(Control ctl)
        {
            this.ctl = ctl;
        }

        public string VirtualPath{get;set;}


        public override void ExecuteResult(ControllerContext context)
        {
            if (context == null)
                throw new ArgumentNullException("context");

            HtmlCtl.CompiledControl.Render(ctl, context.HttpContext.Response);

        }
    }

나는 루벤의 조언 라인을 따라 더 간단한 솔루션을 생각해 냈습니다. 약 한 달 동안 문제없이 작동했습니다.

//Example usage

//reference the control
var emailCTL = new HtmlCtl.ControlOnDisk<MyControlType>(@"~\Views\EmailTemplates\MyControlType.ascx");

//if you have a code behind you will get intellisense allowing you to set these properties
// and re-factoring support works most places except the template file. 
emailCTL.c.title = "Hello World "; //title is a property in the code behind
emailCTL.c.data = data; //data is a property in the code behind

string emailBody = emailCTL.RenderStateless(); 



//Helper Class
    public class ControlOnDisk<ControlType> where ControlType : UserControl
    {
        public ControlType c;
        Page pageHolder = new Page();
        public ControlOnDisk(string path)
        {
            var o = pageHolder.LoadControl(path);
            c = (ControlType)o;
            pageHolder.Controls.Add(c);
        }

        public string RenderStateless()
        {

            StringWriter output = new StringWriter();

            // set up dumby context for use in rendering to email stream
            StringBuilder emailMessage = new StringBuilder();
            TextWriter tw = new StringWriter(emailMessage);
            HttpResponse dumbyResponse = new HttpResponse(tw);
            HttpRequest dumbyRequest = new HttpRequest("", "http://InsertURL.com/", ""); //dummy url requierd for context but not used
            HttpContext dumbyContext = new HttpContext(dumbyRequest, dumbyResponse);
            //HttpContextBase dumbyContextBase = new HttpContextWrapper2(dumbyContext);

            dumbyContext.Server.Execute(pageHolder, output, false);
            return output.ToString();

        }
    }
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top