(MVC) MVC (2015 год)

DropdownList AutoPostBack у ASP.NET MVC

Вимоги до ціеї сторінки завантаження світлин у тому, щоб зробити повне оновлення сторінки при зміні community у select/option з назвою 'Your last event'. Тобто зробити звичайний Autopostback у Dropdownlist, без окремої кнопки Refresh/Reload - найбільш поширений сервіс у ASP.NET. Але як це зробити у ASP.NET MVC?

Тут я опишу техніку DropdownList AutoPostBack, дуже схожу з описаною тут Кешування вхідної сторінки сайт.

Сторінка, яку ви бачите на світлині, має ось таке тіло і цей код нище вже містить в собі відгадку, але спочатку зрозуміємо всю послідовніcть виклику контролів, на верхньому рівні розташован контрол AddFotoBody.ascx:


   1:  <%@ Control Language="VB" Inherits="System.Web.Mvc.ViewUserControl" %>
   2:   
   3:      <%  Dim URI As String = "http://" & System.Configuration.ConfigurationManager.AppSettings("HostingURL")%>
   4:   
   5:      <span style="color:Red"><%:ViewData("lErr1")%></span>
   6:   
   7:      <%If ViewData("lErr1") Is Nothing Then%>
   8:   
   9:      <br /><br />
  10:      Your last event&nbsp; <br />
  11:      <%  Dim LastEvent As System.Collections.Generic.List(Of System.Web.Mvc.SelectListItem) = ViewData("LastEvent")%>
  12:      <%: Html.DropDownList("EventName", LastEvent, New With {.style = "width:900px"})%><br />
  13:      contains <span id="count1" ><%: ViewData("FotoCount")%></span> foto&nbsp; 
  14:      <br /><br />
  15:   
  16:      <fieldset id="upload" class="fieldset3" style="width:888px">
  17:          <legend>
  18:              <span class="gray2">
  19:                  Add New foto
  20:              </span>
  21:          </legend>
  22:   
  23:   
  24:      <form enctype="multipart/form-data" method="post" name="f1"  id="f1" action="<%:URI %>/loaDimage.ashx">
  25:   
  26:      <input type="file" id="file1" name="file1" style = "width:100%;" /><br /><br />
  27:   
  28:      Comment (max 1000 chars)
  29:      <%: Html.TextArea("text1", "", New With {.placeholder = "enter text here", .rows = "5", .style = "width:100%;", .required = "required", .maxlength = "1000"})%>
  30:      
  31:      <br /><br />
  32:      <input type="submit" id="submit1" value="Upload" name="submit1"  style="width:300px" class="button1" /> 
  33:      
  34:      <input type="hidden" id="mail1" name="mail1" value='<%: ViewData("Mail") %>'  />
  35:      <input type="hidden" id="event1" name="event1" value='<%: ViewData("EventID") %>' />
  36:   
  37:   
  38:      </form>
  39:      
  40:      </fieldset>
  41:       
  42:     <%: Html.Partial("UploadedFoto", ViewData("FotoIDs"))%>
  43:          
  44:      <br /><br />
  45:      <a href='<%:URI %>/<%: ViewContext.RouteData.Values("controller") %>/MyEvents/'>
  46:      <input type="image" id="submit2" value="Finish" name="submit1"  style="width:300px;text-align:center;text-decoration:none;" class="button1" /> 
  47:      </a>
  48:   
  49:      <% End If%>
  50:      <br />
  51:   
  52:   <script type="text/javascript" language="javascript" >
  53:       $('#EventName').change(function () {
  54:           var selectedValue = $('#EventName').val();
  55:           $('#event1').val(selectedValue);
  56:           $.post('<%:Url.Action("LoadFotoChangeEvent", "Cab") %>', { newevent: selectedValue }, function (data) {
  57:               $('#count1').text(data.FotoCount);
  58:               $("#fotos").remove();
  59:               $('#upload').after(data.Data);
  60:           });
  61:       });
  62:  </script>

Якийсь вміщуює контрол UploadedFoto.ascx:


   1:  <%@ Control Language="VB" Inherits="System.Web.Mvc.ViewUserControl (of System.Collections.Generic.List(Of OCMR.GetFotoHeaderResult))" %>
   2:   
   3:   
   4:   
   5:      <%  If Model.Count > 0 Then%>
   6:          <fieldset id="fotos" class="fieldset3" style="width:888px">
   7:              <legend>
   8:                   <span class="gray2">
   9:                     Uploaded foto
  10:                   </span>
  11:              </legend>
  12:      <%  Dim db1 As New OCMR.OCMRDataContext
  13:          Dim EventList = (From X In db1.AllEvents Select X Where X.UsersEmail = HttpContext.Current.User.Identity.Name Order By X.CrDate Descending).ToList%>
  14:   
  15:      <%  For i As Integer = 0 To Model.Count - 1%>
  16:             <%:Html.Partial("OneFoto", New With {.Foto = Model(i), .Event = EventList(0)})%>
  17:      <%  Next%> 
  18:   
  19:           </fieldset>
  20:   
  21:      <%  Else%>
  22:           <b>No Foto</b>    
  23:      <%  End If%>

Який, у свою чергу, вміщує послідовність контролов OneFoto.ascx:


   1:  <%@ Control Language="VB" Inherits="System.Web.Mvc.ViewUserControl" %>
   2:   
   3:      <div class="onefoto">
   4:   
   5:      
   6:   
   7:      <%Dim URI As String = "http://" & System.Configuration.ConfigurationManager.AppSettings("HostingURL")%>
   8:      
   9:      <% If Model.Event.ModeratorID Is Nothing Then%>
  10:      <% Using Html.BeginForm("OneFoto", "Cab", Nothing, FormMethod.Post)%>
  11:   
  12:      <input type="image" name="Del<%: Model.Foto.RowGuid %>" src="<%:URI %>/Content/D1.gif" title="Delete foto" alt="Delete foto"   />
  13:      <input type="image" name="RT1<%: Model.Foto.RowGuid %>" src="<%:URI %>/Content/R1.gif" title="Rotate Clockwise" alt="Rotate Clockwise" />
  14:      <input type="image" name="RT2<%: Model.Foto.RowGuid %>" src="<%:URI %>/Content/R2.gif" title="Rotate Counterclockwise" alt="Rotate Counterclockwise" />
  15:      <input type="image" name="CR1<%: Model.Foto.RowGuid %>" src="<%:URI %>/Content/Crop1.gif" title="Crop" alt="Crop" />
  16:   
  17:           
  18:      <%: Html.Hidden("securitytoken1", OCMR.SecurityToken.GetToken(Model.Foto.RowGuid.ToString))%>
  19:   
  20:      <% End Using%>
  21:      <% End If%>
  22:       
  23:   
  24:      <a onclick="window.open('','ShowFotos','resizable=no,menubar=no,scrollbars=no,width=1024,height=900');"  name='ShowFotos' target='ShowFotos' href='<%:URI %>/ShowFoto/Index/<%:model.Foto.RowGuid %>' title="Panorama" >
  25:      <input type="image" src="<%:URI %>/GetImage.ashx?ID=<%:model.Foto.RowGuid %>&Mode=1" title="<%:model.Foto.Comment%>" alt="<%:model.Foto.Comment%>"  /><br />
  26:      </a>
  27:      
  28:   
  29:      </div>

Отже, ми намагаємося приверути AutoPostBack до DropDownList, який задекларован у стрічці 12 контролу AddFotoBody.ascx. Ви можете побачити клієнтську частину кода у стрічках 52-62. У 56-й стрічці робиться AJAX-виклик метода LoadFotoChangeEvent у контролі Cab, якому вхідним параметром передається код нового ком'юніті, а у відповіть у параметрі Data з серверу надходить (повність сформований у вигляді HTML) контрол UploadedFoto.ascx з усіма дінамічно сформованими даними. А даними для формування HTML є FotoIDs, які формуються серверним кодом, залежно від Community непросто:



Тобто, це і є власне сторінка, яка вміщую в собі контрол AddFotoBody.ascx. Таким чином, по AJAX-виклику нам потрібно дінамічно перерахувати MODEL (яка необхідна для роботи контролу AddFotoBody.ascx), заштовхнути цю MODEL у Partial View, дінамічно откомпіліровати Partial View та ітоговий сформований HTML у вигляди JSON відправити у відповідь на реквест з браузеру.

Нище ви можете побачити, як на сервері можна зробити таке чудо.



У коді вище ви можете побачити лише завнішню обв'язку методу дінамічної компіляції RenderPartialViewToString, але цей код теє дуже важливий, він дає змогу побачити зв'язок між jQuery на сторінці і серверним кодом контролеру, важливими тут є і коректні имена параметрів і форматер JSON, результат роботи якого повертається як результат роботи контролеру.

Ну і ось власне сама родзинка - використання класу System.Web.Mvc.ViewEngines для дінамічної компіляціі Partial View:


   1:  Public Class AJAX_Service
   2:      Public Shared Function RenderPartialViewToString(Controller As Controller, ViewName As String, Model As Object) As String
   3:          If String.IsNullOrEmpty(ViewName) Then
   4:              ViewName = Controller.ControllerContext.RouteData.GetRequiredString("action")
   5:          End If
   6:   
   7:          Controller.ViewData.Model = Model
   8:   
   9:          Using SW = New IO.StringWriter()
  10:   
  11:              Dim ViewResult = ViewEngines.Engines.FindPartialView(Controller.ControllerContext, ViewName)
  12:              Dim ViewContext = New ViewContext(Controller.ControllerContext, ViewResult.View, Controller.ViewData, Controller.TempData, SW)
  13:              ViewResult.View.Render(ViewContext, SW)
  14:              Return SW.GetStringBuilder().ToString()
  15:   
  16:          End Using
  17:      End Function
  18:   
  19:  End Class


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