Loading ASCX control created dynamically (via code)

asp.net, c#, dynamic-compilation, user-controls, webusercontrol

Solution

In the end I was able to resolve the problem. Following is the strategy I adopted:

- Create text files containing structure of `CodeBehind`, `Markup` and `Designer` code

- Read the information as to what fields to create.

- Put markup for controls needed in string builders.

- put some other related information into more string builders

- Write files

After this I created the `dll` using `CodeDome` compiler. The main problem faced during compilation, as described in `Edit` part of question, was not finding referenced assemblies, which was resolved by putting path of `bin` directory's path along with dll file name like:

Server.MapPath("~/bin")+"\\Telerik.Web.dll"

etc.

Next problem outlined in `EDIT2` was bit simpler. There was rather moronic. There was some problem in another user control embedded in dynamically generated user control.

Even after this i was not able to load the control into the page from where I compiled the code. This was resolved when I loaded the control in another page. The runtime was able to resolve the type from dynamically compiled `dll`.

Problem

I am creating `Web User Controls` via code (my C# code write-out markup, code-behind and designer files to disk on a callback). The controls are created all fine. I can add them to my web-project and put them on a page. When I try to load the control using `LoadControl(path)` it says: ``` Unable to load type 'MyNameSpace.UseControlClass' ``` which is because control is not yet compiled. But my requirement is to load controls dynamically without recompiling the solution. How can I compile the user control only when I create the control files? As this seems to be the only way out. EDIT:- What my guess is that as the file is not compiled yet it is not allowed to be loaded by runtime. I have tried to compile the code file using `CodeDom` compiler. Like: ``` var filePath = Server.MapPath(path); var provider = CSharpCodeProvider.CreateProvider("C#"); var opts = new CompilerParameters(new[] { "mscorlib.dll", "System.Web.dll", "Telerik.Web.Design.dll", "Telerik.Web.UI.dll", "Telerik.Web.UI.Skins.dll", "MyCurrentDll.dll"}); opts.GenerateExecutable = false; opts.GenerateInMemory = true; var cr = provider.CompileAssemblyFromFile(opts, new string[] { filePath+".cs" }); ``` But it complains about `cannot find metadata file Telerik.Web.Design.dll` etc. I don't want to hardcode the telerik path as it might be different in hosted system (though it is in the `bin` of current web app). Also `MyCurrentDll.dll` is the dll of the file from which I'm compiling the code file. How can I resolve this? My idea is to compile the code file create a `dll` dynamically and copy it to web application's `bin` directory. It might solve the problem I originally stated. EDIT 2:- After hit and trial I am able to compile the code file dynamically and generate the `dll`. Even after generating dll and placing it into `bin` of my application I am not able to load user control using `virtual path`. I have tried the following approach: ``` var asm = Assembly.Load("ddlPath"); var t = asm.GetType(fullTypeName);//NameSpace.Class var ctrl = LoadControl(t,null); ``` The ctrl is loaded after this. I assign its `Id` property and add it to an `asp.net Panel` control. But it is not visible after the postback :( Now I either have to make somehow the dynamically compiled dll's types available to the runtime (appdomain, maybe) so that when I load control using virtual path it is properly loaded and I don't get `HtmlParseException` or figure out why loading control form `Type` is not showing up. PS:- I have loaded a `Label` control using `Type` and it is working properly.

Original source