Alik Levin's

Clarity, Technology, and Solving Problems | PracticeThis.com 

May, 2010

  • Alik Levin's

    Solution Architecture For The Masses. Step 4: Design Your Presentation Layer – Part I

    • 2 Comments
     Alik Levin    In Step 1 I have structured my Visual Studio Solution. In Step 2 I have designed and implemented my Entities and Business Services. In Step 3 I have designed and implemented basic crosscutting functionality – exception, handling, logging, instrumentation and input sanitization. I am ready to build my presentation layer. There are few principles that I must follow when creating presentation layer in Web Application Archetype called Web Application frame.

    Quick Resource Box

    In this post I will be structuring my ASP.NET Web Project following the principles outlined in the Web Application frame:

    • Authentication
    • Authorization
    • Caching
    • Exception Management
    • Logging, Instrumentation
    • Navigation
    • Page Layout (UI)
    • Page Rendering
    • Presentation Entity
    • Request Processing
    • Service Interface
    • Session Management
    • Validation

    Authentication & Authorization

    IIdentity and IPrincipal interfaces are the heart of .Net authentication and authorization. All authentication and authorization implementations implement these interfaces. Concrete classes that implement the IPrincipal interface populated with concrete classes that implement IIdentity and stored in HttpContenxt.Current.User where authorization frameworks such RoleManager will look for it.

    I have not decided where my application will be deployed – Internet, Intranet, or Azure. So the best bet for me in regards to Authentication and Authorization would be to assume this:

    • The concrete Authentication & Authorization framework will be configured in Web.Config without affecting the code.
    • Authorization logic will be made by Authorization framework or in code based on concrete implementation of IPrincipal located in HttpContext.Current.User anyway.

    Main decision to make at this point is to structure the project’s folders the way that there is clean separation between restricted pages and resources that do not require authentication and authorization. Following is how my web application is structure in terms of folders:

    image

    The following folders I have created manually:

    • Controls. This folder will hold user controls, ASCX’s. Does not require authentication. Direct access to ACSX files will be restricted by ASP.NET runtime.
    • CSS. This folder will hold CSS stylesheet files. Does not require authentication. It will be configured for anonymous access purposefully.
    • IMG. This folder will hold image files (JPG, PNG, etc.). Does not require authentication. It will be configured for anonymous access purposefully.
    • JS. This folder will hold JavaScript files. Does not require authentication. It will be configured for anonymous access purposefully.
    • Restricted. This folder will hold any use case that requires authentication/authorization.

    Minimum Authorization configuration in Web.Config:

    <location path="Restricted">
           <system.web>
                 <authorization>
                        <deny users="?"/>
                 </authorization>
           </system.web>
    </location>

    From p&p’s ASP.NET 2.0 Internet Security Reference Implementation

    Partition the site into restricted areas and public areas

    All pages that require authenticated access are placed in either the Restricted or Admin folders. Pages and resources in other directories are anonymously accessible. By partitioning the site, SSL is used only on those pages that need it. Since the use of SSL has a significant overhead, using it sparingly will improve system performance.

    There is more to partitioning than SSL [BTW, I’d argue SSL has “a significant overhead” – it does, but less than significant image ].

    Partitioning to folders fosters authorizing users based on folder names vs. particular pages. Authorizing users to particular pages is bug prone and less secure practice – imagine if someone just copy and pastes SuperSecurePage.aspx to ‘Copy of SuperSecurePage.aspx’ while you authorization configuration was as follows [very bad practice]:

    <location path="SuperSecurePage.aspx">
           <system.web>
                 <authorization>
                        <allow roles="SuperAdmin"/>
                 </authorization>
           </system.web>
    </location>

    Suddenly an attacker has free access to sensitive logic at ‘Copy of SuperSecurePage.aspx’ without being authorized.

    Concentrate restricted pages into folders and authorized on per folder basis, not per page basis.

    Another aspect of partitioning the application in separate folders relates to caching, which is next.

    The summary of my authentication and authorization strategy is:

    • Undecided.
    • Rely on the fact that whatever the implementation comes along it is based on IPrincipal, and IIdentity located in Http.Context.Current.User.

    Caching

    When it comes to caching in distributed web application there are four different types of caching come to mind:

    1. Browser caching. Cached content being stored on client machines and managed by browser’s caching mechanism. Proxy server caching is out of scope for this post.
    2. Output caching. Rendered HTML output by ASP.NET managed by IIS Server and ASP.NET engine on Web Server. Will be discussed in Page Layout (UI) section.
    3. Application data caching. Data retrieved from data sources such SQL Server and cached by middle tier [either by IIS Web Server, or Dedicated Downstream server] – out of scope at this point. More info here: Caching Architecture Guide for .Net Applications
    4. Data source caching. Enabling data source such as SQL Server to cache read only data in the data tier. Out of scope for this post. In short, it’s either achieved by scaling up by setting up a big box with 32 GB RAM and up, or scaling out by separating read and write data as described in Scaling Databases part.

    The summary of my decisions regarding Browser caching was made:

    • Creating separate folders for static content – CSS, IMG, JS. It will help operations system engineering team easily set expiration policies in production which should lead to less HTTP 304’s improving overall user experience and rendering time.
    • Allowing anonymous access to the folders other than Restricted as described in previous section. It will reduce HTTP 401 roundtrips improving user experience and rendering time.

    More info here ASP.NET Performance: Get Rid of HTTP 401 and HTTP 304.

    Exception Management

    General guidelines from Chapter 15: Web Application Archetype:

    • Do not use exceptions to control the logical flow of your application.
    • Do not catch exceptions unless you *must* handle them, you need to strip sensitive information, or you need to add additional information to the exception.
    • Design a global error handler to catch unhandled exceptions.
    • Display user-friendly messages to end users whenever an error or exception occurs.
    • Do not reveal sensitive information, such as passwords, through exception details.

    As per How To: Design Exception Management the key considerations of detecting [catching] exceptions are:

    Guidelines
    My take
    • Only catch the exception when you must perform any of the following tasks:
      • Gathering exception details for logging.
      • Adding relevant and additional information to the exception.
      • Cleaning up any resources used in the code block.
      • Retrying the operation to recover from the exception.
    • Do not catch an exception and allow the exception to propagate up the call stack, if you do not have any task to accomplish.
    • Required information will be gathered in global error handler
    • I do not plan to add more information.
    • Resources will be cleaned as part of try/catch/finally triplet. But main approach will be using *using* clause.
    • I do not plan to retry.

    The strategy for handling such unhandled exceptions is:

    • Gather the required information. I will rely on Web Events to gather the info.
    • Log the exception information. I will rely on Health Monitoring mechanism to publish/log exceptions.
    • Send any notifications. I will not be doing that. If needed, will route the event to event log and configure it for further actions.
    • Perform any clean-up required. I will do it in try/catch/finally triplet or inside using clause.
    • Communicate the error information to the user. I will show generic error page without revealing any implementation details.

    The summary of the my exception handling strategy:

    For now this is what I have in my Visual Studio project regarding exception handling:

    Global.asax:

    protected void Application_Error(object sender, EventArgs e)
    {
        Exception ex = Server.GetLastError().GetBaseException();
        string message = ex.ToString();
        Tracing.TraceMessage(message);
        EventsServices.PublishException("GLOBAL ERROR HANDER: " +
                                        message);
        Server.ClearError();
        Response.Redirect("GenericErrorPage.htm");
    }

    Notice EvenstServices and Tracing classes I use – I utilize previously implemented logging mechanism.

    Web.Config [make sure you have created GenericErrorPage.htm]:

    <customErrors mode="RemoteOnly"
                  defaultRedirect
    ="GenericErrorPage.htm">
    </customErrors>

    Logging & Instrumentation

    Logging is implemented in previous step. In previous section I have used it to publish and log an exception caught in global error handler. Since it is based on built-in ASP.NET health monitoring the following section needed to be added to Web.Config:

    <healthMonitoring>
      <eventMappings>
        <add name="Exception Event"
             type
    ="WebEvents.ExceptionEvent"/>
      </eventMappings>
      <rules>
        <add name="Exception" eventName="Exception Event"
                              provider
    ="EventLogProvider"
                              minInterval
    ="00:00:01"/>
      </rules>
    </healthMonitoring>

     

    It reads as follows:

    • There is a custom event of type “WebEvent.ExceptionEvent”
    • I map it to a friendly name “Exception Event”.
    • I route this event to Event Log [notice provider attribute].

    Anytime a code similar to the following code runs:

    EventsServices.PublishException(“Some Message”);

    I should observe it in Event Log. Here an example for division by zero caught by global error handler:

    image

    Instrumentation is performed by Tracing.TraceMessage(message). I have already used it in global error handler [look in the example above]. The results it produces observed using DebugView:

    image

    Other categories of Web Application frame will be discussed in the next part. Stay tuned.

    Related Books

  • Alik Levin's

    Improving Productivity & Readability With Auto-Implemented Properties, & Object Initializers

    • 0 Comments
     Alik Levin    I have improved readability dramatically by re-implementing my Entities using auto-implemented properties and object initializers. The change is inspired after reading a book LINQ in Action.

    Quick Resource Box

    Remove Old Fashion Constructor

    The original version of my Entities was implemented following the classic approach where you create private fields that are initialized by constructor and the values exposed by public properties. Using auto-implemented properties feature allowed me to dramatically reduce amount of plumbing code.

    Before using auto-implemented properties:

        [DataContract] 
        public class AccountInfo 
        { 
            private string m_id = string.Empty; 
            private string m_ownerId = string.Empty; 
            private string m_currency = string.Empty; 
            private double m_balance = double.NaN; 

            public AccountInfo(string id,
                        string ownerId,
                        string currency,
                        double balance)

            [DataMember] 
            public string Id 
            { 
                get { return m_id; } 
                set { m_id = value; } 
            } 
            [DataMember] 
            public string OwnerId 
            { 
                get { return m_ownerId; } 
                set { m_ownerId = value; } 
            } 
            [DataMember] 
            public string Currency 
            { 
                get { return m_currency; } 
                set { m_currency = value; } 
            } 
            [DataMember] 
            public double Balance 
            { 
                get { return m_balance; } 
                set { m_balance = value; } 
            } 
        } 

    After using auto-implemented properties:

        public class AccountInfo
        {
            [DataMember]
            public string Id{get; set; }
            [DataMember]
            public string OwnerId{get; set; }
            [DataMember]
            public string Currency{get; set; }
            [DataMember]
            public double Balance {get; set; }

        }

    Sweet. 11 lines instead of almost 40!

    Changing Business Services 

    Now I needed to change my business services class that uses the Entities. This is where object initializer kicks in.

    Before object initialzers:

    List<AccountInfo> result = null;
    result = new List<AccountInfo

        new AccountInfo("ac1","ownr1", "USD", 1001), 
        new AccountInfo("ac2","ownr2", "USD", 1002), 
        new AccountInfo("ac3","ownr3", "USD", 1003), 
        new AccountInfo("ac4","ownr4", "USD", 1004), 
        new AccountInfo("ac5","ownr5", "USD", 1005), 
        new AccountInfo("ac6","ownr6", "USD", 1006),
    };

    After using object initializer:

    In this case I needed to add subtle amount of code, such as Id=, Owner=, Currency=, and Balance=. The number of lines stays the same though:

    var result = new List<AccountInfo>
    {
        new AccountInfo{Id="ac1",OwnerId="ownr1",Currency ="USD",Balance= 1001},
        new AccountInfo{Id="ac2",OwnerId="ownr2",Currency ="USD",Balance= 1002},
        new AccountInfo{Id="ac3",OwnerId="ownr3",Currency ="USD",Balance= 1003},
        new AccountInfo{Id="ac4",OwnerId="ownr4",Currency ="USD",Balance= 1004},
        new AccountInfo{Id="ac5",OwnerId="ownr5",Currency ="USD",Balance= 1005},
        new AccountInfo{Id="ac6",OwnerId="ownr6",Currency ="USD",Balance= 1006},
    };

    The interesting part is that Visual Studio supports intellisense when using object initialization feature:

    image 

    Regression Testing

    To make sure I have not broken anything I have ran my Business Services unit test:

    image

    Ahh, heaven ;)

    Conclusion

    Auto-implemented properties help removing ton of plumbing code. That does not mean constructors are dead. But in majority of the situations that’s what’s needed and constructors get in a way with ton of unnecessary code that can be avoided with auto-implemented properties easily initialized with object initalizers.

    Related Books

  • Alik Levin's

    Solution Architecture For The Masses. Step 3: Design Your Cross Cutting Utilities

    • 0 Comments
     Alik Levin    In Step 1 I have structured my Visual Studio Solution. In Step 2 I have designed and implemented my Entities and Business Services. Now I need to make sure I have basic set of utilities I might be needing. These are the cross cutting utilities I will be using in any of the layers. At minimum I need to have utilities related to security, logging & monitoring. I might be further adding more utilities as I go.

    Quick Resource Box

    In this post I will be implementing Logging & Instrumentation and Input & Data Validation security related utilities which I will be using in presentation, business logic, and data tiers.

    Logging & Instrumentation

    General guidelines from Chapter 15: Web Application Archetype:

    Guidelines
    My take
    • Consider auditing for user management events.
    • Consider auditing for unusual activities.
    • Consider auditing for business-critical operations.
    • Create secure log file management policies, such as restricting the access to log files, allowing only write access to users, etc.
    • Do not store sensitive information in the log or audit files.
    • From Logging, Auditing, and Instrumentation: Ensure that a logging failure does not affect normal business layer functionality.
    • I do not manage users.
    • Business critical events will be logged in Business Services components using Web Events mechanism.
    • When deployed in production, log files will reside on separate machine and configured in web.config using Health Monitoring mechanism.
    • I will rely on Health Monitoring mechanism to not to store sensitive information beyond what I publish to it.
    • Will be using Health Monitoring for logging and System.Diagnostics’ Trace class. Both lightweight, configurable, and designed for high scale via throttling.

    The summary of my logging and instrumentation strategy:

    Liability: Web Events designed to work in ASP.NET Web applications or WCF Services hosted in IIS. If one day I decide to move my business logic into separate physical tier not hosted in IIS and not exposed as WCF service then Web Events might be unsuitable. On other hand, I hardly can see that day coming any soon, if any… In any case the logging mechanism is abstracted so the implementation is not visible to its consumers.

    Implementing Instrumentation

    Right click on Crosscutting folder in Visual Studio and add two new Class Library Projects – WebEvents and Instrumentation:

    image_thumb[6]

    Right click on Instrumentation project and add new Class. Name it Tracing. Add implementation similar to the one outlined in Tracing & Instrumenting ASP.NET Application For Performance. At this moment you should be able to report entry and exit to the functions or any arbitrary messages.

    public class Tracing
    {
        public static void TraceFunctionEnter()
        {
            StackTrace st = new StackTrace();
            Trace.WriteLine("TRC:ENTERING: "
                  st.GetFrame(1).GetMethod());
        }
        public static void TraceFunctionExit()
        {
            StackTrace st = new StackTrace();
            Trace.WriteLine("TRC: EXITING: " +
                  st.GetFrame(1).GetMethod());
        }
        public static void TraceMessage(string message)
        {
            Trace.WriteLine("TRC:" + message);
        }
    }

     

    The output is published to default Trace Listener which is added by default. Use either DebugView or Procmon to collect and display the trace messages as described in Tracing & Instrumenting ASP.NET Application For Performance, Sysinternals ProcMon New & Improved – Captures Both System & Application Events.

    In case you are interested to remove the default listener use this configuration in Web.Config. I can’t really think of any good reason to do so. Performance? Nuh….image10 :

    <system.diagnostics>
      <trace>
        <listeners>
          <clear/>
        </listeners>
      </trace>
    </system.diagnostics>

    Implementing Logging

    Next I will implement logging using Web Events and ASP.NET Health Monitoring mechanism.

    Right click on WebEvents project and add new class. Name it ExceptionEvent. Add reference to System.Web, add System.Web and 
    System.Web.Management namespaces in using declaration sections. Add the following implementation:

    class ExceptionEvent : WebBaseEvent
    {
        const int WebEventCode =
                         WebEventCodes.WebExtendedBase + 1;
        internal ExceptionEvent(String message)
            : base(message, null, WebEventCode)
        { }
    }

    Right click on WebEvents project and add new class. Name it EeventServices. This is the abstraction of the event publishing services. Anytime I will be unsatisfied with Web Events [which I doubt] I’d go and change the implementation without breaking other layers:

    public class EventsServices
    {
        public static void PublishException(string message)
        {
            if (null != System.Web.HttpContext.Current)
            {
                ExceptionEvent exceptionEvent = new
                              
    ExceptionEvent(message);
                exceptionEvent.Raise();
            }
            else
           
                //PROBABLY RUNNING INSIDE UNIT TEST OR
                //THE APP IS NOT HOSTED IN WEB SERVER
                //LET'S REPORT IT TO EVENTLOG 
                string sSource = "My App";
                string sLog = "Application"
                if (!EventLog.SourceExists(sSource,"."))
                //THIS LINE FAILS WHEN NOT RUN UNDER
                //ADMINISTARTOR’s ACCOUNT

                    EventLog.CreateEventSource(sSource,
                                               Log);
                EventLog.WriteEntry(sSource, message);
           
        }
    }

    Configuring web events in Web.Config will be covered further when designing presentation layer, stay tuned.

    Implementing Validation

    This section covers basic but critical functions related to security. Specifically HTML encoding, URL encoding, and integrity check. These utilities invaluable when dealing with injection attacks. More info here: How To: Prevent Cross-Site Scripting in ASP.NET.

    Right click on Crosscutting and add new Visual Studio project. Name it Security.

    Right click on the Security project and add new class. Name it EncodingServices. Add the following implementation to the class:

    public class EncodingServices
    {
        public static string HtmlEncode(string x)
        {
            if (x == null)
            {
                return x;
            }

            return HttpUtility.HtmlEncode(x);  

       
        public static string UrlEncode(string x)
        {
            if (x == null)
                return null;
            return HttpUtility.UrlEncode(x); 
        }

    Such abstraction might look redundant but there is a reason. In previous versions of .Net framework HtmlEncode function was encoding only <>&” characters which is insufficient. But recent implementation seem to work just fine. I will be testing it later via Unit Test.

    Unit Testing My Solution

    Right click on any method in any class in any project under Crosscutting folder. Choose “Create Unit Tests…”. Select all methods of our interest as depicted below. Choose to create new Test project and name it CrosscuttingTests. Click Create, click OK.

    image

    Drag CrosscuttingTests project under Crosscutting folder.

    image

    Unit Testing Tracing Services

    Change TracingTest.cs implementation so it looks as follows:

    [TestMethod()]
    public void TraceFunctionEnterTest()
    {
        Tracing.TraceFunctionEnter();
        Assert.Inconclusive("Run DebugView. have you seen 'TRC:
                            EXITING: TraceFunctionEnterTest' 
                            there?"
    ) ;
    }
    [TestMethod()]
    public void TraceFunctionExitTest()
    {
        Tracing.TraceFunctionExit();
        Assert.Inconclusive("Run DebugView. have you seen 'TRC:
                             EXITING: TraceFunctionExitTest'
                             there?"
    ) ;
    }
    [TestMethod()]
    public void TraceMessageTest()
    {
        string message = "RUNNING UNIT TEST"
        Tracing.TraceMessage(message);
        Assert.Inconclusive("Run DebugView. have you seen 'TRC:
                             RUNNING UNIT TEST' there?"
    ) ;
    }

    Open DebugView. Configure to filter messages that include TRC string to avoid massive unrelated noise:

    image

    Run trace related unit tests:

    image

    As a result you should see your messages displayed in DebugView as depicted below [notice lovely Time column]:

    image

    Unit Testing Events Services

    Change EventsServicesTest.cs implementation so it looks as follows:

    [TestMethod()]
    public void PublishExceptionTest()
    {
        string message = "UNIT TESTING PublishExceptionTest";
     
       EventsServices.PublishException(message);
        Assert.Inconclusive("Check Event Log, you should see
                             'UNIT TESTING PublishExceptionTest'
                             there"
    );
    }

    Run event publishing related tests [make sure to run the test under Administrator’s privileges at least once in order to create your apps’ source]:

    image

    The outcome of the run should look as following in the Application Event Log:

    image

    Unit Testing Encoding Services

    Change EncodingServicesTests.cs so it looks as follows:

    [TestMethod()]
    public void HtmlEncodeTest()
    {
        string x = "<script>alert('h&cked')</script>";
        //use this tool or simialr to created expected value
        //http://www.opinionatedgeek.com/DotNet/Tools/HTMLEncode/Encode.aspx
        string expected = "&lt;script&gt;alert(&#39;h&amp;cked&#39;)
                           &lt;/script&gt;"
    ;
        string actual;
        actual = EncodingServices.HtmlEncode(x);
        Assert.AreEqual(expected, actual);
    }
    [TestMethod()]
    public void UrlEncodeTest()
    {
        string x = "<script>alert('h&cked')</script>";
        //use this tool or simialr to created expected value
        //http://www.opinionatedgeek.com/dotnet/tools/urlencode/Encode.aspx
        string expected = "%3cscript%3ealert(%27h%26cked%27)%3c%2fscript%
                           3e"

        string actual;
        actual = EncodingServices.UrlEncode(x);
        Assert.AreEqual(expected, actual);
    }

    Run your encoding related tests:

    image

    You should pass the test:

    image

    At this point I have created and tested basic crosscutting services I will be using in the rest of the layers. The services include Tracing, Event Publishing, and Input Sanitation [HTML and URL encoding].

    Related Books

Page 2 of 3 (8 items) 123