Estou tentando criar um "micro-webapp" muito, muito simples, que suspeito que seja do interesse de alguns Stack Overflow'rs, se eu conseguir fazê-lo. Estou hospedando-o no meu site C # in Depth, que é o ASP.NET 3.5 baunilha (ou seja, não o MVC).
O fluxo é muito simples:
- Se um usuário entrar no aplicativo com um URL que não especifique todos os parâmetros (ou se algum deles for inválido), quero exibir apenas os controles de entrada do usuário. (Existem apenas dois.)
- Se um usuário entra no aplicativo com um URL que faz ter todos os parâmetros necessários, eu quero mostrar os resultados e os controles de entrada (para que eles possam alterar os parâmetros)
Aqui estão meus requisitos auto-impostos (mistura de design e implementação):
- Quero que o envio use GET em vez de POST, principalmente para que os usuários possam marcar a página com facilidade.
- Eu não quero que o URL para acabar parecendo bobo após a apresentação, com pedaços estranhos e pedaços sobre ele. Apenas o URL principal e os parâmetros reais, por favor.
- Idealmente, eu gostaria de evitar a exigência de JavaScript. Não há uma boa razão para isso neste aplicativo.
- Quero poder acessar os controles durante o tempo de renderização e definir valores etc. Em particular, quero poder definir os valores padrão dos controles para os valores de parâmetro passados, se o ASP.NET não puder fazer isso automaticamente para mim (dentro das outras restrições).
- Fico feliz em fazer toda a validação de parâmetros e não preciso muito de eventos do lado do servidor. É realmente simples definir tudo no carregamento da página em vez de anexar eventos aos botões etc.
A maior parte disso está bem, mas não encontrei nenhuma maneira de remover completamente o viewstate e manter o restante da funcionalidade útil. Usando a postagem deste post do blog, eu consegui evitar obter qualquer valor real para o viewstate - mas ainda acaba sendo um parâmetro no URL, que parece realmente feio.
Se eu criar um formulário HTML simples em vez de um formulário ASP.NET (ou seja, remover runat="server"
), não receberei nenhuma viewstate mágica - mas não consigo acessar os controles programaticamente.
Eu poderia fazer tudo isso ignorando a maior parte do ASP.NET e criando um documento XML com LINQ to XML e implementando IHttpHandler
. Isso parece um pouco baixo, no entanto.
Percebo que meus problemas podem ser resolvidos relaxando minhas restrições (por exemplo, usando POST e não me importando com o parâmetro excedente) ou usando o ASP.NET MVC, mas meus requisitos são realmente irracionais?
Talvez o ASP.NET não se reduz a esse tipo de aplicativo? Existe uma alternativa muito provável: estou apenas sendo estúpido, e há uma maneira perfeitamente simples de fazer isso que simplesmente não encontrei.
Alguma idéia, alguém? (Sugira comentários sobre como os poderosos caíram, etc. Tudo bem - espero nunca ter afirmado ser um especialista em ASP.NET, pois a verdade é exatamente o oposto ...)
Respostas:
Esta solução fornecerá acesso programático aos controles na íntegra, incluindo todos os atributos nos controles. Além disso, somente os valores da caixa de texto aparecerão no URL após o envio, para que o URL da solicitação GET seja mais "significativo"
Depois, no code-behind, você pode fazer tudo o que precisa no PageLoad
Se você não quiser um formulário que tenha
runat="server"
, use os controles HTML. É mais fácil trabalhar com seus objetivos. Basta usar tags HTML regulares e colocarrunat="server"
e fornecer um ID. Em seguida, você pode acessá-los programaticamente e codificar sem aViewState
.A única desvantagem é que você não terá acesso a muitos dos controles "úteis" do servidor ASP.NET como
GridView
s. Incluí umRepeater
no meu exemplo porque estou assumindo que você deseja ter os campos na mesma página que os resultados e (que eu saiba) aRepeater
é o único controle DataBound que será executado sem umrunat="server"
atributo na marca Form.fonte
Você está definitivamente (IMHO) no caminho certo ao não usar runat = "server" na sua tag FORM. Isso significa que você precisará extrair valores diretamente do Request.QueryString, como neste exemplo:
Na própria página .aspx:
e no code-behind:
O truque aqui é que estamos usando literais do ASP.NET dentro dos atributos value = "" das entradas de texto, para que as próprias caixas de texto não precisem executar o runat = "server". Os resultados são agrupados dentro de um ASP: Panel e a propriedade Visible configurada na página é carregada, dependendo se você deseja exibir resultados ou não.
fonte
Ok Jon, a questão do viewstate primeiro:
Não verifiquei se há algum tipo de alteração de código interno desde a versão 2.0, mas aqui está como lidei com a eliminação do viewstate há alguns anos. Na verdade, esse campo oculto é codificado no HtmlForm; portanto, você deve derivar o seu novo e entrar na renderização fazendo as chamadas sozinho. Observe que você também pode deixar __eventtarget e __eventtarget de fora se seguir os controles de entrada antigos simples (o que eu acho que você desejaria, pois também ajuda a não exigir JS no cliente):
Então você pega esses 3 MethodInfo estáticos e os chama de ignorar essa parte do viewstate;)
e aqui está o construtor de tipos do seu formulário:
Se estou acertando sua pergunta, você também não deseja usar o POST como a ação dos seus formulários. Veja como você faria isso:
Eu acho que é isso mesmo. Deixe-me saber como vai.
EDIT: esqueci os métodos Page viewstate:
Portanto, seu Form: HtmlForm personalizado obtém seu novo resumo (ou não): System.Web.UI.Page: P
Nesse caso, selo os métodos porque você não pode selar a página (mesmo que não seja abstrata, Scott Guthrie a envolverá em mais uma: P), mas você pode selar seu formulário.
fonte
Você já pensou em não eliminar o POST, mas redirecionar para um URL GET adequado quando o formulário é POST. Ou seja, aceite GET e POST, mas no POST construa uma solicitação GET e redirecione para ela. Isso pode ser tratado na página ou através de um HttpModule, se você quiser torná-lo independente da página. Eu acho que isso tornaria as coisas muito mais fáceis.
EDIT: Suponho que você tenha EnableViewState = "false" definido na página.
fonte
Eu criaria um módulo HTTP que lida com roteamento (semelhante ao MVC, mas não sofisticado, apenas algumas
if
instruções) e o entregaria paraaspx
ouashx
páginas.aspx
é preferido, pois é mais fácil modificar o modelo da página. Eu não usariaWebControls
noaspx
entanto. ApenasResponse.Write
.A propósito, para simplificar as coisas, você pode fazer a validação de parâmetros no módulo (como provavelmente compartilha o código com o roteamento), salvá-lo
HttpContext.Items
e renderizá-lo na página. Isso funcionará da mesma forma que o MVC, sem todos os sinos e assobios. Foi isso que fiz muito antes dos dias do ASP.NET MVC.fonte
Fiquei realmente feliz em abandonar totalmente a classe de página e manipular todas as solicitações com um grande caso de mudança baseado em URL. Todas as "páginas" se tornam um modelo html e um objeto ac #. A classe de modelo usa um regex com um delegado de correspondência que se compara a uma coleção de chaves.
benefícios:
chatices:
Jon, o que estamos fazendo no SO em uma manhã de sábado :)?
fonte
Eu pensei que o asp: controle de repetidor era obsoleto.
O mecanismo de modelo do ASP.NET é bom, mas você pode facilmente repetir com um loop for ...
O ASP.NET Forms está bem, existe um suporte decente do Visual Studio, mas essa coisa runat = "server" está errada. ViewState para.
Eu sugiro que você dê uma olhada no que torna o ASP.NET MVC tão bom, quem se afasta da abordagem do ASP.NET Forms sem jogar tudo fora.
Você pode até escrever seu próprio material de provedor de compilação para compilar visualizações personalizadas como o NHaml. Eu acho que você deve procurar aqui mais controle e simplesmente confiar no tempo de execução do ASP.NET para agrupar o HTTP e como um ambiente de hospedagem CLR. Se você executar o modo integrado, poderá manipular a solicitação / resposta HTTP também.
fonte