Monday 19 November 2012

Get Assembly location of the DLL added to SQL Server


SELECT 
    assembly = a.name, 
    path     = f.name
FROM sys.assemblies AS a
INNER JOIN sys.assembly_files AS f
ON a.assembly_id = f.assembly_id
WHERE a.is_user_defined = 1;

Thursday 8 November 2012

Get GridView Column Headers and Appropriate Row Values in Asp.Net

Get Gridview column header(s) text and Specific Row's Values on Row Command in asp.net. Below Method takes GridView control, Command Source Within the Row(LinkButton, Button, ImageButton, etc..), no of Columns to skip in from Start Column and from End Column as Parameters and returns List<KeyValuePair<headerText,Values>> as output.



private void SetDeleteDetails(GridView pGV, object pCmdSource, int pStartSkipColCount=0, int pEndSkipColCount=0)
        {
            List<KeyValuePair<string, string>> lkvp = new List<KeyValuePair<string, string>>();
            GridViewRow rw = (GridViewRow)((Control)pCmdSource).NamingContainer;

            for (int i = pStartSkipColCount; i < pGV.Columns.Count - pEndSkipColCount; i++)
                if (!string.IsNullOrEmpty(rw.Cells[i].Text))
                    lkvp.Add(new KeyValuePair<string, string>(pGV.Columns[i].HeaderText, rw.Cells[i].Text));
            //Session["DeleteDetails"] = lkvp;
        }

Wednesday 7 November 2012

Get Specific Property Name Using Expression


Hope the program explains all:

class Program
    {
        static void Main(string[] args)
        {
            SomeClass sc = new SomeClass();
            Console.WriteLine(sc.p1.GetType());

            //RemoteMgr.ExposeProperty(() => SomeClass.SomeProperty);
            MemberInfo member = RemoteMgr.GetMemberInfo((SomeClass p) => p.SomeProperty);
            Console.WriteLine(member.Name);
            Console.ReadKey();
        }
    }

    public class SomeClass
    {
        public string SomeProperty
        {
            get { return "Foo"; }
        }
    }

    public class RemoteMgr
    {
        public static MemberInfo GetMemberInfo<T, U>(Expression<Func<T,U>> expression)
        {
            var member = expression.Body as MemberExpression;
            if (member != null)
                return member.Member;
            throw new ArgumentException("Expression is not a member access", "expression");
        }
    }

Monday 22 October 2012

Raising a Button Click Event Programmatically



You can use the following C# code raise the event:
((IPostBackEventHandler)Button1).RaisePostBackEvent(null);
This code will raise the button-click event for Button1 just as though the user clicked the button.  Since we are passing a null as the EventArgs for the event, the registered methods must not attempt to do anything with it.  Or, you could create an EventArgs object and pass it.
There is at least one other approach using reflection, but I think the technique above is the cleaner way to do this. 


Monday 8 October 2012

Understanding ASP.NET View State


Introduction

Microsoft® ASP.NET view state, in a nutshell, is the technique used by an ASP.NET Web page to persist changes to the state of a Web Form across postbacks. In my experiences as a trainer and consultant, view state has caused the most confusion among ASP.NET developers. When creating custom server controls or doing more advanced page techniques, not having a solid grasp of what view state is and how it works can come back to bite you. Web designers who are focused on creating low-bandwidth, streamlined pages oftentimes find themselves frustrated with view state, as well. The view state of a page is, by default, placed in a hidden form field named __VIEWSTATE. This hidden form field can easily get very large, on the order of tens of kilobytes. Not only does the __VIEWSTATE form field cause slower downloads, but, whenever the user posts back the Web page, the contents of this hidden form field must be posted back in the HTTP request, thereby lengthening the request time, as well.
This article aims to be an in-depth examination of the ASP.NET view state. We'll look at exactly what view state is storing, and how the view state is serialized to the hidden form field and deserialized back on postback. We'll also discuss techniques for reducing the bandwidth required by the view state.
Note   This article is geared toward the ASP.NET page developer rather than the ASP.NET server control developer. This article therefore does not include a discussion on how a control developer would implement saving state. For an in-depth discussion on that issue, refer to the book Developing Microsoft ASP.NET Server Controls and Components.
Before we can dive into our examination of view state, it is important that we first take a quick moment to discuss the ASP.NET page life cycle. That is, what exactly happens when a request comes in from a browser for an ASP.NET Web page? We'll step through this process in the next section.

Tuesday 14 August 2012

Simple Business Rules Engine

Rules Engine is a . NET C# project that validates business logic by defining a bunch of rules for your data classes. Rules are defined using a fluent-interface (fluent validation) helper class, and not by decorating your existing objects with attributes, therefore de-coupling validation logic from data (or domain) classes.

Features

  • Rules are inheritable. Defining RuleX for TypeA will also apply to TypeB (given that TypeB inherits from Type A) 
  • Rules are extensible. Creating custom rules are only a matter of implementing an interface. 
  • Conditional validation. When defining rules, it is possible to have different rules given different conditions. E.g. Not Null Rule only applies to FieldA when FieldB > 100
  • Cross-Field validation. Defining a rule that FieldA must be greater than FieldB comes very naturally with the fluent-interface helper class. 
  • Fluent-Interface. Adding rules to objects is done by a fluent-interface helper class. 
  • Error Messages. Defining error messages can be done at the same time as defining your rules (Or separately). They can apply to the Class, A Property of that class, or a Rule for that property. 
Below is the simple example for rules engine:

public class Person
    {
        public string Name { get; set; }
        public string Phone { get; set; }
        public DateTime DateOfBirth { get; set; }
    }

    public class Program
    {
        public static void Main(string[] args)
        {
            Engine engine = new Engine();
            engine.For<Person>()
                    .Setup(p => p.DateOfBirth)
                        .MustBeLessThan(DateTime.Now)
                    .Setup(p => p.Name)
                        .MustNotBeNull()
                        .MustMatchRegex("^[a-zA-z]+$")
                    .Setup(p => p.Phone)
                        .MustNotBeNull()
                        .MustMatchRegex("^[0-9]+$");

            Person person = new Person();
            person.Name = "Bill";
            person.Phone = "1234214";
            person.DateOfBirth = new DateTime(1999, 10, 2);

            bool isValid = engine.Validate(person);
        }
    }


Please Follow the Following LInk for downloading Rules Engine http://rulesengine.codeplex.com/

Tuesday 3 July 2012

SQL Joins

The below fully describes the JOIN concepts in sql.

Alternative for PHP_excel


Alternative for PHP_excel which can "Export to XLSX/XLS" file in a customized format
For Writing Excel
  • PEAR's PHP_Excel_Writer (xls only)
  • php_writeexcel from Bettina Attack (xls only)
  • XLS File Generator commercial and xls only
  • Excel Writer for PHP from Sourceforge (spreadsheetML only)
  • Ilia Alshanetsky's Excel extension (xls only, and requires commercial component)
  • PHP's COM extension (requires a COM enabled spreadsheet program such as MS Excel or OpenOffice Calc running on the server)
  • The Open Office alternative to COM (PUNO) (requires Open Office installed on the server with Java support enabled)
  • PHP-Export-Data by Eli Dickinson (Writes SpreadsheetML - the Excel 2003 XML format, and CSV)
  • Oliver Schwarz's php-excel (SpreadsheetML)
  • Oliver Schwarz's original version of php-excel (SpreadsheetML)
  • excel_xml (SpreadsheetML, despite its name)
For Reading Excel
All are faster than PHPExcel, but (with the exception of COM and PUNO) they don't offer both reading and writing, or both xls and xlsx; may no longer be supported; and (while I haven't tested Ilia's extension) only COM and PUNO offers the same degree of control over the created workbook.

Stress Testing


Recently we made a lot of research on Stress Testing tools to test our server/application capability . Finally our team has choose JMeter.
JMeter is simple and powerful tool for Load Testing. Main advantage is its open source and very simple to learn.
We used JMeter to test asp.net application.

Monday 25 June 2012

Load/Stress Testing JMeter

Recently we made a lot of research on Stress Testing tools to test our server/application capability . Finally our team has choose JMeter.
JMeter is simple and powerful tool for Load Testing. Main advantage is its open source and very simple to learn.
We used JMeter to test asp.net application.


Thursday 14 June 2012

Navigation for ASP.NET Web Forms Framework


The Navigation for ASP.NET Web Forms framework, an open source project hosted at navigation.codeplex.com, lets you write Web Forms code with unit test coverage and adherence to don’t repeat yourself (DRY) principles that would make an ASP.NET MVC application green with envy.
Although there has been some abandonment of Web Forms in favor of MVC, with some developers growing tired of large codebehinds unreachable by unit tests, this new framework—in conjunction with data binding—makes a compelling argument for taking a fresh look at Web Forms.
Data binding with ObjectDataSource controls has been around since Visual Studio 2005, allowing for cleaner codebehinds and data-retrieval code to be unit tested, but there have been some problems inhibiting its uptake—for example, raising an exception was the only way of reporting a business validation failure back to the UI.
The vast majority of the Web Forms development effort for the upcoming release of Visual Studio has been invested in data binding, bringing across model binding concepts from MVC to resolve these issues—for example, the introduction of model state addresses the business validation failure communication issue. However, two thorns remain in the side of data binding related to navigation and data passing—but they can be painlessly extracted using the Navigation for ASP.NET Web Forms framework (which I’ll call the “Navigation framework” hereafter for brevity).
The first thorn is that there’s no abstraction for navigation logic, unlike in MVC where it’s encapsulated in the controller method return types. This results in redirect calls inside data-bound methods, preventing them from being unit tested. The second thorn is that the type of a parameter of an ObjectDataSource determines where its value comes from—for example, a QueryStringParameter always gets its data from the query string. This prevents the same data source from being used in different navigational contexts—such as postback and non-postback—without substantial logic in the dreaded codebehind.
The Navigation framework removes these thorns by taking a holistic approach to navigation and data passing. Regardless of the type of navigation being performed—be it hyperlink, postback, AJAX history or unit test—the data being passed is always held in the same way. In future articles, I’ll show how this leads to empty codebehinds with fully unit-tested data retrieval and navigation logic and also to Search Engine Optimization (SEO)-friendly, progressively enhanced single-page applications with no code duplication for JavaScript-enabled and -disabled scenarios. This article introduces the Navigation framework and demonstrates some of its basic—but key—concepts by building a sample Web application.

Sample Application

The sample Web application is an online survey. This survey has only two questions and displays a “thank you” message upon completion. Each question is represented by a separate ASPX page called Question1.aspx and Question2.aspx respectively, and the “thank you” message has its own page called Thanks.aspx.
The first question asked is, “Which ASP.NET technology are you currently using?” to which the possible answers are either “Web Forms” or “MVC.” So to Question1.aspx I’ll add the question and the hardcoded radio button answers:
  1. <h1>Question 1</h1>
  2. <h2>Which ASP.NET technology are you currently using?</h2>
  3. <asp:RadioButtonList ID="Answer" runat="server">
  4.   <asp:ListItem Text="Web Forms" Selected="True" />
  5.   <asp:ListItem Text="MVC" />
  6. </asp:RadioButtonList>
The second question, “Are you using the Navigation for ASP.NET Web Forms framework?” has answers of “Yes” or “No” and is marked up in a similar fashion.

Getting Started

The most straightforward way to set up the survey Web project to use the Navigation framework is to install it using the NuGet Package Manager. Running the command “Install-Package Navigation” from within the Package Manager Console will add the required reference and configuration. If you’re not using Visual Studio 2010, manual setup instructions can be found at navigation.codeplex.com/documentation.

Navigation Configuration

The Navigation framework can be thought of as a state machine, where each different state represents a page and moving from one state to another—or navigating between pages—is termed a transition. This predefined set of states and transitions is configured in the StateInfo.config file created by the NuGet installation. Without this underpinning configuration, running the survey application will throw an exception.
Because states are essentially just pages, the survey application requires three states, one for each of its three pages:
  1. <state key="Question1" page="~/Question1.aspx">
  2. </state>
  3. <state key="Question2" page="~/Question2.aspx">
  4. </state>
  5. <state key="Thanks" page="~/Thanks.aspx">
  6. </state>
From now on I’ll refer to the different states by their key names, Question1, Question2 and Thanks, rather than by the pages they represent.
Because transitions describe the possible navigations between states, the survey application requires two transitions. One is for the navigation from Question1 to Question2 and another is for the navigation from Question2 to Thanks. A transition appears as a child of the state being exited and points, via its “to” attribute, at the state being entered:
  1. <state key="Question1" page="~/Question1.aspx">
  2.   <transition key="Next" to="Question2"/>
  3. </state>
  4. <state key="Question2" page="~/Question2.aspx">
  5.   <transition key="Next" to="Thanks"/>
  6. </state>
  7. <state key="Thanks" page="~/Thanks.aspx">
  8. </state>
Dialogs are the final element of the configuration and represent a logical grouping of states. The survey application only requires one dialog because Question1, Question2 and Thanks are effectively a single navigation path. The dialog’s “initial” attribute must point to the starting state—that is, Question1:
  1. <dialog key="Survey" initial="Question1" path="~/Question1.aspx">
  2.   <state key="Question1" page="~/Question1.aspx">
  3.     <transition key="Next" to="Question2"/>
  4.   </state>
  5.   <state key="Question2" page="~/Question2.aspx">
  6.     <transition key="Next" to="Thanks"/>
  7.   </state>
  8.   <state key="Thanks" page="~/Thanks.aspx">
  9.   </state>
  10. </dialog>
You’ll notice that each dialog, state and transition has a key attribute. I chose to name the state keys after the page names, but this isn’t necessary. Note, though, that all keys must be unique within their parent; for example, you can’t have sibling states with the same key.
With Question1.aspx as the start page, the survey application now starts successfully in the Question1 state. However, the survey remains stuck in this state because there’s no way to progress to Question2.

Navigation

It’s useful to split the different sorts of Web Forms navigation into two camps. The non-postback camp is where control is passed from one ASPX page to another and takes the form of hyperlinks, redirects or transfers. The postback camp is where control remains on the same page and takes the form of postbacks, partial page requests or AJAX history. This second kind will be examined in a future article discussing the single-page interface pattern. In this article, I’ll focus on the first type of navigation.
To move between pages, a URL must be built. Prior to Visual Studio 2008, the only option was to manually construct URLs from hardcoded ASPX page names, causing tight coupling between pages that made applications brittle and hard to maintain. The introduction of routing alleviated this problem, with configurable route names used in place of page names. However, the fact that routing throws an exception if used outside a Web environment—­combined with routing’s resistance to mocking—makes it an enemy of unit testing.
The Navigation framework retains the loose coupling provided by routing and is a friend of unit testing. Similar to the use of route names, instead of hardcoding ASPX page names, it’s the dialog and transition keys configured in the preceding section that are referenced in code; the state navigated to is determined by the respective “initial” and “to” attributes.
Returning to the survey, the Next transition key can be used to move from Question1 to Question2. I’ll add a Next button to Question1.aspx and the following code to its associated click handler:
  1. protected void Next_Click(object sender, EventArgs e)
  2. {
  3.   StateController.Navigate("Next");
  4. }
The key passed in to the Navigate method is matched against the configured child transitions of the Question1 state and then the state identified by the “to” attribute is displayed—that is, Question2. I’ll add the same button and handler to Question2.aspx. If you run the survey, you’ll find you can navigate through the three states by clicking the Next buttons.
You might have noticed the second question is Web Forms-specific and, as such, is irrelevant when “MVC” is selected as the first answer. The code needs changing to handle this scenario, navigating directly from Question1 to Thanks and bypassing Question2 entirely.
The current configuration doesn’t allow navigation from Question1 to Thanks because the only transition listed is to Question2. So I’ll change the configuration by adding a second transition below the Question1 state:
  1. <state key="Question1" page="~/Question1.aspx">
  2.   <transition key="Next" to="Question2"/>
  3.   <transition key="Next_MVC" to="Thanks"/>
  4. </state>
With this new transition in place it’s simple to adjust the Next button click handler to pass a different transition key depending on the answer chosen:
  1. if (Answer.SelectedValue != "MVC")
  2. {
  3.   StateController.Navigate("Next");
  4. }
  5. else
  6. {
  7.   StateController.Navigate("Next_MVC");
  8. }
A survey wouldn’t be much good if it didn’t allow the user to change answers. Currently there’s no way to return to a previous question (aside from the browser back button). To navigate back you might think you need to add two transitions below Thanks, pointing to Question1 and Question2, and another below Question2, pointing to Question1. Although this would work, it’s unnecessary because back navigation comes free with the Navigation framework.
Breadcrumb navigation is a set of links providing access to each previous page the user visited in reaching the current one. Web Forms has breadcrumb navigation built into its site map functionality. However, because site maps are represented by a fixed navigational structure, for a given page these breadcrumbs are always the same regardless of the route taken. They can’t handle situations like that found in the survey where the route to Thanks sometimes excludes Question2. The Navigation framework, by keeping track of states visited as navigations occur, builds up a breadcrumb trail of the actual route taken.
To demonstrate, I’ll add a hyperlink to Question2.aspx and in the codebehind programmatically set its NavigateUrl property using back navigation. A distance parameter must be passed indicating how many states to go back to, a value of 1 meaning the immediate predecessor:
  1. protected void Page_Load(object sender, EventArgs e)
  2. {
  3.   Question1.NavigateUrl = StateController.GetNavigationBackLink(1);
  4. }
If you run the app and answer “Web Forms” to question one you’ll see the hyperlink on Question2.aspx takes you back to the first question.
I’ll do the same for Thanks.aspx, although it’s a bit trickier because two hyperlinks are needed (one for each question), and the user may not have seen both questions—that is, if he answered “MVC” to the first. The number of precedent states can be checked before deciding how to set up the hyperlinks (see Figure 1).
Figure 1 Dynamic Back Navigation
  1. protected void Page_Load(object sender, EventArgs e)
  2. {
  3.   if (StateController.CanNavigateBack(2))
  4.   {
  5.     Question1.NavigateUrl = StateController.GetNavigationBackLink(2);
  6.     Question2.NavigateUrl = StateController.GetNavigationBackLink(1);
  7.   }
  8.   else
  9.   {
  10.     Question1.NavigateUrl = StateController.GetNavigationBackLink(1);
  11.     Question2.Visible = false;
  12.   }
  13. }
The survey is now functional, allowing you to fill in questions and amend previous answers. But there’s little point to a survey if these answers aren’t put to use. I’ll show how they can be passed from Question1 and Question2 to Thanks, where they’ll be displayed in summary form.

Data Passing

There are as many different ways of passing data in Web Forms as there are ways to navigate. With non-postback navigation, where control is passed from one page to another (via hyperlink, redirect or transfer), query string or route data can be used. With postback navigation, where control remains on the same page (via postback, partial page request or AJAX history), control values, view state or event arguments are the likely candidates.
Prior to Visual Studio 2005, codebehinds were burdened with handling this passed-in data, so they swelled with value-extraction and type-conversion logic. Their load was considerably lightened with the introduction of data source controls and select parameters (“value providers” in the next version of Visual Studio). However, these select parameters are tied to a specific data source and they can’t dynamically switch sources depending on the navigational context. For example, they can’t retrieve their values alternatively from a control or from the query string depending on whether it’s a postback or not. Working around these limitations causes code to leak back into the codebehind, reverting back to square one of bloated and untestable codebehinds.
The Navigation framework avoids such problems by providing a single data source regardless of the navigation involved, called state data. The first time a page is loaded, the state data is populated with any data passed during the navigation, in a fashion similar to query string or route data. A marked difference, however, is that state data isn’t read-only, so as subsequent postback navigations occur, it can be updated to reflect the page’s current incarnation. This will prove beneficial when I revisit back navigation toward the end of this section.
I’ll change the survey so the answer to the first question is passed to the Thanks state where it will be redisplayed to the user. Data is passed while navigating via a collection of key-value pairs, called NavigationData. I’ll change the Next click handler of Question1.aspx so the answer to the first question is passed to the next state:
  1. NavigationData data = new NavigationData();
  2. data["technology"] = Answer.SelectedValue;
  3. if (Answer.SelectedValue != "MVC")
  4. {
  5.   StateController.Navigate("Next", data);
  6. }
  7. else
  8. {
  9.   StateController.Navigate("Next_MVC", data);
  10. }
This NavigationData passed during navigation is used to initialize the state data that’s made available to the next state via the Data property on the StateContext object. I’ll add a Label to Thanks.aspx and set its Text property to display the answer passed in:
  1. Summary.Text = (string) StateContext.Data["technology"];
If you run the survey, you’ll notice this summary information is only displayed when the answer to the first question is “MVC”; an answer of “Web Forms” is never shown. This is because NavigationData is only available to the next state, but not to any states reached as a result of subsequent navigation. So an answer of “Web Forms” is present in the Question2 state data, but isn’t available by the time Thanks is reached. One way to solve this is to change Question2.aspx so that it relays the answer to the first question—that is, it takes the answer out of its state data and passes it to Thanks when it navigates:
  1. NavigationData data = new NavigationData();
  2. data["technology"] = StateContext.Data["technology"];
  3. StateController.Navigate("Next", data);
This approach isn’t ideal because it couples Question1 and Question2 together, forcing the latter state to be aware of the data being passed in by the former. For example, a new question can’t be inserted between the first and second without a corresponding change to Question2.aspx. A future-proof implementation involves creating a new NavigationData containing all of the Question2 state data; this is achieved by passing true to the NavigationData constructor:
  1. NavigationData data = new NavigationData(true);
  2. StateController.Navigate("Next", data);
Another key difference between state data and query string or route data is that with state data you’re not restricted to passing strings. Rather than pass the answer as a string, as was done for Question1, for Question2 I’ll pass a bool to Thanks, with a value of true corresponding to “Yes”:
  1. NavigationData data = new NavigationData(true);
  2. data["navigation"] = Answer.SelectedValue == "Yes" ? true : false;
  3. StateController.Navigate("Next", data);
You can see its data type is preserved when it’s retrieved from the Thanks state data:
  1. Summary.Text = (string) StateContext.Data["technology"];
  2. if (StateContext.Data["navigation"] != null)
  3. {
  4.   Summary.Text += ", " + (bool) StateContext.Data["navigation"];
  5. }
The survey is complete, except for one problem: Answers to questions aren’t retained when using the back navigation hyperlinks. For example, when returning to Question1 from Thanks the context is lost, so the default “Web Forms” radio button is always selected regardless of the answer given.
In the previous section you saw the benefit of back navigation over static site map breadcrumbs. Another limitation of the breadcrumbs generated by the site map is that they don’t carry any data. This means following them can lose contextual information. For example, they can’t pass the “MVC” answer previously selected when they return to Question1 from Thanks. The Navigation framework, by keeping track of the state data associated with the states visited as navigations occur, builds up a context-sensitive breadcrumb trail. During a back navigation this state data is restored, allowing the page to be recreated exactly as before.
Armed with context-sensitive back navigation, I can change the survey so that answers are retained when revisiting states. The first stage is to set the answers into state data in the Next click handlers, prior to navigating away:
  1. StateContext.Data["answer"] = Answer.SelectedValue;
Now, when Question1 or Question2 are revisited, the state data will contain the answer previously selected. It’s then a simple matter to retrieve this answer in the Page_Load method and preselect the relevant radio button:
  1. protected void Page_Load(object sender, EventArgs e)
  2. {
  3.   if (!Page.IsPostBack)
  4.   {
  5.     if (StateContext.Data["answer"] != null)
  6.     {
  7.       Answer.SelectedValue = 
  8.         (string)StateContext.Data["answer"];
  9.     }
  10.   }
  11. }
The survey, now complete, isn’t susceptible to the errors commonly encountered in Web applications when users press the browser back button (or have multiple browser windows open). Such problems typically arise when page-specific data is persisted in a server-side session. Although there’s only one session object, there can be multiple “current” versions of a single page. For example, using the back button to retrieve a “stale” version of a page from the browser cache might cause the client and server to be out of sync. The Navigation framework faces no such issues because it doesn’t have any server-side cache. Instead, the state, state data and breadcrumb trail are all held in the URL. This does mean, however, that a user can change these values by editing the URL.

Making MVC Jealous

Earlier I stated that the Navigation framework lets you create Web Forms code to make MVC jealous. After such a bold claim you might be feeling a bit short-changed by the survey sample application, because it probably has MVC holding its nose to avoid the unsavory whiff of codebehind about it. But please don’t despair; this was merely an introduction to the core concepts. Future articles will focus on architectural integrity, with particular attention paid to unit testing and DRY principles.
In the second installment I’ll build a data-bound sample with empty codebehinds and complete unit test code coverage. This coverage will even include the navigational code, notoriously difficult to test in an MVC application.
In the third installment I’ll build an SEO-friendly single-page application. It’ll use progressive enhancement, employing ASP.NET AJAX when JavaScript is enabled and degrading gracefully when it’s disabled, with the same data-bound methods used in both scenarios. Again, this is tricky to achieve in an MVC application.
If this whets your appetite and you can’t wait to try out some of the more advanced functionality, be sure to download the comprehensive feature documentation and sample code from navigation.codeplex.com.