WYSIWYG

http://kufli.blogspot.com
http://github.com/karthik20522

Saturday, November 10, 2012

ClipTheTrip.com - How I Built This

Clipthetrip.com is a fun, free crowd sourced destination guides. From a data modeling perspective it has a pretty simple object interaction. There is Location object, there is CLIP object, there is photo object and a user object. MongoDB was used as a data store so objects were quite denormalized instead of a referential model.

Some of the technologies and API used for building the site is as follows:
As part of this article I am sharing code snippets of how I extracted information from external API's and other smaller code snippets. Since most part of the site is just CRUD operations, I feel it would be a waste to explain the code structure or architecture (considering architecture is quite simple!)

Currency data from Webservicex.net
Example page: http://www.clipthetrip.com/city/london
1
2
3
4
5
6
7
8
//code being 3 letter code like USD, INR etc.
  var cur = decimal.Parse(xElement.Value).ToString("#.##");  
 
  jsonResult.Data = new { c = cur, code = code };
   
  return jsonResult;

Business information from Bing
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
var html = new WebClient().DownloadString("http://www.bing.com/local/default.aspx?what=" + name + "&where=" + location);
 
var htmlDoc = new HtmlAgilityPack.HtmlDocument();
htmlDoc.OptionFixNestedTags = true;
htmlDoc.LoadHtml(html);
 
var nodes = htmlDoc.DocumentNode.SelectNodes("//div[@class='ecEnclosure']");
if (nodes != null)
{
 foreach (HtmlNode node in nodes)
 {
  var bName = node.Descendants("a")
    .Where(s => s.GetAttributeValue("class", "").Contains("ecHeaderLink"))
    .Select(s => s.InnerText).FirstOrDefault();
 
  var address = node.Descendants("span")
    .Where(s => s.GetAttributeValue("id", "").Contains("AddressLine"))
    .Select(s => s.InnerText).FirstOrDefault();
 
  var phone = node.Descendants("span")
    .Where(s => s.GetAttributeValue("class", "").Contains("ecAddress"))
    .Select(s => s.InnerText).FirstOrDefault();
 
  var website = string.Empty;
 
  var links = node.Descendants("a")
    .Where(s => s.GetAttributeValue("id", "").Contains("ohlWeb"))
    .Select(s => s).FirstOrDefault();
 
  if (links != null)
   website = links.GetAttributeValue("href", "");
 
  if (!string.IsNullOrEmpty(bName))
  {
   var bCard = new Business()
   {
    Address = address ?? string.Empty,
    Name = bName ?? string.Empty,
    PhoneNumber = phone ?? string.Empty,
    Website = website ?? string.Empty
   };   
                        //do something with bCard
  }
 }
}

Weather information from Accuweather
Example page: http://www.clipthetrip.com/city/london
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
   public class Weather
{
 public string city;
 public int curr_temp;
 public string curr_text;
 public int curr_icon;
 
 public List<Forecast> forecast = new List<Forecast>();
}
public class Forecast
{
 public string day_date;
 public string day_text;
 public int day_icon;
 public int day_htemp;
 public int day_ltemp;
}
 
//code
Weather _weather;
 
if (_weather == null)
{
 _weather = new Weather();
 
 string _location = code;
 string _metric = "0";
 
 string _url = string.Format("http://wwwa.accuweather.com/adcbin/forecastfox/weather_data.asp?location={0}&metric={1}", _location, _metric);
 
 string _xml = Utils.DownloadWebPage(_url);
 
 var _xmlDocument = new XmlDocument();
 _xmlDocument.LoadXml(_xml);
 
 var _mgr = new XmlNamespaceManager(_xmlDocument.NameTable);
 _mgr.AddNamespace("pf", _xmlDocument.DocumentElement.NamespaceURI);
 
 _weather.city =_xmlDocument.SelectSingleNode("/pf:adc_database/pf:local/pf:city", _mgr).InnerText;
 _weather.curr_temp = Convert.ToInt32(_xmlDocument.SelectSingleNode("/pf:adc_database/pf:currentconditions/pf:temperature", _mgr).InnerText);
 _weather.curr_text = _xmlDocument.SelectSingleNode("/pf:adc_database/pf:currentconditions/pf:weathertext", _mgr).InnerText;
 _weather.curr_icon = Convert.ToInt32(_xmlDocument.SelectSingleNode("/pf:adc_database/pf:currentconditions/pf:weathericon", _mgr).InnerText);
 
 var _xmlNodeList = _xmlDocument.SelectNodes("/pf:adc_database/pf:forecast/pf:day", _mgr);
 int _day = _xmlNodeList.Count;
 int i = 0;
 foreach (var _dayItem in _xmlNodeList)
 {
  var _forecast = new Forecast();
 
  _forecast.day_date = _dayItem["obsdate"].InnerXml;
  _forecast.day_text = _dayItem.SelectSingleNode("pf:daytime", _mgr)["txtshort"].InnerXml;
  _forecast.day_icon = Convert.ToInt32(_dayItem.SelectSingleNode("pf:daytime", _mgr)["weathericon"].InnerXml);
  _forecast.day_htemp = Convert.ToInt32(_dayItem.SelectSingleNode("pf:daytime", _mgr)["hightemperature"].InnerXml);
  _forecast.day_ltemp = Convert.ToInt32(_dayItem.SelectSingleNode("pf:daytime", _mgr)["lowtemperature"].InnerXml);
 
  _weather.forecast.Add(_forecast);
 
  i++;
  // 5 day forecast
  if (i == 5) break;
 }
}

Image Resizing using SimpleDotImage
1
2
3
4
5
6
7
8
9
10
using (var _imgProcessing = new ImageProcessing())
{
 using (var _waterMarkedImage = _imgProcessing.Process(
         imagePath: file,
         resize: 164
       ))
 {
  ImageHelper.SaveStream(_waterMarkedImage, thumbFile);
 }
}

Javascript and CSS bundling using Web.Optimization
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
using System.Web.Optimization;
 
namespace ClipTheTripWeb
{
 public class BundleConfig
 {
  public static void RegisterBundles(BundleCollection bundles)
  {
   var homeBundleJs = new Bundle("~/content/js/home", new JsMinify());
   homeBundleJs.Include (
      "~/Content/Js/jquery.fullscreenr.js",      
      "~/Content/Js/jquery.autoSuggest.js",
      "~/Content/Js/home.js"
   );
 
   var homeBundleCss = new Bundle("~/content/css/home", new CssMinify());
   homeBundleCss.Include (
    "~/Content/Css/Site.css",
    "~/Content/Css/autoSuggest.css",
    "~/Content/Css/tiles.css"
   );
    
   .
   .
   .
   bundles.Add(homeBundleCss);
   bundles.Add(homeBundleJs);
  }
 }
}
 
 
//Global.ascx
protected void Application_Start()
{
 AreaRegistration.RegisterAllAreas();
 BundleConfig.RegisterBundles(BundleTable.Bundles);
 .
 .
}

Labels: , , ,