<%%>ブロックをページまたはコントロールに実行時に追加するか、コードブロックを実行してコントロール/ページに挿入する方法はありますか?C#動的に<% Code %>をaspxページまたはascxコントロールに追加します
これは特にC#ASP.netコンパイル済みWebアプリケーションフレームワークのためです4.5 そうでない場合は、これを行う別の方法がありますか? ユーザーはascxまたはaspxページを編集せずに単純なものを追加できます。
<%%>ブロックをページまたはコントロールに実行時に追加するか、コードブロックを実行してコントロール/ページに挿入する方法はありますか?C#動的に<% Code %>をaspxページまたはascxコントロールに追加します
これは特にC#ASP.netコンパイル済みWebアプリケーションフレームワークのためです4.5 そうでない場合は、これを行う別の方法がありますか? ユーザーはascxまたはaspxページを編集せずに単純なものを追加できます。
おそらく最も簡単な方法は、.ascx
ファイルを実行時にいくつかの一時ディレクトリに作成することです。次に、(Html.RenderPartial
または他の同様の方法で)これらのファイルを参照できます。これは、実行時にコンパイルを起動し、あなたのためにすべての作業を行う必要があります。
また、この機能を使用すると、データベースアクセスなど、サーバー上で任意のコードを実行する権限がユーザーに与えられます。
そのWebFormsアプリケーションではありませんので、html.RenderPartialはありませんが、LoadControlについても同じことができます。この方法を避けることを望んでいました。ユーザーが50個のコードブロックをページに追加した場合、50個のユーザーコントロールを作成して読み込む必要があります。それは非常に効率的ではありません。また、既存のページ上のすべてのオブジェクトを各ユーザーコントロールに渡してアクセスできるようにする必要があります。何らかの形でロードするか、コントロールコレクションに追加する前に、既存のページ/コントロールに<%%>ブロックを挿入する方法がいくつかあると考えていました。 – Tyrone
実行するコードブロックを指定する巨大なスイッチで1つのコントロールを生成できます。その後、同じコントロールを50回呼び出すことができます。 50個のコントロールよりもはるかに安くなければならない。 – usr
C#コードをコンパイルする必要があるため、これを回避する方法はありません。 .NETには "eval"はありません。あなたはRoslynを試すことができますが、RoslynはASPXをサポートしていません。したがって、ユーザーが入力するコードは通常のC#コードでなければなりません。 – usr
以下はどの程度効率的かはっきりしていませんが、ハードディスクにascxを書き込まなくても動作するようです。
VirtualCompilerに一意の名前とコードをパラメータとして追加します。
VirtualCompiler.Add("MyName", @"<%@ Control Language=\"C#\" AutoEventWireup=\"false\" CodeBehind=\"...\" Inherits=\"...\" %>\r\n<% Response.Write(DateTime.Now);\r\n%>");
次にコントロールをロードする:
Page.Controls.Add(Page.LoadControl("~/DynamicCode/MyName.ascx"));
クラス
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Caching;
using System.Web.Hosting;
namespace Admin.UI.Utility
{
public class VirtualCompiler
{
protected static Dictionary<String, String> _code = new Dictionary<String, String>();
public static void Add(String Name, String Code)
{
Name = Name.ToUpper();
if (_code.ContainsKey(Name))
_code.Remove(Name);
_code.Add(Name, Code);
}
public static String Get(String Name)
{
Name = Name.ToUpper();
if (_code.ContainsKey(Name))
return _code[Name];
return String.Empty;
}
public static Boolean Exists(String Name)
{
Name = Name.ToUpper();
return _code.ContainsKey(Name);
}
}
public class VirtualControl : VirtualFile
{
public String WebControlContent = String.Empty;
public VirtualControl(String VirtualPath)
: base(VirtualPath)
{
int ndx = VirtualPath.LastIndexOf("/");
String filename = ndx >= 0 ? VirtualPath.Substring(ndx + 1) : VirtualPath;
WebControlContent = VirtualCompiler.Get(filename);
}
public override System.IO.Stream Open()
{
MemoryStream ms = new MemoryStream();
if (!String.IsNullOrWhiteSpace(WebControlContent))
{
byte[] data = System.Text.ASCIIEncoding.ASCII.
GetBytes(WebControlContent);
ms.Write(data, 0, data.Length);
}
ms.Flush();
ms.Seek(0, SeekOrigin.Begin);
return ms;
}
}
public class VirtualControlProvider : VirtualPathProvider
{
public static void AppInitialize()
{
VirtualControlProvider db = new VirtualControlProvider();
System.Web.Hosting.HostingEnvironment.RegisterVirtualPathProvider(db);
}
public override CacheDependency GetCacheDependency(string VirtualPath, IEnumerable VirtualPathDependencies, DateTime UTCStart)
{
return IsPathVirtual(VirtualPath) ? null : base.GetCacheDependency(VirtualPath, VirtualPathDependencies, UTCStart);
}
private bool IsPathVirtual(string VirtualPath)
{
String checkPath = VirtualPathUtility.ToAppRelative(VirtualPath);
return checkPath.StartsWith("~/DynamicCode/".ToLower().ToString(), StringComparison.InvariantCultureIgnoreCase);
}
public override bool FileExists(String VirtualPath)
{
if (IsPathVirtual(VirtualPath))
{
VirtualControl file = (VirtualControl)GetFile(VirtualPath);
// Determine whether the file exists on the virtual file
// system.
if (file != null && !String.IsNullOrWhiteSpace(file.WebControlContent))
return true;
else
return Previous.FileExists(VirtualPath);
}
else
return Previous.FileExists(VirtualPath);
}
public override VirtualFile GetFile(String VirtualPath)
{
if (IsPathVirtual(VirtualPath))
{
return new VirtualControl(VirtualPath);
}
else
return Previous.GetFile(VirtualPath);
}
}
}
の下には、ユーザーが実際にC#のコードを入力することはできますか? – usr
私は、データベースに格納されているテンプレートにユーザがc#コードを入力してから、テンプレートがレンダリングされたときにそのテンプレートを実行させる必要があります。例えば、質問が表示されませんでしたが、私はそれらに "Response.write(DateTime.Now)"のようなものを追加できるようにします – Tyrone