我正在开发一个ASP.NET应用程序,我们想要添加在某些请求期间调用客户脚本的功能。由于我们不信任此脚本,因此我们在IIS请求中生成一个具有有限权限的子AppDomain,并加载客户程序集和Script Runner程序集。如果满足某些条件,客户脚本可以执行更改业务对象描述或将状态代码更改为错误的操作。因为更改是如此多样化,所以我不能将它们包含在从方法调用返回的单个对象中。当脚本运行时,我需要它来改变启动这个子项的Request内部对象的值。
这个post建议使用NetNamedPipeBinding,但我越来越担心它不适合在IIS内部运行的代码,其中多个请求可以同时运行。我会为每个IIS请求设置一个新主机吗?为整个过程设置一个静态主机,然后使用端点确保正确的子进程与正确的请求对话?这是正确的技术吗?
如果这不是正确的技术,那是什么?这个post告诉你如何检索父AppDomain的句柄,但是其中很多似乎都使用了mscoree.dll,而且我的印象是COM和IIS没有很好地混合。 This post谈论消除您的初始AppDomain并创建一个新的AppDomain。也许这在IIS中没有必要?
是否有一种方法可以让子AppDomain有效地执行产生它的Request对象内部的方法,如果有,它是什么?
答案 0 :(得分:4)
我认为我已经找到一种简单的技术,让孩子 AppDomain 在不使用WCF或mscoree.dll的情况下改变父 AppDomain 中的状态。重读上面的第一篇文章,我看到他确实提到它是一种可能性,但是由于我不清楚的原因而拒绝它。诀窍是在父对象中创建一个派生自 MarshalByRefObject 的对象,获取 ObjectHandle ,然后将 ObjectHandle 传递给子<强>应用程序域即可。然后,子进程可以解包该句柄以获取代理,然后可以调用将改变父对象状态的方法。这是代码示例:
class Program
{
public class ParentFacade : MarshalByRefObject
{
public List<string> Collection { get; set; }
public void AddElement(string el)
{
Collection.Add(el);
}
}
public class ChildFacade : MarshalByRefObject
{
public void AlterParentState(ObjectHandle handle)
{
var parent = handle.Unwrap() as ParentFacade;
parent.AddElement("Message from child");
}
}
static void Main(string[] args)
{
var child = AppDomain.CreateDomain("child");
var childFacadeType = typeof(ChildFacade);
var childProxy = child.CreateInstanceAndUnwrap(childFacadeType.Assembly.FullName, childFacadeType.FullName) as ChildFacade;
var parentColl = new List<string>();
var facade = new ParentFacade();
facade.Collection = parentColl;
var facadeHandle = new ObjectHandle(facade);
childProxy.AlterParentState(facadeHandle);
foreach (var item in parentColl)
Console.WriteLine(item);
}
}
此代码显示子进程中的方法能够更改父对象的状态。这个特殊的例子并不是非常有用,但是当你设置一个沙箱时,这是非常强大的,并且在你不信任的子程序集中包含.dll。不受信任的程序集可以调用ChildFacade中的方法,从而以受控和安全的方式更改父级中的状态。