cmdSave.Enabled = False

Nemaz nav prātīgi domāt, ka, ASP.Net kontrole (piemēram, poga), kas it kā ir “atspējota” (disabled, not enabled), patiesībā tāda ir. Vienīgais, ko patiesībā ASP.Net izdara, ir, ģenerējot HTML kodu, kontroles kodā ieraksta disabled=true.

Taču, ja šo pogu klienta pusē atkal “iespējojam” (eneiblojam), piemēram, ar šāda te:

javascript:( 
    function(){
      d=document;
      l=d.getElementsByTagName("INPUT");
      for(var i=0;i<l.length;i++){
         l[i].disabled=false}
 }())

JavaScript bookmarkleta palīdzību, ASP.Net neveiks nekādas servera puses pārbaudes, vai poga ir bijusi ieslēgta, vai nav. Tas jādara pašiem. Vislabāk nemaz nedot lietotājam rokās pogu, kuru nevar nospiest, bet, ja gribas saglabāt skaistu interfeisu, tad cmdSave_Click(...) kods jāpapildina ar pārbaudi, vai poga šobrīd vispār ir ieslēgta.

Paldies par uzmanību :-)

Month names. i18n, you know

Whenever you see something like this you should come to an idea something is wrong (for instance, the guy who wrote this is still alive):

'month names in Latvian
Dim sMonth() As String = _
            {"Janvāris", "Februāris", "Marts", "Aprīlis", _
            "Maijs", "Jūnijs", "Jūlijs", "Augusts", _
            "Septembris", "Oktobris", "Novembris", "Decembris"}

Dim oListItem as ListItem
For iMonth as Integer = 1 To 12
  oListItem = New ListItem(sMonth(iMonth-1),  iMonth.ToString())
  Me.lstYears.Items.Add(oListItem)
Next

Explanation – if MS Windows knows quite well how months are named in Latvia, why should you try to be smarter than the big brother? Another explanation – if this is a web project (and in my case it is), you should think of internationalization whenever possible.

So a more correct way to add month names to a dropdown menu is:

Imports System.Globalization
....
Dim oListItem as ListItem
For iMonth As Integer = 0 To 11
   oEntry = New Web.UI.WebControls.ListItem( _
         CultureInfo.CurrentUICulture.DateTimeFormat.MonthNames(iMonth), _
            iMonth.ToString)
   Me.lstMonths.Items.Add(oEntry)
Next

And, to be even more precise, you could first check how many months there are in the current culture:

For iMonth As Integer = 0 To _
                CultureInfo. CurrentUICulture.Calendar. _ 
                GetMonthsInYear(Now.Year) - 1
    ....

/Just trying to be a good boy and use the facilities provided by the framework/

ASP.Net pāradresācijas un kļūdu apstrāde

ASP.Net, kaut gan tā lapas paredzētas darbam kā notikumu bāzētas web formas, spēj strādāt arī ar vienkāršiem HTTP jēdzieniem, piemēram, HTTP headeriem. Viens no populāriem headerim ir Location, kura semantiskā jēga ir paziņojums HTTP aģentam (pārlūkprogrammai) “pārtrauc šī dokumenta apstrādi un pieprasi tā vietā šo te dokumentu!”

ASP.Net šāda iespēja ir pieejama, lietojot Response objekta Redirect() metodi. Piemēram,

If booleanNosacijums Then
       Response.Redirect("http://naivist.net")
End If

Ja vien Redirect() metodei netiek speciāli norādīts, ka otrā neobligātā parametra EndResponse vērtība ir False, šajā brīdī notiek sekojošais:

  • lietotājam tiek nosūtīts HTTP headeris Location:http://naivist.net
  • ASP.Net iekšienē tiek mesta System.Threading.ThreadAbortException kļūda, kuru pārķer .Net runtime un aptur pašreiz izpildāmā pavediena darbību.

Šāds darbības princips garantē to, ka pēc pāradresācijas headera nosūtīšanas tālākais kods neizpildīsies. Ja pavediens netiktu apturēts, izpildītos citi notikumu apstrādes koda fragmenti rezultāti tiktu nosūtīti klientam pēc pāradresācijas headera (kur lietotājs to vienala uz ekrāna neredzētu).

Kā zināms, labi programmētāji lieto strukturēto kļūdu apstrādi. Piemēram, faila dzēšanu ievieto Try-Catch blokā. Ja failu neizdosies nodzēst, kodā notiks ar kļūda, kas tiks noķerta Catch blokā. Ja failu izdosies nodzēst, pēc dzēšanas pāradresēsimies uz citu lapu.

    Try
        Dim oFile As New IO.FileInfo("c:\temp\fails.txt")
        oFile.Delete()
        Response.Redirect("failsLabiNodzests.aspx")
    Catch ex As Exception
        Me.lblInfo.Text="Nav izdevies nodzēst failu"
       System.Diagnostics.EventLog.WriteEntry("MyApp",  _
                                      "Kļūda dzēšot failu", EventLogEntryType.Error)
    End Try

Tomēr šāds kods nestrādās īsti korekti, jo arī pie veiksmīgas faila dzēšanas izpildīsies Catch bloks, noķerot ThreadAbortException kļūdu. Līdz ar to EventLog parādīsies nekorekta informācija.

Viens no veidiem, kā novērst problēmu, ir vispirms ķert specifisko ThreadAbortException kļūdu un tikai tad apstrādāt pārējās:

    Catch ex As Threading.ThreadAbortException
        Throw ex
    Catch ex As Exception 
    ...

Šāds veids ir funkcionāls, bet nav elegants, jo kļūda tiek ķerta un pārmesta vēlreiz – neglīti. Lietojot Visual Basic .Net specifisko kļūdu apstrādes principu, kodu var padarīt elegantāku:

    Catch ex As Exception When _
        Not TypeOf (ex) Is Threading.ThreadAbortException
        Me.lblInfo.Text="Nav izdevies nodzēst failu"
   ...

Tagad tiek ķertas tikai tās kļūdas, kuru tips nav ThreadAbortException, kas arī bija jāpanāk. When nosacījumā drīkst ierakstīt jebkādu nosacījumu, kura izpildes rezultāts ir Boolean tipa. Ir iespējams izmantot arī kodā definētu mainīgo vērtības, ar nosacījumu, ka mainīgais ir redzamības apgabalā (variable scope).

ASP.NET features – ViewState

Solīts ir un paliek solīts – rakstām par ASP.Net atribūtiku. Šoreiz – par ViewState.
Jau iepriekš pieņemu, ka lasītājs ir iepazinies ar rakstu par ASP.Net pamatiem un par ASP.Net koda izpildes modeli

Īsumā, kas ir ViewState:

  • veids, kā ASP.Net uzglabā informāciju par WebFormas stāvokli, informāciju nesaglabājot sesijas mainīgajos
  • izstrādātājam – datu masīvs, kurā var ievietot datus un tos nolasīt neatkarīgi no WebFormas dzīves cikla. Tāpat arī – iespēja vienu reizi dinamiski uzstādīt kādas kontroles kādu atribūtu un pēc tam ļaut par atribūta vērtību parūpēties pašam ASP.Net
  • pārlūkprogrammai – burtu virknīte, hidden lauks HTML dokumentā, kas jāpārsūta atpakaļ serverim.

Vēlreiz parunāsim par ASP.Net WebFormu dzīves ciklu. Piemēram, esam atvēruši lapu http://localhost/default.aspx Šajā lapā ir viens teksta ievades lauks txtName un viena poga. Nospiežot pogu, tiek izpildīta HTTP POST operācija, datus atkal pārsūtot uz http://localhost/default.aspx, tas ir, lapa tos pārsūta “pati uz sevi”. Saņemtos datus apstrādā ASP.Net, ģenerē atjaunotu WebFormas izskatu un to nosūta uz pārlūku.

Saņemtajos formas POST datos parādās lauka txtName vērtība, kādu to ir ievadījis vai izmainījis lietotājs. Taču, lai varētu korekti apstrādāt lauka vērtības izmaiņas, nepieciešams salīdzināt šī lauka vērtību pirms to ļāva lietotājam mainīt un tad, kad saņemtas lietotāja veiktās izmaiņas, tas ir, nepieciešams zināt, kāda bija lauka vērtība, kad lapa iepriekšējo reizi tika sūtīta lietotājam. Tieši šādam mērķim arī kalpo ViewState – tajā ir atrodamas dažādu informācijas lauku “vecās versijas”. Tādējādi ASP.Net, procesējot lapu http://localhost/default.aspx, var salīdzināt, ka šobrīd aktuālā txtName vērtība ir “ArčibaldsKronins”, taču pēc ViewState datiem laukā txtName bijis ierakstīts “VitālijsMētra” un, pamatojoties uz to, apstrādāt txtName_TextChanged notikumu.

Jāatzīmē, ka katra lapas kontrole var ViewState saglabāt dažādus savus atribūtus. Piemēram, visas klases, kas mantotas no Web.UI.WebControls.WebControl klases, ViewState informācijā saglabā Enabled, AccessKey, TabIndex, ToolTip, Visible un papildus tam vēl specifiski kontrolei piemītošas īpašības, piemēram, Web.UI.WebControls.Label papildus tam saglabā arī Text atribūtu.

To, vai kāda ekrāna kontrole vispār saglabā savus datus ViewState vai nē, nosaka no System.Web.UI.Control klases mantotā atribūta EnableViewState vērtība. Ja EnableViewState=False, kontrole savu informāciju ViewState datos nesaglabā. Ja True, saglabā visu šim tipam atbilstošo informāciju (bieži vien pat par daudz). Par to, kā samazināt ViewState apjomu, raksta daudzi, ir vērts iepazīties ar Microsoft ieteikumiem aplikācijas stāvokļa saglabāšanai.

Lai saprastu tālāk, jāpaskatās, kā izskatās ViewState dati no HTML viedokļa. Tas ir slēpts datu lauks, kura vērtība apstrādāta ar Base-64 algoritmu

< input type="hidden" 
name="__VIEWSTATE" 
value="dDw5NDE3OTg0NzE7Oz6gEYYV9S+G2OiSz/XslX9Ha+7t5Q==" />

Atkodējot datus, var iegūt pa pusei lasāmu datu virkni, kas satur informāciju par visām kontrolēm, kas izmanto ViewState. Piemēram, manis demonstrētais ViewState ir atkodējams uz šādu t<941798471;;> †õ/†Ųč’Ļõģ•Gkīķå. Nav sevišķi izteiksmīgs teksts, taču dators saprot. Pēdējie baiti ir informācija pašam ASP.Net, lai varētu pārbaudīt, vai dati nav modificēti pēc nosūtīšanas klientam, pirmie – satur svarīgo informāciju par ekrāna kontroļu atribūtiem.

Kā redzams no atkodētajiem datiem, ViewState saglabātā informācija nav piekārtota ekrāna kontrolēm pēc to identifikatoriem vai nosaukumiem, bet gan pēc secības, kādā kontroles novietotas lapā. Tieši šī iemesla dēļ ir svarīgi, ka ekrāna kontroļu kolekcija nav tikusi mainīta kopš iepriekšējās lapas ielādes.
Ja atšķiras kontroļu skaits vai tips, ASP.Net ģenerēs kļūdas paziņojumu par nekorektiem ViewState datiem. Šī īpatnība nerada problēmas gadījumā, kad visas ekrāna kontroles ir sagatavotas .aspx lapā un kontroļu kolekcija ir nemainīga visā WebFormas dzīves laikā, bet problēma aktualizējas brīdī, kad kontroles tiek pievienotas lapai dinamiski.

Piemēram, ja veidosim WebFormu, kas parāda uz ekrāna kāda faila EXIF atribūtus un gribēsim ļaut tos visus vienlaicīgi mainīt uz ekrāna – katram EXIF laukam būs jāveido atsevišķa TextBox kontrole, kurā jāparāda esošā vērtība un jāļauj ievadīt citus datus. Tādējādi šo formu nevarēs sagatavot jau iepriekš un kontroļu skaits būs atšķirīgs.

Līdz ar to, lai pirmo reizi parādītu visus EXIF laukus, veidosim jaunu TextBox objektu:

    Dim oTxt As New Web.UI.WebControls.TextBox
    oTxt.ID = "txtResolution"
    oTxt.Text = oSomeObj.Resolution 'šis ir objekts, no kura "lasām" EXIF datus

un pievienosim šo objektu ekrāna kontroļu kolekcijai ar kodu Page.Controls.Add(oTxt).
Taču nākamajā lapas ielādes reizē, kad gribēsim izmantot ViewState datus, mums jāizveido attiecīgais TextBox objekts un jāļauj tam patstāvīgi nolasīt savu vērtību no ViewState. Objekta veidošanu ierakstām Page_Load metodē, kas izpildās pirms ViewState datu lasīšanas:

Private Sub Page_Load _
            (ByVal s As System.Object, ByVal e As System.EventArgs) _
             Handles MyBase.Load
    'izņemot gadījumu, ja lapa ielādējas pirmo reizi - tad jāizpilda augstāk aprakstītā procedūra
    If Not Page.IsPostBack() Then
        Dim oTxt As New Web.UI.WebControls.TextBox
        oTxt.ID = "txtResolution"
    Else
        'izsaukums uz augstāk aprakstīto procedūru, kas nolasa datus no paša faila
    End If
End Sub

Jādomā, ka problēma šeit jau ir jūtama – kā zināt, kā saucas ekrāna kontroles, kas jāveido, lai tās pašas no sevis nolasītu datus. Piemērā esmu izmantojis nosaukumu “txtResolution”, jo pieņemu, ka gandrīz katrā EXIF galvenē būs dati par attēla izšķirtspēju, taču ko darīt, ja datus ielādējam patiešām dinamiski?

Viens no risinājumiem (apkārtceļiem, protams), kādu esmu lietojis, ir – savākt visu pirmajā reizē izveidoto kontroļu ID-us vienā garā String tipa mainīgajā, atdalītā, piemēram ar “#” simboliem. Un, kad dinamiskā ģenerēšana beigusies, šo String noglabāt turpat ViewState datos:

Viewstate.Add("ControlNames", sControlNames)

Pēc tam, nākamo reizi ielādējot lapu, pārbaudām, vai ViewState satur mainīgo ControlNames. Ja satur – sadalām šo String pa atsevišķiem nosaukumiem, analizējam nosaukumus, pēc analīzes rezultātiem veidojam kontroles. Piemēram, no šāda te ControlNames satura – “txtResolution#chkMakePublic” var secināt, ka jāveido teksta ievades lauks ar nosaukumu txtResolution un ķekškaste ar nosaukumu chkMakePublic.

Kāpēc jālieto šāds apkārtceļš? Lai atkārtoti nelasītu datus no paša faila (pieņemsim, ka fiziskā faila atribūtu lasīšana ir resursietilpīga procedūra). Ja datus varam atkārtoti lasīt no paša faila, nav nepieciešams izmantot ViewState, jo var vienkārši salīdzināt lietotāja piesūtītos datus ar oriģinālajiem.

Ja pieļaujams darbam izmantot SessionState datus jeb “sesijas mainīgos”, lielu daļu no ViewState var pārcelt uz SessionState, tādējādi atslogojot klienta-servera saziņas datu kanālu, bet vairāk noslogojot serveri.

Jāatceras, ka daudzas no Microsoft piedāvātajām datu ievades kontrolēm strādās jocīgi vai nestrādās nemaz, ja ViewState tām būs izslēgts. Piemēram, ļoti ērtā DataGrid kontrole intensīvi izmanto ViewState un pie izslēgta ViewState darbojas slikti. Taču tieši šī kontrole saglabā ļoti daudz datu ViewState masīvā. No tā varam viegli secināt, ka ViewState būs labs risinājums gadījumos, kad klienta-servera komunikācija ir viegla un saziņas kanāls ir plats (piemēram, iekšējā tīkla risinājumos), bet ar to jāuzmanās tad, kad datu plūsmas apjoms ir svarīgs.

Starp citu – ViewState datos var saglabāt, šķiet, jebkuru objektu, kas atbalsta ISerializable interfeisu, piemēram, DataSet, taču ļoti jāuzmanās, vai dotais datu tips netiek serializēts nejēdzīgi lielā bināru datu virknē.

ASP.NET koda modelis

Šajā rakstā tiek pieņemts, ka lasītājs ir iepazinies ar ievadrakstu par ASP.Net

Šis ir īss izklāsts latviešu valodā no MSDN izklāsta par ASP.Net koda modeli

ASP.Net koda modelis ir viens no pirmajiem soļiem pretim Longhorn paredzēto aplikāciju izstrādes tehnikai, kur aplikācijas izskats tiek nodalīts no koda, kas apstrādā notikumus. Tādējādi “layouts” un “eventi” ir koda ziņā divi dažādi faili, kuru saturs aplikācijas izpildes laikā tiek ar “maģiskās mērces” palīdzību saķibināts vienotā baitu plūsmā.
Būtībā tiek risināta problēma, kuras dēļ, piemēram PHP skriptu gadījumā radīti tādi “template dzinēji” kā Smarty, tikai šeit problēmas risinājums iešūts pašā dzinējā.

ASP.Net lapas pamatā vienmēr būs koda klase System.Web.UI.Page. Šajā klasē implementētas visas darbam pamatā nepieciešamās metodes (piemēram, RenderControl, Validate un citas), pieejamas datu kolekcijas un svarīgākie objekti, kas atbalsta HTTP ideoloģiju(piemēram Request, Response, ViewState), klase realizē pietiekami sarežģītu notikumu modeli (pieejami notikumi, piemēram Init, Load, PreRender, DataBinding un citi)

Sākot veidot jaunu ASP.Net lapu, jāveido klase, kas mantota no Page klases. Tas ir, ja vēlamies izveidot primitīvu webformu uz kuras varētu atrasties viens nerediģējama teksta klucītis, kods ir šāds:

Public Class MyPage
    Inherits Web.UI.Page
    Protected MyLabel As Web.UI.WebControls.Label
End Class

Failu, kas satur šādu klasi, iespējams kompilēt, lietojot parasto Visual Basic.net kompilatoru vbc.exe un rezultātā iegūt *.dll failu, ko dēvē par code-behind bibliotēku.

Viegli pamanīt, ka iepriekš minētajā kodā nav informācijas par to, kāds izskatīsies Label objekts. WebFormas vizualizācija tiek veidota kā atsevišķs fails, kura paplašinājums parasti ir *.aspx. Šāda faila pirmā rinda ir norāde interpretatoram, kur meklēt no kādas klases mantota dotā webforma:

< %@ Page Language="vb" AutoEventWireup="false" Inherits="MyApp.MyPage"%>

Mazliet īpatnēji šajā kontekstā šķiet izmantot terminu mantošana, jo šādi sanāk, ka teksta fails manto koda klasi, bet tā to dēvēt izvēlējušies tehnoloģijas arhitekti. Ir iespējams vienai koda klasei piekārtot vairākas izskata lapas, bet ne otrādi.

Webformas layout fails tiek veidots kā HTML un ASP iezīmju maisījums, lietojot speciālas birkas kontroļu ievietošanai. Mūsu piemērs izskatās šādi (atvainojiet par liekajām atstarpēm birku sākumā, ir nelielas problēmas ar manu publicēšanas sistēmu):

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
  <body>
  <form id="Form1" method="post" runat="server">
    <asp:Label id="MyLabel" runat="server"></asp:Label>
  </form>
  </body>
</HTML>

Šeit svarīgi ir tas, ka asp:Label ID atribūts sakrīt ar MyPage koda klases atribūta nosaukumu. Šādā veidā webformas lietotāja interfeisa kontrole tiek piesaistīta kodam, kas ar to darbojas. Ja ASP.Net lapa tiek veidota ar MS Visual Studio .Net, formas kontroļu saderību ar klases atribūtiem tiek nodrošināta automātiski.

Kas tad notiek tālāk. Rezultātā esam ieguvuši divus atsevišķus failus – mypage.aspx, kur definēts lapas izskats un myapp.dll, kurā implementētas lapas loģika. Izveidojam Internet Information Server pieejamu direktoriju uz cietā diska, piemēram, c:\inetpub\wwwroot\myapp\. Direktorijā ievietojam tikai .aspx failu un izveidojam papildus apakšdirektoriju bin, kurā ievietojam .dll failu.

IIS konfigurācijā izveidojam jaunu aplikāciju direktorijai c:\inetpub\wwwroot\myapp\ (kā to izdarīt).
Šajā brīdī IIS zina, ka visi .aspx faili, kas atrodas šajā direktorijā, turpmāk jāapstrādā ar ASP.Net ISAPI filtru jeb interpretatoru, kas tiks ielādēts no C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\aspnet_isapi.dll (Tā arī tā manis minētā *maģiskā mērce*).

Kad lietotājs pieslēdzas tīmekļa serverim un pieprasa mūsu izstrādāto lapu (http://localhost/myapp/mypage.aspx) , IIS process sevī ielādē (ja vēl nav ielādējis) aspnet_isapi.dll bibliotēku un tai palūdz procesēt lapu mypage.aspx. Interpretators noskaidro, ka mypage.aspx ir mantota no koda klases MyPage, kas atrodama bibliotēkā myapp.dll. Rezultātā IIS procesā tiek ielādēta arī myapp.dll bibliotēka’. Tālāk tiek izpildīts kods, kas galu galā atgriež rezultātu IIS procesam, kurš to nodod atpakaļ lietotājam.

Koda izpildes laikā lapa ‘izdzīvo’ savudzīves ciklu. Lai imitētu Windows formas darba stilu, tiek veiktas daudzas lietotājam nezināmas darbības, piemēram, lapā saliktas datu ievades kontroles, to vērtības atjaunotas uz sākotnējām vai tādām, uz kādām lietotājs tās pamainījis pirms kādas pogas nospiešanas, tiek apstrādāti notikumi kā “nospiesta poga A” vai “nomainījies izvēlētais ieraksts listboxī” un citi.

Skaists un pilnīgs lapas dzīves cikla apraksts atrodams 15Seconds rakstā, bet īsumā, kas notiek:

  • Objektu un kontroļu inicializēšana
  • ViewState datu atjaunošana (par šo stāstīšu nākamajā rakstā)
  • PostBack datu apstrāde- tas, ko lietotājs ir pamainījis formā
  • Tiek pacelti izmaiņu notikumi (onclick, onselectedindexchanged etc)
  • Tiek ģenerēts HTML
  • Tiek ģenerēts jaunais ViewState

Pēc tam lietotājs atkal kaut ko pamaina WebFormā, katra darbība pārsūta datus uz serveri, un atkal notiek šāda pat procedūra. Tādējādi jebkuras pogas nospiešana patiesībā pārsūta datus atkārtoti uz serveri, tur tiek apstrādāts šīs pogas onClick notikums un ģenerēts jauns, droši vien jau citāds HTML kods. Visu tekstu ievades lauku dati saglabājas, jo arī tie tiek pārsūtīti uz serveri, bet, atšķirībā no PHP aplikācijām, izstrādātājam ne obligāti būs jārūpējas par to, lai no POST (vai GET) datiem atjaunotu ievades lauka stāvokli – to izdarīs ASP.net.

ASP.Net – sākumam

Ir tāds bieži dzirdēts vārds ASP.Net, ko katrs saprot pa savam. Cits uzskata, ka tā ir programmēšanas valoda (patiesībā nav vis), cits tajā saskata tālāku attīstību no Microsoft Active Server Pages (un tā arī ir), cits atzīst par nopietni apskatāmu kandidatūru web aplikācijas risinājumiem (līdzvērtīgu PHP vai ColdFusion), cits spēj vien kārtējo reizi nospļaudīties “Ak, tas [pīiii] maikrosofts”.

Iegūstot zināmu darba pieredzi ar ASP.Net tehnoloģiju, esmu sapratis, ka tas patiešām ir sava veida turpinājums “vecajam ASP”, kas veidots tā, lai tīmekļa aplikāciju izstrāde būtu līdzīga Windows aplikāciju izstrādei (kontroles, to dzīves cikls u.c.) Parādījies jēdziens “web forma“, kas tuvināts Windows formām – ir pat izveidoti GUI redaktori, ar kuriem strādājot nav jūtama liela atšķirība starp WebFormu un Windows formu (ne tikai VisualStudio.net, bet arī, piemēram SharpDevelop) .

ASP.Net web formu izstrādātājs dizaina laikā teorētiski darbojas tikai ar kontroļu izkārtojumu uz “formas”, nav jāuztraucas par to, kāds HTML kods tiks ģenerēts šai webformai (tas tiešām tiek ģenerēts atkarībā no lietotāja aģenta, kas lapu pieprasījis – piemēram, mobilās ierīces saņem pavisam citādu kodu nekā FireFox pārlūks. Savukārt MS Internet Explorer saņem kodu, kas “pārbāzts” ar Microsoft papildinājumiem HTML4.0 standartam. Manuprāt, korekts risinājums, ja citi pārlūki netiek ar to traucēti).

Pateicoties pietiekami interesantajai arhitektūrai, ASP.Net ir labi piemērots mērogojamu aplikāciju izstrādei, savukārt tas, ka tehniski sīkumi ir paslēpti pašā ASP.Net infrastruktūrā, ļauj vairāk koncentrēties uz biznesa loģikas implementēšanu. No otras puses, tieši sīkumu paslēpšana ļauj darboties diletantiski, kā rezultātā rodas jautājumi kā, piemēram “Kā es varu norādīt faila upload dialogam, kurus faila tipus drīkst izvēlēties?”

Protams, jāsaprot arī tos, kuri par šo tehnoloģiju izsakās nievājoši – tās sarežģītības dēļ rodas pārpratumi, kuru pamatā visbiežāk tas, ka kāds rīks tiek lietots citiem mērķiem nekā tas sākotnēji paredzēts. Tādēļ, izstrādājot ASP.Net aplikācijas, ir tomēr jāizprot WWW būtība, HTTP protokola īpatnības (sesijas, datu pārsūtīšana u.c.) un rūpīgi jālasa dokumentācija, kuras gan šajā gadījumā netrūkst.

Cits bieži minēts arguments ir, ka ASP.Net ģenerē W3C standartiem neatbilstošu HTML kodu. Tā ir taisnība, taču, cik zināms ASP.Net 2.0 šī vaina būs labota un tiks ģenerēts tīrs XHTML. Tik jājautā, vai tas būs efektīvi, ja zinām, ka Microsoft parasti neaizraujas ar kompakta HTML ģenerēšanu?

ASP.Net darbojas uz serveriem, kur instalēts .Net Framework un lieliski sadarbojas ar Internet Information Server. IIS nebūt nav vienīgā iespēja, ASP.Net var darbināt arī caur Apache 2.0, ja tam papildus tiek izmantots Cassini modulis vai Mono projekta ietvaros izstrādāto Apache moduli mod_mono. Strādājot ar IIS, protams, ir ērti pieejama visu veidu lietotāju autorizācija (Basic/Windows/Digest), kas citu webserveru gadījumā, šķiet, varētu nebūt tik vienkārša.

MSDN mazliet mānās par ASP.Net failu upload

Mēģinām augšuplādēt (upload) failu ASP.net lapā. Priekš tam lapas kodā jāievieto apmēram šāds:

<input id="myFile" type="file" runat="server" />
<input type=button id="cmdUp" runat="server" />

Pēc tam varam ķert notikumu, kad nospiesta upload poga. Pēc MSDN rādītā piemēra, pietiek pārbaudīt vai UploadedFile atribūts nav nothing, tas ir, šādi:

Private Sub Uploads (ByVal s As System.Object, ByVal e As System.EventArgs) Handles cmdUp.ServerClick
         If  Not Me.myFile.PostedFile Is Nothing Then
        '... darām kaut ko
        End If
End Sub

Tomēr patiesībā “Not Me.myFile.PostedFile is Nothing” vienmēr atgriež True – pat tad, ja faila nav. Vismaz pie konfigurācijas, kāda tā ir man. Līdz ar to vienīgais veids, kā pārbaudīt, ka tiešām kaut kas ir uploadēts, ir:

Private Sub Uploads (ByVal s As System.Object, ByVal e As System.EventArgs) Handles cmdUp.ServerClick
         If  (Not Me.myFile.PostedFile Is Nothing) AndAlso _ 
            (Me.myFile.PostedFile.ContentLength>0) Then
        '... darām kaut ko
        End If
End Sub

Tā, redz!