(550) File unavailable (e.g., file not found, no access).


If you are getting above error while using FtpWebRequest method to upload file to a FTP sever, please check your URL, The URL must be case sensitive. Otherwise you will get this error.

author: hmloo | Posted On Thursday, October 18, 2012 2:43 AM | Comments (1)

The remote server returned an error: 227 Entering Passive Mode


Today while uploading file to FTP sever, the codes throw an error - "The remote server returned an error: 227 Entering Passive Mode", after research, I got some knowledge in FTP working principle.

FTP may run in active or passive mode, which determines how the data connection is established.

Active mode:


command connection: client >1024  -> server 21
data connection:    client >1024  <-  server 20

active

passive mode:


command connection: client > 1024 -> server 21
data connection:    client > 1024 <- server > 1024

passive

In active mode, the client connects from a random unprivileged port (N > 1023) to the FTP server's command port(default port 21). If the client needs to transfer data, the client will use PORT command to tell the server:"hi, I opened port XXXX, please connect to me." and then server will use port 20 to initiate the data connection to that client port number.

In passive mode, the client connects from a random unprivileged port (N > 1023) to the FTP server's command port(default port 21). If the client needs to transfer data, the sever will tell the client:"hi, I opened port XXXX , please connect to me." and then client will initiate the data connection to that sever port number.

In a nutshell, active mode is used to have the server connect to the client, and passive mode is used to have the client connect to the server.

So if your FTP server is configured to work in active mode only or the firewalls between your client and the server are blocking the data port range, then you will get error message, to fix this issue, just set System.Net.FtpWebRequest property UsePassive = false.

Hope this helps!

Thanks for reading!

author: hmloo | Posted On Tuesday, October 16, 2012 1:55 PM | Comments (3)

Web optimization


1. CSS Optimization

Organize your CSS code

Good CSS organization helps with future maintainability of the site, it helps you and your team member understand the CSS more quickly and jump to specific styles.

Structure CSS code

For small project, you can break your CSS code in separate blocks according to the structure of the page or page content. for example you can break your CSS document according the content of your web page(e.g. Header, Main Content, Footer)

Structure CSS file

For large project, you may feel having too much CSS code in one place, so it's the best to structure your CSS into more CSS files, and use a master style sheet to import these style sheets. this solution can not only organize style structure, but also reduce server request.

/*--------------Master style sheet--------------*/
@import "Reset.css";
@import "Structure.css";
@import "Typography.css";
@import "Forms.css";
Create index for your CSS

Another important thing is to create index at the beginning of your CSS file, index can help you quickly understand the whole CSS structure.

/*----------------------------------------
1. Header
2. Navigation
3. Main Content
4. Sidebar
5. Footer
------------------------------------------*/
Writing efficient CSS selectors

keep in mind that browsers match CSS selectors from right to left and the order of efficiency for selectors

1. id (#myid)
2. class (.myclass)
3. tag (div, h1, p)
4. adjacent sibling (h1 + p)
5. child (ul > li)
6. descendent (li a)
7. universal (*)
8. attribute (a[rel="external"])
9. pseudo-class and pseudo element (a:hover, li:first)

the rightmost selector is called "key selector", so when you write your CSS code, you should choose more efficient key selector. Here are some best practice:

Don't tag-qualify

Never do this:

div#myid
div.myclass
.myclass#myid

IDs are unique, classes are more unique than a tag so they don't need a tag. Doing so makes the selector less efficient.

Avoid overqualifying selectors

for example

#nav a

is more efficient than

ul#nav li a


Don't repeat declaration
Example:

body {font-size:12px;}
h1 {font-size:12px;font-weight:bold;}

since h1 is already inherited from body, so you don't need to repeate atrribute.

Using 0 instead of 0px

Always using #selector { margin: 0; } There’s no need to include the px after 0, removing all those superfluous px can reduce the size of your CSS file.

Group declaration
Example:
h1
{
    font-size: 16pt;
}

h1
{
    color: #fff;
}

h1
{
    font-family: Arial, sans-serif;
}

it’s much better to combine them:

h1
{
    font-size: 16pt;
    color: #fff;
    font-family: Arial, sans-serif;
}
Group selectors
Example:
h1
{
    color: #fff;
    font-family: Arial, sans-serif;
}

h2
{
    color: #fff;
    font-family: Arial, sans-serif;
}

it would be much better if setup as:

h1, h2
{
    color: #fff;
    font-family: Arial, sans-serif;
}

Group attribute
Example:
h1
{
    color: #fff;
    font-family: Arial, sans-serif;
}

h2
{
    color: #fff;
    font-family: Arial, sans-serif;
    font-size: 16pt;
}

you can set different rules for specific elements after setting a rule for a group

h1, h2
{
    color: #fff;
    font-family: Arial, sans-serif;
}

h2
{
    font-size: 16pt;
}

Using Shorthand Properties
Example:
#selector
{   
 margin-top: 8px;  
 margin-right: 4px;  
 margin-bottom: 8px;  
 margin-left: 4px;
}

Better:
#selector
{  
 margin: 8px 4px 8px 4px;
}

Best:
#selector
{   
 margin: 8px 4px;
}

a good diagram illustrated how shorthand declarations are interpreted depending on how many values are specified for margin and padding property.

Untitled

instead of using:

#selector
{   
  background-image: url(”logo.png”);
  background-position: top left;
  background-repeat: no-repeat;
}

is used:

#selector
{   
  background: url(logo.png) no-repeat top left;
}

2. Image Optimization

Image Optimizer

Image Optimizer is a free Visual Studio2010 extension that optimizes PNG, GIF and JPG file sizes without quality loss. It uses SmushIt and PunyPNG for the optimization. Just right click on any folder or images in Solution Explorer and choose optimize images, then it will automatically optimize all PNG, GIF and JPEG files in that folder.

CSS Image Sprites

CSS Image Sprites are a way to combine a collection of images to a single image, then use CSS background-position property to shift the visible area to show the required image, many images can take a long time to load and generates multiple server requests, so Image Sprite can reduce the number of server requests and improve site performance.
You can use many online tools to generate your image sprite and CSS, and you can also try the Sprite and Image Optimization framework released by The ASP.NET team.

author: hmloo | Posted On Thursday, September 13, 2012 2:18 PM | Comments (2)

How to Implement Single Sign-On between Websites


Introduction

Single sign-on (SSO) is a way to control access to multiple related but independent systems, a user only needs to log in once and gains access to all other systems. a lot of commercial systems that provide Single sign-on solution and you can also choose some open source solutions like Opensso, CAS etc. both of them use centralized authentication and provide more robust authentication mechanism, but if each system has its own authentication mechanism, how do we provide a seamless transition between them. Here I will show you the case.

How it Works

The method we’ll use is based on a secret key shared between the sites. Origin site has a method to build up a hashed authentication token with some other parameters and redirect the user to the target site.

variables Status Description
ssoEncode required hash(ssoSharedSecret + , + ssoTime + , + ssoUserName)
ssoTime required timestamp with format YYYYMMDDHHMMSS used to prevent playback attacks
ssoUserName required unique username; required when a user is logged in

Note : The variables will be sent via POST for security reasons

Building a Single Sign-On Solution

Origin Site has function to
1. Create the URL for your Request.
2. Generate required authentication parameters
3. Redirect to target site.

using System;
using System.Web.Security;
using System.Text;

public partial class _Default : System.Web.UI.Page 
{
    protected void Page_Load(object sender, EventArgs e)
    {
        string postbackUrl = "http://www.targetsite.com/sso.aspx";
        string ssoTime = DateTime.Now.ToString("yyyyMMddHHmmss");
        string ssoUserName = User.Identity.Name;
        string ssoSharedSecret = "58ag;ai76"; // get this from config or similar
        string ssoHash = FormsAuthentication.HashPasswordForStoringInConfigFile(string.Format("{0},{1},{2}", ssoSharedSecret, ssoTime, ssoUserName), "md5");
        string value = string.Format("{0}:{1},{2}", ssoHash,ssoTime, ssoUserName);
        Response.Clear();
        StringBuilder sb = new StringBuilder();
        sb.Append("<html>");
        sb.AppendFormat(@"<body onload='document.forms[""form""].submit()'>");
        sb.AppendFormat("<form name='form' action='{0}' method='post'>", postbackUrl);
        sb.AppendFormat("<input type='hidden' name='t' value='{0}'>", value);
        sb.Append("</form>");
        sb.Append("</body>");
        sb.Append("</html>");
        Response.Write(sb.ToString());
        Response.End();

    }
}

Target Site has function to
1. Get authentication parameters.
2. Validate the parameters with shared secret.
3. If the user is valid, then do authenticate and redirect to target page.
4. If the user is invalid, then show errors and return.

using System;
using System.Web.Security;
using System.Text;

public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            if (User.Identity.IsAuthenticated)
            {
                Response.Redirect("~/Default.aspx");
            }
        }
        if (Request.Params.Get("t") != null)
        {
            string ticket = Request.Params.Get("t");
            char[] delimiters = new char[] { ':', ',' };
            string[] ssoVariable = ticket.Split(delimiters, StringSplitOptions.None);
            string ssoHash = ssoVariable[0];
            string ssoTime = ssoVariable[1];
            string ssoUserName = ssoVariable[2];
            DateTime appTime = DateTime.MinValue;
            int offsetTime = 60; // get this from config or similar
            try
            {
                appTime = DateTime.ParseExact(ssoTime, "yyyyMMddHHmmss", null);
            }
            catch
            {
                //show error
                return;
            }
            if (Math.Abs(appTime.Subtract(DateTime.Now).TotalSeconds) > offsetTime)
            {
                //show error
                return;
            }
            bool isValid = false;
            string ssoSharedSecret = "58ag;ai76"; // get this from config or similar
            string hash = FormsAuthentication.HashPasswordForStoringInConfigFile(string.Format("{0},{1},{2}", ssoSharedSecret, ssoTime, ssoUserName), "md5");
            if (string.Compare(ssoHash, hash, true) == 0)
            {
                if (Math.Abs(appTime.Subtract(DateTime.Now).TotalSeconds) > offsetTime)
                {
                    //show error
                    return;
                }
                else
                {
                    isValid = true;
                }
            }
            if (isValid)
            {
                //Do authenticate;
            }
            else
            {
                //show error
                return;
            }
        }
        else
        {
            //show error
        }
    }
}

Summary

This is a very simple and basic SSO solution, and its main advantage is its simplicity, only needs to add a single page to do SSO authentication, do not need to modify the existing system infrastructure.

author: hmloo | Posted On Monday, July 9, 2012 7:42 PM | Comments (2)

My Generation Drivers DropdownList Empty


I just installed MyGeneration 1.3.1 on my Windows Vista, and when I try to setup the default settings there are no drivers to select from. but it's OK in my Windows XP machine. At last I got the answers from search engine, it is caused by multi .Net Frameworks coexist and MyMeta.dll is registered by the .Net v2.0 while it should be registered with the .Net v4.0. So we have to manually register the dll. Please follow these steps:
1. Run Visual Studio Command Prompt (2010) with "Run as Administrator".
2. Enter the command "regasm.exe "C:\Program Files\MyGeneration13\MyMeta.dll" /tlb: MyMeta.tlb"
3. Exit Command Prompt when successfully registered.
4. Run MyGeneration and the proplem should be disapear.
Hope this helps.
Thanks for reading.

author: hmloo | Posted On Sunday, July 1, 2012 4:57 PM | Comments (1)

Encryption and Decryption in the .NET Framework


What Is Symmetric Encryption?

 

image

Symmetric encryption uses the same key for both encryption and decryption.

Symmetric Algorithm in the .NET Framework

SymmetricAlgorithm

What Is Asymmetric Encryption?

image

Asymmetric cryptography uses separate keys for encryption and decryption

Encrypted Text with public key can be decrypted only with the private key

Asymmetric Algorithm in the .NET Framework

AsymmetricAlgorithm,

Hash Algorithm

 image

 

Has Algorithm in the .NET Framework

HashAlgorithm 

What is Digital Signature?

 

image

 

Hash + Asymmetric Encryption = Digital Signature

author: hmloo | Posted On Wednesday, May 23, 2012 2:37 PM | Comments (0)

How to remove the last character from Stringbuilder


We usually use StringBuilder to append string in loops and make a string of each data separated by a delimiter. but you always end up with an extra delimiter at the end. This code sample shows how to remove the last delimiter from a StringBuilder.

using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;

class Program
{
    static void Main()
    {
        var list =Enumerable.Range(0, 10).ToArray();
        StringBuilder sb = new StringBuilder();
        foreach(var item in list)
        {
            sb.Append(item).Append(",");
        }
        sb.Length--;//Just reduce the length of StringBuilder, it's so easy
        Console.WriteLine(sb);
    }
}

//Output : 0,1,2,3,4,5,6,7,8,9

Alternatively,  we can use string.Join for the same results, please refer to blow code sample.

using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;

class Program
{
    static void Main()
    {
        var list = Enumerable.Range(0, 10).Select(n => n.ToString()).ToArray();
        string str = string.Join(",", list);
        Console.WriteLine(str);
    }
}

author: hmloo | Posted On Sunday, April 8, 2012 12:12 PM | Comments (2)

How to create Checkboxes that act like Radio buttons with Jquery


I have a post here to show code examples for check/uncheck all checkbox with Jquery. This time I will implement another request that the user should only be able to check at most one of the checkboxes, it's behave like radio buttons.

There are 2 cases. Case 1 shows function that has little difference with radio button. It allows the user to deselect checkbox. Case 2 is same as radio button.

Case 1

<head id="Head1" runat="server"> 
    <title></title> 
    <script src="Scripts/jquery-1.4.1.min.js" type="text/javascript"></script> 
    <style type="text/css"> 
           .cbRowItem {display:block;} 
     </style> 
    <script type="text/javascript"> 
    $(document).ready(function() 
    { 
        var $chk = $('input:checkbox .cbRowItem'); 
        $chk.click(function() 
        { 
            $chk.not(this).removeAttr('checked'); 
        }); 
    }); 
  </script> 
</head> 
<body> 
    <form id="form1" runat="server"> 
    <div style="display:block;"> 
    <asp:CheckBox id="CheckBox1" runat="server" class="cbRowItem" Text = "CheckBox 1"/> 
    <asp:CheckBox id="CheckBox2" runat="server" class="cbRowItem" Text = "CheckBox 2"/> 
    <asp:CheckBox id="CheckBox3" runat="server" class="cbRowItem" Text = "CheckBox 3"/> 
    <asp:CheckBox id="CheckBox4" runat="server" class="cbRowItem" Text = "CheckBox 4"/> 
    </div> 
    </form> 
</body> 
</html>

Case 2

<head id="Head1" runat="server">
    <title></title>
    <script src="Scripts/jquery-1.4.1.min.js" type="text/javascript"></script>
    <style type="text/css">
           .cbRowItem {display:block;}
     </style>
    <script type="text/javascript">
    $(document).ready(function()
    {
        var $chk = $('input:checkbox .cbRowItem'); 
        $chk.click(function()
        {
            $chk.removeAttr('checked');
            $(this).attr('checked', 'checked');
        });
    });
  </script>
</head>
<body>
    <form id="form1" runat="server">
    <div style="display:block;">
    <asp:CheckBox id="CheckBox1" runat="server" class="cbRowItem" Text = "CheckBox 1"/>
    <asp:CheckBox id="CheckBox2" runat="server" class="cbRowItem" Text = "CheckBox 2"/>
    <asp:CheckBox id="CheckBox3" runat="server" class="cbRowItem" Text = "CheckBox 3"/>
    <asp:CheckBox id="CheckBox4" runat="server" class="cbRowItem" Text = "CheckBox 4"/>
    </div>
    </form>
</body>
</html>

author: hmloo | Posted On Thursday, March 22, 2012 1:22 PM | Comments (0)

Replace broken image with noimage icon using Jquery


Sometimes when the image isn't available on server, the web page will show a broken image. so we can display a "no image available" image for good user experience. I will implement it using Jquery.

$(document).ready(function()
{
    $("img").error(function()
    {
        $(this).hide();
    })
    .attr("src", "noimage.jpg");
});

Please note that we must first hide the broken image, or else even if we set the src to noimage, it still can not show  noimage icon.

author: hmloo | Posted On Tuesday, March 20, 2012 7:23 PM | Comments (0)

The device is not ready


When you retrieve the drive info using the DriveInfo class, if you don't use the IsReady property to test whether a drive is ready, it will throw error as "The device is not ready". so you must use IsReady property to determines if the drive is ready to be queried, written to, or read from. The following code example demonstrates querying information for all drives on current system.

using System;
using System.IO;

class Test
{
    public static void Main()
    {
        DriveInfo[] allDrives = DriveInfo.GetDrives();

        foreach (DriveInfo d in allDrives)
        {
            Console.WriteLine("Drive {0}", d.Name);
            Console.WriteLine("  File type: {0}", d.DriveType);
            if (d.IsReady == true)
            {
                Console.WriteLine("  Volume label: {0}", d.VolumeLabel);
                Console.WriteLine("  File system: {0}", d.DriveFormat);
                Console.WriteLine(
                    "  Available space to current user:{0, 15} bytes", 
                    d.AvailableFreeSpace);

                Console.WriteLine(
                    "  Total available space:          {0, 15} bytes",
                    d.TotalFreeSpace);

                Console.WriteLine(
                    "  Total size of drive:            {0, 15} bytes ",
                    d.TotalSize);
            }
        }
    }
}

author: hmloo | Posted On Sunday, March 18, 2012 6:16 PM | Comments (0)