Alik Levin's

Clarity, Technology, and Solving Problems | PracticeThis.com 

May, 2010

  • Alik Levin's

    Solution Architecture For The Masses. Step 1: Structure Your Solution

    • 0 Comments

     Alik Levin    This is a first post in series “Solution Architecture for the Masses”. I decided to take p&p’s Application Architecture Guide (2nd Edition) for a test drive.

    This post follows the guidelines described in the resources outlined in the Quick Resource Box on the right or at least the way I understood it.

    Quick Resource Box

    The rest of the post is an explanation of how I partitioned my Visual Studio solution according to the guidelines.

    Layers Mapped to Visual Studio Solution

    From the How To - Structure Your Application:

    Layers represent a logical grouping of components into different areas of concern. For example, business logic represents an area of concern that should be grouped into a layer. This is probably the most important decisions you will make during the initial design phase of your application. …

    From Application Architecture Guide - Chapter 9 - Layers and Tiers:

    image

    Red square that I have added in the figure above should map to the solution in Visual Studio. Right click on the solution node in Solution Explorer –>Add –> New Solution Folder to create the structure similar to below:

    image

    I have added numbers to the names so that VS sorts it top down like in the conceptual diagram. It helps navigating the solution.

    User Interface [UI] Folder

    The UI Solution folder holds Web App and Silverlight applications – notice there might be several Silverlight applications that will be used for different Use Cases [UC] for the same web app.

    image

    Service Interface [SI] Folder

    Service Interface folder holds WCF projects that will be consumed by remote clients or by our own Silverlight applications – notice it has svc file, interfaces, and interfaces implementations (servicecontract/operationcontract). It does not contain datacontract which is factored out into separate project (later on this one):

    image

    Entities Folder

    Entities folder holds Entities project. It is my data model that flows through layers. I have factored it into separate project so I will be able to reference it from different projects as entities usually flow through all layers and sometimes tiers.

    image

    Business Services Folder

    Business services folder holds Business Services objects that will be activated by WCF and ASPX on the server side. It is a bunch of Use Case oriented classes with static methods that should access DAL when processing entities.

    image

    Data Access Folder

    Data Access folder holds project for Data Access Layer [DAL] that’s responsible for accessing the entities in the data sources and downstream services. For each entity I have a set of CRUD related operations. It also contains data access helper classes:

    image

    Crosscutting Folder

    Crosscutting folder contains non-functional aspects such monitoring, exception handling, security, etc:

    image

    I am ready to expand each folder and add the implementation to it. Business Entities and Business Services are next.

    Related Books
  • Alik Levin's

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

    • 0 Comments
     Alik Levin    This post is a follow up of Part I. I am following the Web Application frame outlined in Web Application Archetype. In Part I I covered Authentication, Authorization, Caching, Exception, Management, Logging & Instrumentation. In this post I will cover the rest of Web Application categories – Navigation, Page Layout (UI), Page Rendering, Presentation Entity, Request Processing, Session Management, and Validation

    Quick Resource Box

    Navigation

    To visualize navigation I am using ASP.NET’s built-in treeview control bound to web.sitemap file and SiteMapPath [bread crumb] control for visualization. The navigation controls located in dedicated ACSX files that are placed inside formatted Master Page – more on that in Page Layout (UI) section. Follow these steps:

    • Add site map xml file to the root folder. Right click on the root folder of the web project and add new item, site map xml file. Site map located under Web category:

    image

    • Edit the XML site map file to reflect the desired site structure, for example:

    <?xml version="1.0" encoding="utf-8" ?>
    <siteMap xmlns="http://schemas.microsoft.com...." >
        <siteMapNode url="deafault.aspx"
                    
    title="Home" 
                    
    description="">
            <siteMapNode url="Restricted/UC1.aspx"
                        
    title="UC1"  
                        
    description="" />
            <siteMapNode url="Restricted/UC2.aspx"
                        
    title="UC2" 
                        
    description="" />
        </siteMapNode>
    </siteMap>

    • Create two ASCX controls in Controls folder, Header.ascx and Sidebar.ascx.

    image

    • Double click the Header.ascx file, switch to design mode, and drag SiteMapPath on it:

    image

    • Double click Sidebar.ascx file, switch to design mode, and drag TreeView control on it, follow the wizard to configure it to use the XML site map:

    image 

    • Add output caching to the both ASCX controls:

    <%@ OutputCache Duration="3000" VaryByParam="None"%>

    Page Layout (UI)

    Page layout is based on ASP.NET built-in Master Pages. Think of Master Page as a “server side frameset”. The page assembled on the server from the Master Page and the controls it hosts, rendered as a single HTML output and sent for rendering in the browser. The advantages are:

    • Maintainability. Visual components implemented as a separate ASCX files can be reused and changed separately from the rest of the UI improving maintainability.
    • Performance. Breaking the UI into separate parts allows to partially cache relatively static components like side bar, header, search control, and other. The technique known as partial Output Caching, more info -  Caching Explained. The fact that the page assembled and cached on the server, either partially or as a whole, helps to avoid heavy manipulation on the client using JavaScript and CSS which in some cases can lead to sever responsiveness [performance] problems, more info - Understanding Internet Explorer Rendering Behaviour.

    Follow these steps to implement page layout based on Master Page:

    • Right click on the root folder and add new item – Master Page. Master Page located under Web category. Call it Base.Master:

    image

    • Implement the HTML layout using HTML table. Note, though that from rendering perspective table based formatting is slower than using CSS. Keep in mind that the fact that the page is broken into visual components will allow to further implement it using CSS without breaking it. From the guide:
      • Use Cascading Style Sheets (CSS) for layout whenever possible.
      • Use table-based layout when you need to support a grid layout, but remember that table-based layout can be slow to render, does not have full cross-browser support, and there may be issues with complex layout.
      • Use a common layout for pages where possible to maximize accessibility and ease of use.
      • Use master pages in ASP.NET applications to provide a common look and feel for all of the pages.
      • Avoid designing and developing large pages that accomplish multiple tasks, particularly where only a few tasks are usually executed with each request.
    • While in the Master Page, from the menu choose Table->Insert Table. Make it two rows and two columns with one of them spanning over the two rows. Notice the ContentPlaceHolder – this is where the actual dynamic content of the pages will be rendered – more on it in Page Rendering section below:

    <table class="style1">
        <tr>
            <td colspan="2" align="left" valign="top">
            </td>
        </tr>
        <tr>
            <td  align="left" valign="top">
            </td>
            <td  align="left" valign="top">
        <asp:ContentPlaceHolder ID="ContentPlaceHolder1"
                                runat
    ="server">
        </asp:ContentPlaceHolder>
            </td>
        </tr>
    </table>

    • Switch to the Design mode and drag Sidebar.acsx on the left side of the table and the Header.ascx control to the upper part of the table. The result should look as follows:

    image

    • ContentPlaceHolder depicted above will hold the actual pages that “inherit” from the Master Page.

    Page Rendering

    Page rendering is the process of generating and displaying HTML in the browser. It usually involves displaying dynamic data from some data source such as SQL Server.

    For example, if I am required to present all transactions I have made, I’d follow these steps:

    • Add new page to Restricted folder [access to the page should be authorized – see Authorization in Part I]. To do so right click on the Restricted folder, then Add ->New Item and choose Web Form  using Master Page. Name it Transactions. Click Add. Specify available Master Page. Click OK.
    • From the tool box, under  Data category, drag ListView control on the placeholder area. 
    • Performance degrades with the number of items presented in the grid. Use paging to improve the responsiveness for the pages that present many rows. More info on paging - The DataPager Control, How To: Page Records Using AJAX, How To: Page Records in .NET Applications. Add DataPager control. The result should look similar to this:

    image

    • Configure the DataPager to control  the ListView

    <asp:DataPager ID="DataPager1"
                  
    runat="server" 
                   PageSize="3"
                   PagedControlID="ListView1">

    • Next step is to add the actual data to this view, the presentation entity as described in the next section.

    Presentation Entity

    Presentation entity is the data being presented on the page. In my case it is TransactionInfo that was implemented together with its business services in Step 2. In my case I get the list of the transactions generated by corresponding business services component and then bind it to the ListView control for presentation. Also I handle the paging event by calling ListView1_PagePropertiesChanging function [with little help from this post]. Code behind looks similar to the one that follows this paragraph. Notice IsPostBack check to make sure I do not run this code in case of postback [POST]. In this case the presentation re-generated from the ViewState so I save on CPU cycles and improve performance with regards to response time and resource utilization:

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            BindListView();
        }
    }
    protected void ListView1_PagePropertiesChanging(
                        object sender,
                       
    PagePropertiesChangingEventArgs e)
    {
        this.DataPager1.SetPageProperties(e.StartRowIndex,
                                          e.MaximumRows,
                                          false);
        BindListView();
    }
    void BindListView()

        List<TransactionInfo> transactions =
              TransactionServices
    .GetCurrentUserTransactions();
        ListView1.DataSource = transactions;
        ListView1.DataBind();
    }

    In this specific case all the input was available immediately in the request. In fact GetCurrentUserTransactions would use IPrincipal and IIdentity interfaces to access HttpContext.Current.User to locate the actual current user internally as described in Part I – that is why I do not pass any parameters to it. In some cases I will need to provide parameters submitted from different controls such as in the case of search scenario. In that case the parameter submitted by one ASCX control and the rendering of the result performed by other control or page. This is covered in the next section, Request Processing.

    Request Processing

    When looking at the guidelines for request processing the recurrent theme is separating user interface, processing, and the data. The patterns that mentioned are MVC and MVP. Following these patterns achieves loosely coupling between the components which increases maintainability. In other words, when one component changes it does not affect the other one. One recurrent scenario is search. I followed these steps to implement my search:

    • Create new user ASCX control, SearchInput.ascx, by right clicking on the Controls folder, Add-> New Item…-> Web User Control.
    • Place the text box and the button on the SearchInput.ascx.
    • Double click the button and add the following code to the even handler. That way anyone who’d need to use the search criteria would just check the Page.Items collection without even knowing who put it there. It follows the principle of decoupling [or loosely coupling, or pub/sub specifically]:

    protected void btnSearch_Click(object sender, EventArgs e)
    {
        string searchCriteria = txtSearch.Text;
        Page.Items.Add("SearchCriteria", searchCriteria);
    }

    • Add new page under Restricted folder, name it AccountSearchResult.aspx, switch to design mode.
    • Drag onto it the SearchInput.ascx control.
    • Drag onto it Label control.
    • Drag onto it DatGrid control. The result should look similar to this:

    image

    • Add the following code the page’s prerender event:

    protected void Page_Prerender(object sender, EventArgs e)
    {
        string searchCriteria =
                       Page.Items["SearchCriteria"] as string;
        if (null != searchCriteria) 
        {
            Label2.Text =
                     
    string.Format("Your search for {0}
                                    generated the following
                                    results: "
    ,searchCriteria);
            List<AccountInfo> accounts =
                    AccountServices.FindAccountsBySearchCriteria
                                    (searchCriteria);
           GridView1.DataSource = accounts;
           GridView1.DataBind();
        }
    }

    • The code assumes there is a search criteria in page’s items collection, and if it’s there then it executes the search and binds the results to the grid. The rendered result should look as the following:

    image

    In this example the page shows the results that and it’s completely decoupled from the search input control that accepts the input.

    Session Management

    The guide stresses the importance of session management with regards to scalability and performance: “When designing a Web application, an efficient and secure session-management strategy is important for performance and reliability.” Here are variations and implications:

    • Use in-proc Session would require me to configure my load balancer for sticky session. Generally it’s the most common approach and works fairly well for most scenarios. The biggest downside is when one of the servers dies the state of user dies too, and the user loses his state. For example, if the user was in the middle of transaction – it all lost.
    • Use out of proc state. This approach would eliminate the risk of losing the state since in this case the state is usually stored in DB. The downside is that the performance gets hurt as a result of extra N/W hope, serialization, and security checks. I observed few cases where the performance hit was significant.

    For my case I will be using in-proc Session state. It’s easy to implement, I do not plan to store large data to avoid memory pressure, serialization cost, and recycles. I am taking the risk of the case when the end user loses the state due to the server failure since my scenarios do not assume massive data input.

    Validation

    Input and Data Validations are extremely important aspects that affect system’s security and reliability. Making sure only sanitized input gets in prevent unnecessary exceptions that eat up CPU cycles. It also helps prevent injection attacks. Making sure the system produces encoded output prevents Cross Site Scripting [XSS] attacks that usually end up with identity theft. For input and data validation I will use:

    • ASP.NET built in validation controls.
    • My encoding security services I have implemented in Step 3.

    After reviewing the code I have produced so far, following are the changes that need to be done:

    • Add HTML encoding when echoing the input in AccountSearchResults.aspx:

    Label2.Text =  EncodingServices.HtmlEncode( string.Format
                   ("Your search for {0} generated the following
                    results: "
    ,searchCriteria));

    • Encoded the output in Transactions.aspx:

    <%# EncodingServices.HtmlEncode(((Entities.TransactionInfo)Container.DataItem).TransactionAccount)%> ||

    <%# EncodingServices.HtmlEncode(((Entities.TransactionInfo)Container.DataItem).TransactionAmount.ToString())%> ||

    ...

    • Added validation control to the search input control, SearchInput.ascx:

    <asp:RegularExpressionValidator 
                                ID
    ="RegularExpressionValidator1" 
                                runat="server" 
                                ControlToValidate="txtSearch"
                                ErrorMessage="Invlaid input" 
                                ValidationExpression=
                           "&quot;^[a-zA-Z'.\s]{1,40}$&quot; ">
     </asp:RegularExpressionValidator>

    • To make sure the outcome of the validation control is taken into account I need to add the Page.IsValid in my AccountSearcResults.aspx before rendering the results in Prerender event:

    if (!Page.IsValid)
    {
        //THE BETTER WAY WOULD BE TO USE 
        //VALIDATION SUMMARY CONTROL
        throw new ApplicationException("Invalid input 
                                        provided."
    );
    }

    Related Books

  • 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

Page 1 of 3 (8 items) 123