(MVC) MVC (2016 год)

Як будуються адаптивні сайти для мобільників та десктопів на CLASSIC ASP.NET


1. Загальна схема - єдині інтерфейси для контролів та Generic-код.



На цієї сторінці я хотів розповісти, яким чином я будую сайти для мобільників на ASP.NET. Загально для мобільників звичайні сторінки виглядають як SPA-page (single page application). Але інша справа у тому, що URL сторінки повинен бути тим же самим, що для звичайного сайту. Але сторінка вже має бути побудована інакше, тобто без пейджерів, у вигляді SPA-page.

Ось порівняйте, будь ласка, як виглядає та є сама сторінка якщо її подивитися з мобільника та з десктопного комп'ютера.



Як бачите, одна і та ж сторінки побудовані зовсім по-різному, в залежності від того чи з мобільника ви неї заходите, чи з десктопу. Хоча мають один і той же URL.

Зараз я розповім, як це робиться на класіке ASP.NET.


Все починається є того, що всі сторінки, які повинні мати мобільний вариант (а наприклад адмінка чи кабінет може й не повинна мати такий вигляд) наслідуються від специфічної сторінки, яка виглядає ось приблизно так:



Ось тут є її source-код 8. Сайт для мобільників..Як бачите, ця базова сторінка робить такі головні операції - по-перше, дивиться на куку (мобільна/немобільна), якщо ніякої куки немає взагалі, то цей код дивиться на тип браузеру та розмір екрану, що приносить браузер у реквесті, і залежно від цього додає до базової сторінки свойство - мобільний чи не мобільний реквест. Ну по-друге, якщо реквест мобільний то ця базова сторінка змінює мастер-пейжд на мобільний варіант.

Зверніть увагу, друзі, що цей клас відпрацьовує раніше всіх інших класів проеєкту, бо він працює у дуже специфічній момент PreInit.


Далі усі сторінки з кодом будуються приблизно ось так - по-перше, в них є загальний якийсь розподіл коду на дві частини - тобто на сторінці присутній якийсь великий IF - одна половина коду відпрацьовує для десктопного варіанту, інша - для мобільного.



З іншого боку, всі файли з розміткою побудовані таким точно чином - тобто є половина коду для мобільного варіанту і половина коду - для десктопного.



Але на цьому все не закінчується, а тільки починається. Справа в тому, що всі контроли на десктопной та мобільній версії мати якийсь однаковий інтерфейс. Для того, щоб контроли можно було зачепити якимось ось таким кодом на дженеріку, обидва контрола повинні мати єдиний інтерфейс OneBestObjectCommon. Тоді можливий якийсь єдиний код для обох варіантів сайту - мобільного та десктопного.

  ...   
  57:      Protected Sub DataList1_ItemDataBound(sender As Object, ByVal e As System.Web.UI.WebControls.RepeaterItemEventArgs) Handles DataList1.ItemDataBound
  58:          ItemDataBound(Of OneBestObject)("OneBestObject1", sender, e)
  59:      End Sub
  60:   
  61:      Protected Sub DataList2_ItemDataBound(sender As Object, e As System.Web.UI.WebControls.RepeaterItemEventArgs) Handles DataList2.ItemDataBound
  62:          ItemDataBound(Of OneBestObject_Mobile1)("OneBestObject_Mobile11", sender, e)
  63:      End Sub
  64:   
  65:      Sub ItemDataBound(Of T As OneBestObjectCommon)(ControlID As String, sender As Object, e As System.Web.UI.WebControls.RepeaterItemEventArgs)
  66:          If e.Item.DataItem IsNot Nothing Then
  67:              Dim OneBestObject1 As T = CType(e.Item.FindControl(ControlID), T)
  68:              GetOneObject.SelectParameters("ID").DefaultValue = e.Item.DataItem("ToObject").ToString
  69:              Dim DV1 As Data.DataView = GetOneObject.Select(New DataSourceSelectArguments)
  70:              If DV1 IsNot Nothing Then
  71:                  If DV1.Count > 0 Then
  72:                      If IsDBNull(DV1(0)("IsModerBan")) Then
  73:                          OneBestObject1.i = e.Item.DataItem("i")
  74:                      Else
  75:                          OneBestObject1.Visible = False
  76:                      End If
  77:                  End If
  78:              End If
  79:          End If
  80:      End Sub
  81:  End Class

На сторінці обидва типа контролів (мобільний та десктопний) теж повинні бути вкладені однаковим чином, наприклад якось ось так (aле не так, що один контрол вкладений у Datalist, а інший у Repiter):


  ...   
  42:     <asp:Repeater ID="DataList1" runat="server" 
  43:     DataMember="DefaultView" DataSourceID="GetBestObjects">
  44:        <HeaderTemplate>
  45:            <table style="width:100%;border-collapse:collapse;" cellspacing="0" border="0">
  46:        </HeaderTemplate>
  47:        <ItemTemplate>
  48:            <tr><td>
  49:                <uc1:OneBestObject ID="OneBestObject1" runat="server" />
  50:            </td></tr>
  51:        </ItemTemplate>
  52:        <FooterTemplate>
  53:            </table>
  54:      </FooterTemplate>
  55:     </asp:Repeater>
  ...     
  67:     <asp:Repeater ID="DataList2" runat="server" 
  68:           DataMember="DefaultView" DataSourceID="GetBestObjects">
  69:           <HeaderTemplate>
  70:              <ul class="objects">
  71:           </HeaderTemplate>
  72:           <ItemTemplate>
  73:              <uc4:OneBestObject_Mobile1 ID="OneBestObject_Mobile11" runat="server" />
  74:           </ItemTemplate>
  75:           <FooterTemplate>
  76:              </ul>
  77:           </FooterTemplate>
  78:     </asp:Repeater>
  ...   

Усі контроли, які існують у обох варіантах - мобільного та десктопного, побудовані приблизно однаково, якось ось так:


   1:  Imports Microsoft.VisualBasic
   2:   
   3:  Public Class OneBestObjectCommon
   4:      Inherits System.Web.UI.UserControl
   5:      Implements IOneBestObject
   6:   
   7:      Public Property i As Integer Implements IOneBestObject.i
   8:          Get
   9:              Return ViewState("BestObject_i")
  10:          End Get
  11:          Set(ByVal value As Integer)
  12:              ViewState("BestObject_i") = value
  13:          End Set
  14:      End Property
  15:  End Class

Взагалі усі контроли у цьому проєкті з суфіксом COMMON - це контроли, які мають два варіанта - десктопний та мобільний.



Далі контроли наслідуються від свого загального для мобільного/десктопного контролу класу і програмуються звичайним чином.



2. Приклад реального коду класу для адаптивного сайту.



Сподіваюсь, вище ви зрозуміли глобальну схему будування адаптивних сайтів, тому далі, трохи скорочено (насправді цей код набагато більше), я покажу як можна використовувати якийсь функционал у обох варіантах сторінки - у мобільному та десктопному. Я тут наведу вам трошки скорочений, але реальний приклад класу, щоб ви могли подивитися, яким чином можливо викликати МАЙЖЕ однаковий функціонал у обох різних варіантах сайту. Тут мова іде лише про формування заголовка, який буде однаковий для обох варіантів мобільного та десктопного, але інші надписи на формі будуть різні.

Отже, ось ще раз глобальна схема.



Як бачите, вона ось така - ми перевіряємо редіректи у обох варіантах, потім формуємо однакові мета-теги, а далі різні надписи для мобільного та десктопного варіанту:


  ...  
  41:          If Me.IsMobile Then
  ...                  '
  63:                  Dim E2 As New ObjListParameters
  64:                  E2.CheckRedirect()
  65:                  SetMetaTagAndTitle(E2)
  66:                  SetMobileLabel(E2)
  ...  
  68:          Else
  ...  
  89:                  Dim E2 As New ObjListParameters
  90:                  E2.CheckRedirect()
  91:                  SetMetaTagAndTitle(E2)
  92:                  SetDesktopLabel(E2)
  ...              '
  95:          End If

Загальний для обох варіантів сайту алгоритм, до того ж не пов'язаний з HTML-розміткою я втопив у клас. Тобто ця сторінка може мати 6 засобів виклику з URL, перерахованих у переліку ObjListExecType - як у мобільному, так і у десктопному варіанті. Як і у мобільному, так і у десктопному варіантіі потрібно схиляння (склонение/спряжение). Також для обох варіантів потрібен редірект по Криму, бо цей сайт працює на Росії по їхньому "законодавству". Як бачите, увесь цей загальний для обох типів я втопив у класс.


   1:  Imports Microsoft.VisualBasic
   2:  Imports System.ComponentModel
   3:   
   4:  Public Class ObjListParameters
   5:   
   6:      Public Sub New()
   7:          If HttpContext.Current.Request.QueryString("Country") IsNot Nothing And HttpContext.Current.Request.QueryString("Country") <> "" And HttpContext.Current.Request.QueryString("Country") <> "0" Then
   8:              _CNID = HttpContext.Current.Request.QueryString("Country")
   9:              _CountryName = Grammar.Padej("zCountry", _CNID, "I")
  10:              _CountryName_P = Grammar.Padej("zCountry", _CNID, "P")
  11:              _CountryName_R = Grammar.Padej("zCountry", _CNID, "R")
  12:          End If
  13:          If HttpContext.Current.Request.QueryString("City") IsNot Nothing And HttpContext.Current.Request.QueryString("City") <> "" And HttpContext.Current.Request.QueryString("City") <> "0" Then
  14:              _CTID = HttpContext.Current.Request.QueryString("City")
  15:              _CityName = Grammar.Padej("zKurort", _CTID, "I")
  16:              _CityName_P = Grammar.Padej("zKurort", _CTID, "P")
  17:              _CityName_R = Grammar.Padej("zKurort", _CTID, "R")
  18:          End If
  19:          _NumTypeCheck = IsNumeric(HttpContext.Current.Request.QueryString("Type"))
  20:          If HttpContext.Current.Request.QueryString("Type") IsNot Nothing And _NumTypeCheck Then
  21:              _TID = CInt(HttpContext.Current.Request.QueryString("Type"))
  22:              _TypeName = Grammar.Padej("ObjType", _TID, "I")
  23:              _TypeName_V = Grammar.Padej("ObjType", _TID, "V")
  24:              _TypeName_R = Grammar.Padej("ObjType", _TID, "R")
  25:          End If
  26:          If HttpContext.Current.Request.QueryString("p") IsNot Nothing Then
  27:              If HttpContext.Current.Request.QueryString("p") <> "" Then
  28:                  If IsNumeric(HttpContext.Current.Request.QueryString("p")) = True Then
  29:                      PageNum = HttpContext.Current.Request.QueryString("p")
  30:                  Else
  31:                      PageNum = "0"
  32:                  End If
  33:              End If
  34:          End If
  35:      End Sub
  36:   
  37:      Dim _CNID As String = ""
  38:      ''' <summary>
  39:      ''' ид страны
  40:      ''' </summary>
  41:      Property CNID As String
  42:          Get
  43:              Return _CNID
  44:          End Get
  45:          Set(value As String)
  46:              _CNID = value
  47:          End Set
  48:      End Property
  49:      Dim _CountryName As String = ""
  50:      ''' <summary>
  51:      ''' Страна Именительный
  52:      ''' </summary>
  53:      Property CountryName As String
  54:          Get
  55:              Return _CountryName
  56:          End Get
  57:          Set(value As String)
  58:              _CountryName = value
  59:          End Set
  60:      End Property
  61:      Dim _CountryName_P As String = ""
  62:      ''' <summary>
  63:      ''' Страна предложный
  64:      ''' </summary>
  65:      Property CountryName_P As String
  66:          Get
  67:              Return _CountryName_P
  68:          End Get
  69:          Set(value As String)
  70:              _CountryName_P = value
  71:          End Set
  72:      End Property
  73:      Dim _CountryName_R As String = ""
  74:      ''' <summary>
  75:      ''' Страна родительный
  76:      ''' </summary>
  77:      Property CountryName_R As String
  78:          Get
  79:              Return _CountryName_R
  80:          End Get
  81:          Set(value As String)
  82:              _CountryName_R = value
  83:          End Set
  84:      End Property
  85:      Dim _CTID As String = ""
  86:      ''' <summary>
  87:      ''' Курорт
  88:      ''' </summary>
  89:      Property CTID As String
  90:          Get
  91:              Return _CTID
  92:          End Get
  93:          Set(value As String)
  94:              _CNID = value
  95:          End Set
  96:      End Property
  97:      Dim _CityName As String = ""
  98:      ''' <summary>
  99:      ''' Курорт Именительный
 100:      ''' </summary>
 101:      Property CityName As String
 102:          Get
 103:              Return _CityName
 104:          End Get
 105:          Set(value As String)
 106:              _CityName = value
 107:          End Set
 108:      End Property
 109:      Dim _CityName_P As String = ""
 110:      ''' <summary>
 111:      ''' Курорт предложный
 112:      ''' </summary>
 113:      Property CityName_P As String
 114:          Get
 115:              Return _CityName_P
 116:          End Get
 117:          Set(value As String)
 118:              _CityName_P = value
 119:          End Set
 120:      End Property
 121:      Dim _CityName_R As String = ""
 122:      ''' <summary>
 123:      ''' Курорт предложный
 124:      ''' </summary>
 125:      Property CityName_R As String
 126:          Get
 127:              Return _CityName_R
 128:          End Get
 129:          Set(value As String)
 130:              _CityName_R = value
 131:          End Set
 132:      End Property
 133:      Dim _TID As Integer = 0
 134:      ''' <summary>
 135:      ''' тип
 136:      ''' </summary>
 137:      Property TID As Integer
 138:          Get
 139:              Return _TID
 140:          End Get
 141:          Set(value As Integer)
 142:              _TID = value
 143:          End Set
 144:      End Property
 145:      Dim _TypeName As String
 146:      ''' <summary>
 147:      ''' тип Именительный
 148:      ''' </summary>
 149:      Property TypeName As String
 150:          Get
 151:              Return _TypeName
 152:          End Get
 153:          Set(value As String)
 154:              _TypeName = value
 155:          End Set
 156:      End Property
 157:      Dim _TypeName_V As String = "жилье"
 158:      ''' <summary>
 159:      ''' тип винительный
 160:      ''' </summary>
 161:      Property TypeName_V As String
 162:          Get
 163:              Return _TypeName_V
 164:          End Get
 165:          Set(value As String)
 166:              _TypeName_V = value
 167:          End Set
 168:      End Property
 169:      Dim _TypeName_R As String = "жилья"
 170:      ''' <summary>
 171:      ''' тип родительный
 172:      ''' </summary>
 173:      Property TypeName_R As String
 174:          Get
 175:              Return _TypeName_R
 176:          End Get
 177:          Set(value As String)
 178:              _TypeName_R = value
 179:          End Set
 180:      End Property
 181:      Dim _NumTypeCheck As Boolean
 182:      ''' <summary>
 183:      ''' Цифровой ли параметр задан в типе?
 184:      ''' </summary>
 185:      Property NumTypeCheck As Boolean
 186:          Get
 187:              Return _NumTypeCheck
 188:          End Get
 189:          Set(value As Boolean)
 190:              _NumTypeCheck = value
 191:          End Set
 192:      End Property
 193:      Dim _PageNum As String
 194:      ''' <summary>
 195:      ''' номер странички пейджера
 196:      ''' </summary>
 197:      Property PageNum As String
 198:          Get
 199:              Return _PageNum
 200:          End Get
 201:          Set(value As String)
 202:              _PageNum = value
 203:          End Set
 204:      End Property
 205:   
 206:      Public Sub CheckRedirect()
 207:          'редирект по Крыму
 208:          Dim Arr1() As String = {"UA01", "UA02", "UA03", "UA04", "UA05", "UA06", "UA08", "UA09", "UA10", "UA105", "UA11", "UA12", "UA13", "UA14", "UA16", "UA17", "UA19", "UA20", "UA21", "UA22", "UA23", "UA24", "UA243", "UA246", "UA25", "UA250", "UA253", "UA26", "UA46", "UA49", "UA50", "UA51", "UA52", "UA54", "UA55", "UA65", "UA66", "UA69", "UA70", "UA71", "UA77", "UA80"}
 209:          For i As Integer = 0 To Arr1.Length - 1
 210:              If _CNID.ToLower = "ru" And _CTID = Arr1(i) Then
 211:                  Dim redirUrl As String = "//arenda.votpusk.ru/Object_list.aspx?Country=CRM&City=" & Arr1(i) & "&Type=0&PriceType=1&From=&To="
 212:                  HttpContext.Current.Response.Status = "301 Moved Permanently"
 213:                  HttpContext.Current.Response.AddHeader("Location", redirUrl)
 214:                  HttpContext.Current.Response.End()
 215:              End If
 216:          Next
 ....  
 248:      End Sub
 249:   
 250:      Public Function CheckExecType() As ObjListExecType
 251:          If _CNID = "" And _CTID = "" And _TID = 0 Then
 252:              Return ObjListExecType.Empty
 253:          ElseIf _CNID <> "" And _CTID = "" And _TID = 0 Then
 254:              Return ObjListExecType.CountryOnly
 255:          ElseIf _CNID <> "" And _CTID <> "" And _TID = 0 Then
 256:              Return ObjListExecType.ContryAndCity
 257:          ElseIf _CNID <> "" And _CTID <> "" And _TID > 0 Then
 258:              Return ObjListExecType.CountryAndCityAndType
 259:          ElseIf _CNID <> "" And _CTID = "" And _TID > 0 Then
 260:              Return ObjListExecType.CountryAndType
 261:          ElseIf _CNID = "" And _CTID = "" And _TID > 0 Then
 262:              Return ObjListExecType.TypeOnly
 263:          End If
 264:      End Function
 265:   
 266:  End Class
 267:   
 268:  Public Enum ObjListExecType
 269:      ''' <summary>
 270:      ''' ничего нет
 271:      ''' </summary>
 272:      Empty = 1
 273:      ''' <summary>
 274:      ''' есть страна
 275:      ''' </summary>
 276:      CountryOnly = 2
 277:      ''' <summary>
 278:      ''' есть страна и курорт
 279:      ''' </summary>
 280:      ContryAndCity = 3
 281:      ''' <summary>
 282:      ''' есть страна, курорт и тип жилья
 283:      ''' </summary>
 284:      CountryAndCityAndType = 4
 285:      ''' <summary>
 286:      '''есть страна и тип жилья
 287:      ''' </summary>
 288:      CountryAndType = 5
 289:      ''' <summary>
 290:      ''' есть тип жилья
 291:      ''' </summary>
 292:      TypeOnly = 6
 293:  End Enum

Але далі є різний функціонал, це і є адапрація чи до десктопного виклику, чи до мобільного.


 191:      Sub SetMobileLabel(E2 As ObjListParameters)
 192:          'ничего нет
 193:          If E2.CheckExecType = ObjListExecType.Empty Then
 194:              'заголовок
 195:              TitleLiteral.Text = "Аренда жилья в частном секторе"
 196:   
 197:              'есть страна
 198:          ElseIf E2.CheckExecType = ObjListExecType.CountryOnly Then
 199:              'заголовок
 200:              TitleLiteral.Text = "Аренда жилья в " & E2.CountryName_P
 201:   
 202:              ' есть страна и курорт
 203:          ElseIf E2.CheckExecType = ObjListExecType.ContryAndCity Then
 204:              'заголовок
 205:              TitleLiteral.Text = "Аренда жилья в " & E2.CityName_P & " (" & E2.CountryName & ")"
 206:    
 207:              ' есть страна, курорт и тип жилья
 208:          ElseIf E2.CheckExecType = ObjListExecType.CountryAndCityAndType Then
 209:              'заголовок
 210:              TitleLiteral.Text = "Аренда " & E2.TypeName_R & " в " & E2.CityName_P & " (" & E2.CountryName & ")"
 211:   
 212:              ' есть страна и тип жилья
 213:          ElseIf E2.CheckExecType = ObjListExecType.CountryAndType Then
 214:              'заголовок
 215:              TitleLiteral.Text = "Аренда " & E2.TypeName_R & " в " & E2.CountryName_P
 216:   
 217:              ' есть тип жилья
 218:          ElseIf E2.CheckExecType = ObjListExecType.TypeOnly Then
 219:              'заголовок
 220:              TitleLiteral.Text = "Аренда " & E2.TypeName_R & " в частном секторе"
 221:   
 222:          End If
 223:      End Sub
 224:   
 225:   
 226:      Sub SetDesktopLabel(E2 As ObjListParameters)
 227:          'ничего нет
 228:          If E2.CheckExecType = ObjListExecType.Empty Then
 229:               'заголовок
 230:              TitleLabel.Text = "<h1 class='ar_title'>Аренда жилья в частном секторе</h1>"
 231:              'синипет
 232:              InfoLabel.Text = "<div class='snip'>Все предложения по аренде жилья для отдыха в частном секторе от владельцев-арендодателей. Для просмотра подробной информации перейдите по ссылке в объявлении. Чтобы уточнить поиск, укажите дополнительные параметры – страну, город (курорт) и тип объекта в форме поиска жилья.</div>"
 233:   
 234:              'есть страна
 235:          ElseIf E2.CheckExecType = ObjListExecType.CountryOnly Then
 236:              'заголовок
 237:              TitleLabel.Text = "<h1 class='ar_title'>Аренда жилья в " & E2.CountryName_P & "</h1>"
 238:              'синипет
 239:              InfoLabel.Text = "<div class='snip'>Объявления о посуточной аренде жилья в " & E2.CountryName_P & ", варианты аренды частного сектора " & E2.CountryName_R & " на сутки, на неделю, месяц и на другие сроки. Чтобы снять посуточно квартиру, частный дом, коттедж или номер в гостинице для вашего отдыха в " & E2.CountryName_P & ", перейдите по ссылке в объявлении. Чтобы уточнить полученные варианты посуточной аренды в частном секторе, укажите город (курорт) и тип объекта в форме поиска  жилья.</div>"
 240:   
 241:              ' есть страна и курорт
 242:          ElseIf E2.CheckExecType = ObjListExecType.ContryAndCity Then
 243:                'заголовок
 244:              TitleLabel.Text = "<h1 class='ar_title'>Аренда жилья в " & E2.CityName_P & " (" & E2.CountryName & ")</h1>"
 245:              'синипет
 246:              InfoLabel.Text = "<div class='snip'>Объявления о посуточной аренде жилья в " & E2.CityName_P & " в " & E2.CountryName_P & ", варианты аренды частного сектора " & E2.CityName_R & " на сутки, на неделю, месяц и на другие сроки. Чтобы снять посуточно квартиру, частный дом, коттедж или номер в гостинице для вашего отдыха в " & E2.CityName_P & ", перейдите по ссылке в объявлении. Чтобы уточнить полученные варианты посуточной аренды в частном секторе, укажите тип объекта в форме поиска жилья.</div>"
 247:              'хлебные крошки
 248:              Navigator1.NavigateList("Аренда", "//arenda.votpusk.ru", E2.CountryName, "//arenda.votpusk.ru/Object_list.aspx?Country=" & E2.CNID & "&City=0&Type=0&PriceType=1&From=&To=")
 249:   
 250:              ' есть страна, курорт и тип жилья
 251:          ElseIf E2.CheckExecType = ObjListExecType.CountryAndCityAndType Then
 252:              'заголовок
 253:              TitleLabel.Text = "<h1 class='ar_title'>Аренда " & E2.TypeName_R & " в " & E2.CityName_P & " (" & E2.CountryName & ")</h1>"
 254:              'синипет
 255:              InfoLabel.Text = "<div class='snip'>Предложения по аренде " & E2.TypeName_R & " в " & E2.CityName_P & " в " & E2.CountryName_P & ". Чтобы получить дополнительную информацию по объекту отдыха и снять " & E2.TypeName_V & " в конкретном предложении частного сектора " & E2.CityName_R & ", перейдите по ссылке в выбранном объявлении о сдаче жилья.</div>"
 256:              'хлебные крошки
 257:              Navigator1.NavigateList("Аренда", "//arenda.votpusk.ru", E2.CountryName, "//arenda.votpusk.ru/Object_list.aspx?Country=" & E2.CNID & "&City=0&Type=0&PriceType=1&From=&To=")
 258:   
 259:              ' есть страна и тип жилья
 260:          ElseIf E2.CheckExecType = ObjListExecType.CountryAndType Then
 261:              'заголовок
 262:              TitleLabel.Text = "<h1 class='ar_title'>Аренда " & E2.TypeName_R & " в " & E2.CountryName_P & "</h1>"
 263:              'синипет
 264:              InfoLabel.Text = "<div class='snip'>Предложения по аренде " & E2.TypeName_R & " в " & E2.CountryName_P & ". Чтобы ознакомиться с полной информацией предложения частного сектора городов и курортов " & E2.CountryName_R & " и снять " & E2.TypeName_V & " из представленного списка, перейдите по ссылке в объявлении. Чтобы уточнить поиск, укажите город (курорт) в форме поиска жилья.</div>"
 265:   
 266:              ' есть тип жилья
 267:          ElseIf E2.CheckExecType = ObjListExecType.TypeOnly Then
 268:              'заголовок
 269:              TitleLabel.Text = "<h1 class='ar_title'>Аренда " & E2.TypeName_R & " в частном секторе</h1>"
 270:              'синипет
 271:              InfoLabel.Text = "<div class='InfoRam'><div class='tx'>Все предложения по аренде " & E2.TypeName_R & "  в частном секторе городов и курортов мира от владельцев жилья для отдыха в частном секторе. Чтобы снять " & E2.TypeName_V & " из представленного списка, перейдите по ссылке в объявлении. Чтобы уточнить поиск, укажите страну и город (курорт) в форме поиска жилья.</div></div>"
 272:   
 273:          End If
 274:      End Sub

Код мета-тегов сторінки можливо б було теж втопити у клас, але він декілька разів вже змінювався (SEO-шник задає що там повинно бути), тому я розташував цей код не у класі, а на сторінці, незважаючи на те, що це НЕ адаптивний функціонал, а єдиний для обох варіантів десктопного та мобільного.


 100:      Sub SetMetaTagAndTitle(E2 As ObjListParameters)
 101:          '
 102:          Dim HeadKey As New HtmlMeta
 103:          HeadKey.Name = "keywords"
 104:          Dim HeadDesc As New HtmlMeta
 105:          HeadDesc.Name = "description"
 106:          Dim link As New HtmlLink()
 107:          link.Attributes.Add("rel", "canonical")
 108:          '
 109:          'ничего нет
 110:          If E2.CheckExecType = ObjListExecType.Empty Then
 111:              'Тайтл на страницу
 112:              Me.Title = "Аренда жилья В Отпуск.ру: Поиск объектов частного сектора для отдыха"
 113:              'Ключевые слова
 114:              HeadKey.Content = "частный сектор, аренда жилья, аренда жилья для отдыха, отдых в частном секторе, дом у моря, снять дом, снять виллу, снять коттедж, снять квартиру"
 115:              'описание страницы
 116:              HeadDesc.Content = "Поиск предложений частного сектора для отдыха, краткосрочная аренда жилья в России и зарубежом. Выбор недорогого варианты проживания, бесплатный сервис для владельцев жилья"
 117:              'canonical
 118:              link.Attributes.Add("href", "https://arenda.votpusk.ru/Object_list.aspx?Country=0&City=0&Type=0&PriceType=1&From=&To=")
 119:   
 120:              'есть страна
 121:          ElseIf E2.CheckExecType = ObjListExecType.CountryOnly Then
 122:              'Тайтл на страницу
 123:              Me.Title = "Аренда жилья в " & E2.CountryName_P & ". Частный сектор в " & E2.CountryName_P
 124:              'Ключевые слова
 125:              HeadKey.Content = "частный сектор " & E2.CountryName & ", аренда жилья в " & E2.CountryName_P
 126:              'описание страницы
 127:              HeadDesc.Content = "Поиск предложений частного сектора в " & E2.CountryName_P & ", краткосрочная аренда жилья в " & E2.CountryName_P & ". Выбор недорогого варианта проживания, бесплатный сервис для владельцев жилья. В Отпуск.ру"
 128:              'canonical
 129:              link.Attributes.Add("href", "https://arenda.votpusk.ru/Object_list.aspx?Country=" & E2.CNID & "&City=0&Type=0&PriceType=1&From=&To=")
 130:   
 131:              ' есть страна и курорт
 132:          ElseIf E2.CheckExecType = ObjListExecType.ContryAndCity Then
 133:              'Тайтл на страницу
 134:              Me.Title = "Аренда жилья в " & E2.CityName_P & " (" & E2.CountryName & ") - арендовать жилье в частном секторе. Снять жилье в  " & E2.CityName_P
 135:              'Ключевые слова
 136:              HeadKey.Content = "аренда жилья в " & E2.CityName_P & ", снять жилье в " & E2.CityName_P
 137:              'описание страницы
 138:              HeadDesc.Content = "Аренда жилья в " & E2.CityName_P & " (" & E2.CountryName & "). Поиск предложений по аренде частного сектора в " & E2.CityName_P & ". Выбор не дорогого варианта проживания. В Отпуск.ру"
 139:              'canonical
 140:              link.Attributes.Add("href", "https://arenda.votpusk.ru/Object_list.aspx?Country=" & E2.CNID & "&City=" & E2.CTID & "&Type=0&PriceType=1&From=&To=")
 141:   
 142:              ' есть страна, курорт и тип жилья
 143:          ElseIf E2.CheckExecType = ObjListExecType.CountryAndCityAndType Then
 144:              'Тайтл на страницу
 145:              Me.Title = "Снять " & E2.TypeName_V & "  в " & E2.CityName_P & " (" & E2.CountryName & "). Аренда " & E2.TypeName_R & " в " & E2.CityName_P
 146:              'Ключевые слова
 147:              HeadKey.Content = "снять " & E2.TypeName_V & "  в " & E2.CityName_P & ", аренда " & E2.TypeName_R & " в " & E2.CityName_P & " (" & E2.CountryName & ")"
 148:              'описание страницы
 149:              HeadDesc.Content = "Аренда " & E2.TypeName_R & " в " & E2.CityName_P & ". Выбор не дорогого варианта проживания в " & E2.CityName_P & " (" & E2.CountryName & "). В Отпуск.ру"
 150:              'canonical
 151:              link.Attributes.Add("href", "https://arenda.votpusk.ru/Object_list.aspx?Country=" & E2.CNID & "&City=" & E2.CTID & "&Type=" & E2.TID & "&PriceType=1&From=&To=")
 152:   
 153:              ' есть страна и тип жилья
 154:          ElseIf E2.CheckExecType = ObjListExecType.CountryAndType Then
 155:              'Тайтл на страницу
 156:              Me.Title = "Снять " & E2.TypeName_V & "  в " & E2.CountryName_P & ". Аренда " & E2.TypeName_R & " в " & E2.CountryName_P
 157:              'Ключевые слова
 158:              HeadKey.Content = "снять " & E2.TypeName_V & "  в " & E2.CountryName_P & ", аренда " & E2.TypeName_R & " в " & E2.CountryName_P
 159:              'описание страницы
 160:              HeadDesc.Content = "Аренда " & E2.TypeName_R & " в " & E2.CountryName_P & ". Выбор не дорогого варианта проживания в " & E2.CountryName_P & ". В Отпуск.ру"
 161:              'заголовок            'canonical
 162:              link.Attributes.Add("href", "https://arenda.votpusk.ru/Object_list.aspx?Country=" & E2.CNID & "&City=0&Type=" & E2.TID & "&PriceType=1&From=&To=")
 163:   
 164:   
 165:              ' есть тип жилья
 166:          ElseIf E2.CheckExecType = ObjListExecType.TypeOnly Then
 167:              'Тайтл на страницу
 168:              Me.Title = "Аренда " & E2.TypeName_R & " В Отпуск.ру: Поиск " & E2.TypeName_R & " для отдыха"
 169:              'Ключевые слова
 170:              HeadKey.Content = "частный сектор, аренда жилья, аренда жилья для отдыха, отдых в частном секторе, дом у моря, снять дом, снять виллу, снять коттедж, снять квартиру"
 171:              'описание страницы
 172:              HeadDesc.Content = "Поиск предложений частного сектора для отдыха, краткосрочная аренда жилья в России и зарубежом. Выбор недорогого варианты проживания, бесплатный сервис для владельцев жилья"
 173:              'canonical
 174:              link.Attributes.Add("href", "https://arenda.votpusk.ru/Object_list.aspx?Country=0&City=0&Type=" & E2.TID & "&PriceType=1&From=&To=")
 175:   
 176:          End If
 177:   
 178:          ' если это не первая страница приписываем номер
 179:          If E2.PageNum IsNot Nothing And E2.PageNum <> "0" And E2.PageNum <> "" Then
 180:              Me.Title = Me.Title + " Стр.№" & CInt(E2.PageNum) + 1
 181:              HeadDesc.Content = HeadDesc.Content + " Стр.№" & CInt(E2.PageNum) + 1
 182:          End If
 183:   
 184:          'выводим мета теги
 185:          Me.Header.Controls.Add(HeadDesc)
 186:          Me.Header.Controls.Add(HeadKey)
 187:          Me.Header.Controls.Add(link)
 188:          '
 189:      End Sub

Зверніть, будь ласка, увагу на те, що у мене все зроблено з Intellisense.



Отже, друзі, у другому розділі ви змогли побачити трохи скорочений, але реальний код реального проєкту. Змогли побачити як взагалі будуються адаптивні сайти, як розподіляється функціонал загальний та специфічній по класам та сторінкам.


3. Специфіка мобільних сайтів - SPA-page на Classic ASP.NET та jQuery.



Далі, на окремій сторінці, я розповім про головну специфіку будування сайтів для мобільників - SPA-page на Classic ASP.NET та jQuery.



Comments ( )
<00>  <01>  <02>  <03>  <04>  <05>  <06>  <07>  <08>  <09>  <10>  <11>  <12>  <13>  <14>  <15>  <16>  <17>  <18>  <19>  <20>  <21>  <22>  <23
Link to this page: //www.vb-net.com/ForMobile/index.htm
<SITEMAP>  <MVC>  <ASP>  <NET>  <DATA>  <KIOSK>  <FLEX>  <SQL>  <NOTES>  <LINUX>  <MONO>  <FREEWARE>  <DOCS>  <ENG>  <CHAT ME>  <ABOUT ME>  < THANKS ME>