Line 1: using System;
Line 2: using System.Data;
Line 3: using System.Data.SqlClient;
Line 4: using System.Collections.Specialized;
Line 5: using System.Data;
Line 6: using System.Data.SqlClient;
Line 7: using System.Web.Caching;
Line 8: using System.Security.Cryptography;
Line 9: using System.Text;
Line 10: using IOSI.Database;
Line 11: using Newtonsoft.Json;
Line 12: using System.Collections.Generic;
Line 13:
Line 14:
Line 15: public class SearchResultsSnapshot
Line 16: {
Line 17: [JsonProperty("searchResultsUrl")]
Line 18: public string SearchResultsUrl { get; set; }
Line 19:
Line 20: [JsonProperty("nextResultsPageUrl")]
Line 21: public string NextResultsPageUrl { get; set; }
Line 22:
Line 23: [JsonProperty("query")]
Line 24: public object Query { get; set; }
Line 25:
Line 26: [JsonProperty("results")]
Line 27: public List<SearchResultsSnapshotUnit> Results { get; set; }
Line 28:
Line 29: public SearchResultsSnapshot(string resultsPageUrl, string nextResultsPageUrl, object query)
Line 30: {
Line 31: SearchResultsUrl = resultsPageUrl;
Line 32: NextResultsPageUrl = nextResultsPageUrl;
Line 33:
Line 34: Query = query;
Line 35:
Line 36: Results = new List<SearchResultsSnapshotUnit>();
Line 37: }
Line 38: }
Line 39:
Line 40: public class SearchResultsSnapshotUnit
Line 41: {
Line 42:
Line 43: [JsonProperty("id")]
Line 44: public int ID { get; set; }
Line 45:
Line 46: [JsonProperty("segment")]
Line 47: public string Segment { get; set; }
Line 48:
Line 49: [JsonProperty("year")]
Line 50: public int Year { get; set; }
Line 51:
Line 52: [JsonProperty("make")]
Line 53: public string Make { get; set; }
Line 54:
Line 55: [JsonProperty("model")]
Line 56: public string Model { get; set; }
Line 57:
Line 58: [JsonProperty("type")]
Line 59: public string Type { get; set; }
Line 60:
Line 61: [JsonProperty("askingPrice")]
Line 62: public float? AskingPrice { get; set; }
Line 63:
Line 64: [JsonProperty("specsheetUrl")]
Line 65: public string SpecsheetUrl { get; set; }
Line 66:
Line 67: [JsonProperty("thumbnailUrl")]
Line 68: public string ThumbnailUrl { get; set; }
Line 69:
Line 70: [JsonProperty("photoUrl")]
Line 71: public string PhotoUrl { get; set; }
Line 72:
Line 73:
Line 74: public SearchResultsSnapshotUnit(int id, string segment, int year, string make, string model, string type, float? price, string specsheetUrl)
Line 75: {
Line 76: ID = id;
Line 77: Year = year;
Line 78: Make = make;
Line 79: Model = model;
Line 80: Type = type;
Line 81: AskingPrice = price;
Line 82:
Line 83: SpecsheetUrl = specsheetUrl;
Line 84: }
Line 85:
Line 86: public static SearchResultsSnapshotUnit FromAzureSearchResult(dynamic unit)
Line 87: {
Line 88: int unitID = int.Parse((string)unit.id);
Line 89:
Line 90: var specsheet = RouteGenerator.GetSpecSheetUrl(unitID,
Line 91: (string)unit.segment,
Line 92: (int)(Int64)unit.year,
Line 93: (string)unit.make,
Line 94: (string)unit.model,
Line 95: "");
Line 96:
Line 97: var ret = new SearchResultsSnapshotUnit(unitID,
Line 98: (string)unit.segment,
Line 99: (int)(Int64)unit.year,
Line 100: (string)unit.make,
Line 101: (string)unit.model,
Line 102: (string)unit.type,
Line 103: (float?)unit.price,
Line 104: specsheet
Line 105: );
Line 106:
Line 107:
Line 108:
Line 109: if(unit.photos.Count > 0)
Line 110: {
Line 111: ret.ThumbnailUrl = Helpers.GetDynamicUnitPhotoUrl(ret.ID, "300x", ret.Year, ret.Make, ret.Model, 1);
Line 112: ret.PhotoUrl = Helpers.GetDynamicUnitPhotoUrl(ret.ID, "800x", ret.Year, ret.Make, ret.Model, 1);
Line 113: }
Line 114:
Line 115: return ret;
Line 116: }
Line 117: }
Line 118:
Line 119:
Line 120: public class SearchManager
Line 121: {
Line 122:
Line 123: private static string VolatileGetSearchID(object query)
Line 124: {
Line 125: var text = JsonConvert.SerializeObject(query);
Line 126:
Line 127: return VolatileGetSearchID(text);
Line 128: }
Line 129:
Line 130: private static string VolatileGetSearchID(string queryText)
Line 131: {
Line 132: using (var sha1 = new SHA1Managed())
Line 133: {
Line 134: var hash = sha1.ComputeHash(Encoding.UTF8.GetBytes(queryText));
Line 135:
Line 136: return Convert.ToBase64String(hash)
Line 137: .Replace("+", "-")
Line 138: .Replace("/", "-")
Line 139: .Replace("=", "");
Line 140: }
Line 141:
Line 142: return null;
Line 143: }
Line 144:
Line 145: /*
Line 146: private static string VolatileGetSearchKey(string id)
Line 147: {
Line 148: return string.Format("soarr.com:search:{0}", id);
Line 149: }
Line 150:
Line 151: private static string VolatileGetAzureSearchResultsKey(string id)
Line 152: {
Line 153: return string.Format("soarr.com:search:azure:results:{0}", id);
Line 154: }
Line 155: */
Line 156:
Line 157: private static string VolatileGetSearchResultsSnapshotKey(string id)
Line 158: {
Line 159: return string.Format("soarr.com:search:snapshot:v1:{0}", id);
Line 160: }
Line 161:
Line 162: /*
Line 163: public static bool VolatileSearchExists(object query)
Line 164: {
Line 165: var id = VolatileGetSearchID(query);
Line 166: var key = VolatileGetSearchKey(id);
Line 167:
Line 168: try
Line 169: {
Line 170: return RedisCacheManager.Instance.KeyExists(key);
Line 171: }
Line 172: catch
Line 173: {
Line 174:
Line 175: }
Line 176:
Line 177: return false;
Line 178: }
Line 179:
Line 180: public static bool VolatileAzureSearchResultsExists(object query)
Line 181: {
Line 182: var id = VolatileGetSearchID(query);
Line 183: var key = VolatileGetSearchKey(id);
Line 184:
Line 185: try
Line 186: {
Line 187: return RedisCacheManager.Instance.KeyExists(key);
Line 188: }
Line 189: catch
Line 190: {
Line 191:
Line 192: }
Line 193:
Line 194: return false;
Line 195: }
Line 196: */
Line 197:
Line 198: public static string VolatileSaveResultsSnapshot(string searchResultsUrl, AzureSearchResult result)
Line 199: {
Line 200: return VolatileSaveResultsSnapshot(searchResultsUrl, null, result);
Line 201: }
Line 202:
Line 203: public static string VolatileSaveResultsSnapshot(string searchResultsUrl, string nextResultsPageUrl, AzureSearchResult result)
Line 204: {
Line 205: if(result == null || result.Query == null)
Line 206: return null;
Line 207:
Line 208: const CACHE_MINUTES = 45;
Line 209: var queryText = JsonConvert.SerializeObject(result.Query);
Line 210: var id = VolatileGetSearchID(queryText);
Line 211:
Line 212: var snapshot = new SearchResultsSnapshot(searchResultsUrl, nextResultsPageUrl, result.Query);
Line 213:
Line 214: foreach(var unit in result.Value)
Line 215: {
Line 216: snapshot.Results.Add(SearchResultsSnapshotUnit.FromAzureSearchResult(unit));
Line 217: }
Line 218:
Line 219: var text = JsonConvert.SerializeObject(snapshot);
Line 220: var key = VolatileGetSearchResultsSnapshotKey(id);
Line 221:
Line 222: try
Line 223: {
Line 224: RedisCacheManager.Instance.Set(key, text, TimeSpan.FromMinutes(CACHE_MINUTES));
Line 225:
Line 226: return id;
Line 227: }
Line 228: catch
Line 229: {
Line 230:
Line 231: }
Line 232:
Line 233: return null;
Line 234:
Line 235: }
Line 236:
Line 237:
Line 238: public static SearchResultsSnapshot VolatileGetSearchResultsSnapshot(string id)
Line 239: {
Line 240: if(string.IsNullOrEmpty(id))
Line 241: return null;
Line 242:
Line 243: var key = VolatileGetSearchResultsSnapshotKey(id);
Line 244:
Line 245: try
Line 246: {
Line 247: string value = RedisCacheManager.Instance.Get<string>(key);
Line 248:
Line 249: return JsonConvert.DeserializeObject<SearchResultsSnapshot>(value);
Line 250: }
Line 251: catch(Exception ex)
Line 252: {
Line 253: //System.Web.HttpContext.Current.Response.Write(ex.Message);
Line 254: }
Line 255:
Line 256: return null;
Line 257:
Line 258: }
Line 259:
Line 260: /*
Line 261: public static string VolatileSaveAzureSearchResults(AzureSearchResult result)
Line 262: {
Line 263: if(result == null || result.Query == null)
Line 264: return null;
Line 265:
Line 266: var queryText = JsonConvert.SerializeObject(result.Query);
Line 267: var id = VolatileGetSearchID(queryText);
Line 268:
Line 269: var text = JsonConvert.SerializeObject(result);
Line 270: var key = VolatileGetAzureSearchResultsKey(id);
Line 271:
Line 272: try
Line 273: {
Line 274: RedisCacheManager.Instance.Set(key, text, TimeSpan.FromMinutes(20));
Line 275:
Line 276: return id;
Line 277: }
Line 278: catch
Line 279: {
Line 280:
Line 281: }
Line 282:
Line 283: return null;
Line 284: }
Line 285:
Line 286:
Line 287: public static AzureSearchResult VolatileGetAzureSearchResults(string id)
Line 288: {
Line 289: if(string.IsNullOrEmpty(id))
Line 290: return null;
Line 291:
Line 292: var key = VolatileGetAzureSearchResultsKey(id);
Line 293:
Line 294: try
Line 295: {
Line 296: string value = RedisCacheManager.Instance.Get<string>(key);
Line 297:
Line 298: return JsonConvert.DeserializeObject<AzureSearchResult>(value);
Line 299: }
Line 300: catch(Exception ex)
Line 301: {
Line 302: //System.Web.HttpContext.Current.Response.Write(ex.Message);
Line 303: }
Line 304:
Line 305: return null;
Line 306:
Line 307: }
Line 308:
Line 309: public static string VolatileSaveSearch(object query)
Line 310: {
Line 311: if(query == null)
Line 312: return null;
Line 313:
Line 314: var text = JsonConvert.SerializeObject(query);
Line 315: var id = VolatileGetSearchID(text);
Line 316: var key = VolatileGetSearchKey(id);
Line 317:
Line 318: try
Line 319: {
Line 320: RedisCacheManager.Instance.Set(key, text, TimeSpan.FromHours(2));
Line 321:
Line 322: return id;
Line 323: }
Line 324: catch
Line 325: {
Line 326:
Line 327: }
Line 328:
Line 329: return null;
Line 330: }
Line 331:
Line 332: public static object VolatileGetSearch(string id)
Line 333: {
Line 334: if(string.IsNullOrEmpty(id))
Line 335: return null;
Line 336:
Line 337: var key = VolatileGetSearchKey(id);
Line 338:
Line 339: try
Line 340: {
Line 341: string value = RedisCacheManager.Instance.Get<string>(key);
Line 342: if(string.IsNullOrEmpty(value))
Line 343: return null;
Line 344:
Line 345: return JsonConvert.DeserializeObject(value);
Line 346: }
Line 347: catch(Exception ex)
Line 348: {
Line 349: //System.Web.HttpContext.Current.Response.Write(ex.Message);
Line 350: }
Line 351:
Line 352: return null;
Line 353: }
Line 354: */
Line 355:
Line 356:
Line 357: public static bool SaveSearch(NameValueCollection queryString)
Line 358: {
Line 359: SqlConnection conn = SOARRDatabase.GetSqlConnection();
Line 360: bool ret = false;
Line 361:
Line 362: SqlCommand cmd = new SqlCommand("sp_LocatorSearchAdd", conn);
Line 363: cmd.CommandType = CommandType.StoredProcedure;
Line 364:
Line 365: try
Line 366: {
Line 367: cmd.Parameters.AddWithValue("@vehtype", GetQueryStringValue(queryString, "vehtype", (int?)null));
Line 368: cmd.Parameters.AddWithValue("@breakout", GetQueryStringValue(queryString, "breakout", (string)null));
Line 369: cmd.Parameters.AddWithValue("@year_min", GetQueryStringValue(queryString, "lyear", (short?)null));
Line 370: cmd.Parameters.AddWithValue("@year_max", GetQueryStringValue(queryString, "hyear", (short?)null));
Line 371: cmd.Parameters.AddWithValue("@make", GetQueryStringValue(queryString, "make", (string)null));
Line 372: cmd.Parameters.AddWithValue("@model", GetQueryStringValue(queryString, "model", (string)null));
Line 373: cmd.Parameters.AddWithValue("@engine_make", GetQueryStringValue(queryString, "enginemake", (string)null));
Line 374: cmd.Parameters.AddWithValue("@hp_min", GetQueryStringValue(queryString, "lhp", (short?)null));
Line 375: cmd.Parameters.AddWithValue("@hp_max", GetQueryStringValue(queryString, "hhp", (short?)null));
Line 376: cmd.Parameters.AddWithValue("@price_min", GetQueryStringValue(queryString, "lprice", (float?)null));
Line 377: cmd.Parameters.AddWithValue("@price_max", GetQueryStringValue(queryString, "hprice", (float?)null));
Line 378: cmd.Parameters.AddWithValue("@state", GetQueryStringValue(queryString, "state", (string)null));
Line 379: cmd.Parameters.AddWithValue("@webdomain", "soarr.com");
Line 380:
Line 381:
Line 382: conn.Open();
Line 383: cmd.ExecuteNonQuery();
Line 384:
Line 385: ret = true;
Line 386: }
Line 387: catch(Exception e)
Line 388: {
Line 389:
Line 390: }
Line 391: finally
Line 392: {
Line 393: if(conn.State != ConnectionState.Closed)
Line 394: conn.Close();
Line 395: }
Line 396:
Line 397: return ret;
Line 398: }
Line 399:
Line 400: public static DataTable GetTopSearches(string segment, int count)
Line 401: {
Line 402: return GetTopSearches(segment, null, null, count);
Line 403: }
Line 404:
Line 405: public static DataTable GetTopSearches(string segment, int? unitTypeID, string make, int count)
Line 406: {
Line 407: string cacheKey = string.Format("topsearches:{0}:{1}:{2}:{3}", segment ?? "all", unitTypeID.GetValueOrDefault(), make ?? "", count);
Line 408:
Line 409: DataTable dt = GetCachedValue<DataTable>(cacheKey);
Line 410: if(dt != null)
Line 411: return dt;
Line 412:
Line 413: using(SqlConnection conn = SOARRDatabase.GetSqlConnection())
Line 414: {
Line 415: dt = new DataTable();
Line 416: SqlCommand cmd = new SqlCommand("sp_LocatorGetTopSearches", conn);
Line 417: cmd.CommandType = CommandType.StoredProcedure;
Line 418:
Line 419: cmd.Parameters.AddWithValue("@webdomain", "soarr.com");
Line 420: cmd.Parameters.AddWithValue("@breakout", segment);
Line 421: cmd.Parameters.AddWithValue("@unit_type_id", unitTypeID);
Line 422: cmd.Parameters.AddWithValue("@make", make);
Line 423: cmd.Parameters.AddWithValue("@count", count);
Line 424: cmd.Parameters.AddWithValue("@start_date", DateTime.Now.AddMonths(-6));
Line 425:
Line 426: try
Line 427: {
Line 428: SqlDataAdapter da = new SqlDataAdapter(cmd);
Line 429:
Line 430: da.Fill(dt);
Line 431:
Line 432: SetCachedValue<DataTable>(cacheKey, dt, DateTime.Now.AddHours(48));
Line 433: }
Line 434: catch(Exception ex)
Line 435: {
Line 436: System.Web.HttpContext.Current.Response.Write(ex.Message);
Line 437: }
Line 438: }
Line 439:
Line 440:
Line 441: return dt;
Line 442: }
Line 443:
Line 444: private static T GetCachedValue<T>(string key)
Line 445: {
Line 446: try
Line 447: {
Line 448: return (T)System.Web.HttpContext.Current.Cache[key];
Line 449: }
Line 450: catch
Line 451: {
Line 452:
Line 453: }
Line 454:
Line 455: return default(T);
Line 456: }
Line 457:
Line 458: private static void SetCachedValue<T>(string key, T value, DateTime absoluteExpiration)
Line 459: {
Line 460: try
Line 461: {
Line 462: System.Web.HttpContext.Current.Cache.Add(key, value, null, absoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.High, null);
Line 463: }
Line 464: catch
Line 465: {
Line 466:
Line 467: }
Line 468: }
Line 469:
Line 470: private static string GetQueryStringValue(NameValueCollection nvc, string key, string defaultVal)
Line 471: {
Line 472: string ret = defaultVal;
Line 473: string s = null;
Line 474:
Line 475: try
Line 476: {
Line 477: s = nvc[key];
Line 478:
Line 479: if(s != null)
Line 480: ret = s;
Line 481: }
Line 482: catch
Line 483: {
Line 484:
Line 485: }
Line 486:
Line 487: return ret;
Line 488: }
Line 489:
Line 490: private static int? GetQueryStringValue(NameValueCollection nvc, string key, int? defaultVal)
Line 491: {
Line 492: int? ret = defaultVal;
Line 493: string s = null;
Line 494:
Line 495: try
Line 496: {
Line 497: s = nvc[key];
Line 498:
Line 499: if(s != null && s.Length > 0)
Line 500: {
Line 501: try
Line 502: {
Line 503: ret = int.Parse(s);
Line 504: }
Line 505: catch
Line 506: {
Line 507:
Line 508: }
Line 509: }
Line 510: }
Line 511: catch
Line 512: {
Line 513:
Line 514: }
Line 515:
Line 516: return ret;
Line 517: }
Line 518:
Line 519: private static short? GetQueryStringValue(NameValueCollection nvc, string key, short? defaultVal)
Line 520: {
Line 521: short? ret = defaultVal;
Line 522: string s = null;
Line 523:
Line 524: try
Line 525: {
Line 526: s = nvc[key];
Line 527:
Line 528: if(s != null && s.Length > 0)
Line 529: {
Line 530: try
Line 531: {
Line 532: ret = short.Parse(s);
Line 533: }
Line 534: catch
Line 535: {
Line 536:
Line 537: }
Line 538: }
Line 539: }
Line 540: catch
Line 541: {
Line 542:
Line 543: }
Line 544:
Line 545: return ret;
Line 546: }
Line 547:
Line 548: private static float? GetQueryStringValue(NameValueCollection nvc, string key, float? defaultVal)
Line 549: {
Line 550: float? ret = defaultVal;
Line 551: string s = null;
Line 552:
Line 553: try
Line 554: {
Line 555: s = nvc[key];
Line 556:
Line 557: if(s != null && s.Length > 0)
Line 558: {
Line 559: try
Line 560: {
Line 561: ret = float.Parse(s);
Line 562: }
Line 563: catch
Line 564: {
Line 565:
Line 566: }
Line 567: }
Line 568: }
Line 569: catch
Line 570: {
Line 571:
Line 572: }
Line 573:
Line 574: return ret;
Line 575: }
Line 576:
Line 577: }
Line 578:
Line 579:
|