Aug 25 2007

Update on Website Menu + web.sitemap: A smart combination

Category: ASP.NET 2.0 - GeneralBil@l @ 19:00

I have updated the code I presented yesterday in: Website Menu + web.sitemap: A smart combination to handle pages that are not listed in the web.sitemap. Here is the updated code in bold:

        private static string GetSubRootNode()
        {
            // Get the current code
            SiteMapNode current = SiteMap.CurrentNode;
            // Get the root node
            SiteMapNode root = SiteMap.RootNode;
            // Get a copy of the root node
            SiteMapNode node = root;
            string url = "";
   
            // If we are processing the parent node,
            // then return its url.
            if (current != null)
            {
                if (current != root)
                {
                    // We check if the current's parent node
                    // is different from the root, go up
                    // one level in the web.sitemap. Kepp up looping
                    // until the current node's parent is the root
                    while (current.ParentNode != root)
                    {
                        current = current.ParentNode;
                    }
                    node = current;
                }
               
                // If localhost, then remove /CodeSuite/CodeSuiteWeb/
                url = node.Url;
                if (HttpContext.Current.Request.IsLocal)
                    url = url.Substring(24, url.Length - 24);
            }
            return url;
        }

If you still find any problems with the above code, please let me know!

Hope this helps,
Regards

Tags:

Aug 25 2007

A new starter-kit on the way ...

Category:Bil@l @ 18:43

I have been working for 2 weeks on a new community starter kit. I am almost done with the major functionalities! Still having few stuff and clean up to do and testing.

I am still not sure where I will announce it, but for sure I will be sharing it with all of you. The name of this starter-kit will be Freelancer Starter Kit. I will be the first to use it for a new community website for myself [:)].

More on this starter kit will be coming soon!

 

Regards

Tags:

Aug 23 2007

Website Menu + web.sitemap: A smart combination

Category: ASP.NET 2.0 - GeneralBil@l @ 18:30

I am working on a website that contains a main menu on top. In addition, I am making use of the SiteMapPath to show a breadcrumb that helps the user while browsing the website. I might have the following heirarchy in the website:

Default.aspx
Articles.aspx
         --> BrowseArticles.aspx
                             -->  ShowArticle.aspx

 

I prepared first of all an xml file of the major pages something like this:

<?xml version="1.0" encoding="utf-8" ?>
<MainMenu>
    <MenuItem>
        <Title>Home</Title>
        <Href>Default.aspx</Href>
    </MenuItem>
    <MenuItem>
        <Title>Articles</Title>
        <Href>ShowCategories.aspx</Href>
    </MenuItem>
</MainMenu>

So, my aim is to show a main menu of the major pages in the website. I prepare some code using XLinq to browse the XML file and based on the URL of the currently accessed page, I know which menu item I can style it differently since it is the one accessed currently.

However, when I go through the heirarchy, I loose the ability to catch the major page to style it differently. This is explained since those sub pages are not included in my menu xml file. What I need to do is whereever I am in the heirarchy of a major item for instance, going deep through the Articles section, I always want the Articles item to be selected. So I made use of the web.sitemap to know the sub-root of the currently visited page.

Sub-Root means all pages that are one level below the root. Because I want to show in my main menu the major pages, so I am interested only in the sub-root nodes!

So, here is the code I used to construct the main menu:

        /// <summary>
        /// This method is required to build the main menu.
        /// It first starts by loading the XML menu file,
        /// then select all MenuItem elements and add them to
        /// a collection of MenuItem. The final step is a call
        /// to GenerateHTML which will generate the actual code
        /// for the main menu with the right item selected!
        /// </summary>
        /// <returns></returns>
        public static string BuildMainMenu()
        {
            // Query the menu.xml file into an XElement
            XElement menuItems= null;
           
            // Load Data from Cache
            if (Utility.Cache["MainMenu"] != null)
                menuItems= (XElement)Utility.Cache["MainMenu"];
           
            // Cache empty load from the xml file
            if (menuItems == null)
            {
                try
                {
                    menuItems = XElement.Load(HttpContext.Current.Server.MapPath("~/menu.xml"));
                   
                    // Store the XML in a Cache - For better peformance
                    // Caching of the menu for 90 days with cache dependency on the menu.xml
                    // file
                    System.Web.Caching.CacheDependency depend=
                            new System.Web.Caching.CacheDependency(HttpContext.Current.Server.MapPath("menu.xml"));
                    Utility.Cache.Insert("MainMenu", menuItems, depend, DateTime.Now.AddDays(90), TimeSpan.Zero);
                }
                catch (System.Xml.XmlException ex)
                {
                    throw ex;
                }
            }
           
            // Get the MenuItems collection
            List<MenuItem> menuItemsCol= new List<MenuItem>();
            IEnumerable<XElement> iElements=
                    from e in menuItems.Elements("MenuItem")
                    select e;
                   
            foreach (XElement x in iElements)
            {
                CodeSuiteWeb.Menu.MenuItem item =
                    new CodeSuiteWeb.Menu.MenuItem {Title=(string)x.Element("Title"), Href=(string)x.Element("Href")};
                if (item != null)
                    menuItemsCol.Add(item);
            }           
           
            // Generate HTML for the menu
            if ((menuItemsCol != null) && (menuItemsCol.Count > 0))
                return GenerateMenuHTML(menuItemsCol);
               
            return string.Empty;  
        }

The code above is well documented through XML documentation. There are left few major methods that will helps in building the menu:

        /// <summary>
        /// Generates the HTML code that constitutes
        /// the main menu of the website
        /// </summary>
        /// <param name="menuItemsCol">
        ///     A collection of <seealso cref="MyWeb.Menu.MenuItem" />
        ///     representing the items in the menu xml file/>
        /// </param>
        /// <returns></returns>
        private static string GenerateMenuHTML(List<MenuItem> menuItemsCol)
        {
            // Container to hold the HTML generated
            StringBuilder sb= new StringBuilder();
           
            // Get the visited page
            string currentPage= GetCurrentPage();
                        
            // Generate the Menu HTML
            foreach (MyWeb.Menu.MenuItem item in menuItemsCol)
            {                
                if (item.Href.StartsWith(GetSubRootNode(), StringComparison.CurrentCultureIgnoreCase))
                    sb.AppendFormat("<li><a href=\"{0}\" title=\"{1}\" class=\"hover\">{1}</a></li>", item.Href, item.Title);
                else
                    sb.AppendFormat("<li><a href=\"{0}\" title=\"{1}\">{1}</a></li>", Utility.BasePath + item.Href, item.Title);
            }
           
            return sb.ToString();
        }
   
        /// <summary>
        /// Gets the Sub-Parent node's URL of the current node.
        /// </summary>
        /// <returns>
        ///     A <see cref="System.String"/> that represents the URL of the sub-parent node
        /// </returns>
        private static string GetSubRootNode()
        {
            // Get the current code
            SiteMapNode current = SiteMap.CurrentNode;
            // Get the root node
            SiteMapNode root = SiteMap.RootNode;
            // Get a copy of the root node
            SiteMapNode node = root;
            string url = "";
   
            // If we are processing the parent node,
            // then return its url.
            if (current != root)
            {
                // We check if the current's parent node
                // is different from the root, go up
                // one level in the web.sitemap. Kepp up looping
                // until the current node's parent is the root
                while (current.ParentNode != root)
                {
                    current = current.ParentNode;
                }
                node = current;
            }
           
            // If localhost, then remove /CodeSuite/CodeSuiteWeb/
            url = node.Url;
            if (HttpContext.Current.Request.IsLocal)
                url = url.Substring(24, url.Length - 24);
 
            return url;
        }

        private static string GetCurrentPage()
        {
            string rawUrl= HttpContext.Current.Request.FilePath;  
            
            // If localhost, then remove /CodeSuite/CodeSuiteWeb/
            if (HttpContext.Current.Request.IsLocal)
                rawUrl = rawUrl.Substring(24, rawUrl.Length - 24);
           
            return rawUrl;
            //// Remove all the path and extension and reture pure page name
            //rawUrl= rawUrl.Substring(rawUrl.LastIndexOf('/')+1);            
            //return rawUrl;
        }   
 

As you can see, no matter how deep you go through the heirarchy of pages under one sub-root node, always the sub-root node (which is one of the major nodes in the main menu) will be selected!

Hope this helps!
Regards

Tags:

Aug 21 2007

LINQ To SQL and Allow Null in SQL Server 2005

Category: DLinq | LinqBil@l @ 21:06

I figured out tonight something new in LINQ To SQL related to updating records in the database and here it is:

Suppose you have a table in SQL Server 2005, that stores data related to Article. Each article has the ArticleID, Body, Abstract, title, etc ... Also, the Body column has AllowNull set to false, so it is a must to always have a value for the Body column.

When I open the web form used to update the article, and then I change the value of the Body field into "null", that is I simply delete the body value from the HTML Editor I am using (FCKEditor). Then i press Update, everything goes fine, but then i notice that the Body column in the table is still the old value and not the "null".

What happened here is that, LINQ To SQL will check if the value for a column, who has AllowNull is false, is null, then the old value of the column will be preserved. However, if I update the value of the Body field to another value different from null, then the Body column is being updated sucessfully!!

Hope this feature helps you out while working on LINQ To SQL.

Regards

Tags: ,

Aug 16 2007

ASP.NET 2.0 AJAX Shorthand Syntax

Category: AJAX-ATLASBil@l @ 20:14

A very nice blog post by Joe Stagner on the existing ASP.NET 2.0 AJAX Shortcuts can be reached here:

http://joeon.net/archive/2007/08/16/ASP.NET-AJAX-Shorthand-Syntax.aspx

It is a must-read post!!

 

Regards

Tags:

Aug 14 2007

Extension Methods in C# 3.0 and ASP.NET Code-Inline

Category: C# 3.0 | LinqBil@l @ 00:14

I was customizing a ListView today to show a small key gif beside each article listed to indicate that the article requires a login to be viewed based on whether the user is authenticated or not. So I decided to use inline checking to see if the current user is logged in or not and accordingly show/hide the Image. The code is like this:

                <asp:Image runat="server" ID="imgKey" ImageUrl="~/Images/key.gif" AlternateText="Requires login"
                    Visible='<%# (bool)Eval("OnlyForMembers") && !Page.IsAuthenticated() %>' />

Notice the Page.IsAuthenticated() method. I have added this as an extension method that targets the Page class as follows:

        /// <summary>
        /// A Method that returns whether the user checkin the webpage
        /// is currently authenticated or not.
        /// </summary> 
        /// <param name="page">A <see cref="System.Web.UI.Page"/> instance</param>
        /// <returns>A <see cref="System.Boolean"/> that specifies whether the user is currently authenticated or not</returns>
        public static bool IsAuthenticated(this System.Web.UI.Page page)
        {
            HttpContext context = HttpContext.Current;

            if (context.User != null && context.User.Identity != null && !String.IsNullOrEmpty(context.User.Identity.Name))
            {
                return true;
            }

            return false;
        }

When using this extension method inside the code-behind, you should import the class library that holds the class that adds an extension method. What I discovered today was that, even if you had imported the class library in the code behind, if you want to use any extension method inside the HTML you should add another import to the page header using the Import tag.

Hope this helps,
Regards

Tags: ,

Aug 13 2007

Deferred Loading in DLinq - Orcas Beta 2

Category: DLinq | LinqBil@l @ 23:30

In a previous post of mine (Deferred Loading in DLinq - https://bhaidar.net/cs/archive/2007/07/26/deferred-loading-in-dlinq.aspx), I explained to you how deferred loading works in DLinq. There have been some changes to the object used to enable/disable deferred loading in Orcas Beta 2! The new object used is now called System.Data.Linq.DataLoadOptions.

Suppose you have two tables: Customer and Orders from the Northwind database. Now suppose you executed this query:

var getCustomers= from c in db.Customers select c;

The above query will get only the customer's data from the database as this SQL Statement show:

SELECT [t0].[CustomerID], [t0].[CompanyName], [t0].[ContactName], [t0].[ContactTitle], [t0].[Address], [t0].[City], [t0].[Region], [t0].[PostalCode], [t0].[Country], [t0].[Phone], [t0].[Fax]
FROM [dbo].[Customers] AS [t0]

From the above query, it seems that the Orders records was not retrieved. This means, if you were binding this collection of objects to a GridView, and you have a column that repsents the OrderID of each order done by a customer, this means we will have to access the database with the number of customers bound to the GridView + 1 (representing the first query to get Customers). And this is really bad!

The solution is by diabling Deferred loading and asking the Linq To SQL to get the associated objects as follows:

NorthwindDataContext db= new NorthwindDataContext("...");
db.LoadOptions= new System.Data.Linq.DataLoadOptions().LoadWith<Customer>(c => c.Orders);
var query= from c in db.Customers select c;

Linq To SQL will generate the following query:

SELECT [t0].[CustomerID], [t0].[CompanyName], [t0].[ContactName], [t0].[ContactTitle], [t0].[Address], [t0].[City], [t0].[Region], [t0].[PostalCode], [t0].[Country], [t0].[Phone], [t0].[Fax], [t1].[OrderID], [t1].[CustomerID] AS [CustomerID2], [t1].[EmployeeID], [t1].[OrderDate], [t1].[RequiredDate], [t1].[ShippedDate], [t1].[ShipVia], [t1].[Freight], [t1].[ShipName], [t1].[ShipAddress], [t1].[ShipCity], [t1].[ShipRegion], [t1].[ShipPostalCode], [t1].[ShipCountry], (
    SELECT COUNT(*)
    FROM [dbo].[Orders] AS [t2]
    WHERE [t2].[CustomerID] = [t0].[CustomerID]
    ) AS [count]
FROM [dbo].[Customers] AS [t0]
LEFT OUTER JOIN [dbo].[Orders] AS [t1] ON [t1].[CustomerID] = [t0].[CustomerID]
ORDER BY [t0].[CustomerID], [t1].[OrderID]

As you can see, the above Linq statment forced the query to get customers to load with it the information about the orders of each customer. All this is done in one database access,

Hope this helps you,
Regards

Tags: ,

Aug 7 2007

Extend System.Web.HttpResponse with a WriteLine method

Category: C# 3.0Bil@l @ 11:50

While working with Console applications, you always use Console.WriteLine. I always got bothered why the HttpResponse has only Write or WriteFile. Why can't we have WriteLine? Many times you need to print something on a web page and also print a break line, and you always had to append a "<br>".

Now, with the Extension Methods that ship as part of C# 3.0, we can add the WriteLine method as follows. Create a new Class Library and place this code inside it:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Data.Linq;
using System.Text;
using System.CodeDom;
using System.Reflection;
using System.IO;

namespace Utils
{
    public static class CodeSuiteExtensionMethods
    {
        #region HttpResponse Extension Methods
        /// <summary>
        /// This method prints the contents of a string s followed
        /// by a new line.
        /// </summary>
        /// <param name="response">An <see cref="System.Web.HttpResponse" object/></param>
        /// <param name="s">A <see cref="=System.String"/> to be printed</param>
        public static void WriteLine(this System.Web.HttpResponse response, string s)
        {
            // Call default Write method
            System.Web.HttpContext.Current.Response.Write(s);
           
            // Add a new line
            System.Web.HttpContext.Current.Response.Write("<br>");
        }
        /// <summary>
        /// This method prints the contents of a character ch followed
        /// by a new line.
        /// </summary>
        /// <param name="response">An <see cref="System.Web.HttpResponse" object/></param>
        /// <param name="ch">A <see cref="=System.char"/> to be printed</param>
        public static void WriteLine(this System.Web.HttpResponse response, char ch)
        {
            // Call default Write method
            System.Web.HttpContext.Current.Response.Write(ch);
           
            // Add a new line
            System.Web.HttpContext.Current.Response.Write("<br>");
        }
        /// <summary>
        /// This method prints the contents of a buffer of characters followed
        /// by a new line.
        /// </summary>
        /// <param name="response">An <see cref="System.Web.HttpResponse" object/></param>
        /// <param name="buffer">An array of characters</param>
        /// <param name="index">An <see cref="System.Integer"/> to start printing from</param>
        /// <param name="count">An <see cref="=System.Integer"/> that states number of characters to print</param>
        /// <param name="s">A <see cref="=System.String" to be printed/></param>
        public static void WriteLine(this System.Web.HttpResponse response, char[] buffer, int index, int count)
        {
            // Call default Write method
            System.Web.HttpContext.Current.Response.Write(buffer, index, count);
           
            // Add a new line
            System.Web.HttpContext.Current.Response.Write("<br>");
        }
        /// <summary>
        /// This method prints the ToString of an object obj followed
        /// by a new line.
        /// </summary>
        /// <param name="response">An <see cref="System.Web.HttpResponse" object/></param>
        /// <param name="obj">A <see cref="=System.Object"/> to be printed</param>
        public static void WriteLine(this System.Web.HttpResponse response, object obj)
        {
            // Call default Write method
            System.Web.HttpContext.Current.Response.Write(obj);
           
            // Add a new line
            System.Web.HttpContext.Current.Response.Write("<br>");
        }
        #endregion
    }
}

I have create Extension Methods for all the overloads of the Write method. What I do is simply call the original Write method, then add another call to write a break line.

How to use it? Add this namespace to your current page:

using Utils; // name of the namespace containing the extension methods.

Before importing the namespace make sure you Add a Reference to that namespace.

Now, in your code you can do something:

Response.WriteLine("Hello world"); // This will print the statement Hello world with a break line!!

Even if you wanted to use the Response.WriteLine same as Console.WriteLine to customize it with parameters, you can do something as:

Response.WriteLine(string.Format("Hello {0}", "Bilal"));

 

Hope this helps,
Regards

 

Tags:

Aug 7 2007

How to Load XML using System.Xml.Linq

Category: XLinqBil@l @ 10:17

I have been blogging for a while on C# 3.0, DLinq, and now it is time to blog about XLinq. In this post, I will show you how to load an XML file using the new XML namespace: System.Xml.Linq. This sample loads an XML for a menu on a website (under development), then creates a list of all the menu items as a List<MenuItem> collection.

The menu XML file is as follows:

<?xml version="1.0" encoding="utf-8" ?>
<CodeSuiteMenu>
    <MenuItem>
        <Title>Home</Title>
        <Href>default.aspx</Href>
    </MenuItem>
    <MenuItem>
        <Title>About us</Title>
        <Href>aboutus.aspx</Href>
    </MenuItem>
    <MenuItem>
        <Title>Articles</Title>
        <Href>articles.aspx</Href>
    </MenuItem>
    <MenuItem>
        <Title>Resources</Title>
        <Href>Training</Href>
    </MenuItem>
    <MenuItem>
        <Title>Training</Title>
        <Href>training.aspx</Href>
    </MenuItem>
    <MenuItem>
        <Title>Consulting</Title>
        <Href>consulting.aspx</Href>
    </MenuItem>
    <MenuItem>
        <Title>Contact</Title>
        <Href>contact.aspx</Href>
    </MenuItem>
</CodeSuiteMenu>

The MenuItem.cs class is as follows:

    public class MenuItem
    {

        private string title;
        private string href;

        public string Title
        {
            get { return this.title; }
            set { this.title = value; }
        }
        public string Href
        {
            get { return this.href; }
            set { this.href = value; }
        }
       
       internal MenuItem()
        { }

        public MenuItem(string p_Name, string p_Href)
        {
            this.title = p_Name;
            this.href = p_Href;
        }
    }

The MenuItem class shall be populated with the items in the XML file.

Now, how to fill the collection of MenuItems from the XML file?

            // Query the menu.xml file into an XElement
            XElement menuItems= null;
            try
            {
                menuItems = XElement.Load(HttpContext.Current.Server.MapPath("menu.xml"));
            }
            catch (System.Xml.XmlException ex)
            {
                throw ex;
            }
           
            // Get the MenuItems collection
            List<MenuItem> menuItemsCol= new List<MenuItem>();
            foreach (XElement x in menuItems.Elements("MenuItem"))
            {
                CodeSuiteWeb.Menu.MenuItem item =
                    new CodeSuiteWeb.Menu.MenuItem {Title=(string)x.Element("Title"), Href=(string)x.Element("Href")};
                if (item != null)
                    menuItemsCol.Add(item);
            }           
           

As  you can see, we use the Load method of the XElement to load an xml file, then in the foreach, we use the Elements method to retrieve the content of the root XElement as an IEnumerable of all the XElements in the xml file. For each XElement, we initialize a new instance of MenuItem using C# 3.0 Object Initialization. If the item created not null, we add it to the collection!

Hope this helps you,
Regards

Tags:

Aug 2 2007

Intellisense in VB.NET vs. C#

Category:Bil@l @ 16:45

I have been watching few videos on LINQ nowadays and most of the demo code in those videos is written in VB.NET.
I noticed that there is a big intellisense support for VB.NET LINQ Query Expressions. For instance, when you write:
 

var query = from c in db.customers
 
Then press <enter> key a list of the other operators that we can use like “where, order by, select” are shown in a small intellisense window! Is this powerful intellisense present in C#? I am working now on VS 2008 Beta 2, and I still cannot see this intellisense!  Is it present there and I am unable to find it out, or is it missing from C#?

Thanks,

Tags: