Monday, August 31, 2009

Saving files from one website to another website.

This blog is based on my recent requirement where I had to save some image files from one website to another website. Lets see the requirement and the solution for the requirement.

Requirement

The requirement is as follows. The user will select a file which needs to be uploaded using a website (UploadFilesWebsite) and these selected files will be saved in another website (SaveFilesWebsite). Cross website posting of data. We all know it’ very easy to save files within the same site by making use of a file upload control and calling its SaveAs method. E.g. is pasted below.

fileUploadCntl.SaveAs(System.IO.Path.Combine(Server.MapPath("."), fileUploadCntl.FileName))

But in my case it was different, the file needs to be saved in a different website from the one from where file upload is done.

Solution

The problem was solved by making use of HttpWebRequest and HttpWebResponse object. Below is steps which are needed to solve this problem.

  • First create an ASPX file which will be capable of receiving any type of file stream and saving this stream to the required folder. This file should be created/placed in the website where you want to save the files, in my case it is “SaveFiles” website.
  • Create a HttpWebRequest object and pump the file content to the RequestStream of the HttpWebRequest object.
  • Get the response using the GetResponse method of the HttpWebRequest object. GetResponse will return a HttpWebResponse object.
  • Get the response stream from the HttpWebResponse object by executing the GetResponseStream method.

These are the steps which you need to follow to post file contents from one website to another. Lets see each one of these one by one.

Create an aspx file capable of saving request stream.

The first step is to create an aspx file which will be capable of saving a request stream. This file should be created and saved in the web site where you plan to save your file. This file will receive requests from other website for saving files in the website. So we will create this file in “SaveFiles” website and we will name it as SaveFile.asxp. After creating and saving the file go to the HTML source view of the file. It will look something like this.

<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="SaveFile.aspx.cs" Inherits="SaveFile" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
    </div>
    </form>
</body>
</html>

Remove the HTML source from the file leaving only the Page attribute. The page should look something like this.

<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="SaveFile.aspx.cs" Inherits="SaveFile" %>

Now lets go to the codebehind and do some coding to save the request stream. The codebehind (SaveFile.aspx.cs) file of SaveFile looks something like this.

using System;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;

public partial class SaveFile : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        try
        {
            /*Retrieving the file name from the headers in the request. */
            string fileName = System.IO.Path.Combine(Server.MapPath("."), Request.Headers["FileName"].ToString());
            using (System.IO.FileStream fileStream = System.IO.File.Create(fileName))
            {
                /*Getting stream from the Request object.*/
                using (System.IO.Stream stream = Request.InputStream)
                {
                    int byteStreamLength = (int)stream.Length;
                    byte[] byteStream = new byte[byteStreamLength];
                    /*Reading the stream to a byte array.*/
                    stream.Read(byteStream, 0, byteStreamLength);
                    /*Writing the byte array to the harddisk.*/
                    fileStream.Write(byteStream, 0, byteStreamLength);
                }
            }
            Response.Clear();
            /*Writing the status to the response.*/
            Response.Write("File successfully saved");
        }
        catch (Exception ex)
        {
            /*Writing the error message to the response stream.*/
            Response.Clear();
            Response.Write("Error: " + ex.Message);
        }
    }
}

From the above code one can see we are first retrieving the filename from Request object’ Headers property. We will shortly see how to send info in headers of a request. After getting the filename we are opening a file stream to flush the content to the hard disk. Once the file stream is successfully created, next, we are creating a stream by getting the InputStream of the Request object. The InputStream property of the Request object will hold the content which needs to be saved. In the next line we are reading the stream content to a byte array and finally passing the byte array to the FileStream object and writing/saving to a file. Once the file is successfully saved we are writing the status to the Response after clearing the Response. Also if there is any exception thrown while the file is saved the same is written to the Response.

So that’ about the page which will save the content in the desired filename. So now we will move to our next steps like creating the HttpWebRequest object and passing the file content to the SaveFile.aspx file to save it in the website.

Create an aspx page to upload the images.

The file which we will be creating will have the capability to upload files from the user’ hard disk and will send these file contents to the SaveFile.aspx page. The UploadFile.aspx will be created in a separate website/virtual directory called “UploadFiles” website. This aspx page will have a FileUpload control and a save button. So here is the HTML source of UploadFile.aspx.

<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="FileUpload.aspx.cs" Inherits="FileUpload" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
    </div>
       <asp:Label ID="lblMessage" runat="server"></asp:Label><br />
        <asp:FileUpload ID="fileUpload" runat="server" /><br />
        <asp:Button ID="btnSave" runat="server" Text="Save Files"
        onclick="btnSave_Click" />
    </form>
</body>
</html>

From the HTML you can see that we have an FileUpload control and a save button with an OnClick event handler. So that’ our simple UploadFile page. Now lets see the real action i.e. the place where the code to upload files and sending the content of these files to the SaveFile.aspx in “SaveFiles” website happen. So here is the click event of the save button where all the action takes place.

protected void btnSave_Click(object sender, EventArgs e)
{
        /*Creating the WebRequest object using the URL of SaveFile.aspx.*/
        System.Net.HttpWebRequest webRequest =
(System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create
("Http://Localhost/SaveFiles/SaveFile.aspx");
        webRequest.Method = "POST";
        webRequest.KeepAlive = false;
        /*Assigning the content type from the FileUpload control.*/
        webRequest.ContentType = fileUpload.PostedFile.ContentType;
        /*Creating the Header object.*/
        System.Net.WebHeaderCollection headers = new System.Net.WebHeaderCollection();
        headers.Add("FileName", fileUpload.FileName);
        /*Adding the header to the WebRequest object.*/
        webRequest.Headers = headers;
        /*Getting the request stream by making use of the GetRequestStream method of WebRequest object.*/
        using (System.IO.Stream stream = webRequest.GetRequestStream())//Filling request stream with image stream.
        {
            /*Writing the FileUpload content to the request stream.*/
            stream.Write(fileUpload.FileBytes, 0, fileUpload.FileBytes.Length);
        }
        /*Creating a WebResponse object by calling the GetResponse method of WebRequest object.*/
        using (System.Net.HttpWebResponse webResponse = (System.Net.HttpWebResponse)webRequest.GetResponse())
        {
            /*Retrieving the response stream from the WebResponse object by calling the GetResponseStream method.*/
            using (System.IO.StreamReader sr = new System.IO.StreamReader(webResponse.GetResponseStream()))
            {
                lblMessage.Text = sr.ReadToEnd();
            }
        }
}

In the above code first I am creating a WebRequest object by passing the URL of the page which will handle the saving mechanism. Once the WebRequest object is created next I am assigning the Method as POST. This is a very important step. If you don’t assign the method property it will default to “GET”. If you use “GET” as the method to send data then you will receive System.Net.ProtocolViolationException with the following message.

"Cannot send a content-body with this verb-type."

Once the method is set to “POST” we are setting the KeepAlive property to false. KeepAlive property will be responsible for maintaining a live connection. The next line we are setting the ContentType of the request. The content type can be easily retrieved by calling the ContentType property from PostedFile property of the FileUpload Control. Next line we are creating a WebHeaderCollection object to pass additional information in the headers of the request. You can see we are passing the file name as one of the header value. These header details are read in SaveFile.aspx. So if you want send some extra information you can do that using WebHeaderCollection. In the next few lines we are retrieving the request stream using the GetRequestStream method and then writing the contents of the selected file to request stream using the Write method of the Stream object. To pump the content of the chosen file we are making use of the FileBytes property of the FileUpload control. One can note that we are making use of the “using” statement quite a lot. To know more about the usefulness of the “using” statement you can refer my blog on using statement here.

Once the FileUpload contents are pumped to the request stream of the HttpRequest object in the next line I am creating the HttpWebResponse using the GetResponse method of the HttpWebRequest object. So what GetResponse does is that it sends a request to the Url (savefile.aspx) specified while creating the HttpWebRequest object. When the HttpWebRequest object sends request to the url its similar to the way we access url through the browser. So the whole life cycle of the page executes and response is saved in the form of HttpWebResponse object. After getting the HttpWebResponse object we are reading what output was returned by the page using the StreamReader object’ ReadToEnd method. You can retrieve the StreamReader object by calling the GetResponseStream method of the WebRequest object. The response which I am getting is directly assigned to the Text property of a label control. What we get in the ResponseStream object is what we have written to the response using the Write method of the Response property in the SaveImage.aspx page. So if the image is successfully saved we get “File Successfully saved” as the response else we get error as the response.

That’ it, we are done. With this technique we can save files or contents from one website to another site i.e. cross website posting of data. This technique is very simple but can be very dangerous. You should make sure that you implement some sort of authentication so that hackers can be evaded from saving some malicious files.

Try to know more.

Sandeep

Monday, August 10, 2009

Creating RESTful web services in .NET

This blog is about creating RESTful web services using Windows Communicaiton Foundation (WCF) in .NET. The intention of this blog is not to teach what is Representation State Transfer (REST) but how to create web services which support REST by making use of WCF. So lets start by having a look at what was the requirement which prompted me to create a RESTful web service and how we did it.

As with any change in software, this change, to have RESTful web service was also raised by the client. The client in our case had some Business Access Layer (BAL) and he wanted to expose some of the methods to the outside world through RESTful web service. So what we did was we created a Facade layer to expose the required methods of the BAL and called exposed this Facade layer with the help of WCF web service. Thats the simple solution to our requirement. Now lets see the code wise implementation of the solution.

As per company rules and other client agreement I may not be able to publish the same implementation but will try to take another e.g. and try to replicate the same scenario and create RESTful web services. We will see two ways of creating WCF, one is implementing the interface in class file and then exposing the class methods using a .SVC file and second approach is the default way i.e. implementing an interface to a .SVC file. Lets see the first way (this was the solution implemented to solve our problem).

For creating a WCF service first thing you need is a contract. A contract is nothing but an Interface with the methods you want to expose. So lets create our contract (interface) which will be implemented by the WCF service. Any WCF webservice (RESTful or non RESTful) needs a contract, if no contract is defined then the class should be have the ServiceContract attribute to it and this is mandatory. Below is the interface definition.

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

namespace CarService
{
    [System.ServiceModel.ServiceContract]
    public interface ICarService
    {
       [System.ServiceModel.OperationContract] 
       [System.ServiceModel.Web.WebGet(UriTemplate="cars", 
         ResponseFormat = System.ServiceModel.Web.WebMessageFormat.Xml)]
        List<Car> GetCars();

       [System.ServiceModel.OperationContract] 
       [System.ServiceModel.Web.WebGet(UriTemplate="cars/search?carName={theCarName}")]
        Car GetCar(string theCarName);
    }
}

From the above interface definition one can see that we are using some attributes. Lets see each of these attributes one by one. First up is the ServiceContract attribute.

ServiceContract: This attribute tells the system that the interface defines a service contract for a WCF application. If an interface which is being inherited by a WCF web service doesn’t have a ServiceContract attribute then the following error will thrown by the system.

Service 'CarService' implements multiple ServiceContract types, and no endpoints are defined in the configuration file. WebServiceHost can set up default endpoints, but only if the service implements only a single ServiceContract. Either change the service to only implement a single ServiceContract, or else define endpoints for the service explicitly in the configuration file.

Just applying the ServiceContract attribute above the interface will solve the above error. Now lets see the various properties associated with the ServiceContract attribute

Property Description
ConfigurationName

The element name in the configuration file which defines the service.

Name

Using the property you can provide a different name to the interface.

Namespace Can be used to provide namespace.
ProtectionLevel

enum value specifies what type of protection should be applied to the service. The enum values are ProtectionLevel.None, ProtectionLevel.Sign and ProtectionLevel.EncryptAndSign

SessionMode

enum specifies whether sessions are allowed or not. The enum values are SessionMode.Allowed, SessionMode.Required and SessionMode.NotAllowed.

That’ about ServiceContract attribute. The next attribute which we have used in all the methods is the OperationContract attribute. Lets see what does OperationContract do.

OperationContract: OperationContract attribute tells the system that the method needs to be exposed as part of a service contract. A method which is not having OperationContract will not be exposed. So its imperative to have OperationContract attribute to expose a method. The properties which can be used along with OperationContract are.

Property Description
Action

Using the action property you can specify a url to which the incoming messages needs to be posted. Action uniquely identifies a method with a Url.

AsyncPattern

Specifies whether the method can be called asynchronously or not.

IsOneWay

Specifies whether the operation returns a value or not.

IsInitiating

Specifies whether the method needs to be called when session is started.

IsTerminating

Tells the system to execute the method when session is completed.

Name

If you want to give some other name to the method then you can make use of the name property.

ProtectionLevel

enum value specifies what type of protection should be applied to the service. The enum values are ProtectionLevel.None, ProtectionLevel.Sign and ProtectionLevel.EncryptAndSign

Next attribute which you will notice is the WebGet. Here is the explanation of WebGet attribute.

WebGet: If you would have worked on ASP.NET application then you know that the forms in ASP.NET post data in two ways, one is the GET method and the other one is the POST method. WebGet attribute tells the system that the method is a pure data retrieval method to which HTTP GET method is associated. The properties associated with WebGet are listed below.

Property Description
BodyStyle

enum specifies how messages should be sent. Enum values are WebMessageBodyStyle.Bare, WebMessageBodyStyle.Wrapped, WebMessageBodyStyle.WrappedRequest and WebMessageBodyStyle.WrappedResponse.

RequestFormat

enum specifies what is the request format. Enum values are WebMessageFormat.Xml and WebMessageFormat.Json.

ResponseFormat

Same as RequestFormat. Specifies the type of the response.

UriTemplate

The Uri to access the method/operation.

UriTemplate here is the endpoint. Here endpoint means a unique Url to access the method in a restful webservice. This is one of the requirement of a RESTful method which says there should be unique endpoint to access the methods.

One thing to note in UriTemplate property is that whatever you specify inside a curly brace, {}, and if the same name is used in the parameter of the method then the value which comes in the querystring is passed on as the parameter for the method. In our second method in the interface we have given the UriTemplate as something like this “cars/search?carName={theCarName} ” which means the querystring value in carName will be passed as the parameter to the method, as the parameter name and value inside the curly brace are the same. If you want more parameters you can very well do this by declaring more parameters in the querystring. A hypothetical method is pasted below.

[System.ServiceModel.OperationContract]
[System.ServiceModel.Web.WebGet(UriTemplate = "cars/Carsearch?carName={theCarName}&color={theColor}&price={thePrice}")]
Car SearchCar(string theCarName, string theColor, string thePrice);

In the above e.g. theCarName, theColor and thePrice will be passed as parameter to the method SearchCar. The url may look something like this “http://localhost:2333/cars/carsearch?carName=ferrari&color=red&price=432544”. The values ferrari, red and 432544 will be passed as parameters to the SearchCar method. So if you want to pass parameters to a RESTful web method then you need to just follow the above approach.

Now that was about making use of HTTP GET method. The next obvious question would be how to make use of HTTP POST method. To make use of HTTP POST method one need to apply another attribute called “WebInvoke” All the properties are same as in WebGet except for an extra property called Method. Using the method property you can specify the HTTP method like POST, PUT, DELETE and HEAD. When to use each of these HTTP method is given below.

HTTP Method Description
GET Whenever you want to retrieve some information you will make use of get.
POST When you want to submit data which will be processed by the service.
PUT When you want create or update a resource you will make use of PUT.
DELETE As the name suggest whenever you want to delete a resource you will make use of DELETE.

Now we have our contract defined. So the first step is over. Now we need to implement the interface and that is what we are going to do next. We will be implementing the interface in a class called CarService. The code is pasted below.

namespace CarService
{
    public class CarService : ICarService
    {
        List<Car> carList;
        public CarService()
        {
            carList = new List<Car> {new Car{ModelName="Ferrari", Color="Ferrari Red", CubicCentimeter= "2345",
             Price=34324324}, new Car{ModelName="BMW 3 Series", Color="Blue", CubicCentimeter= "2200",
             Price = 32423}, new Car{ModelName="Benz SLR", Color="Milky White", CubicCentimeter = "3200",
             Price = 32424}};//Storing the car objects in a collection
        }
        List<Car> ICarService.GetCars()
        {
            return carList;
        }

        Car ICarService.GetCar(string theCarName)
        {          
            var car = from c in carList where c.ModelName == theCarName select c;
            Car cs = null;
            foreach (var c in car)
            {
                cs = c as Car;
            }
            return cs;
        }
    }
}

You can see from the above code we have implemented ICarService interface into a class called CarService. The first method returns the Car collection and the second method searches the carList collection object based on the name of the car and returns the matching Car object. No rocket science here. The Car class is discussed in detail at the end of the blog. So we will move on to the next step.

We have defined the base requirement and now we have to expose the methods to the outside world using WCF service. For that you can either add a new WCF Service Applicaiton project from the file menu or you can right click on your ASP.NET or web service project and from the popup menu select Add—>New Item option. From the Add New Item dialog box select WCF Service and give a name to your service. I have named it CarService. The screenshot of Add New Item dialog is pasted below.

image

You can do the same from file menu as well.

When you add WCF Web service application or a SVC file the system will automatically add an interface by the name ICarService or I followed by whatever name given to the project or SVC file. Delete the interface, as we have already defined the contract. Also delete the SVC.cs file. Now open the SVC file, in my case CarService.svc. You can see a markup something like this.

<%@ ServiceHost Language="C#" Debug="true" Service="CarService.CarService" CodeBehind="Service1.svc.cs" %>

Delete the CodeBehind attribute and add Factory attribute as shown below.

<%@ ServiceHost Language="C#" Debug="true"
Service="CarService.CarService" Factory="System.ServiceModel.Activation.WebServiceHostFactory" %>

You may get an error something like the one pasted below.

Service 'CarService.CarService' has zero application (non-infrastructure) endpoints. This might be because no configuration file was found for your application, or because no service element matching the service name could be found in the configuration file, or because no endpoints were defined in the service element.

If you come across an error like this then the possible reason could be you will be missing the Factory attribute in the ServiceHost tag. Just by adding the Factory attribute will solve the prob.

Visual studio also embeds the following tag in Web.config file.

<system.serviceModel>
        <behaviors>
   <serviceBehaviors>
    <behavior name="RestFulWebservice.CarServiceBehavior">
     <serviceMetadata httpGetEnabled="true" />
     <serviceDebug includeExceptionDetailInFaults="false" />
    </behavior>   
   </serviceBehaviors>
  </behaviors>
        <services>
   <service behaviorConfiguration="RestFulWebservice.CarServiceBehavior"
    name="RestFulWebservice.CarService">
    <endpoint address="" binding="wsHttpBinding" contract="CarService.ICarService">
     <identity>
      <dns value="localhost" />
     </identity>
    </endpoint>
    <endpoint address="" binding="mexHttpBinding" contract="IMetadataExchange" />   
   </service>
  </services>
</system.serviceModel>

Now you are ready to go. Just hit F5 and see the output. If you see a message saying there is no endpoint defined you need not panic. Just type one of the endpoints defined in the contract (interface) you can see the output. In my case the two url which I used are as follows.

http://localhost:3891/CarService.svc/cars
Ouput of the above url

<GetCarsResponse xmlns="http://tempuri.org/">
     <GetCarsResult xmlns:a="http://schemas.datacontract.org/2004/07/CarService" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
         <a:Car>
          <a:Color>Ferrari Red</a:Color>
          <a:CubicCentimeter>2345</a:CubicCentimeter>
          <a:ModelName>Ferrari</a:ModelName>
          <a:Price>34324324</a:Price>
          </a:Car>
         <a:Car>
          <a:Color>Blue</a:Color>
          <a:CubicCentimeter>2200</a:CubicCentimeter>
          <a:ModelName>BMW 3 Series</a:ModelName>
          <a:Price>32423</a:Price>
          </a:Car>
         <a:Car>
          <a:Color>Milky White</a:Color>
          <a:CubicCentimeter>3200</a:CubicCentimeter>
          <a:ModelName>Benz SLR</a:ModelName>
          <a:Price>32424</a:Price>
          </a:Car>
      </GetCarsResult>
</GetCarsResponse>

http://localhost:3891/CarService.svc/cars/search?carName=Ferrari

Output of the above url.

<Car xmlns="http://schemas.datacontract.org/2004/07/CarService" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <Color>Ferrari Red</Color>
  <CubicCentimeter>2345</CubicCentimeter>
  <ModelName>Ferrari</ModelName>
  <Price>34324324</Price>
</Car>

The car class which is getting serialized is shown below.

[System.Runtime.Serialization.DataContract]
public class Car
{       
        [System.Runtime.Serialization.DataMember]
        public string Color
        { get; set; }
        [System.Runtime.Serialization.DataMember]
        public string ModelName
        { get; set; }
        [System.Runtime.Serialization.DataMember]       
        public int Price
        { get; set; }
        [System.Runtime.Serialization.DataMember]
        public string CubicCentimeter
        { get; set; }
}

The objects used in WCF should be qualified by DataContract attribute. Some of the properties of DataContract are listed below.

Property Description
Name If you want to give a different name to the class when it is serialized then you can make use of the name property.
Namespace To provide a namespace to the xml attribute you can make use of the “Namespace” property. When you provide namespace it has abide by w3 guidelines. As a general practice we provide urls as namespace.

The other attribute is the DataMember. DataMember attribute tells the serializer that the property/field is part of a DataContract and it can be serilizable. Some of the properties are explained below.

Property Description
EmitDefaultValue Property which tells the serializer whether to emit default value if the property is not having any value.
IsRequired This property can be set when you want the property/field to be present while serializing and deserializing the object.
Name If you want to give some other name other than name of the property/field then you can make use the Name property.
Order When the object is serialized in what order the property/field needs to be serialized.

Now lets see the second way of implementing the WCF webservice. This is the most common way which everyone will be aware off. Open VS 2008 and add a new project of type WCF Service Application from File—>New—>Project menu. This will automatically add a contract (interface) and the necessary .SVC files (a .svc and a .svc.cs file inheriting from the interface). Rest we need to follow the same steps for defining various methods in the Interface as explained above.

Saturday, August 8, 2009

Formatting numeric data types in .NET

Recently I was discussing with one of my friend and he informed me that he was breaking his head on creating a utility to format decimals, float and other datatypes. Out of curiosity I asked him how are you doing these, for e.g. displaying a decimal datatype with only two decimal place value. Bang came the reply that he is doing some string manipulation. I was surprised and informed him that he need not take so much of a pain instead he can use ToString methods of most of the datatype to format the data types. In this blog I will highlight some of the commonly needed number formatting techniques.

First up formatting for decimal places.

This is one of the common requirement where we always come across situation to format float, decimal and double datatypes to some number of decimal places. One of the easiest way to format is given below.

double doub = 8457.3299;
float fl = 28398.39843289f;
decimal dec = 982389.348093m;
Console.WriteLine(doub.ToString(".00"));//Output: 8467.33
Console.WriteLine(fl.ToString(".000"));//Output: 28398.400
Console.WriteLine(dec.ToString(".0000"));//Output: 982389.3481

In the above e.g. I have used zero in combination with decimal symbol to format the numbers according to the required precision required. If the need is to format to the max of two decimal places I have used “.” (dot) followed by 2 zeroes. Similarly how many precision points you want you can use that number of zeroes along with dot. Isn’t it so simple? One thing to note here is that the system will automatically round off the numbers if there are more decimal places than what is specified in the format string as you can see in the above e.g.

Formatting numbers

Some number formatting e.g. are given below.

double doub = 8457.3299;
float fl = 28398.39843289f;
decimal dec = 982389.348093m;
Console.WriteLine(doub.ToString("000"));//Ouput 8457
Console.WriteLine(fl.ToString("00000000"));//Ouput 00028398
Console.WriteLine(dec.ToString("00000.000"));//Ouput 982389.348
Console.WriteLine(dec.ToString("00 - 00 - 0.000"));//Ouput 982 - 38 - 9.348
Console.WriteLine(dec.ToString("(00000) (00) (0)"));//Ouput (00982) (38) (9)

In the above e.gs we have used zeroes to format numbers. First formatting using 3 zeroes doesn’t do much. It just displays the numbers as it is. The second one with 8 zeroes formats numbers and adds extra zeroes if the number doesn’t have the required digits i.e. in the above e.g. there are only 5 digits and because of formatting applied it adds extra zeroes preceeding the number. Use of zero to format numbers tells the system that even if zero is not a significant number it should display zero. One can use other characters along with zero to format the numbers. Few e.g. have been highlighted above.

Formatting numbers using # symbol

One of the problem while using 0 to format numbers is that it will show the insignificant numbers or club zeroes to fill the gap. To avoid just this you can make use of # symbol in place of 0. To show the difference between # and 0 I have pasted below same e.g. with both the format string.

double twoDeci = 1234.34;
int flo = 2343243;
decimal deci = 23434355.6749m;
Console.WriteLine(twoDeci.ToString("######.####"));\\Output 1234.34
Console.WriteLine(twoDeci.ToString("000000.0000"));\\Ouput 001234.3400
Console.WriteLine(flo.ToString("(####) - (###) - (##)"));\\Output (23) - (432) - (43)
Console.WriteLine(flo.ToString("(0000) - (000) - (00)"));\\Output (0023) - (432) - (43)
Console.WriteLine(deci.ToString(".##"));\\Output 23434355.67
Console.WriteLine(deci.ToString(".00"));\\Output 23434355.67

From the above e.gs one can make out that if you are using 0 as the format string then it adds insignificant zeroes preceding or leading the numbers, whereas # will ignore insignificant zeroes. Also one thing to note is that if you use # with numbers with insignificant zeroes then it will ignore those zeroes whereas 0 will consider the zeroes as significant. The difference is shown below.

float preecedingZeroes = 00034556;
double leadingZeroes = 34345.983000;
Console.WriteLine(preecedingZeroes.ToString("########"));\\Ouput 34556
Console.WriteLine(preecedingZeroes.ToString("00000000"));\\Ouput 00034556
Console.WriteLine(leadingZeroes.ToString("#####.######"));\\Ouput 34345.983
Console.WriteLine(leadingZeroes.ToString("00000.000000"));\\Ouput 34345.983000

From the above e.g. differences are clear that # never takes into consideration the insignificant zeroes even if there is one in the datatype. So if you want the insignificant zeroes to be considered then you need to use 0 instead of #.

Formatting for thousand separator.

Many a times we get numbers from the database without any formatting applied and we may require the numbers to be formatting with thousand separators. Its very easy to apply thousand separators to a number. E.g. are pasted below.

double preecedingZeroes = 345563434;
Console.WriteLine(preecedingZeroes.ToString("#,#"));\\Output 345,563,434
Console.WriteLine(preecedingZeroes.ToString("0,0"));\\Output 345,563,434

The above e.g. makes use of both # and 0 along with “,” sign for thousand formatting. Comma (,) can be used along with other format strings to apply thousand formatting. One thing to note here is that when you apply thousand separator formatting then the system makes use of the system’ culture and thousand separator associated with the culture. If you want to use a specific culture’ thousand separator then you need to provide the culture you want to use along with the “ToString” method. Here are e.g. in Danish and Indian format.

//Applies Hindi-India culture and formats the number based on Indian notations.
Console.WriteLine(preecedingZeroes.ToString("#,#", System.Globalization.CultureInfo.CreateSpecificCulture("hi-IN")));//Ouput 34,55,63,434
//Applies Danish culture and formats the number based on Danish culture.
Console.WriteLine(preecedingZeroes.ToString("0,0", System.Globalization.CultureInfo.CreateSpecificCulture("da-DK")));//Ouput 345.563.434

So you can see from the above e.g. that in the Indian culture the thousand separator used is comma (,) whereas in Danish culture the thousand separator is represented by a dot (.)

One thing to note here is that if you use “,” one after the other without any number formatting characters in between them, then the meaning of comma completely changes. The system consider each comma as 1000 and divides the number to which formatting is applied by 1000. Confused, let me explain with e.g.

double dou = 23432432423;
Console.WriteLine(dou.ToString("#,,"));//Output 23432
Console.WriteLine(dou.ToString("0,,,"));//Output 23

In the above e.g. if you see in the first formatting we have used two commas which means the number “23432432423” will be divided by thousand two times as the number of commas occur two times in the formatting string. Similarly in the second sample code the commas occur thrice so the number will be divided by 1000 three times.

Formatting for positive and negative numbers.

There may situation where you don’t know what type of number you are getting from the database, whether the number is a positive or a negative one. Even the number can be a zero. You would like to apply different formatting for positive number and different formatting for negative number. Also you would like to show zero in a different way. I have faced a similar prob in one of my projects where the client wanted to display a positive symbol enclosed in brackets (+) in front of a positive number, a negative symbol enclosed in brackets (-) in case of negative numbers and a zero enclosed in brackets (0) in the case of zero. If you also face a similar kind of situation you can make use “;” (semi colon) to separate the formatting. Sample formatting code is given below.

double positiveNo = 3746;
double negativeNo = -3435;
double zero = 0;
string formatString = "(+)#;(-)#;(0)";
Console.WriteLine(positiveNo.ToString(formatString));//Output (+)3746
Console.WriteLine(negativeNo.ToString(formatString));//Output (-)3435
Console.WriteLine(zero.ToString(formatString));//Output (0)

In the above e.g. if you notice I have defined the formatting string for positive, negative and zero in the variable “formatString”. Semi colon (;) is used as the separator for the different number format. This is how this works, starting from left in the formatString variable the format string to the left of the first semi colon is considered as the formatting string for positive numbers, and the format string in between the first semi colon and the second semi colon is considered the format string for negative values and the format string to the right of second semi colon is taken as the format string for zeroes.

If you don’t want to give separate formatting for zero then you can just leave the format string after the second semi colon empty i.e. you need to only specify format strings for positive and negative values. In such situation the format string for positive value will be applied to format zeroes. The sample is given below.

double positiveNo = 3746;
double negativeNo = -3435;
double zero = 0;
string formatString = "(+)#;(-)#";
Console.WriteLine(positiveNo.ToString(formatString));//Output (+)3746
Console.WriteLine(negativeNo.ToString(formatString));//Output (-)3435
Console.WriteLine(zero.ToString(formatString));//Output (+)

Multiplying a number by 100.

If you want to multiply a number by 100 one can make use of the % symbol in the format string along with other format strings. Sample code is pasted below.

double dd = .459;
double ddd = 849;
Console.WriteLine(dd.ToString("#%"));//Output 46%
Console.WriteLine(dd.ToString(".#%"));//Output 45.9%
Console.WriteLine(ddd.ToString("#%"));//Output 84900%
Console.WriteLine(dd.ToString("#.#%"));//Output 45.9%
Console.WriteLine(ddd.ToString("0%"));//Output 84900%

You can see from the above e.g. that by using the % sign along with other format strings the number gets multiplied by 100 and % symbol is appended at the end of the number.

Appending currency symbol to a number.

Another common requirement is to append the currency symbol along with numbers. To do just that one can make use of “C” or “c” character in the format string. The e.g. is given below.

double curFor = 329.5943;
Console.WriteLine(curFor.ToString("C"));//Output $329.59
Console.WriteLine(curFor.ToString("C3"));//Output $329.594

The currency symbol and precision points will be taken from the current culture set for the system. If you want to specify precision points for decimal value then you can specify the number of precision points after the “C” symbol as shown in the above e.g. If you want to change the current culture and apply some other culture then you can do that as shown in the below e.g.

Console.WriteLine(curFor.ToString("C3", System.Globalization.CultureInfo.CreateSpecificCulture("en-GB")));//Output £329.594

In the above e.g. we are using currency format specifier with 3 decimal point precision and also we are applying Great Britain’ i.e. UK’ culture. This formats the number and adds the pound symbol.

Displaying numbers in exponential form

If you want to display numbers in exponential format you can make use of “E” or “e”. Sample code is pasted below.

double exp = 43895.04390;
Console.WriteLine(exp.ToString("e"));//Output 4.389504e+004

If you want you can specify the number of precision decimal points to be displayed. If the precision points are not specified then the system by default will add 6 precision points after the decimal point. Sample code with precision point is pasted below.

double exp = 43895.04390;
Console.WriteLine(exp.ToString("E9"));//Output 4.389504390E+004

So with that I have covered some of the common number formatting requirements.

Try to know more.

Sandeep