Archive

Archive for the ‘.NET’ Category

ASP.NET MVC and Unobtrusive Ajax with jQuery Part II

September 18th, 2008

In my last post, I introduced this series in which I add Ajax to an ASP.NET MVC application as a progressive enhancement, allowing the site to function without requiring JavaScript, but creating a better user experience for users with JavaScript enabled. In this post, I will discuss the feature I am working on and introduce the base controller and view code as well as introduce a minor change to the initial controller code to add support for Ajax calls/return data without breaking the standard post-based behavior.

The Target Functionality

The functionality that we will be looking at for the purpose of these posts will be a simple content page that allows comments. The comment form will exist on the content page and will call a controller that will then insert a record in the database. Since the comments live on the page with the associated content, the controller will redirect to the view that the form was submitted from (showing the content again, along with the comments). The page will be reloaded, just as you would expect from a typical form submission that redirects following the submission. Once that works, we can update the code to make the form submit via Ajax, at which point we will need to update the page through client script.

The Initial Code

The initial code is a simple controller action which makes a call to a business object that will handle inserting the comment into the database. I will be displaying a code comment as a placeholder for that code since it has very little relevance to the topic at hand.

[AcceptVerbs("POST")]
public ActionResult AddComment(string commentBody, int articleID)
{
//Logic and Database insert code...

//redirect to re-load the page
return RedirectToRoute("Default",
new { controller = "Article",
action = "Show",
id = articleID });
}

At this point, since the View for our content will re-query and display all of the associated comments all that this code needs to do is redirect the user back to the content page and the new comment will be loaded along with the rest of the comments. The above code accomplishes this redirect in a single line of code.

Updating The Controller Action

Now that we have the form in the view successfully submitting its content to the controller action through a post, we need to update the action code to distinguish between a standard post and an ajax-based post in order to return JSON when needed. One of the goals was to make any controller changes minimal. We also want to make sure that none of the business logic changes due to the addition of Ajax. So let’s take a look at the code for the first step:

[AcceptVerbs("POST")]
public ActionResult AddComment(string commentBody, int articleID, string mode)
{
   //Logic and Database insert code...

   //redirect to re-load the page
   return RedirectToRoute("Default",
      new { controller = "Article",
            action = "Show",
            id = articleID });
}

The only change we have made at this point is to add an additional string argument to the method’s signature. This “mode” argument isn’t part of the original form post, and that’s ok. Our form doesn’t need to change. The only time (at this point) the mode value will be passed is when we are making the call from JavaScript. Now we will add a simple check to see if that string has been passed. If it hasn’t been passed, then we know it was a standard post and we will perform the redirect, just like we have been doing:

[AcceptVerbs("POST")]
public ActionResult AddComment(string commentBody, int articleID, string mode)
{
   //Logic and Database insert code...

   if (!string.IsNullOrEmpty(mode) && mode == "ajax")
   {
      //handle json result for ajax call
   }
   else
   {
      //redirect to re-load the page
      return RedirectToRoute("Default",
         new { controller = "Article",
               action = "Show",
               id = articleID });
   }
}

Now all that’s left to do is return JSON formatted data if the mode has been passed. The final version of the controller action is listed below.

[AcceptVerbs("POST")]
public ActionResult AddComment(string commentBody, int articleID, string mode)
{
   //Logic and Database insert code...

   if (!string.IsNullOrEmpty(mode) && mode == "ajax")
   {
      //The comment object is returned after the data insert above
      return this.Json(comment);
   }
   else
   {
      //redirect to re-load the page
      return RedirectToRoute("Default",
         new { controller = "Article",
               action = "Show",
               id = articleID });
   }
}

This code includes a call to the Controller’s Json method (referenced as this.Json) which accepts your data object (in our case, a comment object that was returned from the omitted data insert code) and returns a JsonResult object that can be returned from the controller. The passed object is then made available to your JavaScript when it receives the Ajax result. We will take a closer look at the comment object in the next post, when we add the JavaScript that will trigger the JsonResult object being returned.

This controller action meets our goals of using the same logic regardless of the method that was used to post the form and I think the changes are fairly minimal (again, this is pretty subjective).

Coming Up

We still need to add the jQuery code required to make an Ajax call to the controller and ensure that there is a return value. After we have the code in place to make the call and run the controller code, there will be a couple more posts to explain how to handle the return data and add some other nice UX features for those with JavaScript enabled.

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

.NET, ASP.NET, Ajax, JavaScript, MVC, jQuery , , , , ,

ASP.NET MVC and Unobtrusive Ajax with jQuery Part I

September 15th, 2008

I have recently started developing a website using ASP.NET MVC (preview 5). One of the things I love about the MVC framework is the total control I have over my markup. I can keep the HTML clean, use ID values that make sense and won’t change each time the page is rendered and I can add all of my own client-side interactivity using jQuery (without the id mess that web controls create).

One of my goals with this new site is to create a functional site that works and renders in a usable manner even with CSS and JavaScript disabled. In order to do this, I have been creating all of the required interactions using standard get and post operations. The next logical step is to add Ajax functionality as a progressive enhancement using jQuery. Since ASP.NET MVC is still pre-beta, there isn’t a lot of documentation or published best practices with specifics about how to best handle this through the framework. I have read several posts from others with different solutions, they range anywhere from routing hacks (including ajax or html in the url) to seperate views (one standard view and an ajax enabled view). None of the solutions I have found have been what I wanted to do, so I set some goals for how I wanted it to work and through a process of trial and error, I have a solution. Through the next couple of posts, I will outline how I am handling this. I look forward to any feedback (good or bad) and if somebody has a better solution, please let me know.

The Goals

  1. Site should work in an acceptable manner without JavaScript enabled
  2. The same view should handle both Ajax enabled and standard post/get operations
  3. All controller code should be run in either scenario except for returning the ActionResult
  4. Changes to the controller action signature should be minimal and the same approach should work for any controller action (with minimal change)

Some of these goals are no-brainers, it helped to have all of the goals in place to keep myself from creating a massive amount of “Franken-code” in order to get the site working. I also realize that using the word “minimal” when talking about code changes is subjective, so if you don’t think what I have done is minimal, feel free to comment on the posts that contain the code and we can discuss it, please just share something more than “your solution sucks…” that won’t help anybody. And, if you have any other goals that you think I shoudl keep in mind, please let me know. I can’t promise that I’ll be able to attain more than I have already planned for in this series, but if something that I haven’t thought of seems important enough, I will do my best to try to meet the new criteria.

Upcoming Posts

Stay tuned. I have the code worked out for the most part, but it hasn’t been fully implemented, so I will be posting as I make more progress and I have tested enough to feel confident that I will have working code. I’m hoping to get the first post that has any real substance out before the end of the week.

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

.NET, ASP.NET, Ajax, JavaScript, MVC, jQuery , , , , ,

Alternating Item Styles In The ASP.NET ListView Control with jQuery

September 15th, 2008

In my last post I demonstrated how you could simply add alternating CSS styles to a ListView control without the need to duplicate your markup in an AlternateItemTemplate. This was accomplished through server-side code using the DataItemIndex to determine which style to apply. This time, we will look at how simple it is to apply the same effect using jQuery on the same simple markup that I used in the last post. I have removed the DataItemIndex related code and we are now left with this markup:

<asp:ListView ID="lvPeople" runat="server" ItemPlaceholderID="plcItem">
   <LayoutTemplate>
      <div id="people">
         <asp:PlaceHolder runat="server" ID="plcItem" />
      </div>
   </LayoutTemplate>
   <ItemTemplate>
      <div>
         First Name: <asp:Label runat="server" ID="lblFirstName" Text='<%# Eval("FirstName") %>' /><br />
         Last Name: <asp:Label runat="server" ID="lblLastName" Text='<%# Eval("LastName") %>' /><br />
         Age: <asp:Label runat="server" ID="lblAge" Text='<%# Eval("Age") %>' />
      </div>
   </ItemTemplate>
</asp:ListView>

With the markup in place, I have added a reference to the jQuery library in my page like so:

<script language="javascript" type="text/javascript" src="jquery-1.2.6.js"></script>

Now all that’s left is to add a little bit of jQuery code and we can apply our alternating css classes.

<script language="javascript" type="text/javascript">
   $(function() {
      $("div#people div")
         .filter(":even").addClass("even")
         .end().filter(":odd").addClass("odd");
   });
</script>

It’s that simple. The code listing above was broken out onto multiple lines, but could just as easily have been written in one single line, I prefer the format above for readability, but that’s just me.

The jQuery code selects all divs that are children of the wrapper div (identified with the “people” id attribute) and runs a filter that only returns the even items. It then adds a css class called “even” to those divs. The end() method then returns scope back to the first selection containing all of the child divs. The second filter runs just like the first, only this one returns the odd items and aplies the “odd” class to those divs.

If you haven’t used jQuery before, I suggest you check it out. It makes selecting items and then manipulating them simple and in a pretty intuitive way (IMHO). If you don’t think it looks easy, try writing code to do this without the aid of a JavaScript library such as jQuery, make it work across browsers and then decide if this way isn’t easier.

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

.NET, ASP.NET, JavaScript, jQuery , , ,

Alternating Item Styles In The ASP.NET ListView Control

September 15th, 2008

If you have used the asp.net listview control, you know that you place your output elements in between the ItemTemplate tags. You may or may not have noticed that there is also an AlternateItemTemplate tag that can be used to render every other item differently. This is great when you want to alter the layout of every other item, but if you just want to apply a different CSS class on alternate items, you will be duplicating a lot of markup for a fairly minor change. Well, I have good news, there is an easier way. All you need to do is look at the DataItemIndex for your data item, determine if it is even or odd and apply the appropriate css class. The code is pretty self-explanatory, so here it is:

<asp:ListView ID="lvPeople" runat="server" ItemPlaceholderID="plcItem">
   <LayoutTemplate>
      <div id="people">
         <asp:PlaceHolder runat="server" ID="plcItem" />
      </div>
   </LayoutTemplate>
   <ItemTemplate>
      <div class='<%# Container.DataItemIndex % 2 == 0 ? "even" : "odd" %>'>
         First Name: <asp:Label runat="server" ID="lblFirstName" Text='<%# Eval("FirstName") %>' /><br />
         Last Name: <asp:Label runat="server" ID="lblLastName" Text='<%# Eval("LastName") %>' /><br />
         Age: <asp:Label runat="server" ID="lblAge" Text='<%# Eval("Age") %>' />
      </div>
   </ItemTemplate>
</asp:ListView>

The key is this line of code:

<div class='<%# Container.DataItemIndex % 2 == 0 ? "even" : "odd" %>'>

This allows alternating styles without duplicating your markup, which makes changing the item layout in the future much easier. You could also accomplish this with some javascript (in a line or two using jQuery) but that is a topic for another post.

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

.NET, ASP.NET ,

The ASP.NET DropDownList Hates Me

July 22nd, 2008

It must, or I wouldn’t have spent nearly as much time over the last few days fighting with it as I have. He started it!

Ok, maybe it was slightly my fault that I’ve been having the issues I’ve been having. Maybe my expectations were just set too high. I figured the DropDownList could handle whatever I threw at it. I was wrong.

So I found myself in a position recently where I needed a DropDownList to allow users to select an item based on a search. So the workflow is a bit like this:

  • User enters a search term into a textfield
  • User clicks search
  • Resulting items are displayed in a DropDownList for selections
  • User selects appropriate item from DropDownList and moves on

Now, based on the search term, there is a good chance that multiple items in the list will have the same underlying value attached to them. That’s ok, it’s what is expected of the system. This allows the user to make their choice based on the display and still give the application the value that it needs to get the job done. This seems like something that should be reasonably easy to do, and at the beginning, it was.

The search returns its items and binds them to the DropDownList. No problem. The user can select an item in the list as part of the form completion process and submit the form. The value can be picked up on the server and the app can do what it needs with the data. Also, no problem.

At this point, there hasn’t been a problem. The problems arise when you go beyond simply binding a list of values and having that field as part of a larger form. Let’s look at each problem seperately.

The first problem arises when the form is bound to an exsiting record. When binding the form, the options that were available in the list for the initial selection will be populated again. This puts multiple items in the DropDownList and in this scenario, there are multiple entries with matching values (but different text). Now as part of the binding process, text fields are set, checkboxes are checked and an item (prefereably the correct one) needs to be pre-selected in the DropDownList based on our record. To account for this, the display value from the selected item is stored as well (strictly to put the selection back in this scenario). So we pull the display value since those are unique and use that to find our desired item. Set the returned item to selected and we’re set. But we’re not. Even thought we have picked the item based on a unique property and we know that in the code-behind, only one item was selected, the page will result in an http error letting you know that you cannot select more than one item in the DropDownList. Removing the other items from the list prevents this, but it is not ideal since the original options should be available during an edit operation.

The second problem occurs when you want to perform some operation based on the DropDownList changing. Typically, you would attach a SelectedIndexChanged event handler to the DropDownList and then set its AutoPostBack property to true. So, when I needed this functionality, I followed those steps and it worked. It worked until there were items with matching values in the list. Once that happened, changing the value would cause a postback, but would not trigger the SelectedIndexChanged event handler. I worked around this one with a Page Method and some client-side ASP.NET Ajax code. Again, not an ideal use for my time.

So why are these tings happening? Well, based on everything I have seen happen here, I have to say that the value of each item is important and probably should be unique. In my opinion, the event and method names lead you to believe that it is looking at the Index, or that you can select an item based on picking the right ListItem object. Apparently, at some point, the value needs to be used to complete the setting, change detecting, etc. so it should be treated as a unique key.

My situation is not the most common way to use a DropDownList, but I can’t imagine that I’m the first person that needed to do something like this. Oh well, I’ll come up with a better way to handle the UI in situations like this in the future.

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

.NET, ASP.NET

Back To Basics - Container.DataItem

June 16th, 2008

Since asp.net 2.0 was in beta, I pretty much bailed on .NET 1.1 and Visual Studio 2003 and I’ve been pretty happy that way.

One of my favorite features in asp.net 2.0 (it’s a long list after working in 1.1) was the shortened syntax for declarative databinding to objects using Eval(”propertyname”) where “propertyname” is, well, a property in the object being bound to the control. This works when binding to a collection of objects where the values you want to use are stored in properties of the object. What about simple types such as integers or strings?

It’s pretty easy to bind a databound control to a collection of simple types such as a List<string> or a string array but since I don’t do it very often, I have to stop and remember (or look up) how to do it. So for my own reference and anybody else that may find this useful, here is a simple code example:

<ul>
  <asp:Repeater ID="rptSampleStrings" runat="server">
    <ItemTemplate>
      <li>
        <asp:Label runat="server" ID="lblStringDisplay"
          Text='<%#Container.DataItem %>' />
      </li>
    </ItemTemplate>
  </asp:Repeater>
</ul>

Here I have a repeater that will render a bulleted list of items from my List<string>. Notice the use of Container.DataItem for the text property… this is the point of this post. This is the syntax I always have to think about.

This is just to illustrate a point, I know I could use a ListView or the BulletedList control to do this. Anyway, here is the code-behind that creates the List<string> and binds it to the repeater (this code is in the Page_Load event handler):

var sampleStrings = new List<string>();
sampleStrings.Add("Test One");
sampleStrings.Add("Test Two");
sampleStrings.Add("Test Three");
sampleStrings.Add("Test Four");
sampleStrings.Add("Test Five");

//Set repeater datasource
rptSampleStrings.DataSource = sampleStrings;
rptSampleStrings.DataBind();

So, as you can see, it’s very simple to bind control properties to a list of strings, integers, etc. as long as you can remember the syntax.

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

.NET, ASP.NET, Back to Basics, programming , , ,

MyBlogPost

April 23rd, 2008

A few years back, I was working on an ASP.NET project and in order to help me meet the tight deadline, my boss brought in a consultant. We’ll call him John. John had done some work with the company before I had started and was available at the time, so the decision was made and he came in and started working. I went over the requirements and the design for the app. I assigned him a portion of the app to start working on and went about my work. A couple days into the project, I asked how he was doing and as I was talking to him I glanced over his shoulder at his monitor and I couldn’t believe what I was looking at. There was a variable in his code-behind file called “MyDataSet”!!

I think my head almost exploded! I asked him about it and did an informal code review, at which point I asked him to update his variable names and to make them more meaningful. I was going to be responsible for all of the code once it launched and I had no interest in trying to interpret the variable and control names. A week later, there were still instances of “MyDataSet” and “MyTextBox” all over the code. Needless to say, he didn’t last long on that project, and I spent a couple of late nights “fixing” the code so I would be able to understand it.

So where did the “my” prefix come from? In his case, it came from books and the msdn site. I saw it just today in a demo, hosted by Microsoft and produced by a Microsoft employee…

When Microsoft and the authors of technical books put together demos, there is typically a contrived scenario that they are supplying code for. Why can’t they look at the code and the scenario and come up with some meaningful variable names? Why does it make sense to name a texbox intended to accept a username, “myTextBox”? Why wouldn’t you call it “UsernameTextbox” or “txtUsername” or just “Username”?

In simple examples, this can be annoying, in larger ones, it can be thoroughly confusing. When taken seriously by a new developer, it can have more severe consequences.

What happened to the naming standards and best practices? What about self-documenting code?

I’ve probably been guilty of this once or twice, in my early years of teaching .NET, but I probably caught it from a book.

It doesn’t take much effort to use more meaningful names and the development community leaders, especially those working for Microsoft, should be held to a higher standard. I propose a ban on using “my<Object Name>” as variable names.

Who’s with me?

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

.NET, C#, programming , , ,

Unit Testing as a Method to Enforce Requirements

April 10th, 2008

I have recently started putting a lot of stock in automated unit testing. Not that I didn’t think unit testing was important in the past, I just didn’t know how to write them properly. A little instruction from a co-worker has corrected that situation and I am now writing proper unit tests. I like the test first approach, though I don’t know that I’ll be doing the full “TDD, no code without a test” thing just yet, but at the moment, I am writing tests first. Only time will tell if I can keep it up throughout the life of my project.

I recently ran into a situation that made me see some additional value in my tests. Beyond making sure everything works properly and lives through changes to the application, I am starting to see how my tests keep me in check and make sure I don’t stray from the requirements.

As an example we’ll assume we are testing classes from an application’s business layer. Each class in this layer will inherit from an abstract base class called “ServiceBase”. In this case, the ServiceBase is a generic class with some abstract members, but it also contains implementation code for a Save method.

The Save method accepts a business entity as an argument and decides whether to call Insert or Update in the underlying data access class. If the value passed in is null, the method throws an exception. This behavior is pretty standard, but some classes that inherit from it may have a need to perform some additional steps when saving. To account for this, I have also made the Save method virtual so any implementation that needs to can override the Save method.

Now we will create a couple of subclasses for ServiceBase. Let’s call them ProductService, CustomerService and OrderService. To start we create the ProductService class and make it inherit from the ServiceBase class. Now in order to make sure we have a complete set of unit tests, we create a test that expects an exception if a null item is passed to the save method. As long as the ServiceBase class throws the exception, it will pass for our test against the ProductService class. Now if we repeat the process (including the test) each class (ProductService, CustomerService, and OrderService), they will all have the ability to save an item, and each test that expects the exception should pass.

Now, let’s say the ProductService class has a need to write to a log when its Save method is called. This is easy, all we have to do is create an override for the Save method in our ProductService class. We add our logging code and all is good. We run our test and it fails.

Why did it fail? Because in my contrived story, we forgot to add the code that throws an exception if a null value is passed in. This is an honest mistake, but it’s ok because our test has saved us. This type of requirement cannot be enforced by the compiler through an interface or abstract base class. As far as the compiler is concerned, this code is completely valid. The unit test however, has alerted us to the fact that we did not implement the code according to our requirements (which was the basis for writing the test in the first place).

While this may be a no-brainer for those of you who have been practicing test driven development or just writing solid unit tests for a while, but for those of us who are just starting down this road this is an added benefit that may not seem obvious at first.

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

.NET, C#, TDD, Unit Testing, programming , ,

Visual Studio Unit Tests and Abstract Base Classes

April 6th, 2008

I am taking a semi-TDD approach to my most recent project. As I started writing my initial tests, it occurred to me that all of the ServiceLayer/Manager classes in my business layer inherit from a standard base class and that at least a few of the tests will be identical (except of course for the datatypes used). Each test class will also have essentially the same setup and breakdown.

So of course, I immediately fire up a new class and create a generic base class. I added a type parameter for the entity type that will be transported/manipulated through my Bll, one for the class being tested and another for the data access interface that I would be mocking through Rhino Mocks.

I added the internal and private members that would be used for setup and the test initialization method, commented it all out in my actual test class and added my inheritance. So far, so good. My tests ran, but they were still implemented in the original test class, so I commented them out, copied them into my base class and updated them to use my generic type arguments.

At this point, the “CreateInstance()” method that I was using to get a new instance of my target object caused a compiler error due to the fact that it called a constructor on my genric type argument that accepted a parameter. In order to pass in the mock for my data access interface, the parameter had to be there, but there is no way to specify constructor arguments in the constraints for generic type references.

I decided that making the “CreateInstance()” method abstract would give me access to it and then I would just have to add an implementation into my actual test classes… not a bad trade for the ability to “share” a group of core unit tests. So I marked the class as abstract, removed the method implementation, added the override into my actual test class and compiled.

At this point, my test project compiled with no problem, but my tests didn’t show up in test view. I compiled again, closed and re-opened my test class, closed and re-opened Visual Studio… still no tests in the test view window.

A quick Google search turned up this. I haven’t spent much time researching it at this point, but it seems that Visual Studio doesn’t recognize (or won’t run) Unit Tests that are defined in an abstract class. This problem is pretty specific to the unit testing framework that ships with Visual Studio. Sounds to me like this sort of thing would be possible if I were using NUnit (or some other xUnit framework) to do my unit testing.

The base class still seems to handle my setup and breakdown pretty well and I can use it for support methods that I share between tests so it isn’t a total loss, it just would have been nice to be able to inherit some tests as well.

If I find any new information, I will be sure to post it. If you know something I don’t (I’m sure you do but I mean something related…) feel free to share in the comments.

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

.NET, TDD, Tools, Unit Testing, Visual Studio , ,

ASP.NET’s Built-in Maintenance Page

April 2nd, 2008

This was originally posted on vanslaars.com in April of 2006.

Web applications require updates, maintenance and sometimes there are problems behind the scenes that require an app be taken offline temporarily. In the past I have accomplished this by setting my IIS default documents to index.html and default.aspx, in that order. My applications always use Default.aspx as the home page and I leave a file called “_index.html” sitting in the root directory. This html file contains a standard message letting users that the system is temporarily down. When I need to perform maintenance, I rename “Default.aspx” to “_Default.aspx” and remove the underscore from the html file to leave “index.html” as the default page for the application. This stops bookmarks to Default.aspx from working and displays the error message.

This approach works reasonably well, but it has some inherent problems. For one, the application continues to run, so bookmarks to other pages in the site continue to work. People looking for “Default.aspx” will get a 404 (page not found) error, and renaming both files is more work than I care to do for such a common need. Well, ASP.NET 2.0 comes to the rescue again with a very simple, yet elegant solution…the “App_Offline.htm” file.

Placing a file in the application root with the name “App_Offline.htm” causes the application domain to be unloaded and requests stop being processed. There is no need to rename any files, or change anything in the application. Just add the file and all requests will be directed to that file. Place your friendly message there, upload the file and perform your maintenance. When you are done, remove the file and the application runs normally for the next request.

The nice thing about this is that you can keep the file off of the server, FTP it up when you need it and delete it when you are done. The local copy can be used again in the future and no files need to be moved or renamed for the application to start again. There is also no requirement to change any setting in IIS.

Who would have thought a simple html page would become a key tool for application maintenance?

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

.NET, ASP.NET ,