(MVC) MVC (2019)

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

This is addtion to my post Simplest Single Page Application (SPA-page) template in ASP.NET on @Ajax.ActionLink. This is most ancient ASP.ENT technique How classic ASP.NET programmers has realized WEB.API since 2005 year, SPA-page на Classic ASP.NET та jQuery, I have described this technique many times in my site for example Рефакторінг сайта IMK. and now I continue description of this postback method.

This is full VB.NET code, but there are difference between other site I described because in this site :



   1:  @Code
   2:      ViewData("Title") = "Login"
   3:  End Code
   4:  <div>
   5:      <div class="page-header header-filter" filter-color="gray" style="background-image: url('@Url.Content("~/Assets/Image/background.jpg")'); background-size: cover; background-position: top center;">
   6:          <div id="page-content" class="container">
   7:              <div class="row">
   8:                  <div class="col-lg-4 col-md-6 col-sm-6 ml-auto mr-auto">
   9:                      <div class="card card-signup">
  10:                          <div class="card-header card-header-danger text-center">
  11:                              <h4 class="card-title">@Resources.Home.Index.Registration</h4>
  12:                          </div>
  13:                          <div class="card-body" style="padding-top:18px;">
  14:                              @Using Ajax.BeginForm("User/Authenticate", "Service", New AjaxOptions() With {
  15:                                   .HttpMethod = "POST",
  16:                                   .OnBegin = "OnAuthenticationBegin",
  17:                                   .OnSuccess = "OnAuthenticationSuccess",
  18:                                   .OnFailure = "OnAuthenticationFailure"})
  19:                                  @<div class="form-group has-danger">
  20:                                      <div class="input-group">
  21:                                          <div class="input-group-prepend">
  22:                                              <span class="input-group-text">
  23:                                                  <i class="material-icons">person_outline</i>
  24:                                              </span>
  25:                                          </div>
  26:                                          @Html.TextBox("input-username", Nothing, New With {.class = "form-control", .placeholder = Resources.Home.Index.UserName})
  27:                                      </div>
  28:                                  </div>
  29:                                  @<div class="form-group has-danger">
  30:                                      <div class="input-group">
  31:                                          <div class="input-group-prepend">
  32:                                              <span class="input-group-text">
  33:                                                  <i class="material-icons">lock_outline</i>
  34:                                              </span>
  35:                                          </div>
  36:                                          @Html.Password("input-password", Nothing, New With {.class = "form-control", .placeholder = Resources.Home.Index.Pass})
  37:                                      </div>
  38:                                  </div>
  39:                                  @Html.AntiForgeryToken()
  40:                                  @<div class="text-center" style="margin-top: 8px; margin-left: 6px; margin-right: -16px;">
  41:                                      <label id="status-message" class="label" style="color: tomato;"></label>
  42:                                  </div>
  43:                                  @<div class="text-center" style="margin-left: -10px; margin-right: -30px; margin-top: 18px; margin-bottom: 18px;">
  44:                                      <input id="button-authentication-submit" class="btn btn-danger btn-round" type="submit" value=@Resources.Home.Index.Enter />
  45:                                  </div>
  46:                              End Using
  47:                          </div>
  48:                      </div>
  49:                  </div>
  50:              </div>
  51:          </div>
  52:      </div>
  53:  </div>
  54:  @Section Scripts
  55:      <script type="text/javascript" src="@Url.Content("~/Assets/JS/customized/AuthenticateAdministrator.js")"></script>
  56:  End Section

Result in browser is:

   1:   
   2:   
   3:  <!DOCTYPE html>
   4:  <html lang="en">
   5:     <head>
   6:        <meta charset="utf-8" />
   7:        <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0, shrink-to-fit=no">
   8:        <link rel="icon" type="image/png" href="/Assets/Image/favicon.png">
   9:        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
  10:        <title>Login</title>
  11:        <link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Roboto+Slab:400,700|Material+Icons" rel="stylesheet"/>
  12:        <link href="https://maxcdn.bootstrapcdn.com/font-awesome/latest/css/font-awesome.min.css" rel="stylesheet"/>
  13:        <link href="/bundle/css?v=lWghUxA7Yx4tUdtDUVCEg1IL6Y4eg4-SB2HoAR_k_Lc1" rel="stylesheet"/>
  14:     </head>
  15:     <body>
  16:        <div class="navbar navbar-transparent navbar-color-on-scroll fixed-top navbar-expand-lg" color-on-scroll="100" id="sectionsNav">
  17:           <div class="container">
  18:              <div class="navbar-translate">
  19:                 <a class="navbar-brand" href="/">TaxiStar</a>
  20:              </div>
  21:              <div class="navbar-collapse collapse">
  22:                 <ul class="nav navbar-nav ml-auto"></ul>
  23:              </div>
  24:           </div>
  25:        </div>
  26:        <div>
  27:           <div>
  28:              <div class="page-header header-filter" filter-color="purple" style="background-image: url('/Assets/Image/background.jpg'); background-size: cover; background-position: top center;">
  29:                 <div id="page-content" class="container">
  30:                    <div class="row">
  31:                       <div class="col-lg-4 col-md-6 col-sm-6 ml-auto mr-auto">
  32:                          <div class="card card-signup">
  33:                             <div class="card-header card-header-danger text-center">
  34:                                <h4 class="card-title">Registration</h4>
  35:                             </div>
  36:                             <div class="card-body" style="padding-top:18px;">
  37:                                <form action="/Service/User/Authenticate"  data-ajax-begin="OnAuthenticationBegin" data-ajax-failure="OnAuthenticationFailure"  data-ajax-success="OnAuthenticationSuccess" data-ajax-method="POST" data-ajax="true" id="form0" method="post">
  38:                                   <div class="form-group has-danger">
  39:                                      <div class="input-group">
  40:                                         <div class="input-group-prepend">
  41:                                            <span class="input-group-text">
  42:                                            <i class="material-icons">person_outline</i>
  43:                                            </span>
  44:                                         </div>
  45:                                         <input class="form-control" id="input-username" name="input-username" placeholder="UserName" type="text" value="" />
  46:                                      </div>
  47:                                   </div>
  48:                                   <div class="form-group has-danger">
  49:                                      <div class="input-group">
  50:                                         <div class="input-group-prepend">
  51:                                            <span class="input-group-text">
  52:                                            <i class="material-icons">lock_outline</i>
  53:                                            </span>
  54:                                         </div>
  55:                                         <input class="form-control" id="input-password" name="input-password" placeholder="Password" type="password" />
  56:                                      </div>
  57:                                   </div>
  58:                                   <input name="__RequestVerificationToken" type="hidden" value="ecXnd6Bi_13pZ3bRJhvsiC36eErwYEaZg2z13OpWwZXCNvc3ehrl4QOmanM1dgn2N7SYEvYLk6EZfBYtqoHmkymcZwSz6tQBo4-4y40rdu01" />                                
  59:                                   <div class="text-center" style="margin-top: 8px; margin-left: 6px; margin-right: -16px;">
  60:                                      <label id="status-message" class="label" style="color: tomato;"></label>
  61:                                   </div>
  62:                                   <div class="text-center" style="margin-left: -10px; margin-right: -30px; margin-top: 18px; margin-bottom: 18px;">
  63:                                      <input id="button-authentication-submit" class="btn btn-danger btn-round" type="submit" value=Enter />
  64:                                   </div>
  65:                                </form>
  66:                             </div>
  67:                          </div>
  68:                       </div>
  69:                    </div>
  70:                 </div>
  71:              </div>
  72:           </div>
  73:        </div>
  74:        <footer class="footer fixed-bottom">
  75:           <div class="container">
  76:              <div class="copyright float-right" style="color: white;">
  77:                 &copy; 2021 <a href="http://vb-net.com" target="_blank" style="color: white;"><u>vb-net.com</u></a>
  78:              </div>
  79:           </div>
  80:        </footer>
  81:        <script src="/bundle/js?v=7FhHZBIcjGtGSptqWbQVOLH1N6t5YCzWsSoaqCO1Hls1"></script>
  82:        <script type="text/javascript" src="/Assets/JS/customized/AuthenticateAdministrator.js"></script>
  83:     </body>
  84:  </html>

As you can see, need to process the same ASP.NET data-ajax-XXX. For process it need to pack all script in Bundle.config.


   1:  Imports System.Web.Optimization
   2:   
   3:  Public Module BundleConfig
   4:      Public Sub RegisterBundles(ByVal bundles As BundleCollection)
   5:          bundles.UseCdn = True
   6:   
   7:          Dim GoogleFontBundle As New StyleBundle("~/bundle/font/google", "https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Roboto+Slab:400,700|Material+Icons")
   8:          bundles.Add(GoogleFontBundle)
   9:   
  10:          Dim AwesomeFontBundle As New StyleBundle("~/bundle/font/awesome", "https://maxcdn.bootstrapcdn.com/font-awesome/latest/css/font-awesome.min.css")
  11:          bundles.Add(AwesomeFontBundle)
  12:   
  13:          Dim CSSBundle As New StyleBundle("~/bundle/css")
  14:          CSSBundle = CSSBundle.Include("~/Assets/CSS/material-kit*", "~/Assets/CSS/site.css")
  15:          bundles.Add(CSSBundle)
  16:   
  17:          Dim AdminCSSBundle As New StyleBundle("~/bundle/admin/css")
  18:          AdminCSSBundle = AdminCSSBundle.Include("~/Assets/Admin/css/bootstrap-datetimepicker.min.css")
  19:          bundles.Add(AdminCSSBundle)
  20:   
  21:          Dim JSBundle As New ScriptBundle("~/bundle/js")
  22:          JSBundle = JSBundle.Include("~/Scripts/jquery-{version}.js", "~/Scripts/jquery.unobtrusive-ajax.min.js", "~/Assets/JS/core/popper.min.js", "~/Assets/JS/core/bootstrap-material-design.min.js")
  23:          JSBundle = JSBundle.Include("~/Assets/JS/plugins/moment.min.js", "~/Assets/JS/plugins/bootstrap-datetimepicker.js", "~/Assets/JS/plugins/nouislider.min.js")
  24:          JSBundle = JSBundle.Include("~/Assets/JS/material-kit*")
  25:          bundles.Add(JSBundle)
  26:   
  27:          Dim AdminJSBundle As New ScriptBundle("~/bundle/admin/js")
  28:          AdminJSBundle = AdminJSBundle.Include("~/Scripts/jquery-{version}.js", "~/Scripts/jquery.unobtrusive-ajax.min.js", "~/Assets/Admin/js/core/popper.min.js", "~/Assets/Admin/js/core/bootstrap-material-design.min.js")
  29:          AdminJSBundle = AdminJSBundle.Include("~/Assets/Admin/js/plugins/perfect-scrollbar.jquery.min.js", "~/Assets/Admin/js/plugins/bootstrap-notify.js")
  30:          AdminJSBundle = AdminJSBundle.Include("~/Assets/Admin/js/plugins/moment.min.js", "~/Assets/Admin/js/plugins/arrive.min.js", "~/Assets/Admin/js/plugins/bootstrap-datetimepicker.min.js", "~/Assets/Admin/js/plugins/bootstrap-selectpicker.js")
  31:          AdminJSBundle = AdminJSBundle.Include("~/Assets/Admin/js/material-dashboard.min.js")
  32:          AdminJSBundle = AdminJSBundle.Include("~/Assets/Admin/js/site.js")
  33:          bundles.Add(AdminJSBundle)
  34:   
  35:          BundleTable.EnableOptimizations = True
  36:   
  37:      End Sub
  38:  End Module

In this case script AuthenticateAdministrator.js contains all dynamic future of this page, for example change text "Login" to "Loginning".



Thats is about how to attach custom script to @Ajax tag in ASP.NET. ASP.NET controller accept request and process it.



Three attached Javascripts change button state or form color before authentication started, and script after authentication analyze server response (XHR) and can write to form something more than simple server answer as retcode or json with simple litheral "true".


   1:  function OnAuthenticationBegin(xhr)
   2:  {
   3:      var textUsername = $('#input-username');
   4:      var textPassword = $('#input-password');
   5:      var buttonAuthenticationSubmit = $('#button-authentication-submit');
   6:   
   7:      var labelStatusMessage = $('#status-message');
   8:      labelStatusMessage.empty();
   9:   
  10:      var username = textUsername.val().trim();
  11:      var password = textPassword.val().trim();
  12:   
  13:      if (username.length <= 0)
  14:      {
  15:          labelStatusMessage.text("Please enter Username");
  16:          return false;
  17:      }
  18:   
  19:      if (password.length <= 0)
  20:      {
  21:          labelStatusMessage.text("Please enter Password");
  22:          return false;
  23:      }
  24:   
  25:      buttonAuthenticationSubmit.prop('disabled', true);
  26:      buttonAuthenticationSubmit.val("Logging in..");
  27:      return true;
  28:  }
  29:   
  30:  function OnAuthenticationSuccess(data, status, xhr)
  31:  {
  32:      var labelStatusMessage = $('#status-message');
  33:   
  34:      if (xhr.status == 200 && data === "TRUE")
  35:      {
  36:          labelStatusMessage.text("Successfully logged in!");
  37:          window.location = "Dashboard";
  38:      }
  39:      else
  40:      {
  41:          labelStatusMessage.text("A temporary error occured");
  42:      }
  43:  }
  44:   
  45:  function OnAuthenticationFailure(xhr, status, error)
  46:  {
  47:      var buttonAuthenticationSubmit = $('#button-authentication-submit');
  48:      var labelStatusMessage = $('#status-message');
  49:   
  50:      buttonAuthenticationSubmit.prop('disabled', false);
  51:      buttonAuthenticationSubmit.val("Login");
  52:   
  53:      switch (xhr.status)
  54:      {
  55:          case 400:
  56:              labelStatusMessage.text("Enter username and password");
  57:              break;
  58:   
  59:          case 403:
  60:              labelStatusMessage.text("Incorrect username or password !");
  61:              break;
  62:   
  63:          case 500:
  64:          default:
  65:              labelStatusMessage.text("A temporary error occurred");
  66:              break;
  67:      }
  68:  }

If you not attached this script you can use alternative and more simple way - return in controller redirect to other success/failure view.



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