Getting the absolute path in ASP.NET which is application independent

There comes a time when you need to get the absolute path to reference a file or some resource existing at some relative path of the website or web application. As things turned i was in need some of the similar functionality. The first thing that came to my mind was doing something similar :

 

//get the absolute path for the following relative path
String relPath = @"~/ImageResource/ImageName.jpg";
Control cntrl = new Control();
String absPath = cntrl.ResolveClientUrl(relPath);

As it is this works great, but i wanted something more elegant, which doesnt involve the creation of the Control object. So i searched for sometime and stumbled upon an unknown utility function available, right over in .NET framework. Interesting to know that there so many useful functionality in-built in .NET framework which rarely are seen in practice.

Ok then about this utility API is called VirtualPathUtility and it is contained in the System.Web namespace. So using the VirtualUtilityPath you can rewrite the above piece of code as follows

 //get the absolute path for the following relative path
String relPath = @"~/ImageResource/ImageName.jpg";
String absPath =VirtualPathUtility.ToAbsolute(relPath);

Nice little function. But beware there are some pitfalls you need to avoid. This function is not one size fits all solution. You need to be aware of some of shortfalls described in some of the posts below. But for simple use, this works great.

 

Related Posts
MSDN: VirtualPathUtility Class
Weblogs.asp.net: VirtualPathUtility Class
How VirtualPathUtility combines paths in .Net 2.0 – level 100

How-To : Splitting delimited strings using XQuery in SQL

Well, this was just kind of an experiment of sorts of using XQuery. The idea just occured some time back when i was trying some other similar experiment.

Now as you all know there is no in-built function for Split in SQL. So lots of people have come out with different solution. This solution is just another solution to the old problem of splitting delimited strings.

The solutions i found mostly revolved around string manipulation, and i have been using the same before my chance encounter with XML support in SQL. The solution i came out with was using XQuery support in SQL Server and it works pretty well too. My thoughts are, it might be just a little wee faster than the other implementation (no numbers from me on that front :) )

Implementation

DECLARE @DelimitedString NVARCHAR(500)
DECLARE @Delimiter NVARCHAR(10)
DECLARE @DelimitedStringXML XML

SET @DelimitedString = 'Apples,Bananas,Mangoes,Peaches,Watermelons'

SET @Delimiter = ','

--Create a document fragment for the delimited string
SET @DelimitedString = REPLACE('<s>' + @DelimitedString + '</s>',@Delimiter, '</s><s>' )
PRINT @DelimitedString --PRINTS <s>Apples</s><s>Bananas</s><s>Mangoes</s><s>Peaches</s><s>Watermelons</s>

--Cast the string to xml format, for use in the xquery
SET @DelimitedStringXML = CAST(@DelimitedString AS XML)

SELECT t.r.query('./text()')
FROM @DelimitedStringXML.nodes('/s') t(r)

For people who are unfamiliar with Xquery can check out the reference section.

Have fun and happy coding

Reference

MSDN :: Introduction to XQuery in SQL Server 2005

MSDN Blogs :: XQuery Inside SQL Server 2005

Trimming extra space in SQL

Sometime back i had come across this small problem. Mind you this is not a problem you come across many times, but it is interesting little problem nonetheless. The problem was removing extra spaces in a given string.

For e.g if you have some string like so “This is a                   line which    contains multiple        spcaes.” and the disired result is with only one space seperating the words “This is a line which contains multiple spcaes.”

There are various ways you can do it; here i outline 2 methods

  • Using SQL REPLACE function
  • Using SQL FOR XML XPATH

Using SQL REPLACE function

First the solution :

--Using string replace
DECLARE @text NVARCHAR(MAX)

SET @text = 'This is a                   line which    contains multiple        spaces.'
PRINT @text

SET @text = REPLACE(REPLACE(REPLACE(@text, SPACE(1), '<>'), '><', SPACE(0)), '<>', SPACE(1));
PRINT @text

Can you figure out what is happening here? Ok, lets split the REPLACE function for more clarity. I am not going to explain the code, you can see the comments :)

 

--using replace : explanation
DECLARE @text NVARCHAR(MAX)
SET @text = 'This is a                   line which    contains multiple        spaces.'
PRINT @text --Print

--Replace each space character with the following characters '<>'
SET @text = REPLACE(@text, SPACE(1), '<>');
PRINT @text --PRINTS --This<>is<>a<><><><><><><><><><><><><><><><><><><>line<>which<><><><>contains<>multiple<><><><><><><><>spaces.

--Replace each '<>' character with the following characters with empty string
SET @text = REPLACE(@text, '><', SPACE(0));
PRINT @text --PRINTS This<>is<>a<>line<>which<>contains<>multiple<>spaces.

--Now you have only single spaces which are denoted by '<>'
--Replace the '<>' with the space character 
SET @text = REPLACE(@text, '<>', SPACE(1));
PRINT @text --PRINTS This is a line which contains multiple spaces.

Using SQL FOR XML XPATH

Now this one is just for kicks :) I wanted to see if the same problem could be solved using the FOR XML PATH. And here is how it can be done.

--using xml 
DECLARE @text NVARCHAR(MAX)
DECLARE @xmlText XML

SET @text = 'This is a                   line which    contains multiple        spaces.'

--Add the following string <r> at the beginning
--Add the following string </r> at the end
--Replace each space with the following string '</r><r>'. 
--This will give a document fragment in the following format
--<r>word</r><r></r>.....</r>
SET @text = REPLACE('<r>' + @text + '</r>' , SPACE(1), '</r><r>' )
PRINT @text --PRINTS <r>This</r><r>is</r><r>a</r><r></r><r></r><r></r><r></r><r></r><r></r><r></r><r></r><r></r><r></r><r></r><r></r><r></r><r></r><r></r><r></r><r></r><r></r><r>line</r><r>which</r><r></r><r></r><r></r><r>contains</r><r>multiple</r><r></r><r></r><r></r><r></r><r></r><r></r><r></r><r>spaces.</r>

--Cast the string to XML datatype so that we can work with the xml data type function
SET @xmlText = CAST(@text AS xml)

SET @text =
    (
    --Select all the nodes which are not empty
--Append a space at the end
        SELECT t.r.value('.[1]', 'nvarchar(max)') + SPACE(1)
        FROM @xmlText.nodes('//r') t(r)
        WHERE t.r.value('.[1]', 'nvarchar(max)') <> SPACE(1)
        FOR XML PATH ('')
    )
PRINT @text --PRINTS This is a line which contains multiple spaces.

It is normally advised to use Exist function instead of Value function as shown above for checking in the where clause. Here is how it can be done with Exist clause.

--using xml 
DECLARE @text NVARCHAR(MAX)
DECLARE @xmlText XML

SET @text = 'This is a                   line which    contains multiple        spaces.'
SET @text = REPLACE('<r>' + @text + '</r>' , SPACE(1), '</r><r>' )

SET @text =
    (
        SELECT t.r.value('.[1]', 'nvarchar(max)') + SPACE(1)
        FROM @xmlText.nodes('//r') t(r)
        WHERE t.r.exist('./child::text()') > 0
        FOR XML PATH ('')
    )
PRINT @text --PRINTS This is a line which contains multiple spaces. 

Nice. Have fun and Happy coding :)

Dataset to XML and loss of information

When weneed to persist a dataset object, usually what we do is use the WriteXml() method for the Dataset object. For most cases the default implementation works fine.

So

DataSet dsObj = GetDatasetObject();
dsObj.WriteXml(filename);

the above command works fine and saves the dataset xml into the specified file, provided that all the columns have data.

This is the default implementation and this is how it works; if the column contains valid value or some sort of value the column will be written to the output else if the column contains a NULL value, that particular column will not be written to the output. Now this is not so much of an issue, if there is atleast one row which contains a proper value while all the other rows contain NULL.

The fun starts when the value in a given column in all the rows contain NULL, what happens? What happens, is that since there is no value for the specified column, the column is not outputted to the file name.

Consider that you want to read the xml into dataset which had been previously written.

DataSet dsObj = null;
dsObj.ReadXml(filename);

If while saving the dataset, a particular contained NULL values, that column information will not be outputted. So when you try to load the xml again in the dataset, what occurs is loss of information, (even though NULL value is no information in particular). So the column will not be created in the dataset and any access to it will result in an exception.

To overcome this scenario, you need to use the overloaded version for the WriteXml and ReadXml function as below

 //Write dataset schema, along with the data
DataSet dsObj = GetDatasetObject();
dsObj.WriteXml(filename, XmlWriteMode.WriteSchema);

What this statement does is it writes the schema associated with the dataset, so even if a column contains all NULL values, we shall not loose the column information. Now it is a simple matter of loading the dataset back.

//create the dataset based on the specified schema
DataSet dsObj = null;
dsObj.ReadXml(filename, XmlReadMode.ReadSchema);

Now we are good. Happy coding.

Online Conversion Websites

Sometime or the other you may want to convert your files from one file to other. There whole lot of sites which allows you to do it. Here are a couple of sites which are nice easy to use and no fuss.

youconverit

ZamZar

pdfonline

Comet Docs

 

Enjoy!!!

Me and my camera : Adventures of an amateur photographer

Photography is one of my hobby. But film photography is very expensive and poor me cannot afford the luxury, so recently i went ahead and gifted myself a digital camera so that i could pursue my hobby.

As digital camera market is ever increasing and there are good cameras with good function around i splurged a little and got a Canon S5is. It turned out to be a pretty good investment, now i can pursue my hobby without feeling a pinch (well i already felt the pinch when i bought it, so now i am ok ;) )

The Canon S5IS provides good control over the manual setting, so i could play around a little with ligthing, focus and the stuff. I was pretty surprised by some of the photos i got, quite pleasing and all the credit goes to my subjects (some of them didnt even know i was capturing them and some didnt care :D )

For posterity i posted the photos online at Photoshop.com. By the some of the photos are pretty old, from the times when i didnt have a camera of my own and

had to borrow one from my friends :)

This is supposed to be frequently updated page, but the lazy person in me stops me every time, so i intend to keep it updated, dont count on it though.

Hope you like them :)

Here is a glimpse of some of the photos, for the complete list follow the link : Photoshop.com.

Retrieving comma seperated values from SQL Server

Many a times, we are pressed with a problem of retrieving comma seperated values from SQL server. There are quite a few ways to do it, for instance using cursors, using user defined functions or using COALESCE (the most preferred). Come SQL Server 2005 and there is one more technique which can be employed (his is the one i prefer the most, simple, elegant and no fuss)

In SQL Server 2005 and above you can use the FOR XML Path mode syntax to achieve the result set. We wont go in details of how FOR XML Path works, please check the reference link for more information

Lets take a small example; suppose we wanted to return a list of all the tables contained in the database in a comma seperated list. Using the XML Path Mode we can do it in the following manner:

 

DECLARE @commaSeperatedTableName NVARCHAR(MAX)

SET @commaSeperatedTableName = (
select ',' + [name]
from sys.tables
for xml path (''))

The @commaSeperatedTableName variable will contain the list of all table contained in the database in the following format : “,tbl1,tb2,tb3,tb4”

Note that there is comma prepended at the beginning of the string, if we want to remove the comma so that the returned result in the following format “,tbl1,tb2,tb3,tb4”, all we need to do is use the STUFF function available in the SQL Server

SELECT STUFF(@commaSeperatedTableName, 1,1,'')

Sweet, this is as easy as it can get. Happy querying.

Reference

MSDN: Using XML PATH Mode

GeeksWithBlogs: FOR XML PATH – A New Mode in FOR XML with SQL Server 2005.

MSDN: STUFF (Transact-SQL)

Using custom serialization to store object information in ViewState

Recently i came across a wierd problem while developing a web user control. I needed to persist some data across page postback’s. I took the ViewState approach, which had been used previously to do the same task.

I had thought that it would be easy as it had been done a multiple times earlier, but i was in for a surprise. The object i was trying to persist could not be serialized, moreover it was a object i could not change to make it serializable, now i was in dilemma. After trying various methods and loosing my hair over it, i finally stumbled upon an interesting solution (not after i a lot of poking and prodding).

The solution i found was how ASP.Net does serialization itself, after a bit of nosing around using .NET reflector in the System.Web namespace.

After persisted searching, I realized that .Net framework used IStateFormatter object to serialize objects. IStateFormatter is contained is part of the PageStatePersister class (Please check the reference section below for more information)

We wont go into much detail about what is PageStatePersister object, we shall see an example of how the problem was resolved. The StateFormatter class provides to methods to serialized and deserialize an object, quite naturally called Serialize and Deserialize namely.

The Serialize method takes a parameter of type Object and returns an serialized string, which we can easily save to ViewState. Conversely the Deserialize method takes this serialized string and converts it back into the Object. We shall need some handling to convert the our object type to and fro during the serialization process

Lets say i needed to persist a collection of objects (BookDetail) to the View State object.

List<BookDetail> bkDetailCollection = new List<BookDetail> (); 

We need to conver the bkDetailCollection collection to Object class inorder to use StateFormatter class. Your can use any way you want to convert it into an object

Object objBookDetails = GetBookDetailCollectionObject(); 

Once we get the above object it is a simple method of just doing the following for serializing the object

IStateFormatter stateFormatter = new ObjectStateFormatter();
String strSerializedObject = stateFormatter.Serialize(objBookDetails ); 

//Persist to view state
ViewState["persistedBookDetails"] = str;

and the reverse code is just as simple

String persistedobjBookDetailsString = ViewState["persistedBookDetails"]; 

                if (!String.IsNullOrEmpty(persistedobjBookDetailsString ))
                {
                    IStateFormatter stateFormatter = new ObjectStateFormatter();
                    objBookDetails = stateFormatter.Deserialize(persistedobjBookDetailsString ); 

if (objBookDetails != null)
                    {
                        List<BookDetail> bkDetailCollection = GetBookDetailCollectionCollection(objBookDetails );
                    } 

                }

Now there it is, using this technique you can serialize and deserialize any type of custom method. Mind you this is a bit of an extreme solution, when nothing else works :)

Happy coding

Reference

MSDN: PageStatePersister Class

4GuysFromRolla.com: Persisting Page State in ASP.NET 2.0

HOW-TO: Search string value contained in comma seperated string

Quite often when we need to pass multiple values to the stored procedure, we pass the value as comma seperated string. The problem is how do we search for a column having a value contained in the comma seperated string.

For e.g. suppose you have a Books table which has "Type" property. The "Type" property can hold one of the following values "Novel", "Magazine", "Journal" etc…

Now we want to search for books based on certain type of books, take for instance Novel and Magazine. For this instance what we would do is pass the values as comma seperated, so our sp will get the values as "Novel,Magazine".

There are various ways by which this can be accomplished. One of these method which is widely used is the split operation. i.e. we split the values in the corresponding values and then we make a search in the table

SELECT *
FROM Books bks
WHERE bks.Type IN
(SELECT *
FROM dbo.Split('Novel,Magazine') --dbo.split is user defined funcation which returns table containing one row per each value 
) 

This method works fine, well and good.

There is another method and the whole credit for this method goes to my collegues Hrishikesh, who showed this method to me. The method is very simple and it makes the use of like operator (which many would shun)

declare @types as nvarchar(250)
set @types= ‘Novel,Magazine’

–add a comma at the start and end of the string
set @types= ‘,’+@types+’,’
select *
from Books
where @types LIKE%,’ +type+ ‘,%

The idea is very simple :

We get the values contained in the column Type and add the comma string at either end so that we get a value in the following format ",Novel,", ",Magazine," etc. Next we check if the value is contained in the comma seperated string, if the value is found we get the result as expected.

This technique uses very less code and works like a charm. Happy coding.

Enum with Flags Attribute and Extension method

For quite some time now i have been intending to write about Enum with Flags attribute set. Enum with Flags attribute set allows the enum to be used as Bit flags where each bit signifies whether a particular option is set or not. When using this very powerful feature there is always a need to check whether a particular bit is set or not and most of them time we end up duplicating the following piece of code.

(enumvariable & EnumType.enumproperty) == EnumType.enumproperty

Needless to say it is a waste of time and clutters the code unnecessarily. So I had been trying to use Extension method, but stumbled upon some problem regarding casting of values. Then i stumbled upon this interesting article which does exactly what i want Enums, Flags, and C# — Oh my! (bad pun…).

Neat really neat. Enjoy coding