在后端类中创建 Ascx 控件的实例 Aspx 页面而不加载 FilePath
问题:是否可以在后端代码中(不是在后面的代码中,而是在实际的后端类中)加载并呈现页面或在 .aspx 或 .ascx 中定义的控件,而无需使用 Load(path) 而只需创建页面/控件类的实例?
我希望能够做到这一点(从后端类而不是后面的代码):
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 WebApp 中,我偶尔需要将用户控件 (.ascx) 或页面 (.aspx) 呈现为 HTML 字符串。当页面或控件从后面的代码继承时,其类会显示在我的后端代码中的智能感知中,我可以创建实例并设置属性,而不会出现编译时或运行时错误。但是,当我尝试渲染页面或控件时,我总是得到一个空字符串,并且经过检查,页面或控件显示受抑制的内部渲染错误,除非我使用其物理文件路径加载页面或控件。
我认为关键问题与何时& .aspx / .ascx 文件如何运行时编译。我不想创建用户控件的预编译类库,因为这会使设计过程变得尴尬,而且我真的很喜欢 .aspx / .ascx 页面提供的设计器功能,所以我很想找到一种方法使页面在解决方案中进行编译,以便它们可以像任何其他后端类一样使用,但仍然可以使用设计器创建。我希望两全其美(1)能够在设计器中编辑页面和控件,(2)创建实例并使用后端类设置其属性。
Question: Is it possible in back end code (not in the code behind but in an actual back end class) to load and render a page or control defined in a .aspx or .ascx without having to use Load(path) and instead just create an instance of the page/control class?
I want to be able to do this (from a back end class NOT a code behind):
MyControl myCtl = new MyApp.Views.Shared.MyControl();
String html = Util.ControlToString(myCtl); //I get an empty string & hidden errors
instead of this
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();
}
Details:
In a Asp.net WebApp I occasionally need to render a user control (.ascx) or page (.aspx) as a HTML string. When a page or control inherits from a code behind, its class shows up in intellisense in my back end code and I can create an instance and set properties without getting compile time or run time errors. However, when I try to render the page or control I always get an empty string and upon inspection the page or control shows suppressed internal rendering errors unless I load the page or control using its physical file path.
I think the key issue has to do with when & how the .aspx / .ascx files are runtime compiled. I don't want to create a pre compiled class library of user controls because that would make the design process awkward and I really like the designer features offered by the .aspx / .ascx pages and so I'd love to find a way to make the pages compile in the solution so that they are usable like any other back end class but can still be created using the designer. I want the best of both worlds (1) to be able to edit pages and controls in the designer and (2) create instances and set their properties using back end classes.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这是一种在这种情况下可能会有所帮助的方法。
“后端”代码可能不知道用户控件位于哪里,但用户控件确实知道它在哪里。
因此,在用户控件中,添加一个如下所示的静态方法:(
包含
CustomDto
是为了说明如何将初始数据传递到用户控件。如果不需要这样做,请采取出来!)有了这个,加载用户控件的代码不需要需要知道用户控件物理位置的路径。如果该位置发生变化,则更新这一位置。使用此 UserControl 的所有其他代码均保持不变。
在您的后端代码或其他任何地方,您可以执行以下操作:
Here is an approach that may help in situations like this.
The "back-end" code may not know where the user control is located, but the User Control does know where it is.
So, in the User Control, add a static method like this:
(The
CustomDto
is included to illustrate how initial data can be passed to the User Control. If you don't need to do that, take it out!)With this, the code that loads the user control does not need to know the path to where the user control is physically located. If that location ever changes, then update this one location. All other code that uses this UserControl is unchanged.
In your back-end code, or anywhere else, you can do something this:
一般来说:没有。
据我所知,ASP.NET从您的类继承,以将 .aspx/.ascx 模板与您的代码结合起来。这就是您的控件显示为空的原因:缺少将模板与您的代码结合起来的代码。这通常是由 ASP.NET 在您第一次访问页面或用户控件时完成的(这正是第一次点击有点慢的原因:它实际上是在生成和编译连接代码)。
对于预编译网站,ASP.NET 会提前生成此代码作为预编译网站 .dll 的一部分,这就是此类网站加载速度更快的原因。但是,IIRC 您仍然需要实例化生成的类而不是原始类。
这是一个非常常见的请求,但到目前为止微软还没有提供执行此操作的工具。
编辑:虽然我不明白为什么您想要将控件渲染到内存中的字符串,但我可能有解决构建问题的方法。
如果您坚持使用非编译的 .ascx 文件(使用网站模型而不是 Web 应用程序模型),您实际上可以通过将它们物理地放置在主项目的子文件夹中来单独开发它们,并仅将它们视为内容文件。然后,您可以使用该子文件夹作为根文件夹创建一个单独的项目。您只需将此子文件夹中的文件视为网站文件即可,主项目仍然可以是Web应用程序。 (实际上是推荐的,因为你不希望 .csproj 文件包含在主项目中。)
但是,共享代码(即在控件项目和主项目之间共享)应该放在单独的库项目中,因此您可以单独编译每个项目,而无需相互依赖。
在主项目中使用
LoadControl
将动态编译它们(代码隐藏是可能的);如果您需要设置属性,则必须在共享项目中定义接口,在适当的用户控件上实现它们,并将LoadControl
创建的控件强制转换为适当的接口。Generally speaking: no.
As far as I know, ASP.NET inherits from your classes to combine the .aspx/.ascx template with your code. This is why your controls show up empty: the code to combine the template with your code is missing. This is usually done by ASP.NET the first time you access a page or user control (that's precisely why the first hit is a little slow: it's actually generating and compiling the hookup-code).
For precompiled websites ASP.NET generates this code as part of your precompiled website's .dll in advance, which is why such sites load quicker. However, IIRC you'll still need to instantiate the generated classes rather than your original classes.
It's a pretty common request, but so far MS has not provided the tools to do this.
Edit: Although I fail to see why you'd want to render a control to an in-memory string, I might have a solution to the build problems.
If you stick to non-compiled .ascx files (using the web site model rather than the web application model), you can actually develop them separately by placing them physically in subfolder of your main project, and treat them as content files only. Then, you can make a separate project with this subfolder as the root folder. You only need to treat the files in this subfolder as web site files, the main project can still be a web application. (Actually recommended, 'cause you don't want the .csproj files included in the main project.)
However, shared code (that is, shared between the controls project and the main project) should be put in a separate library project, so you can compile each project separately without interdependencies.
Using
LoadControl
within the main project will compile them on the fly (code behind is possible); if you need to set properties, you must however define interfaces in the shared project, implement them on the appropriate user controls and cast the control created byLoadControl
to the appropriate interface.我开发了一个解决方案来解决 VS 2008 中的问题:
VS 2008
ASP。 - 编译控件:控件显示在 ASP 下。命名空间和命名方式有两种
A. 如果 .ascx / aspx 页面没有声明“ClassName”,那么它们将使用带有下划线的文件夹和文件名来命名。 <%@ 控制语言="C#" ClassName="Admin_Index" %>
B. 如果他们确实声明了一个类名,那么这就是他们的名字
List item
用法: 示例代码如下
这是一个示例用法
I developed a solution that solves my problem in VS 2008:
VS 2008
ASP. - Compiled Controls: Controls show up under the ASP. namespace and are named in two ways
A. if the .ascx / aspx page did not declare a "ClassName" then they are named using their folder and file name with underscores ex. <%@ Control Language="C#" ClassName="Admin_Index" %>
B. if they did declare a class name then that is their name
List item
Usage: Example code is below
Here is an example usage
我按照鲁本的建议提出了一个更简单的解决方案。
它已经运行了大约一个月,没有出现任何问题:
I've come up with a simpler solution along the lines of Ruben's advice.
It has worked without problems for about a month: