Task 037: .ASAX File Format

Task 037: .ASAX File Format

Updated Code Blocks with Expanded Comments for .ASAX Handling

The following sections present the revised code blocks, incorporating expanded comments for clarity. Comments have been enhanced to detail the purpose of each section, variable, and logic step. The extraction logic for properties has been refined to ensure comprehensive coverage: directives, declaration blocks, render blocks, language, inheritance, and event handlers are extracted from the file content where applicable. Fixed properties (e.g., single instance restriction, automatic parsing, security restriction, recompilation trigger) remain hardcoded as they are intrinsic to the format and not embedded in the file. The event extraction loop processes all specified events, ensuring complete handling. The write functionality continues to focus on variable properties.

1. List of Properties Intrinsic to the .ASAX File Format

The properties intrinsic to the .ASAX file format, as derived from its specifications, encompass the following structural and functional attributes:

  • Application Directives: Optional tags at the beginning of the file that define application-specific settings for the ASP.NET parser, using the syntax <%@ directive attribute=value [attribute=value … ]%>.
  • Code Declaration Blocks: Embedded server-side code within <script runat="server"> tags, used to define event-handling methods and logic.
  • Code Render Blocks: Inline code or expressions executed during page rendering, denoted by <% code %> for inline code or <%= expression %> for inline expressions.
  • Event Handling Capability: Supports definitions for application-level events (e.g., Application_Start, Application_End) and session-level events (e.g., Session_Start, Session_End).
  • Single Instance Restriction: Only one .ASAX file is permitted per ASP.NET application, typically named Global.asax and located in the root directory.
  • Automatic Parsing: The file is automatically detected and processed by the ASP.NET runtime without requiring explicit registration.
  • Inheritance from HttpApplication: The associated code-behind class inherits from the HttpApplication base class, providing access to the ASP.NET object model.
  • Security Restriction: The file cannot be directly requested or downloaded via a web browser, as access is blocked by the web server.
  • Recompilation Trigger: Any modifications to the file prompt automatic recompilation of the application, resetting its state.
  • Language Flexibility: Supports code in any .NET-compatible language, such as C# or VB.NET, specified via directives.

The following are two direct download links to sample .ASAX files hosted on public repositories:

3. HTML with Embedded JavaScript for Drag-and-Drop .ASAX File Analysis

The updated script includes detailed comments explaining the drag-and-drop mechanism, property extraction (including language, inheritance, and all events), and display logic.

.ASAX File Property Dumper
Drag and drop a .ASAX file here
, case-insensitive const declarationBlocks = content.match(/

4. Python Class for .ASAX File Handling

The updated class features expanded comments detailing initialization, reading/decoding (with extraction of all properties), printing, and writing logic.

import re
import os

class AsaxHandler:
    def __init__(self, filepath):
        # Initialize the handler with the file path
        self.filepath = filepath
        # Lists to store extracted variable properties
        self.directives = []
        self.declaration_blocks = []
        self.render_blocks = []
        # Defaults for language and inheritance
        self.language = 'Any .NET language'
        self.inherits = 'HttpApplication (default)'
        # Set to store detected events
        self.detected_events = set()
        # Comprehensive list of all standard ASP.NET events to check for
        self.events_list = [
            'Application_Init', 'Application_Start', 'Application_End', 'Application_BeginRequest',
            'Application_EndRequest', 'Application_AuthenticateRequest', 'Application_AuthorizeRequest',
            'Application_ResolveRequestCache', 'Application_AcquireRequestState', 'Application_PreRequestHandlerExecute',
            'Application_PostRequestHandlerExecute', 'Application_ReleaseRequestState', 'Application_UpdateRequestCache',
            'Application_Error', 'Application_PreSendRequestHeaders', 'Application_PreSendRequestContent',
            'Session_Start', 'Session_End'
        ]

    def read_and_decode(self):
        # Check if the file exists before reading
        if not os.path.exists(self.filepath):
            raise FileNotFoundError(f"File {self.filepath} not found.")
        # Open and read the file content
        with open(self.filepath, 'r', encoding='utf-8') as f:
            content = f.read()
        # Extract directives using regex for <%@ ... %>
        self.directives = re.findall(r'<%@[\s\S]*?%>', content)
        # Extract declaration blocks using regex for <script runat="server"> ... </script>, case-insensitive
        self.declaration_blocks = re.findall(r'<script runat="server">[\s\S]*?</script>', content, re.IGNORECASE)
        # Extract render blocks using regex for <% ... %> excluding directives
        self.render_blocks = re.findall(r'<%(?!@)([\s\S]*?)%>', content)
        
        # Extract language and inheritance from directives
        for dir in self.directives:
            # Search for Language attribute
            lang_match = re.search(r'Language\s*=\s*"([^"]+)"', dir, re.IGNORECASE)
            if lang_match:
                self.language = lang_match.group(1)
            # Search for Inherits attribute
            inh_match = re.search(r'Inherits\s*=\s*"([^"]+)"', dir, re.IGNORECASE)
            if inh_match:
                self.inherits = inh_match.group(1)
        
        # Extract event handlers from declaration blocks
        for block in self.declaration_blocks:
            # For each event in the list, check for handler signature in C# or VB.NET
            for event in self.events_list:
                if re.search(r'(void|Sub)\s+' + event + r'\s*\(', block, re.IGNORECASE):
                    self.detected_events.add(event)

    def print_properties(self):
        # Print extracted application directives
        print("Application Directives:")
        print('\n'.join(self.directives) or "None found")
        # Print extracted code declaration blocks
        print("\nCode Declaration Blocks:")
        print('\n\n'.join(self.declaration_blocks) or "None found")
        # Print extracted code render blocks
        print("\nCode Render Blocks:")
        print('\n'.join(self.render_blocks) or "None found")
        # Print detected events
        print("\nEvent Handling Capability:")
        print(', '.join(self.detected_events) or "None detected")
        # Print fixed single instance restriction
        print("\nSingle Instance Restriction:")
        print("Only one Global.asax file per ASP.NET application")
        # Print fixed automatic parsing property
        print("\nAutomatic Parsing:")
        print("Automatically detected and processed by the ASP.NET runtime")
        # Print extracted inheritance
        print("\nInheritance from HttpApplication:")
        print(f"The associated class inherits from {self.inherits}")
        # Print fixed security restriction
        print("\nSecurity Restriction:")
        print("The file cannot be directly requested or downloaded via a web browser")
        # Print fixed recompilation trigger
        print("\nRecompilation Trigger:")
        print("Modifications to the file prompt automatic recompilation of the application")
        # Print extracted language flexibility
        print("\nLanguage Flexibility:")
        print(f"Supports {self.language}")

    def write(self, new_filepath, directives=None, declaration_blocks=None, render_blocks=None):
        # Initialize content string for new file
        content = ''
        # Add directives if provided
        if directives:
            content += '\n'.join(directives) + '\n'
        # Add declaration blocks if provided, wrapping in <script> tags
        if declaration_blocks:
            content += '\n'.join([f'<script runat="server">\n{block}\n</script>' for block in declaration_blocks]) + '\n'
        # Add render blocks if provided, wrapping in <% ... %>
        if render_blocks:
            content += '\n'.join([f'<% {block} %>' for block in render_blocks]) + '\n'
        # Write the content to the new file
        with open(new_filepath, 'w', encoding='utf-8') as f:
            f.write(content)

# Example usage:
# handler = AsaxHandler('path/to/global.asax')
# handler.read_and_decode()
# handler.print_properties()
# handler.write('path/to/new.asax', directives=['<%@ Application Language="C#" Inherits="MyApp.Global" %>'])

5. Java Class for .ASAX File Handling

The updated class includes comprehensive comments on imports, fields, methods, and extraction logic.

import java.io.*;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class AsaxHandler {
    // File path for the .ASAX file
    private String filepath;
    // Lists for extracted variable properties
    private List<String> directives = new ArrayList<>();
    private List<String> declarationBlocks = new ArrayList<>();
    private List<String> renderBlocks = new ArrayList<>();
    // Defaults for language and inheritance
    private String language = "Any .NET language";
    private String inherits = "HttpApplication (default)";
    // Set for detected events
    private Set<String> detectedEvents = new HashSet<>();
    // Array of all standard ASP.NET events to detect
    private final String[] eventsList = {
        "Application_Init", "Application_Start", "Application_End", "Application_BeginRequest",
        "Application_EndRequest", "Application_AuthenticateRequest", "Application_AuthorizeRequest",
        "Application_ResolveRequestCache", "Application_AcquireRequestState", "Application_PreRequestHandlerExecute",
        "Application_PostRequestHandlerExecute", "Application_ReleaseRequestState", "Application_UpdateRequestCache",
        "Application_Error", "Application_PreSendRequestHeaders", "Application_PreSendRequestContent",
        "Session_Start", "Session_End"
    };

    // Constructor to set the file path
    public AsaxHandler(String filepath) {
        this.filepath = filepath;
    }

    // Method to read and decode the file, extracting all properties
    public void readAndDecode() throws IOException {
        // Check if file exists
        File file = new File(filepath);
        if (!file.exists()) {
            throw new FileNotFoundException("File " + filepath + " not found.");
        }
        // Read file content into a string
        StringBuilder content = new StringBuilder();
        try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
            String line;
            while ((line = reader.readLine()) != null) {
                content.append(line).append("\n");
            }
        }
        String text = content.toString();

        // Extract directives using pattern for <%@ ... %>
        Pattern dirPattern = Pattern.compile("<%@[\\s\\S]*?%>");
        Matcher dirMatcher = dirPattern.matcher(text);
        while (dirMatcher.find()) {
            directives.add(dirMatcher.group());
        }

        // Extract declaration blocks using pattern for <script runat="server"> ... </script>, case-insensitive
        Pattern declPattern = Pattern.compile("<script runat=\"server\">[\\s\\S]*?</script>", Pattern.CASE_INSENSITIVE);
        Matcher declMatcher = declPattern.matcher(text);
        while (declMatcher.find()) {
            declarationBlocks.add(declMatcher.group());
        }

        // Extract render blocks using pattern for <% ... %> excluding directives
        Pattern rendPattern = Pattern.compile("<%(?!@)([\\s\\S]*?)%>");
        Matcher rendMatcher = rendPattern.matcher(text);
        while (rendMatcher.find()) {
            renderBlocks.add(rendMatcher.group());
        }

        // Extract language and inheritance from directives
        for (String dir : directives) {
            // Pattern for Language attribute
            Pattern langPattern = Pattern.compile("Language\\s*=\\s*\"([^\"]+)\"", Pattern.CASE_INSENSITIVE);
            Matcher langMatcher = langPattern.matcher(dir);
            if (langMatcher.find()) {
                language = langMatcher.group(1);
            }
            // Pattern for Inherits attribute
            Pattern inhPattern = Pattern.compile("Inherits\\s*=\\s*\"([^\"]+)\"", Pattern.CASE_INSENSITIVE);
            Matcher inhMatcher = inhPattern.matcher(dir);
            if (inhMatcher.find()) {
                inherits = inhMatcher.group(1);
            }
        }

        // Extract events from declaration blocks
        for (String block : declarationBlocks) {
            // For each event, check for handler signature
            for (String event : eventsList) {
                Pattern eventPattern = Pattern.compile("(void|Sub)\\s+" + event + "\\s*\\(", Pattern.CASE_INSENSITIVE);
                Matcher eventMatcher = eventPattern.matcher(block);
                if (eventMatcher.find()) {
                    detectedEvents.add(event);
                }
            }
        }
    }

    // Method to print all properties, including extracted and fixed
    public void printProperties() {
        System.out.println("Application Directives:");
        System.out.println(String.join("\n", directives).isEmpty() ? "None found" : String.join("\n", directives));
        System.out.println("\nCode Declaration Blocks:");
        System.out.println(String.join("\n\n", declarationBlocks).isEmpty() ? "None found" : String.join("\n\n", declarationBlocks));
        System.out.println("\nCode Render Blocks:");
        System.out.println(String.join("\n", renderBlocks).isEmpty() ? "None found" : String.join("\n", renderBlocks));
        System.out.println("\nEvent Handling Capability:");
        System.out.println(String.join(", ", detectedEvents).isEmpty() ? "None detected" : String.join(", ", detectedEvents));
        System.out.println("\nSingle Instance Restriction:");
        System.out.println("Only one Global.asax file per ASP.NET application");
        System.out.println("\nAutomatic Parsing:");
        System.out.println("Automatically detected and processed by the ASP.NET runtime");
        System.out.println("\nInheritance from HttpApplication:");
        System.out.println("The associated class inherits from " + inherits);
        System.out.println("\nSecurity Restriction:");
        System.out.println("The file cannot be directly requested or downloaded via a web browser");
        System.out.println("\nRecompilation Trigger:");
        System.out.println("Modifications to the file prompt automatic recompilation of the application");
        System.out.println("\nLanguage Flexibility:");
        System.out.println("Supports " + language);
    }

    // Method to write a new .ASAX file with provided variable properties
    public void write(String newFilepath, List<String> newDirectives, List<String> newDeclarationBlocks, List<String> newRenderBlocks) throws IOException {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(newFilepath))) {
            // Write directives if provided
            if (newDirectives != null) {
                for (String dir : newDirectives) {
                    writer.write(dir + "\n");
                }
            }
            // Write declaration blocks if provided
            if (newDeclarationBlocks != null) {
                for (String block : newDeclarationBlocks) {
                    writer.write("<script runat=\"server\">\n" + block + "\n</script>\n");
                }
            }
            // Write render blocks if provided
            if (newRenderBlocks != null) {
                for (String block : newRenderBlocks) {
                    writer.write("<% " + block + " %>\n");
                }
            }
        }
    }

    // Example usage:
    // public static void main(String[] args) throws IOException {
    //     AsaxHandler handler = new AsaxHandler("path/to/global.asax");
    //     handler.readAndDecode();
    //     handler.printProperties();
    //     List<String> dirs = List.of("<%@ Application Language=\"C#\" Inherits=\"MyApp.Global\" %>");
    //     handler.write("path/to/new.asax", dirs, null, null);
    // }
}

6. JavaScript Class for .ASAX File Handling

The updated class (for Node.js) has detailed comments on properties, methods, and extraction processes.

const fs = require('fs');

class AsaxHandler {
    constructor(filepath) {
        // Set the file path
        this.filepath = filepath;
        // Arrays for extracted variable properties
        this.directives = [];
        this.declarationBlocks = [];
        this.renderBlocks = [];
        // Defaults for language and inheritance
        this.language = 'Any .NET language';
        this.inherits = 'HttpApplication (default)';
        // Set for detected events
        this.detectedEvents = new Set();
        // List of all standard ASP.NET events
        this.eventsList = [
            'Application_Init', 'Application_Start', 'Application_End', 'Application_BeginRequest',
            'Application_EndRequest', 'Application_AuthenticateRequest', 'Application_AuthorizeRequest',
            'Application_ResolveRequestCache', 'Application_AcquireRequestState', 'Application_PreRequestHandlerExecute',
            'Application_PostRequestHandlerExecute', 'Application_ReleaseRequestState', 'Application_UpdateRequestCache',
            'Application_Error', 'Application_PreSendRequestHeaders', 'Application_PreSendRequestContent',
            'Session_Start', 'Session_End'
        ];
    }

    readAndDecode() {
        // Check if file exists
        if (!fs.existsSync(this.filepath)) {
            throw new Error(`File ${this.filepath} not found.`);
        }
        // Read file content
        const content = fs.readFileSync(this.filepath, 'utf-8');
        // Extract directives
        this.directives = content.match(/<%@[\s\S]*?%>/g) || [];
        // Extract declaration blocks, case-insensitive
        this.declarationBlocks = content.match(/<script runat="server">[\s\S]*?<\/script>/gi) || [];
        // Extract render blocks excluding directives
        this.renderBlocks = content.match(/<%(?!@)([\s\S]*?)%>/g) || [];
        
        // Extract language and inheritance from directives
        this.directives.forEach(dir => {
            // Match Language
            const langMatch = dir.match(/Language\s*=\s*"([^"]+)"/i);
            if (langMatch) this.language = langMatch[1];
            // Match Inherits
            const inhMatch = dir.match(/Inherits\s*=\s*"([^"]+)"/i);
            if (inhMatch) this.inherits = inhMatch[1];
        });
        
        // Extract events from declaration blocks
        this.declarationBlocks.forEach(block => {
            // For each event, test for handler signature
            this.eventsList.forEach(event => {
                const regex = new RegExp(`(void|Sub)\\s+${event}\\s*\\(`, 'gi');
                if (regex.test(block)) this.detectedEvents.add(event);
            });
        });
    }

    printProperties() {
        // Print directives
        console.log('Application Directives:');
        console.log(this.directives.join('\n') || 'None found');
        // Print declaration blocks
        console.log('\nCode Declaration Blocks:');
        console.log(this.declarationBlocks.join('\n\n') || 'None found');
        // Print render blocks
        console.log('\nCode Render Blocks:');
        console.log(this.renderBlocks.join('\n') || 'None found');
        // Print detected events
        console.log('\nEvent Handling Capability:');
        console.log(Array.from(this.detectedEvents).join(', ') || 'None detected');
        // Print fixed properties
        console.log('\nSingle Instance Restriction:');
        console.log('Only one Global.asax file per ASP.NET application');
        console.log('\nAutomatic Parsing:');
        console.log('Automatically detected and processed by the ASP.NET runtime');
        console.log('\nInheritance from HttpApplication:');
        console.log(`The associated class inherits from ${this.inherits}`);
        console.log('\nSecurity Restriction:');
        console.log('The file cannot be directly requested or downloaded via a web browser');
        console.log('\nRecompilation Trigger:');
        console.log('Modifications to the file prompt automatic recompilation of the application');
        console.log('\nLanguage Flexibility:');
        console.log(`Supports ${this.language}`);
    }

    write(newFilepath, directives = [], declarationBlocks = [], renderBlocks = []) {
        // Build content string
        let content = '';
        // Add directives
        content += directives.join('\n') + '\n';
        // Add declaration blocks
        content += declarationBlocks.map(block => `<script runat="server">\n${block}\n</script>`).join('\n') + '\n';
        // Add render blocks
        content += renderBlocks.map(block => `<% ${block} %>`).join('\n') + '\n';
        // Write to file
        fs.writeFileSync(newFilepath, content, 'utf-8');
    }
}

// Example usage:
// const handler = new AsaxHandler('path/to/global.asax');
// handler.readAndDecode();
// handler.printProperties();
// handler.write('path/to/new.asax', ['<%@ Application Language="C#" Inherits="MyApp.Global" %>']);

7. C++ Class for .ASAX File Handling

The updated class incorporates detailed comments on includes, members, methods, and extraction.

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <set>
#include <regex>
#include <stdexcept>

class AsaxHandler {
private:
    // File path
    std::string filepath;
    // Vectors for extracted properties
    std::vector<std::string> directives;
    std::vector<std::string> declaration_blocks;
    std::vector<std::string> render_blocks;
    // Defaults for language and inheritance
    std::string language = "Any .NET language";
    std::string inherits = "HttpApplication (default)";
    // Set for detected events
    std::set<std::string> detected_events;
    // List of all events
    const std::vector<std::string> events_list = {
        "Application_Init", "Application_Start", "Application_End", "Application_BeginRequest",
        "Application_EndRequest", "Application_AuthenticateRequest", "Application_AuthorizeRequest",
        "Application_ResolveRequestCache", "Application_AcquireRequestState", "Application_PreRequestHandlerExecute",
        "Application_PostRequestHandlerExecute", "Application_ReleaseRequestState", "Application_UpdateRequestCache",
        "Application_Error", "Application_PreSendRequestHeaders", "Application_PreSendRequestContent",
        "Session_Start", "Session_End"
    };

public:
    // Constructor
    AsaxHandler(const std::string& fp) : filepath(fp) {}

    // Read and decode method
    void read_and_decode() {
        // Open file
        std::ifstream file(filepath);
        if (!file.is_open()) {
            throw std::runtime_error("File " + filepath + " not found.");
        }
        // Read content
        std::string content((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
        file.close();

        // Extract directives
        std::regex dir_regex(R"(< %@[\s\S]*?%>)");
        std::sregex_iterator dir_iter(content.begin(), content.end(), dir_regex);
        for (std::sregex_iterator i = dir_iter; i != std::sregex_iterator(); ++i) {
            directives.push_back(i->str());
        }

        // Extract declaration blocks
        std::regex decl_regex(R"(<script runat="server">[\s\S]*?</script>)", std::regex::icase);
        std::sregex_iterator decl_iter(content.begin(), content.end(), decl_regex);
        for (std::sregex_iterator i = decl_iter; i != std::sregex_iterator(); ++i) {
            declaration_blocks.push_back(i->str());
        }

        // Extract render blocks
        std::regex rend_regex(R"(<%(?!@)([\s\S]*?)%>)");
        std::sregex_iterator rend_iter(content.begin(), content.end(), rend_regex);
        for (std::sregex_iterator i = rend_iter; i != std::sregex_iterator(); ++i) {
            render_blocks.push_back(i->str());
        }

        // Extract language and inherits
        std::regex lang_regex(R"(Language\s*=\s*"([^"]+)")", std::regex::icase);
        std::regex inh_regex(R"(Inherits\s*=\s*"([^"]+)")", std::regex::icase);
        for (const auto& dir : directives) {
            std::smatch lang_match;
            if (std::regex_search(dir, lang_match, lang_regex)) {
                language = lang_match[1].str();
            }
            std::smatch inh_match;
            if (std::regex_search(dir, inh_match, inh_regex)) {
                inherits = inh_match[1].str();
            }
        }

        // Extract events
        for (const auto& block : declaration_blocks) {
            for (const auto& event : events_list) {
                std::regex event_regex(R"((void|Sub)\s+)" + event + R"(\s*\()", std::regex::icase);
                if (std::regex_search(block, event_regex)) {
                    detected_events.insert(event);
                }
            }
        }
    }

    // Print properties method
    void print_properties() {
        // Print directives
        std::cout << "Application Directives:" << std::endl;
        if (directives.empty()) {
            std::cout << "None found" << std::endl;
        } else {
            for (const auto& dir : directives) {
                std::cout << dir << std::endl;
            }
        }
        // Print declaration blocks
        std::cout << "\nCode Declaration Blocks:" << std::endl;
        if (declaration_blocks.empty()) {
            std::cout << "None found" << std::endl;
        } else {
            for (const auto& block : declaration_blocks) {
                std::cout << block << std::endl << std::endl;
            }
        }
        // Print render blocks
        std::cout << "\nCode Render Blocks:" << std::endl;
        if (render_blocks.empty()) {
            std::cout << "None found" << std::endl;
        } else {
            for (const auto& block : render_blocks) {
                std::cout << block << std::endl;
            }
        }
        // Print events
        std::cout << "\nEvent Handling Capability:" << std::endl;
        if (detected_events.empty()) {
            std::cout << "None detected" << std::endl;
        } else {
            bool first = true;
            for (const auto& event : detected_events) {
                if (!first) std::cout << ", ";
                std::cout << event;
                first = false;
            }
            std::cout << std::endl;
        }
        // Print fixed properties
        std::cout << "\nSingle Instance Restriction:" << std::endl;
        std::cout << "Only one Global.asax file per ASP.NET application" << std::endl;
        std::cout << "\nAutomatic Parsing:" << std::endl;
        std::cout << "Automatically detected and processed by the ASP.NET runtime" << std::endl;
        std::cout << "\nInheritance from HttpApplication:" << std::endl;
        std::cout << "The associated class inherits from " << inherits << std::endl;
        std::cout << "\nSecurity Restriction:" << std::endl;
        std::cout << "The file cannot be directly requested or downloaded via a web browser" << std::endl;
        std::cout << "\nRecompilation Trigger:" << std::endl;
        std::cout << "Modifications to the file prompt automatic recompilation of the application" << std::endl;
        std::cout << "\nLanguage Flexibility:" << std::endl;
        std::cout << "Supports " << language << std::endl;
    }

    // Write method
    void write(const std::string& new_filepath, const std::vector<std::string>& new_directives = {},
               const std::vector<std::string>& new_declaration_blocks = {},
               const std::vector<std::string>& new_render_blocks = {}) {
        // Open output file
        std::ofstream file(new_filepath);
        if (!file.is_open()) {
            throw std::runtime_error("Unable to write to " + new_filepath);
        }
        // Write directives
        for (const auto& dir : new_directives) {
            file << dir << "\n";
        }
        // Write declaration blocks
        for (const auto& block : new_declaration_blocks) {
            file << "<script runat=\"server\">\n" << block << "\n</script>\n";
        }
        // Write render blocks
        for (const auto& block : new_render_blocks) {
            file << "<% " << block << " %>\n";
        }
        // Close file
        file.close();
    }
};

// Example usage:
// int main() {
//     try {
//         AsaxHandler handler("path/to/global.asax");
//         handler.read_and_decode();
//         handler.print_properties();
//         std::vector<std::string> dirs = {"<%@ Application Language=\"C#\" Inherits=\"MyApp.Global\" %>"};
//         handler.write("path/to/new.asax", dirs);
//     } catch (const std::exception& e) {
//         std::cerr << e.what() << std::endl;
//     }
//     return 0;
// }