Tuesday, 24 February 2009

Managing ASP.NET Navigation

by Mike Gunderloy
04/08/2003

In an ASP.NET application, you can move between Web Forms in a variety of ways: with hyperlinks, with Response.Redirect, with Server.Transfer, or with Server.Execute. In this article, I will take a look at these various navigation methods and help you choose the appropriate one for your application.

Hyperlinks

The simplest possible way to navigate from one Web Form to another is with an HTML hyperlink control. On a Web Form, that might look like this:

<a href="WebForm2.aspx">WebForm2</a>

When the user clicks on the hyperlink, WebForm2.aspx is served up to their browser. You can use this technique just about anywhere, including on HTML pages and in classic ASP. ASP.NET gives you another alternative, the HyperLink Web Server control:

<form id="Form1" method="post" runat="server">
    <asp:HyperLink id="HyperLink1" runat="server"
    NavigateUrl="WebForm2.aspx">WebForm2</asp:HyperLink>
</form>

At runtime, this HTML has exactly the same effect as the first example, since ASP.NET renders the HyperLink Web Server control as an HTML hyperlink control. There is one key difference, though: the Web Server control can be programmed on the server side. In particular, you can change its NavigateUrl property in code, opening up the possibility of a hyperlink whose destination depends on some part of your application's state:

Private Sub Button1_Click( _ 
    ByVal sender As System.Object, _
    ByVal e As System.EventArgs) _
        Handles Button1.Click 
        HyperLink1.NavigateUrl = "WebForm3.aspx" 
End Sub

If the user clicks on the hyperlink after this code has executed, then the link will serve up WebForm3.aspx instead of WebForm2.aspx.

Controlling Transfers Yourself

Although hyperlinks do transfer your application from one page to another, they do so completely under the control of the user. Sometimes it's convenient to control the entire process in code yourself, including deciding when to move to another page. As it happens, ASP.NET provides three different methods to accomplish this. You can call the Redirect method of the Response object, or the Transfer or Execute methods of the Server object. Although they behave very similarly, there are differences between these three methods.

Response.Redirect

The Response.Redirect method causes the browser to connect to a specified URL. When the Response.Redirect() method is called, it creates a response whose header contains a 302 (Object Moved) status code and the target URL. When the browser receives this response from the server, it uses this header information to generate another HTTP request to the new URL. When using the Response.Redirect method, the redirection happens at the client side and involves two round trips to the server: one to request the original page, which is met by the 302 response, and then a second to request the redirected page.

Server.Transfer

The Server.Transfer method transfers execution from the current ASPX file to another ASPX file on the same web Server. When your code calls the Server.Transfer method, the current ASPX page terminates execution and the flow of control is transferred to another ASPX page. The new ASPX page still uses the response stream created by the prior ASPX page. When you use this method to navigate between pages, the URL in the browser still shows the original page, because the redirection occurs on the server side and the browser remains unaware of the transfer.

By default, the Server.Transfer method does not pass the form data or the query string of the original page request to the transferred page. But you can preserve the form data and query string of the original page by setting the optional second argument of the method to True. When you use this technique, though, you need to aware of one thing: the destination page uses the same response stream that was created by the original page, and therefore the hidden _VIEWSTATE field of the original page ends up on the second page. This causes the ASP.NET machine authentication check (MAC) to assume that the ViewState of the new page has been tampered with. Therefore, when you choose to preserve the form and query string collection of the original page, you must set the EnableViewStateMac attribute of the Page directive to False for the destination page.

Server.Execute

The Server.Execute method allows the current ASPX page to execute a specified ASPX page on the same web server. After the specified ASPX page is executed, the control transfers back to the original page from which the Server.Execute method was called. This technique of page navigation is analogous to making a function call to an ASPX page. The called ASPX page has access to the form and query string collections of the calling page, and thus you need to set the EnableViewStateMac attribute of the Page directive to False on the executed page.

By default, the output of the executed page is added to the current response stream. This method also has an overloaded version in which the output of the redirected page can be fetched in a TextWriter object (or one of its children, such as a StringWriter object) instead of added directly to the response stream. This helps you to control where to place the output in the original page.

To see how this works, create a Web Form in a test ASP.NET application and place a Button control (Button1) and a Literal control (Literal1) on the Web Form. Switch to code view and add an Imports statement for the System.IO namespace. Then add code to execute when the user clicks the button:

Private Sub Button1_Click( _
    ByVal sender As System.Object, _
    ByVal e As System.EventArgs) _
        Handles Button1.Click
        Dim sw As StringWriter = New StringWriter()
        Server.Execute("WebForm2.aspx", sw)
        Literal1.Text = sw.ToString()
End Sub

Now create a second Web Form in the same application, WebForm2.aspx. Switch to the HTML view of this second Web Form and modify its Page directive to disable ViewState checking:

<%@ Page Language="vb" AutoEventWireup="false" Codebehind="WebForm2.aspx.vb"
  Inherits="Navigate.WebForm2" EnableViewStateMac="false"%>

Switch back to design view and add some controls to the second Web Form. Now set the first Web Form as the default page and start the application. Click the button, and the controls from WebForm2 will be displayed in the area of WebForm1 where you placed the Literal control, as shown in Figure 1. You'll note from the URL and page title that the browser is still displaying WebForm1.

Screen shot.
Figure 1: A page in the browser composed by using Server.Execute to combine two source files.

There's one more thing to be aware of when you use the Server.Transfer or Server.Execute methods to navigate: the ultimate page may not be valid HTML. That's because the response to the client will contain multiple <html> and <body> tags, among other tags. Internet Explorer seems to tolerate this situation just fine, but you may want to test the results carefully if your users prefer a different browser.

Decisions, Decisions

So, given these choices for navigating from page to page, how do you select the appropriate one for your application? Here are some things to think about:

  • Hyperlinks are appropriate when you want the end user to control when navigation is performed, or to choose where to go.
  • To control the user's destination, but let them decide when to get there, use a Web Server HyperLink control whose NavigateUrl property is dynamically set.
  • Use Response.Redirect to connect to resources outside of the web server where your page is hosted.
  • Use Response.Redirect to connect to non-ASPX resources such as HTML pages.
  • Use Response.Redirect if you need to preserve a query string as an explicit part of the URL.
  • When you want to transfer control to an ASPX page residing on the same web server, you should use Server.Transfer instead of Response.Redirect because Server.Transfer will avoid the unnecessary round trip and provide better performance and a better user experience.
  • To capture the output from an ASPX page and display it at a specified location on another ASPX page, use Server.Execute.
  • If valid HTML output is essential, use Response.Redirect instead of either the Server.Transfer or Server.Execute methods.

Mike Gunderloy is the lead developer for Larkware and author of numerous books and articles on programming topics.

Monday, 23 February 2009

How to make a self-adapting size iframe

I didn't test the code on any browser yet, so if you tried and found any issue please leave a comment here. THX

<iframe id="iFrame1" name="iFrame1" width="100%" 
onload="this.height=iFrame1.document.body.scrollHeight" frameborder="0" src="index.htm">
</iframe>

Thursday, 5 February 2009

How to create WCF service manually

This article will show you how to create a WCF service by hand instead of the VS IDE. The reason of doing so is we can get rid of all the rubbish code created by VS and also it will help us understand more the infrastructure of WCF skills.

To build a WCF service manually we will create 5 assemblies:
1, Contract
2, Service
3, Host
4, ClientProxy
5, Client/WebClient

The Contract assembly (a class library) is the core of a particular WCF service. All the other 4 assemblies need a reference to this Contract.dll. The Contract assembly need a reference to System.ServiceModel so it can use all the related attributes: ServiceContract, OperationContract etc etc.

The Service assembly (a class library) includes the implementation of all the Contract Interfaces. You no need reference to System.ServiceModel for this assembly.

Now we are going to finish our first WCF service. To do so we need create a host. The Host assembly (a console app) will reference to Contract, Service, System.ServiceModel dlls and will need a Service configuration file. Below is a very sample config including two endpoints (using net.tcp and http proxy)
//Config file
<configuration>
  <system.serviceModel>
    <services>
      <service name="WcfTraining.Service.MyFirstService">
        <endpoint address="net.tcp://localhost:4002/MyFirstService"
                  binding="netTcpBinding"
                  contract="WcfTraining.Service.IHelloService"></endpoint>
        <endpoint address="http://localhost:9002/MyFirstService"
                          binding="wsHttpBinding"
                          contract="WcfTraining.Service.IHelloService"></endpoint>
      </service>
    </services>
  </system.serviceModel>
</configuration>


//Code behind
ServiceHost serviceHost = new ServiceHost(typeof(MyFirstService), 
        new Uri("net.tcp://localhost:9002/"));
serviceHost.Open();

Now you can run this Host app and a WCF service is online immediately. How easy it is. Warming: the <configSections> tag has to be always the first tag in the configure file.

Note: the second param of the ServiceHost method IMO is used to test if the Uri address is available. It could be any valid Uri address but if it is not exited in your endpoint list then it means nothing to client.

When the service is runing it is time to build our client. The first thing we need do is build a ClientProxy assembly which is a class library referenced the Contract and System.ServiceModel assemblies. Inside we simply implement the Contract Interface and inherit a generic class CProxy<Interface> which supply a ChannelFactory instance, which is used to communicate with the service. For example if we have a service named GetMessage and we are inheriting from System.ServiceModel’s inner Proxy ClientBase<> then the code will simply be:
    public class Proxy : ClientBase<IHelloService>, IHelloService
    {
        public string GetMessage(string name)
        {
            return Channel.GetMessage(name);
        }
    }

We are almost there now. The final is build our own client which could be a win app, console app or web app. The client need reference the ClientProxy, Contract and System.SerivceModel assemblies. And also the Client need a config file to tell where the service is runing. Please remembet there should be only one endpoint inside the client config file. Below is a client config sample.
  <system.serviceModel>
    <client>
      <endpoint address="net.tcp://localhost:4002/MyFirstService"
                binding="netTcpBinding"
                contract="WcfTraining.Service.IHelloService" />
    </client>
  </system.serviceModel>

Remember the abc in the config file: address, binding and Contract. Inside the Client class, simply create a instance of ClientProxy and directly call any service method you want. All Done.
Proxy proxy = new Proxy();
MessageBox.Show(proxy.GetMessage(textBox1.Text));

Sunday, 21 December 2008

Recommended web 2.0 colour schemes

There is a flash colour scheme generator named ColorToy 2.0: http://www.defencemechanism.com/color/



Also there are 14 colour schemes from: http://zcool.com.cn/color/20070623/color_0623J52007.html

073340007334010733402073340307334040733405073340607334070733408073340907334010073340110733401207334013

Tuesday, 16 December 2008

Differences Between XHTML And HTML

First of all, when we are talking about XHTML it is actually XHTML 1.0. When using VS2008 to create HTML/ASP.NET page the default DOCTYPE details are:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
The Most Important Differences between XHTML and HTML are:
  • XHTML elements must be properly nested.
  • XHTML elements must always be closed, for example "</p>". If tag is empty it should be self-closed, like this: "<br />".
  • XHTML elements must be in lowercase, including property names.
  • XHTML property value should always be quoted.
  • Use id instead of name to identify a XHTML element.
  • the script should be embraced by CDATA section.

Sunday, 14 December 2008

The most popular Web 2.0 color palette

Followed are two sets of web 2.0 color palette. Click the image will open the 1:1 size image.



Tuesday, 9 December 2008

C#: The best way to reverse a string

3 lines simple code here:
string ReverseString (string text)
{
    char[] _ch = text.ToCharArray();
    Array.Reverse(_ch);
    return new string(_ch);
}

Monday, 1 December 2008

C#: struct vs class

The differences between struct and class:
1, struct is value type, allocate space from stack. And class is reference type, allocate space from heap.
2, struct cannot inherit from the other struct or class, only can inherit interfaces. And struct can't be inherited because it is implicit sealed. But class can do them all. Also because the struct is sealed then all its members can't be protected.
3, struct can't have parameterless constructor, but class can
4, the default modifier of struct is public but for class it is private.
5, in struct there is no initializer, but class can. See code below.

public struct myStruct
{
    public myStruct(){}; //compile error
    public string s = "abc"; //compile error
}

Monday, 24 November 2008

JavaScript: How to get the actual page size – cross-browser solution

The code below shows you a way to get the page size from even IE5.5. Since IE6, all the popular browsers have been supporting document.documentElement object, so only browser older than IE6 will be using the else code block.

function getPageSize(doc) {
    var re = {};
    if (doc.documentElement && doc.documentElement.clientHeight) {
        var root = doc.documentElement;
        re.width = (root.clientWidth > root.scrollWidth)
                                     ? root.clientWidth : root.scrollWidth;
        re.height = (root.clientHeight > root.scrollHeight)
                                     ? root.clientHeight : root.scrollHeight;
    }
    else {
        var root = doc.body;
        re.width = (window.innerWidth > root.scrollWidth)
                                     ? window.innerWidth : root.scrollWidth;
        re.height = (window.innerHeight > root.scrollHeight)
                                     ? window.innerHeight : root.scrollHeight;
    }
    return re;
}

The return object re is a JSON object and you can directly use re.width and re.height to get the values.

Monday, 3 November 2008

All Regular Expression Characters and Meaning (Chinese)

The original article: http://yirlin.cnblogs.com/archive/2006/04/12/373222.html

字符 描述
\ 将下一个字符标记为一个特殊字符、或一个原义字符、或一个 向后引用、或一个八进制转义符。例如,'n' 匹配字符 "n"。'\n' 匹配一个换行符。序列 '\\' 匹配 "\" 而 "\(" 则匹配 "("。
^ 匹配输入字符串的开始位置。如果设置了 RegExp 对象的 Multiline 属性,^ 也匹配 '\n' 或 '\r' 之后的位置。
$ 匹配输入字符串的结束位置。如果设置了RegExp 对象的 Multiline 属性,$ 也匹配 '\n' 或 '\r' 之前的位置。
* 匹配前面的子表达式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等价于{0,}。
+ 匹配前面的子表达式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}。
? 匹配前面的子表达式零次或一次。例如,"do(es)?" 可以匹配 "do" 或 "does" 中的"do" 。? 等价于 {0,1}。
{n} n 是一个非负整数。匹配确定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的两个 o。
{n,} n 是一个非负整数。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。
{n,m} m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}" 将匹配 "fooooood" 中的前三个 o。'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。
? 当该字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串 "oooo",'o+?' 将匹配单个 "o",而 'o+' 将匹配所有 'o'。
. 匹配除 "\n" 之外的任何单个字符。要匹配包括 '\n' 在内的任何字符,请使用象 '[.\n]' 的模式。
(pattern) 匹配 pattern 并获取这一匹配。所获取的匹配可以从产生的 Matches 集合得到,在VBScript 中使用 SubMatches 集合,在JScript 中则使用 $0…$9 属性。要匹配圆括号字符,请使用 '\(' 或 '\)'。
(?:pattern) 匹配 pattern 但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用 "或" 字符 (|) 来组合一个模式的各个部分是很有用。例如, 'industr(?:y|ies) 就是一个比 'industry|industries' 更简略的表达式。
(?=pattern) 正向预查,在任何匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,'Windows (?=95|98|NT|2000)' 能匹配 "Windows 2000" 中的 "Windows" ,但不能匹配 "Windows 3.1" 中的 "Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
(?!pattern) 负向预查,在任何不匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如'Windows (?!95|98|NT|2000)' 能匹配 "Windows 3.1" 中的 "Windows",但不能匹配 "Windows 2000" 中的 "Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始
x|y 匹配 x 或 y。例如,'z|food' 能匹配 "z" 或 "food"。'(z|f)ood' 则匹配 "zood" 或 "food"。
[xyz] 字符集合。匹配所包含的任意一个字符。例如, '[abc]' 可以匹配 "plain" 中的 'a'。
[^xyz] 负值字符集合。匹配未包含的任意字符。例如, '[^abc]' 可以匹配 "plain" 中的'p'。
[a-z] 字符范围。匹配指定范围内的任意字符。例如,'[a-z]' 可以匹配 'a' 到 'z' 范围内的任意小写字母字符。
[^a-z] 负值字符范围。匹配任何不在指定范围内的任意字符。例如,'[^a-z]' 可以匹配任何不在 'a' 到 'z' 范围内的任意字符。
\b 匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。
\B 匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。
\cx 匹配由 x 指明的控制字符。例如, \cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 'c' 字符。
\d 匹配一个数字字符。等价于 [0-9]。
\D 匹配一个非数字字符。等价于 [^0-9]。
\f 匹配一个换页符。等价于 \x0c 和 \cL。
\n 匹配一个换行符。等价于 \x0a 和 \cJ。
\r 匹配一个回车符。等价于 \x0d 和 \cM。
\s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。
\S 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。
\t 匹配一个制表符。等价于 \x09 和 \cI。
\v 匹配一个垂直制表符。等价于 \x0b 和 \cK。
\w 匹配包括下划线的任何单词字符。等价于'[A-Za-z0-9_]'。
\W 匹配任何非单词字符。等价于 '[^A-Za-z0-9_]'。
\xn 匹配 n,其中 n 为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,'\x41' 匹配 "A"。'\x041' 则等价于 '\x04' & "1"。正则表达式中可以使用 ASCII 编码。.
\num 匹配 num,其中 num 是一个正整数。对所获取的匹配的引用。例如,'(.)\1' 匹配两个连续的相同字符。
\n 标识一个八进制转义值或一个向后引用。如果 \n 之前至少 n 个获取的子表达式,则 n 为向后引用。否则,如果 n 为八进制数字 (0-7),则 n 为一个八进制转义值。
\nm 标识一个八进制转义值或一个向后引用。如果 \nm 之前至少有 nm 个获得子表达式,则 nm 为向后引用。如果 \nm 之前至少有 n 个获取,则 n 为一个后跟文字 m 的向后引用。如果前面的条件都不满足,若 n 和 m 均为八进制数字 (0-7),则 \nm 将匹配八进制转义值 nm。
\nml 如果 n 为八进制数字 (0-3),且 m 和 l 均为八进制数字 (0-7),则匹配八进制转义值 nml。
\un 匹配 n,其中 n 是一个用四个十六进制数字表示的 Unicode 字符。例如, \u00A9 匹配版权符号 (?)。

Tuesday, 28 October 2008

SQL: Basic Transact-SQL commands and syntax

This article is not suppose to make you become a Transact-SQL export, instead it is only suppose to make me don't look like a idiot when reading a SQL Stored Procedure. In that perspective I wrote this article which covered some basic but very often used SQL syntax and command.

1st of all, how to declare variables. The followed code declared a integer, a string and a record-set point:

DECLARE @Counter int
DECLARE @RegionName NVARCHAR(510)
DECLARE @RegionId TABLE (RegionId int)


2nd of al, let’s take a look how to create code block, a classic sample will be like this:

BEGIN TRY 
  BEGIN TRAN
    IF NOT EXIST (SELECT ...) –- make your condition here
    BEGIN
      -- do your stuff here 
    END
  COMMIT
END TRY
BEGIN CATCH
  IF @@Trancount >0
    ROLLBACK

  DECLARE @err VARCHAR(500)
  SET @err = ERROR_MESSAGE()
  RAISERROR (@err, 16, 1)
END CATCH

GO

Above is a complete cycle when you are trying to do some database operation with Transaction cooperation. We begin a TRY block first (if there is error the CATCH block will catch it), and inside the TRY block we can do anything we want, in this case, typically we put a IF BEGIN END block here. In the CATCH block we first try to ROLLBACK all the changes we made first by check the @@Trancount value to see if there is any Transaction started, and then we raise a error message out.

3rd of all, what does the GO sentence do? GO is not a Transact-SQL statement, it just simply signals the end of a batch of Transact-SQL statements. No any Transact-SQL statement can occupy the same line as a GO command but the comments.

In another word, GO marked a end of a T-SQL batch, after the GO any variable will be brand new and unknown. Here is a example from MSDN:

USE pubs
GO

DECLARE @MyMsg VARCHAR(50)
SELECT @MyMsg = 'Hello, World.'
GO
-- @MyMsg is not valid after this GO ends the batch.

-- Yields an error because @MyMsg not declared in this batch.
PRINT @MyMsg
GO


4th of all, a good stuff, SET IDENTITY_INSERT. Allows explicit values to be inserted into the identity column of a table. As you know after you set the table identity field to auto increasing integer you can insert a record with a particular id value any more. But by swtich on/off the IDENTITY_INSERT you can do it.

SET IDENTITY_INSERT MyTable ON
  -- Insert records with any id value you want
SET IDENTITY_INSERT MyTable OFF


5th of all, create and delete a table in T-SQL:

-- Create products table.
CREATE TABLE products (id int IDENTITY PRIMARY KEY, product varchar(40))
GO

-- Drop products table.
DROP TABLE products
GO 


6th of all, some useful methods you can use in your SQL:

* ISNULL ( check_expression , replacement_value ) , Replaces NULL with the specified replacement value.
* COALESCE ( expression [ ,...n ] ) , Returns the first non null expression among its arguments.
* GETDATE, Returns the current system date and time in the SQL Server standard internal format for date-time values.
…


Then followed is a example to show you how to change current existed table's structure.

If NOT EXISTS ( SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='HighlightBox'
                and COLUMN_NAME='EndPrice' )
BEGIN
  ALTER TABLE HighlightBox ADD EndPrice decimal(10,2) NULL
  ALTER TABLE HighlightBox WITH CHECK ADD CONSTRAINT FK_HighlightBox_TicketAvailabilityID
        FOREIGN KEY(TicketAvailabilityID)
        REFERENCES Ticket_Availability (Ticket_Availability_Id)
END
GO


Finally, there are some rules from MSDN apply to T-SQL batches:

* CREATE DEFAULT, CREATE FUNCTION, CREATE PROCEDURE, CREATE RULE, CREATE TRIGGER, and CREATE VIEW statements cannot be combined with other statements in a batch. The CREATE statement must begin the batch. All other statements that follow in that batch will be interpreted as part of the definition of the first CREATE statement.

* A table cannot be altered and then the new columns referenced in the same batch.

* If an EXECUTE statement is the first statement in a batch, the EXECUTE keyword is not required. The EXECUTE keyword is required if the EXECUTE statement is not the first statement in the batch. Security Note Batch files may contain credentials stored in plain text. Credentials may be echoed to the user's screen during batch execution.

Tuesday, 21 October 2008

C#: Decimal type vs. Float and Double types

Have you ever wondered what is the difference between the .NET "decimal" data type and the similar "float" or "double" data types? Ever wonder when you should use one instead of other? This article is going to help you and myself to work these questions out.

First of all, take a look at the following C# code:

var f = 1.1f;
var dbl = 1.1;
var d = 1.1m;

Response.Write((f + 0.1f).ToString("e20"));
Response.Write("<br />");
Response.Write((dbl + 0.1).ToString("e20"));
Response.Write("<br />"); Response.Write((d + 0.1m).ToString("e20"));

Note: when you declare a float variable like float f = 1.1 you will receive a build error says type 'double' cannot be implicitly converted to type 'float'; use an 'F' suffix to create a literal of this type, which means any decimal without suffix will be created as a double type.

Now here is what the ouptput looks like:

1.20000005000000000000e+000
1.20000000000000020000e+000
1.20000000000000000000e+000

You can see the three results are all slightly different. Why is this? Also, why was 1.20000005 instead of the hard-coded 1.20000000? The reason is simple - we’re working on hardware that uses binary floating point representation as opposed to decimal representation. Binary floating point is really an approximation of the true decimal number because it is base two (binary) instead of base 10 (decimal).

The Decimal Type, instead, is simply a floating point type that is represented internally as base 10 instead of base two. Obviously with base 10 (our real-world numbering system) any decimal number can be constructed to the exact value without approximating. :) The Decimal type is really  really a software implementation of base 10 arithmetic.

Which Type Should I Use?

Since Decimal types are perfectly accurate and float’s are not, why would we still want to use the intrinsic float/double types? Short answer - performance. In my speed tests Decimal types ran over 20 times slower than their float counterparts.

So if you’re writing a financial application for a bank that has to be 100% accurate and performance is not a consideration, use the Decimal type. On the other hand, if you need performance and extremely small floating point variations don’t affect your program, stick with the float and double types.

Other Considerations

Another thing the Decimal type can do that the float and double types cannot is encode trailing zero’s. For example, there is a difference between 7.5 and 7.50 in the decimal type, but there is no way to represent this in a standard float/double. Let’s look at another example:

double dbl = 1.23 + 1.27;
Response.Write(string.Format("double: {0}", dbl));
Response.Write("<br />");
decimal d = 1.23m + 1.27m;
Response.Write(string.Format("decimal: {0}", d));

This output looks like this:

double: 2.5
decimal: 2.50

The first part that uses a double outputs 2.5, but the second one that uses a decimal outputs 2.50 - we didn’t even have to specify a format string in order to get that trailing zero. This could be very useful in applications that deal with dollar amounts.

Thursday, 16 October 2008

ASP.NET Error: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).

There is a chance sometimes you can get this HttpException: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>). Just like itself mentioned, if you check your aspx page you must can find some <% ... %> exception inside. There are two ways to fix it.

Option 1: move the code into any runat="server" tag, which means move the code into a server side html tag. The tag could be <head runat="server"></head>, or <form runat="server"></form>.

If you can’t put the code into any server side tag (it is wired if this happen :-) ) then there is Option 2:
Step 1: override the OnInit(), like this:

protected override void OnInit(EventArgs e)
{
    base.OnInit(e);
    Page.DataBind(); // Add this new line.
}

Then step 2, in your code replace all the <% … %> or <%= … %> to <%# … %>. Done. I will do more research and probably can tell you what actually happened very soon. -- The End

Tuesday, 14 October 2008

JavaScript: JavaScript Better Practices

There are some tips to make your JavaScript code runing faster.
  • Use "var" whenever a variable is to be declared
  • Reduce scopes (Try avoiding nesting functions or loops)
  • Avoid string concatenation, use Array instead - “push” each pieces of the string into array and then use “join” to get the complete string
  • Use less DOM element concatenation - concatenate everything into string/Array first, then assign to the DOM element
  • Introduce function delegate. This one is worth mentioning. When calling a function in a loop, delegate before the loop because JavaScript interpreter will use the function then as local variable and will not lookup in its scope chain for the function body in each iteration. Code:
    var delegate = myFunc; // myFunc is the function
    delegate(el1);
  • Introduct DOM elements and function caching. Similar to function delegation. Example:
    var divContentAppendChild = document.getElementById("div1").appendChild;

    for (var i = 0; i < count; i++)
        divContentAppendChild(element[i]);
  • Avoid using switch if possible, as JavaScript interpreter can’t optimize switch block.
The End. :)

The .NET Framework type to ADO.NET data type mappings

.NET Framework Type ADO.NET Database Type SQL Data Type
String Varchar Varchar()
String Nvarchar Nvarchar()
String NChar Nchar()
String NText NText
String Text Text
Double BigInt Float
DateTime DateTime Datetime
DateTime SmallDateTime Smalldatetime
Int Int Int
Int64 BigInt Bigint
Int16 SmallInt smallint
Byte[] Binary Binary()
Byte[] Image Image
Byte[] VarBinary Varbinary()
Byte TinyInt Tinyint
Bool Bit Bit
Decimal Decimal Decimal
Decimal Money Money
Decimal SmallMoney SmallMoney
Float Float Float
Guid UniqueIdentifier Uniqueidentifier
Real Real Real

Monday, 13 October 2008

ASP.NET MVC: First shoot, the ActionResult type

When I created my first MVC project I noticed this method named Index which is created automatically by MVC framework.

public ActionResult Index()
{
    // Add action logic here
    return View();
}

When you move mouse over the View() method you will see it returns a instance of ViewResult type but not a ActionResult type. The ViewResult type is actually inherited indirectly from ActionResult type. The complete inheritance structure is:

ActionResult
|
|--PartialViewResult
|
|----ViewResult

The whole story here is we created a Index action for current Controller which means when you just go to this website and don’t specify any page name you will go into this Index action. What this action does is initialize the page view and return a ViewResult object for MVC viewer to use.

Tuesday, 29 July 2008

AJAX: How to user Yahoo! Stock Quote CVS service

If you are trying to use AJAX skills to build your stock quote tool and are looking for some stock price feeds, then this article could help you a lot. :) The sample Yahoo! Stock Quote HTTP string looks like this: If you type in the HTTP address above to your browser address bar, it will return you a string like

20.745,-0.385,2590659
If you want the full information about the symbol, you can use **f=sl1d1t1c1ohgvj1pp2wern** instead. Don’t sweat, here comes the explanation for each letter (or letter-digit pair)

* s: the symbol name
* l: last value (or current price). If you use l alone, you will get back a string similar to Mar 22 - 31.26
* l1: (letter l and the number 1) to just get the last value of the symbol
* d: d alone will give you 0, while d1 will return the current date (e.g. 3/22/2007)
* t: t by itself will request the yahoo-generated chart. However, you will get back the chart image with a whole bunch of other HTML garbage, e.g. src=http://chart.yahoo.com/c//y/yhoo.gif" alt="Chart">
* t1: the time of last update, for example 4:00pm.
* c: the change amount. Can either be used as c or c1.
* o: opening value
* h: high value
* g: low value
* v: volume
* j: 52-week low.
* j1: the market cap. This is string like "42.405B" for $42 billion. Man… that can buy **a lot** of hamburger
* p: after hour price (?)
* p1: (?)
* p2: change percentage e.g. "-0.10%"
* w: 52-week range
* e: EPS (Earning per share)
* r: P/E (Prince/Earning) ratio
* n: Company name

Wednesday, 23 July 2008

How to build a popular 3 column HTML laytou

There is a very famous and very popular 2 or 3 columns html framework layout which used by IBM, Sony etc etc, and which is very easy to build and maintain. Below is the screen shot of the layout. The key skills are used in this structure are CSS float style and clear styles. The float style sets or retrieves on which side of the object the text will flow. The clear style sets or retrieves whether the object allows floating objects on its left side, right side, or both, so that the next text displays past the floating objects.

From the screen shot you can see to build the 3 columns we usually set the first two div columns' float style to left and the last one to right. By the way the 3 div areas will be listed horizontally and properly. Then we have to set the followed/next div (in the screen shot, DIV D) clear style to left or both.

The reason to use clear style
As you all know, the div element is a block element. But by set the float to left or right will change the div element to a inline object. In this case the DIV A, DIV B and DIV C are actually inline objects and DIV D is a block object. If don't set the DIV D's clear style to left or both the DIV D will be located at very top/left area inside the DIV MAIN and will be overlapped with DIV A, B and C.

If you don't like the clear style at all, there is a alternative way to set up this html layout, which is put the DIV A, B and C in a table element and you can get the same effect because the table will always auto reset its size to suit for all the element inside it and it is a block element too.

layout

Tuesday, 8 July 2008

Stupid syntax difference between IE and Firefox

When you are doing javascript/AJAX development you probably will add a very useful function trim() into build-in String object to return a copy of a string without both leading and trailing spaces. To do so you just need simply add one sentence in front of your js file. Below is the coding I used in my js framework.

function String.prototype.trim() {return this.replace(/(^\s*)|(\s*$)/g,"");};

Unfortunately this sentence only works on IE browser. It caused an error on Firefox which cost me one hour this afternoon to figure it out. after I changed the sentence to the syntax shown below a peaceful world came back again.

String.prototype.trim = function() {return this.replace(/(^\s*)|(\s*$)/g,"");};

It is painful to find out these tiny differences and it always lets me down. :(  But from the positive side, it makes you always use the standard syntax rule to build your project.

Wednesday, 2 July 2008

My AJAX framework v1.0

Nothing special. Create a new object wjAjax inside there is a XMLHttpRequest object named xmlhttp. And then you can call the function getData (method, url, params, async, func) which attached in wjAjax class. If you call the getData function by asynchronized way, the function will return true or false. But if you call the getData function by synchronized way it will directly return the XMLHttpRequest object for further using.

function wjAjax ()
{
  try
  {
    if (window.XMLHttpRequest)
    {
      this.xmlhttp = new window.XMLHttpRequest();
    }
    else if (window.ActiveXObject)
    {
      this.xmlhttp = new window.ActiveXObject("MSXML2.XMLHTTP.3.0");
      if (!this.xmlhttp)
        this.xmlhttp = new new window.ActiveXObject("MICROSOFT.XMLHTTP");
    }
  }
  catch (e) {return null;}
  this.isRunning = false;
  return this;
}

wjAjax.prototype.getData = getData;

function getData(method, url, params, async, func)
{
  if (this.isRunning) {return false;}
  if (!url) {return false;}
  if (async && !func) {return false;}
  var me = this; //alias of wjAjax object, for reference using in onreadystatechange method.
  method = method || "get";
  params = params || "";
  try
  {
    if (method.toLowerCase() == "get")
    {
      this.xmlhttp.open("get", url+"?"+params, async);
      params = null;
    }
    else if (method.toLowerCase() == "post")
    {
      this.xmlhttp.open("post", url, async);
      this.xmlhttp.setRequestHeader("Method", "POST "+url+" HTTP/1.1");
      this.xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    }
    if (async)
    {
      this.xmlhttp.onreadystatechange = function()
      {
        if (this.readyState == 4)
        {
          me.isRunning = false;
          if (this.status == 200) {func(this);}
          else {alert ("HTTP server error. The HTTP server response status code is " + this.status);}
        }
      }
    }
    this.isRunning = true;
    this.xmlhttp.send(params);
    if (!async)
      this.isRunning = false;
  }
  catch (e) {alert("Run time error: "+e.message); return false;}
  if (async)
    return true;
  else
    return this.xmlhttp;
}