How to throw Exception when class has wrong inheritance
Asked Answered
B

3

6

I have an asp.net webforms application. Every single aspx.cs class needs to inherit from BasePage.cs which inherits from System.Web.UI.Page.

Desired Page Inheritance:

class MyChildPage : BasePage :  System.Web.UI.Page

How do I force that when a new child page is created it inherits from BasePage.cs and not System.Web.UI.Page?

Potential solutions:

  • Is there a way to change default creation of an aspx.cs page?
  • Is there a way to throw a compiler error if it inherits from System.Web.UI.Page?

Note: These child pages to share the same master page so that might help.

Bloody answered 31/3, 2014 at 19:44 Comment(1)
Have you considered a tool like FxCop? Also, you could have a custom build step to validate every page extends BasePage.Veradis
V
1

You could implement this with a custom MSBuild task that validates all pages. For example, here is a Task that will check that only BasePage inherits from Page. If any other class inherits from Page, an error will be logged in the output and the build will fail:

public class CheckBasePage : Task
{
    public override bool Execute()
    {
        var assm = Assembly.LoadFile("/path/to/WebsiteAssembly.dll");
        var types = assm.GetTypes();

        var pages = new List<string>();
        foreach (var t in types)
        {
            if (t.BaseType == typeof(Page) && t.Name != "BasePage")
            {
                pages.Add(t.FullName);
            }
        }

        if (pages.Count > 0)
        {
            Log.LogError("The following pages need to inherit from BasePage: [" + string.Join(",", pages) + "]");
            return false;
        }

        return true;
    }
}

Then you would add this custom task as part of the build process in your project file:

<UsingTask TaskName="CheckBasePage" AssemblyFile="/path/to/MyCustomTasksAssembly.dll" />

<Target Name="PostBuild">
  <CheckBasePage />
</Target>

Now this assumes that MyCustomTasksAssembly is a separate project you create for managing custom MSBuild tasks like this. If you want to embed the CheckBasePage task into the same project as the rest of the code, you will need to apply the same trick from here.

Veradis answered 31/3, 2014 at 22:51 Comment(3)
This causes an issue. Once the assembly is loaded it won't unload the assembly. This breaks the build process because the assembly can't be moved to the bin directory since it is used by the CheckBasePage task. I tried creating loading the assembly in another app domain (msdn.microsoft.com/en-us/library/ms173101.aspx) so I could unload it but then I get file not found exception when trying to open the file. Any ideas?Bloody
Yes, did you read the last paragraph? I tested this myself and was able to get it working.Veradis
Yes thank you. I wanted to do it in the same assembly. I turns out the issue was that you couldn't pass a complex object from within one appDomain to another (Type). So I changee the code to only pass regular objects and it worked.Bloody
V
5

Not sure if it fits your situation but you can specify the base page for the entire application via web.config-

<system.web>
    <pages pageBaseType="BasePage" />
</system.web>

Documentation on msdn: http://msdn.microsoft.com/en-us/library/950xf363(v=vs.85).aspx

Viole answered 31/3, 2014 at 19:48 Comment(1)
@[Kelly Gendron] This actually doesn't work. This only works for stand alone pages without a code behind. Look at documentation in the answer and here velocityreviews.com/forums/… for more details.Bloody
V
1

You could implement this with a custom MSBuild task that validates all pages. For example, here is a Task that will check that only BasePage inherits from Page. If any other class inherits from Page, an error will be logged in the output and the build will fail:

public class CheckBasePage : Task
{
    public override bool Execute()
    {
        var assm = Assembly.LoadFile("/path/to/WebsiteAssembly.dll");
        var types = assm.GetTypes();

        var pages = new List<string>();
        foreach (var t in types)
        {
            if (t.BaseType == typeof(Page) && t.Name != "BasePage")
            {
                pages.Add(t.FullName);
            }
        }

        if (pages.Count > 0)
        {
            Log.LogError("The following pages need to inherit from BasePage: [" + string.Join(",", pages) + "]");
            return false;
        }

        return true;
    }
}

Then you would add this custom task as part of the build process in your project file:

<UsingTask TaskName="CheckBasePage" AssemblyFile="/path/to/MyCustomTasksAssembly.dll" />

<Target Name="PostBuild">
  <CheckBasePage />
</Target>

Now this assumes that MyCustomTasksAssembly is a separate project you create for managing custom MSBuild tasks like this. If you want to embed the CheckBasePage task into the same project as the rest of the code, you will need to apply the same trick from here.

Veradis answered 31/3, 2014 at 22:51 Comment(3)
This causes an issue. Once the assembly is loaded it won't unload the assembly. This breaks the build process because the assembly can't be moved to the bin directory since it is used by the CheckBasePage task. I tried creating loading the assembly in another app domain (msdn.microsoft.com/en-us/library/ms173101.aspx) so I could unload it but then I get file not found exception when trying to open the file. Any ideas?Bloody
Yes, did you read the last paragraph? I tested this myself and was able to get it working.Veradis
Yes thank you. I wanted to do it in the same assembly. I turns out the issue was that you couldn't pass a complex object from within one appDomain to another (Type). So I changee the code to only pass regular objects and it worked.Bloody
W
0

As an alternative to Kelly's answer, you can do this, which is more flexible but more of a pain to configure:

class MyChildPage : BasePage

and...

class BasePage : System.Web.UI.Page

So MyChildPage inherits from BasePage, which inherits from System.Web.UI.Page.

Wordbook answered 31/3, 2014 at 19:59 Comment(1)
This is already what I'm doing. My question is how do I ensure that in the future when I make new pages it will remain this way even if I forget or new developers join the team.Bloody

© 2022 - 2024 — McMap. All rights reserved.