(MVC) MVC (2019)

Simplest Single Page Application (SPA-page) template in ASP.NET on @Ajax.ActionLink

There are dozens of various SPA-page template. Firstly, SPA-page is main site template in classic ASP.NET. I describe some of my SPA-page in page - SPA-page на Classic ASP.NET та jQuery.. Or see please, description of this project on Classic ASP.NET - Рефакторінг сайта IMK.- this site I don't write from same beginning, I done full rebuild it, but as a SPA-page it use most common way of SPA-page <WebMethod()>. Also see page ASP.NET Core and SPA-page on XMLHttpRequest.

Also there are dozens of sophisticated SPA-page template in ASP.NET MVC, for example see this page Декілька моїх останніх тестових проєктів, project number 2 and 3 is a SPA-page, but more complex, than I want to describe in this page. Additional small way is to create request from page not to a main controller, but in WEB.API controller, this way I describe in page The ways to receive complex parameters in ASP.NET

But what is the simplest as possible way?


Look to the screen below. This is a simplest template to create SPA-page. Why data is nothing, you can see only proposal to load data. In this case I do loading data not in this SPA-page because loading process perhaps may generate a lot of error in input file.



Before this moment this is not a SPA-page, this is ordinary ASP.NET MVC page. And I leave link to get data for empty data to show right column name of loaded Excel file.



But from this moment this is really SPA-page. Each next action is open a link of next action or error of previous step.



Below you can see this simplest workflow mechanism. This is controller code.


   1:  Imports System.IO
   2:  Imports System.Web.Mvc
   3:  Imports OfficeOpenXml
   4:  Imports Extension1
   5:  Imports System.Data.SqlClient
   6:  Imports System.Globalization
   7:   
   8:  Namespace Controllers
   9:      Public Class CabController
  ...   
  52:          Function ReorderData() As ActionResult
  53:              If Request.IsAjaxRequest() Then
  54:                  Try
  55:                      db1 = New MgtlDbContext
  56:                      db1.InvoiceFormulars.
  57:                          OrderBy(Function(X) db1.CompanyNames.Where(Function(Y) Y.I = X.ToCompanyName).FirstOrDefault.CompanyNameInCodeWorthy).
  58:                          ThenBy(Function(X) X.Location).
  59:                          ThenBy(Function(X) X.ShiftDate).
  60:                          ThenBy(Function(X) X.DocketID).
  61:                          AsEnumerable().
  62:                          Select(Function(X, Index)
  63:                                     Debug.Print(Index & ":" & X.I)
  64:                                     X.OrderBy = Index
  65:                                     Return X
  66:                                 End Function).ToList
  67:                      db1.SaveChanges()
  68:                      ViewData("OrderError") = Nothing
  69:                  Catch ex As Exception
  70:                      ViewData("OrderError") = ex.Message
  71:                  End Try
  72:                  Return PartialView("OrderSuccess")
  73:              Else
  74:                  Return View("Index")
  75:              End If
  76:          End Function
  77:   
  78:          Function ApplyVBA() As ActionResult
  79:              If Request.IsAjaxRequest() Then
  80:                  Try
  ...   
 102:                      db1.SaveChanges()
 103:                      ViewData("VBAError") = Nothing
 104:   
 105:                  Catch ex As Exception
 106:                      ViewData("VBAError") = ex.Message
 107:                  End Try
 108:                  Return PartialView("ApplyVBA")
 109:              Else
 110:                  Return View("Index")
 111:              End If
 112:          End Function
 113:   
 114:          Function CreatePivot() As ActionResult
  ...   

Index.vbhtml


   1:  @Code
   2:      Layout = "~/Views/Shared/_Layout.vbhtml"
   3:      Dim db1 As New MgtlDbContext
   4:      Dim RecorsCount As Integer = db1.InvoiceFormulars.Count
   5:  End Code
   6:   
   7:  <h3 style="padding-top:50px">InvoiceFormular</h3>
   8:   
   9:  <ul>
  10:      <li>
  11:          <span style="width:200px;display: inline-block;"><a href="/Cab/InvoiceFormular">Load InvoiceFormular</a></span>&nbsp;[&nbsp;
  12:          @Html.ActionLink("Get data", "ShowRawData", New With {.controller = "Cab", .id = "InvoiceFormular"}, New With {.target = "_blank"})
  13:          &nbsp;]
  14:          @If RecorsCount > 0 Then
  15:              @<text>
  16:                  <br />
  17:              </text>
  18:              @Ajax.ActionLink("Order Data", "ReorderData", Nothing, New AjaxOptions() With {
  19:                                                                    .HttpMethod = "GET",
  20:                                                                    .InsertionMode = InsertionMode.InsertAfter,
  21:                                                                    .UpdateTargetId = "ReorderDataID"
  22:                                                                    }, New With {.id = "ReorderID"})
  23:   
  24:   
  25:   
  26:              @<text>
  27:   
  28:                  <div id="ReorderDataID"  />
  29:   
  30:              </text>
  31:          End If
  32:   
  33:      </li>
  34:  </ul>
  35:  <br />

OrderSuccess.vbhtml


   1:  @If ViewData("OrderError") Is Nothing Then
   2:      @<text>
   3:   
   4:          @Ajax.ActionLink("Apply VBA", "ApplyVBA", Nothing, New AjaxOptions() With {
   5:                                                                            .HttpMethod = "GET",
   6:                                                                            .InsertionMode = InsertionMode.InsertAfter,
   7:                                                                            .UpdateTargetId = "ApplyVBAID"
   8:                                                                            }, New With {.id = "VBAID"})
   9:   
  10:          <div id="ApplyVBAID" />
  11:      </text>
  12:  Else
  13:      @<text>
  14:          &nbsp;[&nbsp;
  15:          @ViewData("OrderError")
  16:          &nbsp;]&nbsp;
  17:      </text>
  18:  End If

ApplyVBA.vbhtml


   1:  @If ViewData("VBAError") Is Nothing Then
   2:      @<text>
   3:   
   4:          @Ajax.ActionLink("Create Pivot", "CreatePivot", Nothing, New AjaxOptions() With {
   5:                                                                                          .HttpMethod = "GET",
   6:                                                                                          .InsertionMode = InsertionMode.InsertAfter,
   7:                                                                                          .UpdateTargetId = "CreatePivotID"
   8:                                                                                          }, New With {.id = "PivotID"})
   9:   
  10:          <div id="CreatePivotID" />
  11:      </text>
  12:  Else
  13:      @<text>
  14:          &nbsp;[&nbsp;
  15:          @ViewData("VBAError")
  16:          &nbsp;]&nbsp;
  17:      </text>
  18:  End If

And finally my method to download data. This is also a part of SPA-page, because we are leave in main page. It use my old component Serialize Table to CSV with Iterator and Yeld.


 433:          Sub ShowRawData(ID As String)
 434:              If ID = "InvoiceFormular" Or ID = "WorkType" Or ID = "CompanyName" Or ID = "ItemCode" Or ID = "XeroAccountNumber" Or ID = "AccountNumber" Then
 435:                  Dim CN = New SqlConnection(ConfigurationManager.ConnectionStrings("AuReport").ConnectionString)
 436:                  Dim CMD As String = ID & "s"
 437:                  Dim DbFileName As String = IO.Path.Combine(Server.MapPath("~"), "Tmp\" & ID & ".csv")
 438:                  CN.Open()
 439:                  DBDumper.DumpTableToFile(CN, CMD, DbFileName)
 440:                  Response.Clear()
 441:                  Response.ClearHeaders()
 442:                  Response.ClearContent()
 443:                  Response.AddHeader("Content-Disposition", "attachment; filename=" & ID & ".csv")
 444:                  Response.ContentType = "text/csv"
 445:                  Response.ContentEncoding = Encoding.UTF8
 446:                  Response.Write(IO.File.ReadAllText(DbFileName))
 447:                  Response.Flush()
 448:                  Response.End()
 449:              End If
 450:          End Sub

If you implement this workflow, you will request from server to page only by Xhr object (its a special with protocols other than HTTP), and you can see small response like on screen below.



If no, if response is longer, please firstly check installed package, main package is Install-Package Microsoft.jQuery.Unobtrusive.Ajax -Version 3.2.6, and also check bundle config and calling this bundle in your Layout page.



Continue reading Inject OnBegin/OnSuccess/OnFailure custom Javascript code into ASP.NET @Ajax tag by Bundle of jquery.unobtrusive-ajax.min.js.



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/SPAworkflow/Index.htm
<SITEMAP>  <MVC>  <ASP>  <NET>  <DATA>  <KIOSK>  <FLEX>  <SQL>  <NOTES>  <LINUX>  <MONO>  <FREEWARE>  <DOCS>  <ENG>  <CHAT ME>  <ABOUT ME>  < THANKS ME>