A tecnologia ASP.NET Web Forms é lenta mas seguramente uma coisa do passado. Ele está sendo substituído por uma API da Web por Angular 6 e pilhas semelhantes. Mas herdei um projeto em Web Forms com enorme legado. Tenho alguns amigos que têm uma situação semelhante a mais ou a menos. Aplicativos de longa data sobre tecnologia antiga que precisam ser desenvolvidos e mantidos. O Web Forms tem a capacidade no PostBack de não atualizar a página inteira, mas apenas parte dela. O que está incluído no UpdatePanel. Isso adiciona interatividade, mas ainda funciona bem devagar e consome muito tráfego, porque Cada vez que a renderização ocorre no servidor e a marcação final é passada para o cliente, que precisa ser inserido em vez da div atual atual. A propósito, UpdatePanel é renderizado apenas em uma div, na qual a marcação é substituída.
O que pode ser feito para minimizar o tráfego?
- Escreva WebMethod na página e chame-o pelo cliente usando as ferramentas AJAX. Quando você receber uma resposta, altere o DOM via JS.
A desvantagem desta solução é que você não pode definir o WebMethod no controle. Não quero escrever toda a funcionalidade da página, especialmente se for usada várias vezes em páginas diferentes. - Escreva um serviço asmx e chame-o do cliente. Isso é melhor, mas neste caso não há conexão explícita entre o controle e o serviço. O número de serviços aumentará com um aumento no número de controles. Além disso, o ViewState não estará disponível para nós, o que significa que passaremos os parâmetros explicitamente ao acessar o serviço; portanto, faremos a validação do servidor e verificaremos se o usuário tem o direito de fazer o que ele solicitou.
- Use a interface ICallbackEventHandler. Esta é, na minha opinião, uma boa opção.
Vou me debruçar sobre isso em mais detalhes.
A primeira coisa a fazer é herdar nosso UserControl de ICallbackEventHandler e gravar os métodos RaiseCallbackEvent e GetCallbackResult. É um pouco estranho que existam 2. O primeiro é responsável por receber parâmetros do cliente, o segundo é responsável por retornar o resultado.
Será algo parecido com isto
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 o lado do servidor. Agora cliente
var SomeControl = { _successCallbackHandler: function (responseData) { let data = JSON.parse(responseData); switch (data.Action) { case "continue":
Isso não é tudo. Ainda precisamos gerar JS para conectar todas as nossas funções.
protected override void OnLoad(EventArgs e) { base.OnLoad(e);
Obviamente, esse é o código por trás do controle.
O mais interessante é a geração de funções JS usando o método GetCallbackEventReference.
Nós passamos por ele
- link para o nosso controle
- o nome da variável JS cujo valor será passado para o servidor no método RaiseCallbackEvent via eventArgument (a linha acima serializa o objeto em JSON para transmissão e realmente define o valor dessa variável args)
- Nome de retorno de chamada da função JS para obter sucesso
- contexto de execução (não o uso)
- o nome da função de retorno de chamada JS no caso de algo dar errado
- validaremos a solicitação que chegou ao servidor usando as ferramentas ASP.NET
Como tudo isso funcionará juntos?
No JS, podemos chamar SomeControl.CallServer, essa função criará uma variável local args e passará o controle para uma função que fará uma solicitação ao servidor através do AJAX.
Em seguida, o controle é passado para o método do servidor RaiseCallbackEvent. Tudo o que estava na variável do cliente args agora caiu no parâmetro de entrada de servidor eventArgument.
Depois que o RaiseCallbackEvent for executado, o controle será passado para GetCallbackResult.
A string que retornaremos por retorno será enviada ao cliente e entrará no parâmetro de entrada da função SomeControl._successCallbackHandler, ou seja, em responseData.
Se, em algum momento, o código do servidor lançar uma exceção, o controle será transferido para o cliente SomeControl._failCallbackHandler
Ainda preciso dizer sobre o ViewState. O ViewState é transferido do cliente para o servidor e pode ser usado, mas apenas no modo ReadOnly, como O ViewState não é enviado de volta ao cliente.
O design é confuso à primeira vista, mas, se você observar, é bastante conveniente e o tráfego foi economizado.
A segunda pergunta que quero abordar neste artigo é divs clicáveis ou como você pode chamar a atualização UpdatePanel no lado do cliente.
Por que divs clicáveis são necessárias, você pode simplesmente usar <asp: Button>?
Eu gosto que a div possa ser composta como eu quero, não estou limitado pelo tipo de entrada = "botão"
Para implementação, é necessário ser herdado da interface IPostBackEventHandler
Ele tem apenas 1 método
public void RaisePostBackEvent(string eventArgument)
Agora, como no caso anterior, precisamos gerar JS para chamar esse método
Parece que isso
Page.ClientScript.GetPostBackEventReference(this, callbackArgument)
callbackArgument está definido no servidor e alterá-lo no cliente não funcionará. Mas você sempre pode colocar algo em um HiddenField. Temos um PostBack completo
Agora, o resultado do GetPostBackEventReference pode ser suspenso com o clique de qualquer div ou span, ou o que for.
Ou apenas ligue de JS por timer.
Certifique-se de registrar o controle como assíncrono (no OnLoad chamamos
ScriptManager.GetCurrent(Page)?.RegisterAsyncPostBackControl(this);
), caso contrário, mesmo dentro do UpdatePanel, o PostBack síncrono será chamado e a página inteira será atualizada, e não apenas o conteúdo do UpdatePanel
Usando os 2 métodos descritos acima, implementei, por exemplo, esse cenário.
O usuário clicou no botão, uma pequena solicitação para uma operação longa (10 a 15 segundos) foi enviada ao servidor, o usuário recebeu uma resposta curta, durante a análise da qual o script do cliente chama setTimeout. No setTimeout, uma função é passada para um retorno de chamada para o servidor para descobrir os resultados de uma operação solicitada anteriormente. Se o resultado estiver pronto, chame PostBack no UpdatePanel - o UpdatePanel especificado é atualizado. Se o resultado ainda não estiver pronto, chame setTimeout novamente.
Boa sorte para todos que ainda trabalham com Web Forms, espero que o artigo torne seus sistemas mais rápidos e mais bonitos, e os usuários agradecerão.