Deployment: bin folder outside root folder?

  • Thread starter Thread starter Jon Maz
  • Start date Start date
J

Jon Maz

Hi All,

I would like to have the following folder structure for an asp.net website:


MasterFolder
|---\AppRoot
| --- webform.aspx
| --- web.config
| --- global.asax
| |--- \images
| |--- \styles
| |--- \downloads
| |--- \usercontrols
|
|---\DllFolder
| --- some dll's
| |--- \SubDllFolder
| --- other dll's


I'd like to know if it's possible to have the folder containing the dll's
(the "bin" folder, though renamed) outside the root folder. I've done my
research on Google Groups, and don't want to use the GAC (because you will
have to remove and readd the assembly on every change), and it seems if you
use this method:

<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="bin;bin2\subbin;bin3"/>
</assemblyBinding>
</runtime>
</configuration>

....then the directories specified in privatepath *must* be subdirectories of
the application base directory.

What I'm after doesn't seem *that* strange to me - there must be a way of
doing this, surely?

Any help much appreciated,

TIA,

JON
 
Hi,

you may try to hook to AppDomain.AssemblyResove event.

Also, have you tried to put in privatePath a full directory name? if
your path starts without "\" it will look in subdirs, but otherwise it
should work. At least it works with console app, I do not know about
IIS.

Sunny
 
You can try to handle AssemblyResolve event of AppDomain and load
assembly manually from whatever location. It works for me.

BTW, I never tryed but is it possible to setup absolute path in <probing
privatePath="">? or relative path, for example <probing
privatePath="..\DLLFolder\SubDllFolder\my.dll"

Vadim Chekan.
 
One possible solution, which I never got around to try out myself, is to use
something called "Junction". This is really links in UNIX systems but
Windows only ships this feature in the resource kit.
Just search for junction on google.
 
You know, if the OP is talking about deploying to a production system, He
might want to consider how maintainable it will be to move the "bin" folder.
What percentage of all ASP.NET shops are going to do this? You might find, a
few years down the road, that nobody understands where the bin folder has
gone.
 
Hi John,
You know, if the OP is talking about deploying to a production system, He
might want to consider how maintainable it will be to move the "bin"
folder. What percentage of all ASP.NET shops are going to do this? You
might find, a few years down the road, that nobody understands where
the bin folder has gone.

This shouldn't be a problem - it's for a project within a relatively small
team with low staff turnover, and it's the boss (ie the guy who would have
to worry about this issue) who told me he wants this directory structure!

Cheers,

JON
 
Hi Guys,

Vadim Chekan said:
You can try to handle AssemblyResolve event of AppDomain and load
assembly manually from whatever location. It works for me.

you may try to hook to AppDomain.AssemblyResove event.

Thanks for the advice... However, I'm struggling a bit with AppDomain /
AssemblyResolve / Assembly.Load - can anyone point me in the direction of
tutorials / code samples?

TIA,

JON
 
Hi All,

I have failed to get <probing privatePath> to work with either full
directory names / absolute / relative paths as suggested... though, to be
honest, I have failed to get it to work even as it's supposed to, with
subdirectories of a conventional AppRoot\bin folder (and after looking
around old Group threads, it seems I'm not the only one!). Anyway, *all*
the documentation says the privatePath must be to a subfolder of the
AppRoot.

:-(

So it looks like my best bet is to go with AppDomain / AssemblyResolve /
Assembly.Load, but as I just wrote in another posting, I'm struggling a bit
with these (for me, new) topics, and need a bit of code sample and/or
tutorial help to get going...

Hope someone can help me out!

TIA,

JON
 
Hi Jon,

this is my event handler:

private System.Reflection.Assembly app_domain_AssemblyResolve(object
sender, ResolveEventArgs args)
{
string aaa = args.Name;
string[] _asm = args.Name.Split(",".ToCharArray());
string _asmname = @"C:\mybin\" + _asm[0] + ".dll";
System.Reflection.Assembly myassembly = null;
try
{
myassembly = System.Reflection.Assembly.LoadFrom(_asmname);
}
catch {}
return myassembly;
}
 
Hi Sunny,

Thank god you're still following this thread, I'm saved!

:-)

My problem isn't so much with the specific syntax of creating an Assembly
object (though that *is* a useful snippet), it's with the more general issue
of where you put this code, and how it relates to the web application as a
whole.

For example, on Application_Start my global.asax will immediately look for a
dll to execute some code. How does the global.asax know where the dll *is*,
if it isn't in the standard AppRoot\bin folder? Should your code be in my
global.asax somehow?

And then what happens when my default.aspx loads? How will this page find
the dll which contains its Code Behind? All my aspx pages inherit from a
PageBase class, but there's no point putting your code there, since PageBase
is also in the dll that needs to be found, so at this point the problem
becomes circular... :-(

Hope you can understand what I'm not understanding...

Thanks for the help!

JON
 
Hi Jon,

So, you can not completely remove dlls from bin. At least One will be
there, containing the compiled code from Global.asax.cs and
MyPage.aspx.cs.

But what I have tried and it works was:
I have...

1. Created the page the way I wanted. (Test.aspx and Test.aspx.cs)
2. Created a new project in the solution. There I have created
MyTestPageBase.cs, and copied the code from Test.aspx.cs, and changed
the class name form Test to BaseTest
3. Build the project.
4. Added a reference to the newly created object in your app project,
and set the CopyLocal to false.
5. Opened the Test.cs.aspx and modified Test class to inherit from
BaseTest and removed the body of the class. So now my Test.aspx.cs looks
like:

namespace TestApp
{
/// <summary>
/// Summary description for Test.
/// </summary>
public class Test : TestBase
{

}
}
6. In Global.asax.cs in the constructor of the global class, after
InitializeComponents() added the event handler to assembly resolve.
7. Added the snipped I have posted.
8. Moved the dll, generated from the child object in the directory to
which my resolver points.

9. Grabbed a haineken (this is very important) :)

10 It works.


Of course, you do not need to add a project to the current solution. You
just have to put all your codebehind code in a separate project(s) and
compile them. Then from your solution you can reference the dlls
directly and change the base classes for your pages to one, defined in
these dlls.

This is closest to your original request I can reach.

Cheers
Sunny
 
Hi Sunny,

You've been an absolute star, many thanks for your efforts on my behalf!
I'll digest your ideas over the weekend and then see what a talk with my
boss brings on Monday... He said he wanted this unconventional directory
structure for security reasons, but if you simply *cannot* completely
eliminate the AppRoot\bin folder, then maybe he'll be happy with the usual
structure.

I'm still very surprised that there seems *no way* in asp.net to change this
fundamental issue... But unless someone else posts to this thread with new
ideas, I guess I'll just have to accept that it can't be done.

Thanks once more,

JON

PS Depending on what the boss says, I may be asking for more help from you
next week! ;-)
 
I have strong impression that <probing privatePath=..> does not remove
"bin" path but appends it.

Vadim Chekan.
 
Back
Top