Check if ascx control exist in precompiled asp.net website

1.5k views Asked by At

I would like to check if an ASCX file exists before I open it because it is loadded dynamically. That should be easy by using the following code:System.IO.File.Exists(Server.MapPath(controlPath)). But this doesn't work in precompiled website because ASCX files don't exist anymore.

Any help will be appreciated.

Update: I precompile a website without "Allow precompiled site to be updatable" option.

4

There are 4 answers

1
Tal Aloni On BEST ANSWER

File.Exists will not work because when an .ascx is precompiled it will not be physically present on the disk.

HostingEnvironment.VirtualPathProvider.FileExists will not work as well, the default implementation is MapPathBasedVirtualPathProvider, which expects files to be physically present on the disk.

In such scenario, TemplateControl.LoadControl use the BuildManager which already cached those virtual files, so their physical presence is not checked.

Using reflection, it's possible to check if these files are cached (read: exist):

public static bool IsPrecompiledFileExists(string virtualPath)
{
    Type virtualPathType = BuildManager.GetType("System.Web.VirtualPath", true);
    MethodInfo createMethodInfo = virtualPathType.GetMethod("Create", new Type[] {typeof(string)});
    object virtualPathObject = createMethodInfo.Invoke(null, new object[] { virtualPath });

    MethodInfo getVPathBuildResultFromCacheMethodInfo = typeof(BuildManager).GetMethod("GetVPathBuildResultFromCache", BindingFlags.Static | BindingFlags.NonPublic);
    object buildResult = getVPathBuildResultFromCacheMethodInfo.Invoke(null, new object[] { virtualPathObject });
    return buildResult != null;
}

To make the solution compatible with additional deployment scenarios, you may probably want to use:

public static bool IsVirtualFileExists(string virtualPath)
{
    return HostingEnvironment.VirtualPathProvider.FileExists(virtualPath) ||
           IsPrecompiledFileExists(virtualPath);
}

Edit: Peter Blum has a better and faster solution.

p.s. For .Net Framework 2.0, BuildManager.CreateInstanceFromVirtualPath could be used as well (We can learn if the file exist or not based on the exception thrown).

1
Chris On

System.IO.File.Exists(Server.MapPath(path)) should do the trick. As @Leo said in your comment. ascx is a custom user control that is used in aspx page and they are still on the same location when you deployed your project.

1
Ali.Rashidi On

Some times you need to check if a user control exists before dynamically load it to a page. Here are two ways to accomplish this:

using System.Web.Hosting;
...

string virtualPath = "MyControl.ascx";
// or: "controls/MyControl.ascx"
// or: "../controls/MyControl.ascx"
// or: "~/controls/MyControl.ascx"

if (HostingEnvironment.VirtualPathProvider.FileExists(virtualPath))
{
Control control = LoadControl(virtualPath);
...
}

using System.IO;
...

string virtualPath = "MyControl.ascx";
// or: "controls/MyControl.ascx"
// or: "../controls/MyControl.ascx"
// or: "~/controls/MyControl.ascx"

if (File.Exists(Server.MapPath(virtualPath)))
{
Control control = LoadControl(virtualPath);
 ...
}
4
Tran Anh Hien On
 string ucName = "MyUC.ascx";
 if(File.Exists(Server.MapPath("/NameProject/" + (ucName))))
      controlToLoad = ucName;
LoadControl(controlToLoad);

Worked for me =))