Soe Tun

my attempt to solve common tech problems

  Home  |   Contact  |   Syndication    |   Login
  14 Posts | 0 Stories | 211 Comments | 0 Trackbacks

News

Twitter







Archives

Post Categories

Image Galleries

Wednesday, June 4, 2014 #

ASP.NET vNext Blog Post Series

ASP.NET vNext was announced at TechEd 2014, and I have been playing around with it a bit. ASP.NET vNext is an exciting and revolutionary change for the Microsoft .NET development platform. ASP.NET vNext is now open-source, and available on Github at this location: https://github.com/aspnet/Home.
I want to start a blog post series on the ASP.NET vNext, and share my experience as I learn more about it.

Keeping it simple

Each blog post in the series will be short and simple so I can write them in a short amount of time, and keep it focused on one (at most two) topic(s) per post.
My goal is to make it easy to absorb the information as there are a ton of great new stuff to cover.

Many other people in the community have blogged about the key new features of the ASP.NET vNext.
I will link to those blog posts in my next blog post.

MVC 6 POCO Controller

Today, I want to start this blog post series with a teaser code snippet for those developers familiar with the ASP.NET MVC.
Getting Started with ASP.NET MVC 6 article from ASP.NET website shows how to write a lightweight POCO (plain-old CLR object) MVC Controller class in the upcoming ASP.NET MVC 6.

However, it doesn't show us how to use the IActionResultHelper interface to render a View.
This is how I wrote my POCO MVC Controller based on the https://github.com/aspnet/Home/blob/master/samples/HelloMvc/Controllers/HomeController.cs sample from Github.
 
Note that this may not be the best way to write it, but this is good enough for now.

using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc.ModelBinding;
using MvcSample.Web.Models;

namespace MvcSample.Web
{
    public class HomeController
    {
        IActionResultHelper html;
        IModelMetadataProvider mmp;

        public HomeController(IActionResultHelper h, IModelMetadataProvider mmp)
        {
            this.html = h;
            this.mmp = mmp;
        }

        public IActionResult Index()
        {
            var viewData = new ViewDataDictionary<User>(mmp) { Model = User() };
            return html.View("Index", viewData);
        }

        public User User()
        {
            return new User { Name = "My name", Address = "My address" };
        }
    }
}

Please feel free to give me feedback as this will greatly help me organize the blog posts in this series, and plan head.

Thanks for reading!


Monday, April 29, 2013 #

My Color Theme for Notepad++

I really like the color theme from the Adobe Source Code Pro font announcement for HTML and XML as well as the beautiful Source Code Pro font for coding.  Then, I read this Programming Fonts comparison and really like the color theme for C# in the screenshots.

My favorite text editor is Notepad++ on Windows when I don't feel like opening the slow and bloated Visual Studio.  I really wanted a good dark color theme based on the Source Code Pro announcement and Programming Fonts comparison for coding HTML/XML, C#, and Python.  I will eventually optimize the colors for JavaScript and CSS very soon.

It is similar to many many other themes out there.  A friend of mine even mentioned it looks like a typical VIM highlighting theme.  I am going to call it Obsidian PyCs since it is based on the Obsidian theme that comes with Notepad++.

HTML and XML Colors

Source Code Pro Font (sizes: 11pt for HTML, 10pt for XML) with #1E1E1E as Background color.

Description Foreground
Default #F8F8E9
Comment #F16EAA
Attribute Key #1EBEC8
Attribute Value (double-quoted) #DEC065
Attribute Value (single-quoted) #F16EAA
Tags #7AB667

XML Color Theme

XML Theme

HTML Color Theme

HTML Theme

C# Colors

Source Code Pro Font (size 10pt) with #1E1E1E as Background color

Description Foreground
Preprocessor #AA80FF
Default #F0F0F0
Keyword #1 #E9285F (red-pink)
Keyword #2 #5DCAE1 (blue)
Numbers #AA80FF
String #D4D46E
Character #FF8040
@Verbatim #D4D46E
Comment Line #008000
XML Doc #808080

C# Color Theme

C# Theme

Python Colors

Source Code Pro Font (size 10pt) with #1E1E1E as Background color

Description Foreground
Default #F8F8E9
Keyword #E9285F
Class Name #AA80FF
Numbers #AA80FF
String #DEC065
Character #DEC065
Comments #008000
Doc String #808080

Python Color Theme

Python theme

Color Theme Download on Github

I published it as a Github repo https://github.com/soelinn/Npp-Obsidian-PyCs.
Disclaimer: I am a newbie at using and publishing on Github.


Monday, April 8, 2013 #

I like these jQuery methods a lot: addClassremoveClasstoggleClass.
I wish ASP.NET Web Controls have similar functionality out of the box like jQuery for manipulating CSS class like below.

// You MUST include your own namespace here
// in order for the Extension Methods to be visible in your code.
using YourProjectNamespace.ExtensionMethods;

textBoxControl.AddCssClass("enable").RemoveCssClass("disabled");
textBoxControl.ToggleCssClass("enable disable");

So I created extension methods for the WebControl class.  Just make sure you change it to your own project namespace and import it so you don't get a compiler error.

DISCLAIMER:
I haven't tested this code thoroughly since I just wrote it a few minutes ago.
So you are on your own if it is buggy :-)

using System;
using System.Text.RegularExpressions;
using System.Linq;
using System.Web.UI.WebControls;

namespace YourProjectNamespace.ExtensionMethods
{
    public static class WebControlExtensions
    {
        private static Regex re = new Regex("\\S+", RegexOptions.Singleline | RegexOptions.Compiled);

        /// <summary>Regex matches non-whitespace characters.</summary>
        /// <param name="value">string value to match</param>
        /// <returns>returns regex match object if it has matching groups, null if none matches.</returns>
        private static Match GetMatch(string value)
        {
            if (string.IsNullOrEmpty(value))
                return null;
            Match ma = re.Match(value);
            if (ma == null || ma.Groups.Count == 0)
                return null;
            return ma;
        }

        /// <summary>Returns CSS class names as an array of strings.</summary>
        /// <param name="ma">regex match</param>
        /// <returns>returns an array of CSS class name strings</returns>
        private static string[] GetClassNames(Match ma)
        {
            return (from Group g in ma.Groups
                    where g.Success
                    select g.Value).ToArray();
        }

        /// <summary>Adds the CSS class names to the web control.</summary>
        /// <param name="c">web control</param>
        /// <param name="value">css class names to add</param>
        /// <returns>returns the control itself so method calls can be chained</returns>
        public static WebControl AddCssClass(this WebControl c, string value)
        {
            Match ma = GetMatch(value);
            if (ma == null)
                return c;

            string[] classNames = GetClassNames(ma);
            string elemClassName = !string.IsNullOrEmpty(c.CssClass)
                                        ? String.Format(" {0} ", c.CssClass)
                                        : " ";

            foreach (var className in classNames)
            {
                if (elemClassName.IndexOf(" " + className + " ") < 0)
                {
                    elemClassName += className + " ";
                }
            }

            c.CssClass = elemClassName.Trim();

            return c;
        }

        /// <summary>Removes the CSS class names of the web control.</summary>
        /// <param name="c">web control</param>
        /// <param name="value">css class names to remove</param>
        /// <returns>returns the control itself so method calls can be chained</returns>
        public static WebControl RemoveCssClass(this WebControl c, string value)
        {
            Match ma = GetMatch(value);
            if (ma == null)
                return c;

            string[] classNames = GetClassNames(ma);
            string elemClassName = !string.IsNullOrEmpty(c.CssClass)
                                        ? String.Format(" {0} ", c.CssClass)
                                        : " ";

            foreach (var className in classNames)
            {
                string searchString = " " + className + " ";
                if (elemClassName.IndexOf(searchString) >= 0)
                {
                    elemClassName = elemClassName.Replace(searchString, " ");
                }
            }

            c.CssClass = elemClassName.Trim();

            return c;
        }

        /// <summary>Toggles the CSS class names of the web control.</summary>
        /// <param name="c">web control</param>
        /// <param name="value">css class names to toggle</param>
        public static void ToggleCssClass(this WebControl c, string value)
        {
            string elemCssClass = !string.IsNullOrEmpty(c.CssClass)
                                    ? String.Format(" {0} ", c.CssClass)
                                    : " ";

            Match ma = re.Match(value);
            var classNames = GetClassNames(ma);
            foreach (var className in classNames)
            {
                string searchString = " " + className + " ";
                if (elemCssClass.IndexOf(searchString) < 0)
                {
                    elemCssClass += className + " ";
                }
                else
                {
                    elemCssClass = elemCssClass.Replace(searchString, " ");
                }
            }

            c.CssClass = elemCssClass.Trim();
        }
    }
}

Wednesday, January 2, 2013 #

This blog post is based on the information I found from this blog post http://geekswithblogs.net/wesm/archive/2009/11/13/syntaxhighlighter-with-subtextgwb.aspx.

I find it very difficult and tedious to manually format the sample code snippets when writing blog posts on GWB.net since it doesn't have a good built-in syntax highlighting support.
The built-in rich-text editor is cumbersome and it gets in the way while I am writing and thinking.
As a side note, I prefer the WordPress text editor because it stays out of your way and lets you focus on writing your blog post with great user-experience for including images and captions.

GWB includes CSS styles from Manoli Code Formatter at this URL http://geekswithblogs.net/skins/_System/csharp.css.
However, it is quite limited and supports only a few languages (C#, VB, T-SQL).

Google Code Prettify

Setting up Prettify is quite easy.  Here is a good tutorial on how to use it. http://net.tutsplus.com/tutorials/html-css-techniques/quick-tip-how-to-add-syntax-highlighting-to-any-project/

The basic usage:

  1. Include prettify.css stylesheet in your <head> tag.
  2. Put your code snippets inside <pre class=”prettyprint”> tags.
  3. Include prettify.js javascript file right before the </body> closing tag.
  4. Call prettyPrint() on window.load event to initialize the syntax highlighter.

GeeksWithBlogs.net Configuration

  1. Go to Options –> Configure in your GWB admin section.
  2. Choose your favorite syntax highlighting theme from http://google-code-prettify.googlecode.com/svn/trunk/styles/index.html.
  3. Copy-and-paste the CSS style below into the Custom CSS textbox.  I customized the Sons of Obsidian theme as below for extra margin & padding around the code block.
    /* son of obsidian - google prettify */
    .str{color:#ec7600} .kwd{color:#93c763}
    .com{color:#66747b} .typ{color:#678cb1}
    .lit{color:#facd22} .pun{color:#f1f2f3}
    .pln{color:#f1f2f3} .tag{color:#8ac763}
    .atn{color:#e0e2e4} .atv{color:#ec7600}
    .dec{color:purple}
    pre.prettyprint{border:0 solid #888;font-family:Consolas,"Courier New",monospace}
    ol.linenums{margin-top:0;margin-bottom:0}
    .prettyprint{background:#000;margin-top:10px;margin-bottom:25px;padding:20px 0 20px 10px}
    li.L0,li.L1,li.L2,li.L3,li.L4,li.L5,li.L6,li.L7,li.L8,li.L9{color:#555;list-style-type:decimal}
    li.L1,li.L3,li.L5,li.L7,li.L9{background:#111}
    
    @media print{
    .str{color:#060}
    .kwd{color:#006;font-weight:bold}
    .com{color:#600;font-style:italic}
    .typ{color:#404;font-weight:bold}
    .lit{color:#044}
    .pun{color:#440}
    .pln{color:#000}
    .tag{color:#006;font-weight:bold}
    .atn{color:#404}
    .atv{color:#060}
    }
  4. In the Static News/Announcement textbox, copy and paste this
    <script type="text/javascript" language="javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript" language="javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/lang-css.js"></script>
    
    <script type="text/javascript" language="javascript">
    function addLoadEvent(func){
      var oldonload = window.onload;
      if (typeof window.onload != 'function') {
        window.onload = func;
      }else{
        window.onload = function() {
        if (oldonload){oldonload();}
          func();
        }
      }
    }
    addLoadEvent(prettyPrint);</script>
  5. The addLoadEvent function is by http://simonwillison.net/2004/may/26/addloadevent/ because I need to call prettyPrint() function on window.load event.

Important Note

As you noticed, I link the Prettify library directly from http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js since I cannot upload a file onto GWB.
If Google stops serving the file from the URL, this will basically not work anymore.

Maybe we should pester Google to host the Prettify library on the Google Ajax API CDN Winking smile.


Saturday, May 21, 2011 #

Thanks to everyone who attended my Intro to F# presentation at the Cap Area Cloud Computing User Group meeting on May 19th 2011.
I apologize for the slight delay in getting the presentation materials uploaded.

 

In the Demo project source code, I have included both Normal and Async source samples.
It will make it easier to understand what code changes were necessary to transform it to Async Workflow and parallelize it.

In addition, I have included some F# script files (.fsx) so you can try out some code that was written on the fly during my presentation.

 

As mentioned during the presentation, the demo project idea was based on Introduction to Microsoft F# by Luca Bolognese (PDC 2008) presentation.
It was chosen because it highlights the important features like Async Workflow and parallelization in a very small amount of code.

To make it easier to access some of the important Resources from my PowerPoint slides, I will simply list them below.

Online F# Editors
http://tryfsharp.org (requires Silverlight)
http://tryfs.net (no plugin required)

F# Code Snippets
http://fssnip.net

Introduction to F# by Luca Bolognese
http://channel9.msdn.com/blogs/pdc2008/tl11

Side-by-Side Language Comparison between C# and F#
http://blogs.msdn.com/b/timng/archive/2010/04/05/f-object-oriented-programming-quick-guide.aspx

MSDN: F# Language Reference
http://msdn.microsoft.com/en-us/library/dd233181.aspx

F# File Types
http://msdn.microsoft.com/en-us/library/dd233169.aspx

Signature Files (.fsi)
http://msdn.microsoft.com/en-us/library/dd233196.aspx

 

Download link below from my Microsoft SkyDrive.  Please let me know if you have any question (or) unable to download/open the zip file.

 

Thank you and have a great weekend!

P.S. I regularly use Twitter for quick updates and to share links and socialize. Follow me at: twitter.com/SoeLinn.


Monday, April 11, 2011 #

Thanks to everyone who attended my session at Philly Code Camp 2011.1.
It was a very fun and interactive session for me, and I hope it was an informative and helpful session for you as well.

I apologize for the delay in getting the presentation materials uploaded since I was busy catching up with work from last week this morning.

 

The Database backup file (.bak) included in the zip file will have to be restored on your SQL Server.
Please let me know if anything doesn't run (or) compile or you are getting weird errors.

Below is the Download Link from Microsoft Skydrive.

 

P.S:
The MVC View Editor Templates included in my Demo project are used in my actual project at work and been deployed to Production environment.
And I haven't found the need to add new ones as it fits all my needs.

Just letting you know so that you can drop in these same templates in your MVC 3 projects.
They cannot be used in MVC 2 projects because there are slight changes.
For that, you will have to download the presentation materials from my older presentations from Richmond 2010.2 (or) NoVa 2010.2 blog posts.


Friday, January 28, 2011 #

When we were working with ASP.NET MVC 2, we needed to write our own JavaScript to get Client-Side Validation Summary with jQuery Validation plugin.
I am one of those unfortunate people still stuck with .NET Framework Runtime 2.0 and .NET Framework 3.5; meaning I am still on ASP.NET MVC 2.
So I will still keep on supporting by answering any question you may have with my original code.

 

Long awaited ASP.NET MVC 3 has been released, and it supports Client Side Validation Summary with jQuery out-of-the-box with new features like Unobtrusive JavaScript.

 

1. _Layout.cshtml Template

Notice that I am using Protocol Relative URLs ( i.e., '//'.  Not 'http://' or 'https://' ) to reference script files and css files and you should use it too like that!
However, please note that IE7 and IE8 will download the CSS files twice so use it with judgement.

<!DOCTYPE html>
<html>
<head>
    <title>@ViewBag.Title</title>
    <link href="@Url.Content("~/Assets/Site.css")"  rel="stylesheet" type="text/css" />
    <link href="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.9/themes/redmond/jquery-ui.css" rel="stylesheet" type="text/css" media="screen" />
</head>

<body>
    @RenderBody()

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"           type="text/javascript"></script>
    <script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.9/jquery-ui.min.js"      type="text/javascript"></script>
    <script src="//ajax.aspnetcdn.com/ajax/jQuery.Validate/1.7/jQuery.Validate.min.js" type="text/javascript"></script>
    <script src="//ajax.aspnetcdn.com/ajax/mvc/3.0/jquery.validate.unobtrusive.min.js" type="text/javascript"></script>
</body>
</html>

 

2. MVC View Template

There are 3 things you *must* do exactly to get Client Side Validation Summary working.

  1. You must declare your Validation Summary **inside** the `Html.BeginForm()` block like below.
  2. You must pass `excludePropertyErrors: false` to the  Html.ValidationSummary()  method.
    @using (Html.BeginForm()) {
        @Html.ValidationSummary(false, "Please fix these errors.");
    
        <!-- The rest of your View Template -->
    
    }
    Html.ValidationSummary(false, "Please fix these errors.") generates the HTML code below.
    <div class="validation-summary-valid" data-valmsg-summary="true">
        <span>Please fix these errors.</span>
        <ul><li style="display:none"></li></ul>
    </div>
    If you look into the jquery.validation.unobtrusive.js source code, you will understand why I said the Validation Summary declaration must be inside the Html.BeginForm( ) block.
    On line #56 inside the function onErrors(form, validator) { // 'this' is the form element function, it retrieves the validation summary HTML node like below.
    var container = $(this).find("[data-valmsg-summary=true]")
    Basically, it looks for the validation summary HTML node **inside** the corresponding <form> tag.
    If you don't declare the validation summary block using Html.ValidationSummary(false, "Please fix these errors.") using the false parameter, the data tag data-valmsg-summary="true" does NOT get generated, and the jQuery Validation Unobtrusive library won't be able to locate your validation summary to populate the error messages.
    This is needed because you may have multiple <form> tags on the entire page and the validation library needs to know exactly which validation summary block to insert the client-side validation error messages.
     
  3. You have to put the following two elements in the `<appSettings />` block of your Web.config file.
    <add key="ClientValidationEnabled"      value="true"></add>
    <add key="UnobtrusiveJavaScriptEnabled" value="true"></add>


 

3. CSS Styles for Validation

As Anthony mentioned below in the comments, I forgot to mention about the CSS styles used by MVC framework for validation display.
The CSS class names below are pretty self-explanatory of what they do.

.input-validation-error { border: 1px solid #f00 }
.input-validation-valid  { /* Optional: you can set whatever style you want */ }
.field-validation-error { color: #f00 }
.field-validation-valid { display: none }
.validation-summary-errors { font-weight: bold; color: #f00 }
.validation-summary-valid { display: none }

 That is all you need to do.  Simple, right? 


P.S:
Without getting into too much technical details, I just wanted to let you know what I went through to get this to work.
I had to look into the ASP.NET MVC 3 RTM Source Code and the jquery.validate.unobtrusive.js source.

Initially, I thought I have to hack the jquery.validate.unobtrusive.js or something to get this to work.
But after digging into MVC3 RTM source, I found out how to do it.

 

3. Sample Project Download

Please let me know if you cannot download the Sample project from my SkyDrive.

 

Update:

July 12th 2011: elaborated why you have to declare the Validation Summary block inside the <form> tag due to Vincent's comment below.


Saturday, December 11, 2010 #

Thank you to everyone who attended my Retrofit WebForms with ASP.NET MVC session at NoVa Code 2010.2.
It was a fun event for me and I hope you had a great time and learned something from it.

I wish I had more time to go over some more important topics in more detail.
I *promise* I will be writing blog post series about it since I'll have some vacation time during the December holidays to cover some topics that I didn't get to cover in detail.

 

Please note that the ".bak" file included in the zip file is a SQL Server Database backup file.
You have to restore it on your Database server to run it with the source code demo.

 

Please feel free to ask me about the demo project through Twitter or from this blog post. I'll be glad to help you out.
If you want me to give this presentation at your .NET User Group, please let me know and I'll be honored to speak there also.

 

Again, thank you all and have a great holiday season.
Here is the download link to my Demo project Zip file with the PowerPoint presentation in it.

Please let me know if the link doesn't work.


Sunday, October 10, 2010 #

Thanks to all those who attended my session Retrofit WebForms with ASP.NET MVC at the Richmond Code Camp 2010.2.

To be honest, it was my very first time speaking at a big event like this and I was quite nervous during it.
I realized after the demo that I went through the topics quite faster than I should.
Nonetheless, I hope my session was helpful and you learned something from it.

 

Thank you all for asking very good questions so I can improve my presentation for next time.
Please let me know if you wanted to learn more about a certain topic that I didn't spend enough time explaining.

 

To those who are interested in downloading the Powerpoint presentation and the project demo, you can download it below.
Please let me know if you have any problem opening and running it.

The download zip file should contains 3 files.
(1) Demo project zip file
(2) SQL Server 2008 Demo database backup file. You'll need to restore it on your own computer.
(3) PowerPoint 2007

 

I am planning to write up a blog post series on my presentation in the near future as time permits.
So it will be easier for you to learn more about the topics from my presentation in detail.

Thanks,
Soe

Note: Updated and replaced with the NoVa CodeCamp 2010.2 Demo on December 11th 2010.


Thursday, August 26, 2010 #

It has been a while since my last blog post.
I have been busy and lazy at the same time and couldn't find the time to get around posting new blog posts.

I have been thinking of writing a blog post series on ASP.NET MVC for Web Forms Programmers.
Especially because I am planning to give presentations at .NET User Group meetings and Code Camps starting this October-November.

 

So, now I need to buy a 17" screen laptop with Windows 7 64-bit with 8GB RAM.
I have always been a Desktop guy because I hate laptops due to

  • small-screen size
  • tiny keyboard
  • slower performance compared to desktops

To my horror, I end up having to choose from this confusing list of laptop product lines on Dell's website.

  • Adamo
  • Inspiron
  • Mini
  • Studio
  • Studio XPS
  • Latitude
  • Precision
  • Vostro

 

Now, let's compare that with Apple's products lineup on http://www.apple.com/mac/.
From their names alone, I can determine its use and which one I need without any thinking necessary.

  • Macbook      -- regular laptop           (the "poor" mens' laptop)
  • Macbook Pro -- powerful                  (the "I'm fricken rich" laptop)
  • Macbook Air  -- super lightweight      (the "I'm trendy" laptop)
  • Mac Mini      -- small                      ("I can't afford any other Mac" mac)

 How simple is this to choose from?

 

I know the laptop that I need must be a powerful laptop.
So that leaves me with the following choices: Inspiron, Studio, Studio XPS, Latitude, Precision, Vostro

Okay, now this is where it gets confusing.
What is the difference between Inspiron and Latitude? Studio? XPS? Precision? Vostro?

 

Dell's explanation on this page is so full of Marketing-Speak that I get even more confused.
http://www.dell.com/content/topics/global.aspx/solutions/en/why_inspiron?c=us&l=en
Here is the exact quote (as of August 26th 2010):

Inspiron vs. ...

Inspiron vs. XPS Inspiron laptops are designed to deliver an outstanding computing experience with exceptional reliability - offering performance and design at an affordable price. XPS laptops are built around the latest in high performance technologies and offer expanded services with an unrelenting focus on innovation, design, extreme gaming and exhilarating entertainment. XPS is the pinnacle of Dell technology, design and innovation.

Inspiron vs. LatitudeTM While Inspiron laptops offer the latest technology, the Latitude line is Network-optimized for businesses with more than 10 employees and designed to allow for managed transitions and a low total cost of ownership. Latitude is perfect for a large networked environment, long-term stability and business-class computing.

Inspiron vs. Dell PrecisionTM Dell Precision workstations are certified to run a variety of workstation-class applications and are optimized for the high performance requirements and processing demands necessary for many engineering, finance, software development, digital content creation, digital video editing and GIS applications.

Now put yourself in the shoes of a non-technical Home User (or) Small-Business Owner.
You will be completely clueless on which one to buy.

 

Now I am having to

  1. Go back and forth between Home and Small-Business sections.
  2. Navigate through Dell's confusing and cluttered website. See for yourself what the difference is.
           http://www.apple.com/macbookpro/
           v.s
          http://www.dell.com/us/p/studio-n-studio-xps-laptops?~ck=anav
     
  3. Keep many many many Browser Tabs opened between different Product Lines and configurations.

All in all, shopping on Dell's webiste is really cumbersome, ridiculous, and annoying.

 

Gotta give credit to Apple for always providing a clean, simple, and pleasant design and user-experience in *every* product they make (including their website).
Now, don't get me wrong. I am not an Apple fanboi and the only Apple product I own is an iPhone.

 I hate Apple computers because they are ridiculously priced and expensive.
And I also hate how Apple Fanbois say "It is more expensive because Apple uses better quality hardware", which I know is nonsense.

 

Anyway, I'm looking for a good laptop around $1,500 from Dell.
Please let me know if anyone know a good deal/coupon for Dell laptops.

/end-rant