Minimice el tráfico en los formularios web ASP.NET, div cliqueable y sondeo periódico del servidor

La tecnología ASP.NET Web Forms es lenta pero seguramente algo del pasado. Está siendo reemplazado por una API web con Angular 6 y pilas similares. Pero heredé un proyecto en formularios web con gran legado. Tengo algunos amigos que tienen una situación similar positiva o negativa. Aplicaciones escritas en tecnología antigua que necesitan ser desarrolladas y mantenidas. Web Forms tiene la capacidad en PostBack de no actualizar toda la página, sino solo parte de ella. Lo que está envuelto en UpdatePanel. Esto agrega interactividad, pero aún funciona bastante lento y consume mucho tráfico, porque El renderizado ocurre cada vez en el servidor, y el cliente recibe un marcado listo que debe insertarse en lugar del div actual en el interior. Por cierto, UpdatePanel solo se representa en un div, en el que luego se reemplaza el marcado.

¿Qué se puede hacer para minimizar el tráfico?

  1. Escriba WebMethod en la página y llámelo desde el cliente utilizando las herramientas AJAX, cuando reciba una respuesta, cambie el DOM a través de JS.

    La desventaja de esta solución es que no puede definir WebMethod en control. No quiero escribir toda la funcionalidad en la página, especialmente si se usa varias veces en diferentes páginas.
  2. Escriba un servicio asmx y llámelo desde el cliente. Esto es mejor, pero en este caso no hay una conexión explícita entre el control y el servicio. El número de servicios crecerá con un aumento en el número de controles. Además, ViewState no estará disponible para nosotros, lo que significa que pasaremos los parámetros explícitamente al acceder al servicio, por lo que realizaremos la validación del servidor y verificaremos si el usuario tiene derecho a hacer lo que solicitó.
  3. Use la interfaz ICallbackEventHandler. Esta es, en mi opinión, una muy buena opción.

    Me detendré en ello con más detalle.

Lo primero que debe hacer es heredar nuestro UserControl de ICallbackEventHandler y escribir los métodos RaiseCallbackEvent y GetCallbackResult. Es un poco extraño que haya 2 de ellos. El primero es responsable de recibir los parámetros del cliente, el segundo es responsable de devolver el resultado.
Se verá algo así

public partial class SomeControl : UserControl, ICallbackEventHandler { #region  /// <summary> ///    /// </summary> private Guid _someFileId; #endregion #region  ICallbackEventHandler /// <inheritdoc /> public void RaiseCallbackEvent(string eventArgument) { //    try { dynamic args = JsonConvert.DeserializeObject<dynamic>(eventArgument); _someFileId = (Guid) args.SomeFileId; string type = (string) args.Type; } catch (Exception exc) { //  throw; } } /// <inheritdoc /> public string GetCallbackResult() { //  try { // -  return JsonConvert.SerializeObject(new { Action = actionName, FileId = _someFileId, }); } catch (Exception exc) { //  throw; } } #endregion } 

Era el lado del servidor. Ahora cliente

 var SomeControl = { _successCallbackHandler: function (responseData) { let data = JSON.parse(responseData); switch (data.Action) { case "continue": // -   break; case "success": //  -  break; case "fail": //   break; default: //   alert,     alert("      "); break; } }, _failCallbackHandler: function() { alert("      "); }, } 

Eso no es todo. Todavía necesitamos generar JS para conectar todas nuestras funciones.

  protected override void OnLoad(EventArgs e) { base.OnLoad(e); //   SomeControl.js,     Page.ClientScript.RegisterClientScriptInclude(Page.GetType(), "SomeControl", "/Scripts/controls/SomeControl.js?v=2.24.0"); string callbackArgument = //   //***  .***   JS   SomeControl  CallServer.       ,     ScriptManager.RegisterStartupScript(Page, Page.GetType(), "SomeControl.Initialize", $@"SomeControl.CallServer = function(someFileId) {{ let args = JSON.stringify({{ SomeFileId : someFileId, Type: '{callbackArgument}' }}); {Page.ClientScript.GetCallbackEventReference(this, "args", "SomeControl._successCallbackHandler", string.Empty, "SomeControl._failCallbackHandler", true)}; }};", true); //    ScriptManager.GetCurrent(Page)?.RegisterAsyncPostBackControl(this); } 

Obviamente, este es el código detrás del control.

Lo más interesante es la generación de funciones JS utilizando el método GetCallbackEventReference.

Pasamos a ella

  • enlace a nuestro control
  • el nombre de la variable JS cuyo valor se pasará al servidor en el método RaiseCallbackEvent a través de eventArgument (la línea anterior serializa el objeto en JSON para la transmisión y en realidad establece el valor de esta variable args)
  • Nombre de devolución de llamada de función JS para el éxito
  • contexto de ejecución (no lo uso)
  • el nombre de la función de devolución de llamada JS en caso de que algo salga mal
  • Validaremos la solicitud que llegó al servidor utilizando herramientas ASP.NET

¿Cómo funcionará todo esto juntos?

Desde JS podemos llamar a SomeControl.CallServer, esta función creará una variable local args y transferirá el control a una función que hará una solicitud al servidor a través de AJAX.
A continuación, el control se pasa al método del servidor RaiseCallbackEvent. Todo lo que estaba en la variable de cliente args ahora cayó en el parámetro de entrada del servidor eventArgument.
Una vez que se ejecuta RaiseCallbackEvent, el control se pasará a GetCallbackResult.

La cadena que devolveremos a través de return se enviará al cliente y entrará en el parámetro de entrada de la función SomeControl._successCallbackHandler, es decir, en responseData.
Si en algún momento el código del servidor arroja una Excepción, el control se transferirá al cliente SomeControl._failCallbackHandler

Todavía tengo que decir sobre ViewState. ViewState se transfiere del cliente al servidor y se puede usar, pero solo en modo de solo lectura, como ViewState no se devuelve al cliente.

El diseño es confuso a primera vista, pero si nos fijamos, resulta bastante conveniente, y se guardó el tráfico.

La segunda pregunta que quiero cubrir en este artículo es divs clicables o cómo puede llamar a la actualización UpdatePanel desde el lado del cliente.

¿Por qué se necesitan divs en los que se puede hacer clic? ¿Puedes usar <asp: Button>?
Me gusta que el div se pueda hacer como quiera, no estoy limitado por el tipo de entrada = "botón"

Para la implementación, es necesario que se herede de la interfaz IPostBackEventHandler

Él tiene solo 1 método

 public void RaisePostBackEvent(string eventArgument) 

Ahora, como en el caso anterior, necesitamos generar JS para llamar a este método

Se parece a esto

 Page.ClientScript.GetPostBackEventReference(this, callbackArgument) 

callbackArgument está configurado en el servidor y cambiarlo en el cliente no funcionará. Pero siempre puedes poner algo en un HiddenField. Tenemos un PostBack completo

Ahora el resultado de GetPostBackEventReference se puede colgar en el clic de cualquier div o span, o lo que sea.

O simplemente llame desde JS por temporizador.

Asegúrese de registrar el control como asíncrono (en OnLoad llamamos

 ScriptManager.GetCurrent(Page)?.RegisterAsyncPostBackControl(this); 
), de lo contrario, incluso dentro del UpdatePanel, se llamará al PostBack sincrónico y se actualizará toda la página, y no solo el contenido del UpdatePanel

Usando los 2 métodos descritos anteriormente, implementé, por ejemplo, tal escenario.

El usuario hizo clic en el botón, se envió una pequeña solicitud para una operación larga (10-15 segundos) al servidor, el usuario recibió una respuesta breve, durante el análisis del cual el script del cliente llama a setTimeout. En setTimeout, se pasa una función para una devolución de llamada al servidor con el fin de conocer los resultados de una operación solicitada previamente. Si el resultado está listo, llame a PostBack en UpdatePanel: el UpdatePanel especificado se actualiza. Si el resultado aún no está listo, vuelva a llamar a setTimeout.

Buena suerte a todos los que todavía están trabajando con Web Forms, espero que el artículo haga que sus sistemas sean más rápidos y hermosos, y los usuarios se lo agradecerán.

Source: https://habr.com/ru/post/es427291/


All Articles