Próbuję zbudować bardzo, bardzo prostą „mikro-aplikację internetową”, która, jak podejrzewam, zainteresuje kilku użytkowników Stack Overflow, jeśli kiedykolwiek to zrobię. Hostuję go w mojej witrynie C # in Depth, która jest waniliowym ASP.NET 3.5 (tj. Nie MVC).
Przepływ jest bardzo prosty:
- Jeśli użytkownik wejdzie do aplikacji z adresem URL, który nie określa wszystkich parametrów (lub jeśli którykolwiek z nich jest nieprawidłowy), chcę po prostu wyświetlić kontrolki wprowadzania danych przez użytkownika. (Są tylko dwa.)
- Jeżeli użytkownik wprowadzi aplikację z adresem URL, który robi wszystkie wymagane parametry, chcę wyświetlić wyniki i formantów wejściowych (dzięki czemu mogą one zmieniać parametry)
Oto moje narzucone przeze mnie wymagania (połączenie projektu i realizacji):
- Chcę, aby zgłoszenie korzystało z funkcji GET, a nie POST, głównie po to, aby użytkownicy mogli łatwo dodać stronę do zakładek.
- I nie chcą URL skończyć patrząc głupie po złożeniu, z obcych kawałki na nim. Podaj tylko główny adres URL i rzeczywiste parametry.
- Najlepiej byłoby, gdyby w ogóle nie wymagał JavaScript. W tej aplikacji nie ma ku temu żadnego powodu.
- Chcę mieć dostęp do formantów w czasie renderowania i ustawiania wartości itp. W szczególności chcę mieć możliwość ustawienia domyślnych wartości formantów na wartości parametrów przekazane, jeśli ASP.NET nie może tego zrobić automatycznie dla mnie (w ramach innych ograniczeń).
- Cieszę się, że sam wykonuję walidację wszystkich parametrów i nie potrzebuję wiele w zakresie zdarzeń po stronie serwera. Naprawdę łatwo jest ustawić wszystko podczas ładowania strony zamiast dołączać zdarzenia do przycisków itp.
Większość z nich jest w porządku, ale nie znalazłem żadnego sposobu na całkowite usunięcie stanu widoku i zachowanie pozostałych przydatnych funkcji. Korzystając z posta z tego posta na blogu , udało mi się uniknąć uzyskania jakiejkolwiek rzeczywistej wartości stanu widoku - ale nadal kończy się to jako parametr adresu URL, który wygląda naprawdę brzydko.
Jeśli zrobię to jako zwykły formularz HTML zamiast formularza ASP.NET (tj. Wyjmij runat="server"
), nie otrzymam żadnego magicznego stanu widoku - ale nie mogę uzyskać programowego dostępu do elementów sterujących.
I mógłby zrobić to wszystko, pomijając większość ASP.NET i budowania dokumentu XML z LINQ do XML i wykonawczych IHttpHandler
. To jednak wydaje się nieco niski poziom.
Zdaję sobie sprawę, że moje problemy można rozwiązać albo przez złagodzenie moich ograniczeń (np. Używając POST i nie dbając o nadwyżkowy parametr) lub używając ASP.NET MVC, ale czy moje wymagania są naprawdę nieracjonalne?
Może po prostu nie ASP.NET skalowanie w dół do tego typu aplikacji? Jest jednak bardzo prawdopodobna alternatywa: po prostu jestem głupi i jest na to całkiem prosty sposób, którego po prostu nie znalazłem.
Jakieś myśli, ktoś? (Komentarze wskazujące, jak upadli potężni itp. W porządku - mam nadzieję, że nigdy nie twierdziłem, że jestem ekspertem ASP.NET, ponieważ prawda jest zupełnie inna ...)
Odpowiedzi:
To rozwiązanie zapewnia programowy dostęp do całości kontrolek, w tym wszystkich atrybutów kontrolek. Ponadto po przesłaniu w adresie URL pojawią się tylko wartości pola tekstowego, dzięki czemu adres URL żądania GET będzie bardziej „znaczący”
Następnie w swoim kodzie możesz zrobić wszystko, czego potrzebujesz w PageLoad
Jeśli nie chcesz mieć formularza, który ma
runat="server"
, powinieneś użyć kontrolek HTML. Łatwiej jest pracować z Twoimi celami. Po prostu użyj zwykłych tagów HTML oraz umieśćrunat="server"
i nadaj im identyfikator. Następnie możesz uzyskać do nich dostęp programowo i kodować bez rozszerzeniaViewState
.Jedynym minusem jest to, że nie będziesz mieć dostępu do wielu „pomocnych” kontrolek serwera ASP.NET, takich jak
GridView
s.Repeater
W moim przykładzie umieściłem a, ponieważ zakładam, że chcesz, aby pola znajdowały się na tej samej stronie co wyniki i (o ile mi wiadomo) aRepeater
jest jedyną kontrolką DataBound, która będzie działać bezrunat="server"
atrybutu w tagu Form.źródło
Zdecydowanie (IMHO) jesteś na dobrej drodze, nie używając runat = "server" w swoim tagu FORM. Oznacza to po prostu, że musisz wyodrębnić wartości bezpośrednio z obiektu Request.QueryString, jak w tym przykładzie:
W samej stronie .aspx:
a w kodzie:
Sztuczka polega na tym, że używamy literałów ASP.NET wewnątrz atrybutów value = "" danych wejściowych tekstu, więc same pola tekstowe nie muszą uruchamiaćat = "server". Wyniki są następnie pakowane w ASP: Panel, a właściwość Visible jest ustawiana podczas ładowania strony, w zależności od tego, czy chcesz wyświetlić wyniki, czy nie.
źródło
Dobra Jon, najpierw problem z wyświetlaniem:
Nie sprawdzałem, czy od wersji 2.0 nastąpiła jakaś wewnętrzna zmiana kodu, ale oto jak poradziłem sobie z pozbyciem się stanu widoku kilka lat temu. Właściwie to ukryte pole jest zakodowane na stałe w HtmlForm, więc powinieneś wyprowadzić nowy i przejść do jego renderowania, wykonując wywołania samodzielnie. Zwróć uwagę, że możesz również pozostawić __eventtarget i __eventtarget poza, jeśli trzymasz się zwykłych starych kontrolek wejściowych (które, jak sądzę, chciałbyś, ponieważ pomaga to również nie wymagać JS na kliencie):
Więc dostajesz te 3 statyczne MethodInfo i wywołujesz je, pomijając tę część stanu widoku;)
a oto konstruktor typu twojego formularza:
Jeśli dobrze rozumiem twoje pytanie, nie chcesz również używać POST jako akcji twoich formularzy, więc oto jak to zrobić:
Myślę, że to prawie wszystko. Daj mi znać jak idzie.
EDYCJA: Zapomniałem metod wyświetlania stanu strony:
Tak więc Twój niestandardowy Form: HtmlForm otrzymuje zupełnie nową abstrakcję (lub nie) Strona: System.Web.UI.Page: P
W tym przypadku pieczętuję metody, ponieważ nie możesz zapieczętować Strony (nawet jeśli nie jest abstrakcyjna, Scott Guthrie zawinie ją w jeszcze jedną: P), ale możesz zapieczętować swoją Formę.
źródło
Czy myślałeś o nie eliminowaniu POST, ale raczej o przekierowaniu do odpowiedniego adresu URL GET, gdy formularz jest POST. Oznacza to, że zaakceptuj zarówno GET, jak i POST, ale w POST skonstruuj żądanie GET i przekieruj do niego. Można to zrobić na stronie lub za pośrednictwem modułu HttpModule, jeśli chcesz, aby był niezależny od strony. Myślę, że to znacznie ułatwiłoby sprawę.
EDYCJA: Zakładam, że na stronie ustawiono EnableViewState = "false".
źródło
Stworzyłbym moduł HTTP, który obsługuje routing (podobny do MVC, ale nie wyrafinowany, tylko kilka
if
instrukcji) i przekazałbym goaspx
lubashx
stronom.aspx
jest preferowany, ponieważ łatwiej jest modyfikować szablon strony. Nie użyłbymWebControls
w tymaspx
jednak. Po prostuResponse.Write
.Nawiasem mówiąc, aby uprościć sprawę, możesz przeprowadzić walidację parametrów w module (ponieważ prawdopodobnie współdzieli kod z routingiem) i zapisać go,
HttpContext.Items
a następnie wyrenderować na stronie. To będzie działać podobnie jak MVC bez wszystkich dzwonków i gwizdków. To właśnie robiłem przed dniami ASP.NET MVC.źródło
Naprawdę się cieszę, że całkowicie porzuciłem klasę strony i po prostu obsługuję każde żądanie za pomocą dużego przełącznika opartego na adresie URL. Każda „strona” staje się szablonem HTML i obiektem ac #. Klasa szablonu używa wyrażenia regularnego z delegatem dopasowania, który porównuje się z kolekcją kluczy.
korzyści:
bummers:
Jon, co robimy w SO w sobotę rano :)?
źródło
Myślałem, że asp: sterowanie repeaterem było przestarzałe.
Silnik szablonów ASP.NET jest fajny, ale równie łatwo można powtórzyć za pomocą pętli for ...
ASP.NET Forms jest w porządku, program Visual Studio zapewnia przyzwoitą obsługę, ale ta funkcja runat = "server" jest po prostu błędna. ViewState to.
Proponuję przyjrzeć się temu, co sprawia, że ASP.NET MVC jest tak świetny, czyli kto odchodzi od podejścia ASP.NET Forms bez odrzucania tego wszystkiego.
Możesz nawet napisać własne materiały dotyczące dostawcy kompilacji, aby skompilować niestandardowe widoki, takie jak NHaml. Myślę, że powinieneś szukać tutaj większej kontroli i po prostu polegać na środowisku wykonawczym ASP.NET do pakowania HTTP i jako środowiska hostingowego CLR. Jeśli uruchomisz tryb zintegrowany, będziesz mógł również manipulować żądaniem / odpowiedzią HTTP.
źródło