Changing the title of an SPFile object.

Ok, from now on, I’ll write SharePoint related posts here in English. However, English is not my native language, so I beg your pardon in advance for all those grammatical mistakes, style errors etc. I believe the use of commas is the most horrible part of it.

In Sharepoint it’s very easy to believe that a document library is actually a custom list with some “extras”. You can add property fields to a document library the same way you add them to a usual list, the AllItems.aspx form looks quite similar for both usual lists and document libraries etc. Even in the API code model you can work with a SPList and leave SPDocumentLibrary for use only in special cases.
This impression is a bit misleading, however. When it comes to work with an SPFile class instance, you discover that every file is associated with an SPListItem instance.

To read custom properties defined by a document library, we don’t need to use the SPListItem object, we can use the Properties property of SPFile class. For instance, if there is a field in document library named “FileOwnerDepartment”, we can code like this:

        Dim oWeb As SPWeb
        Dim oFile As SPFile
        Dim sDept As String
        oWeb = SPControl.GetContextWeb(context)
        oFile = oWeb.GetFile("fileurl")
        sDept = CStr(oFile.Properties("FileOwnerDepartment"))

To set a value of a custom property we have to use the SPFile.Item property, set the property of the SPListItem object and then update the SPListItem:

        oFile.Item.Item("FileOwnerDepartment") = "someOtherValue"
        oFile.Item.Update()

Due to the fact that Title property is mandatory in every list (generic list definition from onet.xml), there is a property in SPFile class named Title (as described in MSDN – The Title property of the SPFile class gets the display name of the file.) If we try to access the title through Properties property of a file, we get a Nothing value. If we use the Title property, we get the actual title. That is, this script outputs two lines of “True”:

    Console.WriteLine(oFile.Properties("Title") Is Nothing)
    Console.WriteLine(Not oFile.Title Is Nothing)

Even though Title property is read-only (which can make you think there’s no legal way to change the title of a document), you can update it the same way you update any other field:

        oFile.Item("Title") = "newTitle"
        oFile.Item.Update()

The interesting part is that you can also update the title of a file using the localized name (there are language-packs for SharePoint, too) of title field. For instance, in Latvian version of SharePoint we have “Nosaukums” instead of “Title”. That is, both oFile.Item("Title") and oFile.Item("Nosaukums") actually change the same property – title.

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).