5

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.

TheVillageIdiot
  • 40,053
  • 20
  • 133
  • 188
  • That's a really interesting question. I can't think of a use case for this - but the way I normally approach this is to have another assembly that knows how to build controls and emits the HTML etc at run time. Perhaps a similar approach would be possible here by embedding your new controls in another assembly which you can then compile and load from? I'll watch this question with interest! – dash Apr 19 '12 at 08:03
  • @dash The Use case is that we allow user to group some fields (with predefined input types) and get input from end user. I want to create a user control, embedding these fields. – TheVillageIdiot Apr 19 '12 at 08:38
  • Are your controls, and hosting page, in CodeFile instead of CodeBehind ? – jbl Apr 19 '12 at 08:38
  • Had you tried putting the user control in other project in the same solution? You can configure the output dll to the bin in the main project. – jlvaquero Apr 19 '12 at 10:33
  • @user551263 how to do this in a website hosted on a server? @jbl I'm not able to understand what do you mean? you mean `CodeFile` or `CodeBehind` attributes in user control markup file? – TheVillageIdiot Apr 19 '12 at 11:05
  • yahooooo! its done, will post in detail about how to do this later. – TheVillageIdiot Apr 19 '12 at 14:36

2 Answers2

2

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

  1. Create text files containing structure of CodeBehind, Markup and Designer code
  2. Read the information as to what fields to create.
  3. Put markup for controls needed in string builders.
  4. put some other related information into more string builders
  5. 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.

TheVillageIdiot
  • 40,053
  • 20
  • 133
  • 188
1

hmm.. have you considered using App_Code folder for this purpose?

Contains source code for shared classes and business objects (for example, ..cs, and .vb files) that you want to compile as part of your application. In a dynamically compiled Web site project, ASP.NET compiles the code in the App_Code folder on the initial request to your application. Items in this folder are then recompiled when any changes are detected.

avs099
  • 10,937
  • 6
  • 60
  • 110
  • this won't help me as I'm creating a user control and the files are also created dynamically at runtime. the problem was to load the created files in app domain to create control object. i have resolved it and will post answer soon. – TheVillageIdiot Apr 20 '12 at 04:50