Postback de ASP.NET con JavaScript

80

Tengo varios divs pequeños que utilizan jQuerydraggable. Estos mensajes de correo electrónico divse colocan en un UpdatePanel, y en dragstop utilizo la _doPostBack()función JavaScript, donde extraigo la información necesaria del formulario de la página.

Mi problema es que cuando llamo a esta función, se vuelve a cargar toda la página, pero solo quiero que se vuelva a cargar el panel de actualización.

ErnieStings
fuente
¿Todos tus divs tienen una identificación única?
Nathan Taylor

Respuestas:

226

Aquí hay una solución completa

Etiqueta de formulario completo de la página asp.net

<form id="form1" runat="server">
    <asp:LinkButton ID="LinkButton1" runat="server" /> <%-- included to force __doPostBack javascript function to be rendered --%>

    <input type="button" id="Button45" name="Button45" onclick="javascript:__doPostBack('ButtonA','')" value="clicking this will run ButtonA.Click Event Handler" /><br /><br />
    <input type="button" id="Button46" name="Button46" onclick="javascript:__doPostBack('ButtonB','')" value="clicking this will run ButtonB.Click Event Handler" /><br /><br />

    <asp:Button runat="server" ID="ButtonA" ClientIDMode="Static" Text="ButtonA" /><br /><br />
    <asp:Button runat="server" ID="ButtonB" ClientIDMode="Static" Text="ButtonB" />
</form>

Todo el contenido de la clase de código subyacente de la página

Private Sub ButtonA_Click(sender As Object, e As System.EventArgs) Handles ButtonA.Click
    Response.Write("You ran the ButtonA click event")
End Sub

Private Sub ButtonB_Click(sender As Object, e As System.EventArgs) Handles ButtonB.Click
    Response.Write("You ran the ButtonB click event")
End Sub
  • El LinkButton se incluye para garantizar que la función javascript __doPostBack se muestre al cliente. El simple hecho de tener controles de botón no hará que se procese esta función __doPostBack. Esta función se representará en virtud de tener una variedad de controles en la mayoría de las páginas ASP.NET, por lo que normalmente no se necesita un botón de enlace vacío.

¿Que esta pasando?

Se representan dos controles de entrada al cliente:

<input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
<input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
  • __EVENTTARGET recibe el argumento 1 de __doPostBack
  • __EVENTARGUMENT recibe el argumento 2 de __doPostBack

La función __doPostBack se representa así:

function __doPostBack(eventTarget, eventArgument) {
    if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
        theForm.__EVENTTARGET.value = eventTarget;
        theForm.__EVENTARGUMENT.value = eventArgument;
        theForm.submit();
    }
}
  • Como puede ver, asigna los valores a las entradas ocultas.

Cuando el formulario se envía / devuelve:

  • Si proporcionó el UniqueID del botón de control del servidor cuyo controlador de clic de botón desea ejecutar ( javascript:__doPostBack('ButtonB',''), se ejecutará el controlador de clic de botón para ese botón.

¿Qué sucede si no quiero ejecutar un controlador de clics, pero quiero hacer otra cosa en su lugar?

Puedes pasar lo que quieras como argumentos a __doPostBack

Luego puede analizar los valores de entrada ocultos y ejecutar código específico en consecuencia:

If Request.Form("__EVENTTARGET") = "DoSomethingElse" Then
    Response.Write("Do Something else") 
End If

Otras notas

  • ¿Qué sucede si no conozco el ID del control cuyo controlador de clics quiero ejecutar?
    • Si no es aceptable para conjunto ClientIDMode="Static", entonces usted puede hacer algo como esto: __doPostBack('<%= myclientid.UniqueID %>', '').
    • O: __doPostBack('<%= MYBUTTON.UniqueID %>','')
    • Esto inyectará la identificación única del control en el javascript, si lo desea
Brian Webster
fuente
47
+1 para completitud. Un tipo de respuestas geniales que me hacen amar StackOverflow.
Manitra Andriamitondra
3
Esta es una de las mejores explicaciones que he encontrado para __doPostBack () .. ¡+10 para esto!
GuruC
1
@BrianWebster, Muchas gracias por su publicación detallada. ¿Podría sugerirle a cualquier persona que todavía tenga ASP.NET 3.5 y versiones anteriores que usen C # en lugar de VB.NET que cambie las dos últimas líneas en el archivo .aspx de la siguiente manera? <asp: Button runat = "server" ID = "ButtonA" Text = "ButtonA" OnClick = "ButtonA_Click" /> <br /> <br /> <asp: Button runat = "server" ID = "ButtonB" Text = "ButtonB" OnClick = "ButtonB_Click" />
yangli.liy
1
Esta es una solución muy útil. Si está utilizando páginas maestras, la identificación de los botones se confunde un poco. Consulte la respuesta de user489998 a continuación para obtener ayuda para obtener la identificación correcta para la devolución de datos.
DCastenholz
1
@BrianWebster Es realmente raro que alguien pueda proporcionar una solución completa al problema de alguien Y ofrecer alternativas adecuadas a posibles desviaciones.
GoldBishop
15

Per Phairoh: use esto en la página / componente en caso de que el nombre del panel cambie

<script type="text/javascript">
     <!--
     //must be global to be called by ExternalInterface
         function JSFunction() {
             __doPostBack('<%= myUpdatePanel.ClientID  %>', '');
         }
     -->
     </script>
Laramie
fuente
9

Si bien la solución de Phairoh parece teóricamente sólida, también he encontrado otra solución a este problema. Al pasar el ID de UpdatePanels como un parámetro (destino del evento) para la función doPostBack, el panel de actualización se publicará, pero no la página completa.

__doPostBack('myUpdatePanelId','')

* nota: el segundo parámetro es para argumentos de eventos adicionales

¡Espero que esto ayude a alguien!

EDITAR: entonces parece que este mismo consejo se dio anteriormente mientras escribía :)

ErnieStings
fuente
2
Esto funcionará, y he hecho algo similar en una aplicación, pero realmente no es una buena idea y odio tener que hacerlo cuando lo hice. Si el nombre de su panel de actualización alguna vez cambia, se rompe. Si alguna vez pones esto dentro de un control de usuario, se rompe. Si agrega una página maestra, se rompe. Sí, funciona, pero es bastante frágil. Como mínimo, utilice la propiedad ClientId de su panel de actualización en lugar de la cadena estática.
Phairoh
9

Usar __doPostBackdirectamente es taaaan de la década de 2000. Cualquiera que codifique WebForms en 2018 usa GetPostBackEventReference

(Más en serio, sin embargo, agregar esto como una respuesta para completar. Usar el __doPostBackdirectamente es una mala práctica (el prefijo de subrayado simple generalmente indica un miembro privado y el doble indica un miembro privado más universal), aunque probablemente no cambiará ni se volverá obsoleto en este punto. Tenemos un mecanismo totalmente compatible en ClientScriptManager.GetPostBackEventReference .)

Suponiendo que su btnRefresh está dentro de nuestro UpdatePanel y causa una devolución de datos, puede usar GetPostBackEventReference así ( inspiración ):

function RefreshGrid() {
    <%= ClientScript.GetPostBackEventReference(btnRefresh, String.Empty) %>;
}
mlhDev
fuente
Esto funciona muy bien. En mi situación, puedo declarar que los controles Target AJAX se actualicen cuando se hace clic en btnRefresh en el marcado HTML. Al usar esto, fue extremadamente simple implementar esto con soporte para AJAX.
DanielG
6

Si alguien tiene problemas con esto (como yo), puede obtener el código de devolución de un botón agregando el atributo UseSubmitBehavior = "false". Si examina la fuente renderizada del botón, verá el javascript exacto que necesita ejecutar. En mi caso, estaba usando el nombre del botón en lugar de la identificación.

usuario489998
fuente
Muy útil cuando se utilizan páginas maestras.
DCastenholz
1
__doPostBack parece usar siempre el nombre del botón cuando usa páginas maestras.
Dennis T --Reincorpora a Monica--
2

¿Ha intentado pasar el ID de cliente del panel de actualización a la función __doPostBack? Mi equipo ha hecho esto para actualizar un panel de actualización y, hasta donde yo sé, funcionó.

__doPostBack(UpdatePanelClientID, '**Some String**');
Jeremy Bade
fuente
1

Primero, no use paneles de actualización. Son la segunda cosa más malvada que Microsoft haya creado para el desarrollador web.

Segundo, si debes utilizar paneles de actualización, intente establecer la propiedad UpdateMode en Condicional. Luego agregue un disparador a un Asp: control oculto que agregue a la página. Asigne el evento de cambio como desencadenante. En su evento dragstop, cambie el valor del control oculto.

Esto no está probado, pero la teoría parece sólida ... Si esto no funciona, puede intentar lo mismo con un botón asp:, simplemente configure el estilo display: none y use el evento click en lugar del evento change.

Phairoh
fuente
7
¿Cuál es la primera cosa más malvada que Microsoft creó para los desarrolladores web?
ErnieStings
2
el control de inicio de sesión debe estar bastante arriba en esa lista.
kim3er
27
@ErnieStings: IE6
phairoh
1
¿Puede proporcionar alguna explicación por qué UpdatePanels es tan malvado? Si es así, me gustaría leer algunas razones por las que y cuándo no usarlas. Hasta ahora no me he encontrado con ningún problema crucial con UpdatePanels.
Jan Kukacka
@JanKukacka Son una pobre abstracción de AJAX. Las habilidades que aprende al escribir paneles de actualización no se traducen directamente en la capacidad de utilizar AJAX correctamente en cualquier cosa fuera de ASP.NET Web Forms. Los UpdatePanels son difíciles de depurar. Y si tiene ViewState activado, una gran cantidad de datos se transfiere hacia / desde el servidor innecesariamente, lo que hace que requiera un uso intensivo del ancho de banda. Aprender AJAX adecuado (tal vez con una capa de abstracción ligera como jQuery) es una solución mucho mejor cuando necesita hablar con el servidor sin realizar una devolución de datos.
albañil
1

No puede llamar _doPostBack()porque fuerza la presentación del formulario. ¿Por qué no desactivas el PostBackencendido UpdatePanel?

Alex Rodrigues
fuente
1
Una pregunta. Cuando se arrastra un div, el _doPostBack es invocado por usted o automáticamente por ASP.NET?
Alex Rodrigues
lo invoco a través de javascript
ErnieStings