<< назад Сайт с Google-maps API, имперсонализацией и Dynamic LINQ Expression.
Этот мой сайт работает по следующему принципу. Фирма Форт-Нокс имеет постоянный прайс-лист на построенные обьекты и еженедельно рассылает по мылу предложения для риэлтеров в виде Word-таблички с хорошими скидками. Весь прайс лист (относительно редко) и горячие предложения со сниженными ценами, которые рассылают менеджеры в виде WORD-таблички, моими загрузчиками-конвертерами импортируются в базу. Владелец этого бизнеса также заключил множество договорв с другим фирмами-застройщиками и они высылали мне данные точно в формате ФортНокса и эти предложения тоже импортировались в общую базу.
Далее все обьекты отображаются на карте Google-maps, а также поисковый блок справа правильно формирует возможности поиска. То есть, например если проимпортированы все квартиры в подвальных помещениях, то границы поиска будут только минус первый этаж и этот комбобокс будет вообще недоступен. То есть границы работы поисковика формируютс по реально загруженным данным:
1: ALTER procedure[dbo].[GetPriceBound]
2: @Complex as integer as
3: (
4: select
5: MIN (Area) as Min_Area, MAX(Area) as Max_Area ,
6: MIN (TotalArea) as Min_TotalArea, MAX(TotalArea) as Max_TotalArea ,
7: MIN (EURO) as Min_EURO, MAX(EURO) as Max_EURO ,
8: MIN ([Floor]) as Min_Floor, MAX([Floor]) as Max_Floor ,
9: MIN (Rooms) as Min_Rooms, MAX(Rooms) as Max_Rooms
10: from [FortNoks].[dbo].[Price]
11: Where ToComplex=@Complex
12: )
Соответственно, Application_Start вызывает это формирование границ поисковика:
1: Public Shared Sub GetGlobals()
2: Dim db1 As New FortNoksDataContext
3: HttpContext.Current.Application("PriceBound") = (From X In db1.PriceBounds Select X).First
4: HttpContext.Current.Application("PriceNotes") = (From X In db1.PriceNotes Select X).ToList
5: HttpContext.Current.Application("PriceViews") = (From X In db1.PriceViews Select X).ToList
6: HttpContext.Current.Application("SpecialPrice") = (From X In db1.Special1s Select X).ToList
7: End Sub
Качественный поиск и сортировка по разным параметрам - былы главной поставленной мне заказчиком задачей. Потому что на сайтах застройщиков, например Форт-Нокса, вообще ничего толком найти нельзя. Поэтому качественную динамическую сортировку в этом сайте я сделал в этом сайте на динамических выражениях LINQ:
1: Imports System.Linq.Dynamic
2: Imports System.Linq.Expressions
3:
4: Public Class Common
5:
6: Public Shared Function GetPrice(ByVal PRM As FormCollection, PageSize As Integer, PageNum As Integer) As System.Collections.Generic.List(Of Price1)
7: 'Max_Area
8: 'Max_EURO
9: 'Max_Floor
10: 'Max_Rooms
11: 'Max_TotalArea
12: 'Min_Area
13: 'Min_EURO
14: 'Min_Floor
15: 'Min_Rooms
16: 'Min_TotalArea
17: 'PriceNotes
18: 'PriceViews
19: 'Sort1
20: 'Sort4
21: Dim Filter As String = GetFilter(PRM)
22:
23: Dim db1 As New FortNoksDataContext
24: Dim Query = db1.Price1s.Where(Filter).OrderBy(PRM("Sort1") & "," & PRM("Sort4") & ",i").Skip(PageNum * PageSize).Take(PageSize)
25: 'Response.Write(db1.GetCommand(Query))
26: Dim List = (From X In Query Select X).ToList
27: Return List
28: End Function
29:
30: Public Shared Function GetFilter(ByVal PRM As FormCollection) As String
31: Dim Filter As String = ""
32: If PRM IsNot Nothing Then
33: If PRM("ID") IsNot Nothing Then
34: Filter &= "ToComplex=" & PRM("ID")
35: End If
36: If PRM("PriceViews") <> "-" Then
37: If Filter <> "" Then
38: Filter = Filter & " and "
39: End If
40: Filter &= "Views=""" & PRM("PriceViews") & """"
41: End If
42: If PRM("PriceNotes") <> "-" Then
43: If Filter <> "" Then
44: Filter = Filter & " and "
45: End If
46: Filter &= "Notes=""" & PRM("PriceNotes") & """"
47: End If
48: If PRM("Max_Area") <> "" Then
49: If Filter <> "" Then
50: Filter = Filter & " and "
51: End If
52: Filter &= "Area<=" & PRM("Max_Area")
53: End If
54: If PRM("Max_EURO") <> "" Then
55: If Filter <> "" Then
56: Filter = Filter & " and "
57: End If
58: Filter &= "EURO<=" & PRM("Max_EURO")
59: End If
60: If PRM("Max_Floor") <> "" Then
61: If Filter <> "" Then
62: Filter = Filter & " and "
63: End If
64: Filter &= "Floor<=" & PRM("Max_Floor")
65: End If
66: If PRM("Max_Rooms") <> "" Then
67: If Filter <> "" Then
68: Filter = Filter & " and "
69: End If
70: Filter &= "Rooms<=" & PRM("Max_Rooms")
71: End If
72: If PRM("Max_TotalArea") <> "" Then
73: If Filter <> "" Then
74: Filter = Filter & " and "
75: End If
76: Filter &= "TotalArea<=" & PRM("Max_TotalArea")
77: End If
78: If PRM("Min_Area") <> "" Then
79: If Filter <> "" Then
80: Filter = Filter & " and "
81: End If
82: Filter &= "Area>=" & PRM("Min_Area")
83: End If
84: If PRM("Min_EURO") <> "" Then
85: If Filter <> "" Then
86: Filter = Filter & " and "
87: End If
88: Filter &= "EURO>=" & PRM("Min_EURO")
89: End If
90: If PRM("Min_Floor") <> "" Then
91: If Filter <> "" Then
92: Filter = Filter & " and "
93: End If
94: Filter &= "Floor>=" & PRM("Min_Floor")
95: End If
96: If PRM("Min_Rooms") <> "" Then
97: If Filter <> "" Then
98: Filter = Filter & " and "
99: End If
100: Filter &= "Rooms>=" & PRM("Min_Rooms")
101: End If
102: If PRM("Min_TotalArea") <> "" Then
103: If Filter <> "" Then
104: Filter = Filter & " and "
105: End If
106: Filter &= "TotalArea>=" & PRM("Min_TotalArea")
107: End If
108: End If
109: If Filter = "" Then Filter = "1=1"
110: Return Filter
111: End Function
Кроме того, сайт имеет гигабайтную базу фотографий построенных апартаментов, которая конечно же не может уместиться непосредственно на WEB-сервере. Поэтому для доступа к фотографиям требуется имперсонализация учетной записи. Таким образом, сайт содеожит несколько небольших фрагментов кода, о которые есть смысл сказать хоть что-то. Импортер WORD-таблички со спецпредложениями, описанный здесь, код имперсонализации для доступа к удаленному от WEB-сервера рисурсу для того, чтобы забрать оттуда фотографии и отдать их потоку браузера. И код использующий GOGLE MAPS API, который мы рассмотрим чуть подробнее.
Контрол MAP.ascx, в котором содержится DIV map_canvas, вместо которого бужет вставлен фрейм с Google-картой, выглядит вот так:
1: <%@ Control Language="VB" Inherits="System.Web.Mvc.ViewUserControl" %>
2:
3: <style type="text/css">
4: .poputMap {
5: height:500px;
6: position:relative;
7: z-index:1;
8: margin-top:-4px;
9: }
10:
11: </style>
12: <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
13: <div id="map_canvas" class="poputMap">
14: </div>
15: <script type="text/javascript" src="../../map.js" ></script>
Эта страничка содержит вызов библиотеки Google и моего нижеследующего скрипта, который вычитывает с сервера координаты загруженных в базу комплексов (домов) с обьектами продаваемой недвижимости (квартирыми).
1: var MyMap;
2:
3: function addmarker(id, city, name, geo1, geo2) {
4: var pos = new google.maps.LatLng(geo1, geo2);
5: var marker = new google.maps.Marker({
6: position: pos,
7: map: MyMap,
8: title: name + ' (' + city + ')'
9: });
10: google.maps.event.addListener(marker, 'click', function () {
11: window.location.href = '/Complex/Index/' + id;
12: });
13:
14: }
15:
16: function kurort_result(json_array) {
17: if (json_array.length) {
18: $.each(json_array, function (index, term) {
19: addmarker(term.ID, term.City, term.Name, term.Geo1, term.Geo2);
20: });
21: }
22: };
23:
24: function fill_kurort() {
25: $.ajax({
26: 'url': '/GetComplex.ashx',
27: 'dataType': 'json',
28: 'type': 'GET',
29: 'success': kurort_result
30: });
31: };
32:
33: function initialize() {
34: var myLatlng = new google.maps.LatLng(42.706407, 27.751808);
35: var myOptions = {
36: zoom: 13,
37: center: myLatlng,
38: mapTypeId: google.maps.MapTypeId.HYBRID
39: }
40: MyMap = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
41:
42: fill_kurort();
43:
44: }
45:
46: google.maps.event.addDomListener(window, 'load', initialize);
Как видите, в этом jQuery-скрипте вообще ничего такого особенного нет, обыкновенный AJAX-вызов серверного хандлера GetComplex.ashx, содержащие координаты маркера. Маркер Гугловой карты формируется в строке 5, в строке 10 формируется URL сайта для перехода по клику на маркере.
А код хандлера GetComplex.ashx содержит просто обращение к базе и формирвоание JSON:
1: Imports System.Web
2: Imports System.Web.Services
3:
4: Public Class GetComplex
5: Implements System.Web.IHttpHandler
6:
7:
8: Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
9: 'проверка JSON-форматирования
10: 'context.Response.ContentType = "application/json"
11: 'context.Response.Charset = "utf-8"
12: 'context.Response.Write("[""a"",""b"",""c""]")
13: 'Exit Sub
14: '
15: Try
16: Dim DB1 As New FortNoksDataContext
17: Dim Result As New StringBuilder("")
18: Dim AllRecords = (From X In DB1.Complex1s Select X).ToList()
19: If AllRecords.Count > 0 Then
20: Result.Append("[")
21: For i As Integer = 0 To AllRecords.Count - 1
22: Result.Append("{""")
23: Result.Append("ID"":""")
24: Result.Append(AllRecords(i).ID)
25: Result.Append(""",""")
26: Result.Append("City"":""")
27: Result.Append(AllRecords(i).City_Name)
28: Result.Append(""",""")
29: Result.Append("Name"":""")
30: Result.Append(AllRecords(i).Name.Trim)
31: Result.Append(""",""")
32: Result.Append("Geo1"":""")
33: If AllRecords(i).Latitude Is Nothing Then
34: Result.Append("0")
35: Else
36: Result.Append(AllRecords(i).Latitude.Trim)
37: End If
38: Result.Append(""",""")
39: Result.Append("Geo2"":""")
40: If AllRecords(i).Longitude Is Nothing Then
41: Result.Append("0")
42: Else
43: Result.Append(AllRecords(i).Longitude.Trim)
44: End If
45: Result.Append("""},")
46: Result.AppendLine()
47: Next
48: Result.Remove(Result.Length - 3, 3)
49: Result.Append("]")
50: End If
51: context.Response.ContentType = "application/json"
52: context.Response.Charset = "utf-8"
53: context.Response.Write(Result.ToString)
54: Catch ex As Exception
55: context.Response.ContentType = "text/plain"
56: context.Response.Write(ex.Message)
57: End Try
58: End Sub
59:
60:
61: ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
62: Get
63: Return False
64: End Get
65: End Property
66:
67: End Class
Вот таким простым способом координаты из базы попадают на Гугловую карту. Аналогичным способом я делаю все свои сайты с Гугловыми картами, например вот этот:
Жаль, что этот интересный проект не развивался дальше. При разработке этого проекта качество поиска было и отображение на карте было первостепенной задачей, а улучшить дизайн предполагалось позднее (тем более сайт написан на MVC и это сделать совсем просто), но к сожалению, заказчик этого сайта бесследно пропал и развитие проекта было прекращено.
|