Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
42 views

File Upload Option When Adding A New Record: Step 1: Adding An Method To The

This document discusses adding a file upload option when creating a new record in ASP.NET. It describes updating the data access layer to include a method for inserting a record along with an image file. This involves adding a new method to the table adapter to insert all fields, including the image column. It also involves updating the business logic layer to call the new table adapter method. Finally, it discusses configuring the object data source to use the new insert method.

Uploaded by

Everth Alonso
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
42 views

File Upload Option When Adding A New Record: Step 1: Adding An Method To The

This document discusses adding a file upload option when creating a new record in ASP.NET. It describes updating the data access layer to include a method for inserting a record along with an image file. This involves adding a new method to the table adapter to insert all fields, including the image column. It also involves updating the business logic layer to call the new table adapter method. Finally, it discusses configuring the object data source to use the new insert method.

Uploaded by

Everth Alonso
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 17

Thistutorialispartofaset.FindoutmoreaboutdataaccesswithASP.NETintheWorkingwithData inASP.NET2.0sectionoftheASP.NETsiteathttp://www.asp.net/learn/dataaccess/default.aspx.

WorkingwithDatainASP.NET2.0::Includinga FileUploadOptionWhenAddingaNewRecord Introduction


Intheprevioustwotutorialsweexploredtechniquesforstoringbinarydatathatisassociatedwiththeapplications datamodel,lookedathowtousetheFileUploadcontroltosendfilesfromtheclienttothewebserver,andsaw howtopresentthisbinarydatainadataWebcontrol.Weveyettotalkabouthowtoassociateuploadeddatawith thedatamodel,though. Inthistutorialwewillcreateawebpagetoaddanewcategory.InadditiontoTextBoxesforthecategorysname anddescription,thispagewillneedtoincludetwoFileUploadcontrolsoneforthenewcategoryspictureand oneforthebrochure.TheuploadedpicturewillbestoreddirectlyinthenewrecordsPicture column,whereas thebrochurewillbesavedtothe~/Brochures folderwiththepathtothefilesavedinthenewrecords BrochurePath column. Beforecreatingthisnewwebpage,wellneedtoupdatethearchitecture.TheCategoriesTableAdaptersmain querydoesnotretrievethePicture column.Consequently,theautogeneratedInsert methodonlyhasinputsfor theCategoryName,Description,andBrochurePath fields.Therefore,weneedtocreateanadditionalmethodin theTableAdapterthatpromptsforallfourCategories fields.TheCategoriesBLL classintheBusinessLogic Layerwillalsoneedtobeupdated.

Step1:AddinganInsertWithPicture Methodtothe
CategoriesTableAdapter
WhenwecreatedtheCategoriesTableAdapter backintheCreatingaDataAccessLayer tutorial,weconfigured ittoautomaticallygenerateINSERT,UPDATE,andDELETE statementsbasedonthemainquery.Moreover,we instructedtheTableAdaptertoemploytheDBDirectapproach,whichcreatedthemethodsInsert,Update,and Delete.ThesemethodsexecutetheautogeneratedINSERT,UPDATE,andDELETE statementsand,consequently, acceptinputparametersbasedonthecolumnsreturnedbythemainquery.IntheUploadingFilestutorialwe augmentedtheCategoriesTableAdaptersmainquerytousetheBrochurePath column. SincetheCategoriesTableAdaptersmainquerydoesnotreferencethePicture column,wecanneitheradda newrecordnorupdateanexistingrecordwithavalueforthePicture column.Inordertocapturethisinformation, wecaneithercreateanewmethodintheTableAdapterthatisusedspecificallytoinsertarecordwithbinarydata orwecancustomizetheautogeneratedINSERT statement.Theproblemwithcustomizingtheautogenerated INSERT statementisthatweriskhavingourcustomizationsoverwrittenbythewizard.Forexample,imaginethat wecustomizedtheINSERT statementtoincludeuseofthePicture column.ThiswouldupdatetheTableAdapters Insert methodtoincludeanadditionalinputparameterforthecategoryspicturesbinarydata.Wecouldthen createamethodintheBusinessLogicLayertousethisDALmethodandinvokethisBLLmethodthroughthe PresentationLayer,andeverythingwouldworkwonderfully.Thatis,untilthenexttimeweconfiguredthe TableAdapterthroughtheTableAdapterConfigurationwizard.Assoonasthewizardcompleted,our customizationstotheINSERT statementwouldbeoverwritten,theInsert methodwouldreverttoitsoldform,and ourcodewouldnolongercompile! Note:ThisannoyanceisanonissuewhenusingstoredproceduresinsteadofadhocSQLstatements.A

1 of17

futuretutorialwillexploreusingstoredproceduresinlieuofadhocSQLstatementsintheDataAccess Layer. Toavoidthispotentialheadache,ratherthancustomizingtheautogeneratedSQLstatementsletsinsteadcreatea newmethodfortheTableAdapter.Thismethod,namedInsertWithPicture,willacceptvaluesforthe CategoryName,Description,BrochurePath,andPicture columnsandexecuteanINSERT statementthatstores allfourvaluesinanewrecord. OpentheTypedDataSetand,fromtheDesigner,rightclickontheCategoriesTableAdaptersheaderand chooseAddQueryfromthecontextmenu.ThislaunchestheTableAdapterQueryConfigurationWizard,which beginsbyaskingushowtheTableAdapterqueryshouldaccessthedatabase.ChooseUseSQLstatementsand clickNext.Thenextsteppromptsforthetypeofquerytobegenerated.Sincewerecreatingaquerytoaddanew recordtotheCategories table,chooseINSERTandclickNext.

Figure1:SelecttheINSERTOption

WenowneedtospecifytheINSERT SQLstatement.ThewizardautomaticallysuggestsanINSERT statement correspondingtotheTableAdaptersmainquery.Inthiscase,itsanINSERT statementthatinsertsthe CategoryName,Description,andBrochurePath values.UpdatethestatementsothatthePicture columnis includedalongwitha@Picture parameter,likeso:
INSERTINTO[Categories] ([CategoryName],[Description],[BrochurePath],[Picture]) VALUES (@CategoryName,@Description,@BrochurePath,@Picture)

2 of17

ThefinalscreenofthewizardasksustonamethenewTableAdaptermethod.EnterInsertWithPicture andclick Finish.

Figure2:NametheNewTableAdapterMethodInsertWithPicture

Step2:UpdatingtheBusinessLogicLayer
SincethePresentationLayershouldonlyinterfacewiththeBusinessLogicLayerratherthanbypassingittogo directlytotheDataAccessLayer,weneedtocreateaBLLmethodthatinvokestheDALmethodwejustcreated (InsertWithPicture).Forthistutorial,createamethodintheCategoriesBLL classnamedInsertWithPicture thatacceptsasinputthreeStringsandaByte array.TheString inputparametersareforthecategorysname, description,andbrochurefilepath,whiletheByte arrayisforthebinarycontentsofthecategoryspicture.Asthe followingcodeshows,thisBLLmethodinvokesthecorrespondingDALmethod:
<System.ComponentModel.DataObjectMethodAttribute_ (System.ComponentModel.DataObjectMethodType.Insert,False)>_ PublicSubInsertWithPicture(categoryNameAsString,descriptionAsString,_ brochurePathAsString,picture()AsByte) Adapter.InsertWithPicture(categoryName,description,brochurePath,picture) EndSub

Note:MakesurethatyouhavesavedtheTypedDataSetbeforeaddingtheInsertWithPicture methodto theBLL.SincetheCategoriesTableAdapter classcodeisautogeneratedbasedontheTypedDataSet,if youdontfirstsaveyourchangestotheTypedDataSettheAdapter propertywontknowaboutthe

3 of17

InsertWithPicture method.

Step3:ListingtheExistingCategoriesandtheirBinaryData
Inthistutorialwewillcreateapagethatallowsanendusertoaddanewcategorytothesystem,providinga pictureandbrochureforthenewcategory.Intheprecedingtutorial weusedaGridViewwithaTemplateFieldand ImageFieldtodisplayeachcategorysname,description,picture,andalinktodownloaditsbrochure.Lets replicatethatfunctionalityforthistutorial,creatingapagethatbothlistsallexistingcategoriesandallowsfornew onestobecreated. StartbyopeningtheDisplayOrDownload.aspx pagefromtheBinaryData folder.GototheSourceviewand copytheGridViewandObjectDataSourcesdeclarativesyntax,pastingitwithinthe<asp:Content> elementin UploadInDetailsView.aspx.Also,dontforgettocopyoverthe GenerateBrochureLink methodfromthecode behindclassofDisplayOrDownload.aspx toUploadInDetailsView.aspx.

Figure3:CopyandPastetheDeclarativeSyntaxfromDisplayOrDownload.aspx to
UploadInDetailsView.aspx

AftercopyingthedeclarativesyntaxandGenerateBrochureLink methodovertothe UploadInDetailsView.aspx page,viewthepagethroughabrowsertoensurethateverythingwascopiedover correctly.YoushouldseeaGridViewlistingtheeightcategoriesthatincludesalinktodownloadthebrochureas wellasthecategoryspicture.

4 of17

Figure4:YouShouldNowSeeEachCategoryAlongwithItsBinaryData

Step4:ConfiguringtheCategoriesDataSource toSupportInserting
TheCategoriesDataSource ObjectDataSourceusedbytheCategories GridViewcurrentlydoesnotprovidethe abilitytoinsertdata.Inordertosupportinsertingthroughthisdatasourcecontrol,weneedtomapitsInsert methodtoamethodinitsunderlyingobject,CategoriesBLL.Inparticular,wewanttomapittothe CategoriesBLL methodweaddedbackinStep2,InsertWithPicture . StartbyclickingtheConfigureDataSourcelinkfromtheObjectDataSourcessmarttag.Thefirstscreenshowsthe objectthedatasourceisconfiguredtoworkwith,CategoriesBLL.LeavethissettingasisandclickNextto advancetotheDefineDataMethodsscreen.MovetotheINSERTtabandpicktheInsertWithPicture method fromthedropdownlist.ClickFinishtocompletethewizard.

5 of17

Figure5:ConfiguretheObjectDataSourcetousetheInsertWithPicture Method

Note:Uponcompletingthewizard,VisualStudiomayaskifyouwanttoRefreshFieldsandKeys,which willregeneratethedataWebcontrolsfields.ChooseNo,becausechoosingYeswilloverwriteanyfield customizationsyoumayhavemade. Aftercompletingthewizard,theObjectDataSourcewillnowincludeavalueforitsInsertMethod propertyaswell asInsertParameters forthefourcategorycolumns,asthefollowingdeclarativemarkupillustrates:


<asp:ObjectDataSourceID="CategoriesDataSource"runat="server" OldValuesParameterFormatString="original_{0}"SelectMethod="GetCategories" TypeName="CategoriesBLL"InsertMethod="InsertWithPicture"> <InsertParameters> <asp:ParameterName="categoryName"Type="String"/> <asp:ParameterName="description"Type="String"/> <asp:ParameterName="brochurePath"Type="String"/> <asp:ParameterName="picture"Type="Object"/> </InsertParameters> </asp:ObjectDataSource>

Step5:CreatingtheInsertingInterface
AsfirstcoveredintheAnOverviewofInserting,Updating,andDeletingData,theDetailsViewcontrolprovidesa builtininsertinginterfacethatcanbeutilizedwhenworkingwithadatasourcecontrolthatsupportsinserting. LetsaddaDetailsViewcontroltothispageabovetheGridViewthatwillpermanentlyrenderitsinserting interface,allowingausertoquicklyaddanewcategory.UponaddinganewcategoryintheDetailsView,the 6 of17

GridViewbeneathitwillautomaticallyrefreshanddisplaythenewcategory. StartbydraggingaDetailsViewfromtheToolboxontotheDesignerabovetheGridView,settingitsID propertyto NewCategory andclearingouttheHeight andWidth propertyvalues.FromtheDetailsViewssmarttag,binditto theexistingCategoriesDataSource andthenchecktheEnableInsertingcheckbox.

Figure6:BindtheDetailsViewtotheCategoriesDataSource andEnableInserting

TopermanentlyrendertheDetailsViewinitsinsertinginterface,setitsDefaultMode propertytoInsert. NotethattheDetailsViewhasfiveBoundFieldsCategoryID,CategoryName,Description, NumberOfProducts,andBrochurePath althoughtheCategoryID BoundFieldisnotrenderedintheinserting interfacebecauseitsInsertVisible propertyissettoFalse.TheseBoundFieldsexistsbecausetheyarethe columnsreturnedbytheGetCategories() method,whichiswhattheObjectDataSourceinvokestoretrieveits data.Forinserting,however,wedontwanttolettheuserspecifyavalueforNumberOfProducts.Moreover,we needtoallowthemtouploadapictureforthenewcategoryaswellasuploadaPDFforthebrochure. RemovetheNumberOfProducts BoundFieldfromtheDetailsViewaltogetherandthenupdatetheHeaderText propertiesoftheCategoryName andBrochurePath BoundFieldstoCategoryand Brochure, respectively. Next,converttheBrochurePath BoundFieldintoaTemplateFieldandaddanewTemplateFieldforthepicture, givingthisnewTemplateFieldaHeaderText valueof Picture. MovethePicture TemplateFieldsothatitis betweentheBrochurePath TemplateFieldandCommandField.

7 of17

Figure7:BindtheDetailsViewtotheCategoriesDataSource andEnableInserting

IfyouconvertedtheBrochurePath BoundFieldintoaTemplateFieldthroughtheEditFieldsdialogbox,the TemplateFieldincludesanItemTemplate,EditItemTemplate,andInsertItemTemplate.Onlythe InsertItemTemplate isneeded,however,sofeelfreetoremovetheothertwotemplates.Atthispointyour DetailsViewsdeclarativesyntaxshouldlooklikethefollowing:


<asp:DetailsViewID="NewCategory"runat="server"AutoGenerateRows="False" DataKeyNames="CategoryID"DataSourceID="CategoriesDataSource" DefaultMode="Insert"> <Fields> <asp:BoundFieldDataField="CategoryID"HeaderText="CategoryID" InsertVisible="False"ReadOnly="True" SortExpression="CategoryID"/> <asp:BoundFieldDataField="CategoryName"HeaderText="Category" SortExpression="CategoryName"/> <asp:BoundFieldDataField="Description"HeaderText="Description" SortExpression="Description"/> <asp:TemplateFieldHeaderText="Brochure"SortExpression="BrochurePath"> <InsertItemTemplate> <asp:TextBoxID="TextBox1"runat="server" Text='<%#Bind("BrochurePath")%>'></asp:TextBox> </InsertItemTemplate> </asp:TemplateField> <asp:TemplateFieldHeaderText="Picture"></asp:TemplateField> <asp:CommandFieldShowInsertButton="True"/> </Fields> </asp:DetailsView>

8 of17

AddingFileUploadControlsfortheBrochureandPictureFields
Presently,theBrochurePath TemplateFieldsInsertItemTemplate containsaTextBox,whilethePicture TemplateFielddoesnotcontainanytemplates.WeneedtoupdatethesetwoTemplateFields InsertItemTemplatestouseFileUploadcontrols. FromtheDetailsViewssmarttag,choosetheEditTemplates optionandthenselecttheBrochurePath TemplateFieldsInsertItemTemplate fromthedropdownlist.RemovetheTextBoxandthendragaFileUpload controlfromtheToolboxintothetemplate.SettheFileUploadcontrolsID toBrochureUpload.Similarly,adda FileUploadcontroltothePicture TemplateFieldsInsertItemTemplate.SetthisFileUploadcontrolsID to PictureUpload.

Figure8:AddaFileUploadControltotheInsertItemTemplate

Aftermakingtheseadditions,thetwoTemplateFieldsdeclarativesyntaxwillbe:
<asp:TemplateFieldHeaderText="Brochure"SortExpression="BrochurePath"> <InsertItemTemplate> <asp:FileUploadID="BrochureUpload"runat="server"/> </InsertItemTemplate> </asp:TemplateField> <asp:TemplateFieldHeaderText="Picture"> <InsertItemTemplate> <asp:FileUploadID="PictureUpload"runat="server"/> </InsertItemTemplate> </asp:TemplateField>

Whenauseraddsanewcategory,wewanttoensurethatthebrochureandpictureareofthecorrectfiletype.For

9 of17

thebrochure,theusermustsupplyaPDF.Forthepicture,weneedtheusertouploadanimagefile,butdowe allow any imagefileoronlyimagefilesofaparticulartype,suchasGIFsorJPGs?Inordertoallowfordifferent filetypes,wedneedtoextendtheCategories schematoincludeacolumnthatcapturesthefiletypesothatthis typecanbesenttotheclientthroughResponse.ContentType inDisplayCategoryPicture.aspx.Sincewedont havesuchacolumn,itwouldbeprudenttorestrictuserstoonlyprovidingaspecificimagefiletype.The Categories tablesexistingimagesarebitmaps,butJPGsareamoreappropriatefileformatforimagesserved overtheweb. Ifauseruploadsanincorrectfiletype,weneedtocanceltheinsertanddisplayamessageindicatingtheproblem. AddaLabelWebcontrolbeneaththeDetailsView.SetitsID propertytoUploadWarning,clearoutits Text property,settheCssClass propertytoWarning, andtheVisible andEnableViewState propertiestoFalse. TheWarning CSSclassisdefinedinStyles.css andrendersthetextinalarge,red,italicized,boldfont. Note:Ideally,theCategoryName andDescription BoundFieldswouldbeconvertedtoTemplateFieldsand theirinsertinginterfacescustomized.TheDescription insertinginterface,forexample,wouldlikelybe bettersuitedthroughamultilinetextbox.AndsincetheCategoryName columndoesnotacceptNULL values, aRequiredFieldValidatorshouldbeaddedtoensuretheuserprovidesavalueforthenewcategorysname. Thesestepsareleftasanexercisetothereader.ReferbacktoCustomizingtheDataModificationInterface foranindepthlookataugmentingthedatamodificationinterfaces.

Step6:SavingtheUploadedBrochuretotheWebServersFileSystem
WhentheuserentersthevaluesforanewcategoryandclickstheInsertbutton,apostbackoccursandtheinserting workflowunfolds.First,theDetailsViewsItemInserting eventfires.Next,theObjectDataSourcesInsert() methodisinvoked,whichresultsinanewrecordbeingaddedtotheCategories table.Afterthat,the DetailsViewsItemInserted eventfires. BeforetheObjectDataSourcesInsert() methodisinvoked,wemustfirstensurethattheappropriatefiletypes wereuploadedbytheuserandthensavethebrochurePDFtothewebserversfilesystem.Createaneventhandler fortheDetailsViewsItemInserting eventandaddthefollowingcode:
'ReferencetheFileUploadcontrols DimBrochureUploadAsFileUpload=_ CType(NewCategory.FindControl("BrochureUpload"),FileUpload) IfBrochureUpload.HasFileThen 'MakesurethataPDFhasbeenuploaded IfString.Compare(System.IO.Path.GetExtension_ (BrochureUpload.FileName),".pdf",True)<>0Then UploadWarning.Text=_ "OnlyPDFdocumentsmaybeusedforacategory'sbrochure." UploadWarning.Visible=True e.Cancel=True ExitSub EndIf EndIf

TheeventhandlerstartsbyreferencingtheBrochureUpload FileUploadcontrolfromtheDetailsViewstemplates. Then,ifabrochurehasbeenuploaded,theuploadedfilesextensionisexamined.Iftheextensionisnot.PDF, thenawarningisdisplayed,theinsertiscancelled,andtheexecutionoftheeventhandlerends. Note:Relyingontheuploadedfilesextensionisnotasurefiretechniqueforensuringthattheuploadedfile isaPDFdocument.TheusercouldhaveavalidPDFdocumentwiththeextension.Brochure,orcouldhave takenanonPDFdocumentandgivenita.pdf extension.Thefilesbinarycontentwouldneedtobe

10 of17

programmaticallyexaminedinordertomoreconclusivelyverifythefiletype.Suchthoroughapproaches, though,areoftenoverkillcheckingtheextensionissufficientformostscenarios. AsdiscussedintheUploadingFilestutorial,caremustbetakenwhensavingfilestothefilesystemsothatone usersuploaddoesnotoverwriteanothers.Forthistutorialwewillattempttousethesamenameastheuploaded file.Iftherealreadyexistsafileinthe~/Brochures directorywiththatsamefilename,however,wellappenda numberattheenduntilauniquenameisfound.Forexample,iftheuseruploadsabrochurefilenamedMeats.pdf, butthereisalreadyafilenamedMeats.pdf inthe~/Brochures folder,wellchangethesavedfilenameto Meats1.pdf.Ifthatexists,welltryMeats2.pdf,andsoon,untilauniquefilenameisfound. ThefollowingcodeusestheFile.Exists(path) methodtodetermineifafilealreadyexistswiththespecified filename.Ifso,itcontinuestotrynewfilenamesforthebrochureuntilnoconflictisfound.
ConstBrochureDirectoryAsString="~/Brochures/" DimbrochurePathAsString=BrochureDirectory&BrochureUpload.FileName DimfileNameWithoutExtensionAsString=_ System.IO.Path.GetFileNameWithoutExtension(BrochureUpload.FileName) DimiterationAsInteger=1 WhileSystem.IO.File.Exists(Server.MapPath(brochurePath)) brochurePath=String.Concat(BrochureDirectory,_ fileNameWithoutExtension,"",iteration,".pdf") iteration+=1 EndWhile

Onceavalidfilenamehasbeenfound,thefileneedstobesavedtothefilesystemandtheObjectDataSources brochurePath InsertParameter valueneedstobeupdatedsothatthisfilenameiswrittentothedatabase.Aswe sawbackintheUploadingFiles tutorial,thefilecanbesavedusingtheFileUploadcontrolsSaveAs(path) method.ToupdatetheObjectDataSourcesbrochurePath parameter,usethee.Values collection.


'SavethefiletodiskandsetthevalueofthebrochurePathparameter BrochureUpload.SaveAs(Server.MapPath(brochurePath)) e.Values("brochurePath")=brochurePath

Step7:SavingtheUploadedPicturetotheDatabase
TostoretheuploadedpictureinthenewCategories record,weneedtoassigntheuploadedbinarycontenttothe ObjectDataSourcespicture parameterintheDetailsViewsItemInserting event.Beforewemakethis assignment,however,weneedtofirstmakesurethattheuploadedpictureisaJPGandnotsomeotherimagetype. AsinStep6,letsusetheuploadedpicturesfileextensiontoascertainitstype. WhiletheCategories tableallowsNULL valuesforthePicture column,allcategoriescurrentlyhaveapicture. Letsforcetheusertoprovideapicturewhenaddinganewcategorythroughthispage.Thefollowingcodechecks toensurethatapicturehasbeenuploadedandthatithasanappropriateextension.
'ReferencetheFileUploadcontrols DimPictureUploadAsFileUpload=_ CType(NewCategory.FindControl("PictureUpload"),FileUpload) IfPictureUpload.HasFileThen 'MakesurethataJPGhasbeenuploaded IfString.Compare(System.IO.Path.GetExtension(PictureUpload.FileName),_ ".jpg",True)<>0AndAlso_ String.Compare(System.IO.Path.GetExtension(PictureUpload.FileName),_

11 of17

".jpeg",True)<>0Then UploadWarning.Text=_ "OnlyJPGdocumentsmaybeusedforacategory'spicture." UploadWarning.Visible=True e.Cancel=True ExitSub EndIf Else 'Nopictureuploaded! UploadWarning.Text=_ "Youmustprovideapictureforthenewcategory." UploadWarning.Visible=True e.Cancel=True ExitSub EndIf

Thiscodeshouldbeplacedbefore thecodefromStep6sothatifthereisaproblemwiththepictureupload,the eventhandlerwillterminatebeforethebrochurefileissavedtothefilesystem. Assumingthatanappropriatefilehasbeenuploaded,assigntheuploadedbinarycontenttothepictureparameters valuewiththefollowinglineofcode:


'Setthevalueofthepictureparameter e.Values("picture")=PictureUpload.FileBytes

TheCompleteItemInserting EventHandler
Forcompleteness,hereistheItemInserting eventhandlerinitsentirety:
ProtectedSubNewCategory_ItemInserting_ (senderAsObject,eAsDetailsViewInsertEventArgs)_ HandlesNewCategory.ItemInserting 'ReferencetheFileUploadcontrols DimPictureUploadAsFileUpload=_ CType(NewCategory.FindControl("PictureUpload"),FileUpload) IfPictureUpload.HasFileThen 'MakesurethataJPGhasbeenuploaded IfString.Compare(System.IO.Path.GetExtension(PictureUpload.FileName),_ ".jpg",True)<>0AndAlso_ String.Compare(System.IO.Path.GetExtension(PictureUpload.FileName),_ ".jpeg",True)<>0Then UploadWarning.Text=_ "OnlyJPGdocumentsmaybeusedforacategory'spicture." UploadWarning.Visible=True e.Cancel=True ExitSub EndIf Else 'Nopictureuploaded! UploadWarning.Text=_ "Youmustprovideapictureforthenewcategory." UploadWarning.Visible=True

12 of17

e.Cancel=True ExitSub EndIf 'Setthevalueofthepictureparameter e.Values("picture")=PictureUpload.FileBytes

'ReferencetheFileUploadcontrols DimBrochureUploadAsFileUpload=_ CType(NewCategory.FindControl("BrochureUpload"),FileUpload) IfBrochureUpload.HasFileThen 'MakesurethataPDFhasbeenuploaded IfString.Compare(System.IO.Path.GetExtension(BrochureUpload.FileName),_ ".pdf",True)<>0Then UploadWarning.Text=_ "OnlyPDFdocumentsmaybeusedforacategory'sbrochure." UploadWarning.Visible=True e.Cancel=True ExitSub EndIf ConstBrochureDirectoryAsString="~/Brochures/" DimbrochurePathAsString=BrochureDirectory&BrochureUpload.FileName DimfileNameWithoutExtensionAsString=_ System.IO.Path.GetFileNameWithoutExtension(BrochureUpload.FileName) DimiterationAsInteger=1 WhileSystem.IO.File.Exists(Server.MapPath(brochurePath)) brochurePath=String.Concat(BrochureDirectory,_ fileNameWithoutExtension,"",iteration,".pdf") iteration+=1 EndWhile 'SavethefiletodiskandsetthevalueofthebrochurePathparameter BrochureUpload.SaveAs(Server.MapPath(brochurePath)) e.Values("brochurePath")=brochurePath EndIf EndSub

Step8:FixingtheDisplayCategoryPicture.aspx Page
LetstakeamomenttotestouttheinsertinginterfaceandItemInserting eventhandlerthatwascreatedoverthe lastfewsteps.VisittheUploadInDetailsView.aspx pagethroughabrowserandattempttoaddacategory,but omitthepicture,orspecifyanonJPGpictureoranonPDFbrochure.Inanyofthesecases,anerrormessagewill bedisplayedandtheinsertworkflowcancelled.

13 of17

Figure9:AWarningMessageisDisplayedIfanInvalidFileTypeisUploaded

OnceyouhaveverifiedthatthepagerequiresapicturetobeuploadedandwontacceptnonPDFornonJPGfiles, addanewcategorywithavalidJPGpicture,leavingtheBrochurefieldempty.AfterclickingtheInsertbutton,the pagewillpostbackandanewrecordwillbeaddedtotheCategories tablewiththeuploadedimagesbinary contentsstoreddirectlyinthedatabase.TheGridViewisupdatedandshowsarowforthenewlyaddedcategory, but,asFigure10shows,thenewcategoryspictureisnotrenderedcorrectly.

Figure10:TheNewCategorysPictureisnotDisplayed

ThereasonthenewpictureisnotdisplayedisbecausetheDisplayCategoryPicture.aspx pagethatreturnsa 14 of17

specifiedcategoryspictureisconfiguredtoprocessbitmapsthathaveanOLEheader.This78byteheaderis strippedfromthePicture columnsbinarycontentsbeforetheyaresentbacktotheclient.ButtheJPGfilewejust uploadedforthenewcategorydoesnothavethisOLEheadertherefore,valid,necessarybytesarebeingremoved fromtheimagesbinarydata. SincetherearenowbothbitmapswithOLEheadersandJPGsintheCategories table,weneedtoupdate DisplayCategoryPicture.aspx sothatitdoestheOLEheaderstrippingfortheoriginaleightcategoriesand bypassesthisstrippingforthenewercategoryrecords.Inournexttutorialwellexaminehowtoupdateanexisting recordsimage,andwellupdatealloftheoldcategorypicturessothattheyareJPGs.Fornow,though,usethe followingcodeinDisplayCategoryPicture.aspx tostriptheOLEheadersonlyforthoseoriginaleight categories:
ProtectedSubPage_Load(senderAsObject,eAsEventArgs)HandlesMe.Load DimcategoryIDAsInteger=Convert.ToInt32(Request.QueryString("CategoryID")) 'Getinformationaboutthespecifiedcategory DimcategoryAPIAsNewCategoriesBLL() DimcategoriesAsNorthwind.CategoriesDataTable=_ categoryAPI.GetCategoryWithBinaryDataByCategoryID(categoryID) DimcategoryAsNorthwind.CategoriesRow=categories(0) IfcategoryID<=8Then 'OutputHTTPheadersprovidinginformationaboutthebinarydata Response.ContentType="image/bmp" 'Outputthebinarydata 'ButfirstweneedtostripouttheOLEheader ConstOleHeaderLengthAsInteger=78 DimstrippedImageLengthAsInteger=_ category.Picture.LengthOleHeaderLength DimstrippedImageData(strippedImageLength)AsByte Array.Copy(category.Picture,OleHeaderLength,_ strippedImageData,0,strippedImageLength) Response.BinaryWrite(strippedImageData) Else 'Fornewcategories,imagesareJPGs... 'OutputHTTPheadersprovidinginformationaboutthebinarydata Response.ContentType="image/jpeg" 'Outputthebinarydata Response.BinaryWrite(category.Picture) EndIf EndSub

Withthischange,theJPGimageisnowrenderedcorrectlyintheGridView.

15 of17

Figure11:TheJPGImagesforNewCategoriesareCorrectlyRendered

Step9:DeletingtheBrochureintheFaceofanException
Oneofthechallengesofstoringbinarydataonthewebserversfilesystemisthatitintroducesadisconnect betweenthedatamodelanditsbinarydata.Therefore,wheneverarecordisdeleted,thecorrespondingbinarydata onthefilesystemmustalsoberemoved.Thiscancomeintoplaywheninserting,aswell.Considerthefollowing scenario:auseraddsanewcategory,specifyingavalidpictureandbrochure.UponclickingtheInsertbutton,a postbackoccursandtheDetailsViewsItemInserting eventfires,savingthebrochuretothewebserversfile system.Next,theObjectDataSourcesInsert() methodisinvoked,whichcallstheCategoriesBLL classs InsertWithPicture method,whichcallstheCategoriesTableAdaptersInsertWithPicture method. Now,whathappensifthedatabaseisoffline,orifthereisanerrorintheINSERT SQLstatement?Clearlythe INSERTwillfail,sononewcategoryrowwillbeaddedtothedatabase.Butwestillhavetheuploadedbrochure filesittingonthewebserversfilesystem!Thisfileneedstobedeletedinthefaceofanexceptionduringthe insertingworkflow. AsdiscussedpreviouslyintheHandlingBLL andDALLevelExceptionsinanASP.NETPage tutorial,whenan exceptionisthrownfromwithinthedepthsofthearchitectureitisbubbledupthroughthevariouslayers.Atthe PresentationLayer,wecandetermineifanexceptionhasoccurredfromtheDetailsViewsItemInserted event. ThiseventhandleralsoprovidesthevaluesoftheObjectDataSourcesInsertParameters.Therefore,wecan createaneventhandlerfortheItemInserted eventthatchecksiftherewasanexceptionand,ifso,deletesthefile specifiedbytheObjectDataSourcesbrochurePath parameter:
ProtectedSubNewCategory_ItemInserted_ (senderAsObject,eAsDetailsViewInsertedEventArgs)_ HandlesNewCategory.ItemInserted Ife.ExceptionIsNotNothingThen 'Needtodeletebrochurefile,ifitexists Ife.Values("brochurePath")IsNotNothingThen System.IO.File.Delete(Server.MapPath_

16 of17

(e.Values("brochurePath").ToString())) EndIf EndIf EndSub

Summary
Thereareanumberofstepsthatmustbeperformedinordertoprovideawebbasedinterfaceforaddingrecords thatincludebinarydata.Ifthebinarydataisbeingstoreddirectlyintothedatabase,chancesareyoullneedto updatethearchitecture,addingspecificmethodstohandlethecasewherebinarydataisbeinginserted.Oncethe architecturehasbeenupdated,thenextstepiscreatingtheinsertinginterface,whichcanbeaccomplishedusinga DetailsViewthathasbeencustomizedtoincludeaFileUploadcontrolforeachbinarydatafield.Theuploadeddata canthenbesavedtothewebserversfilesystemorassignedtoadatasourceparameterintheDetailsViews ItemInserting eventhandler. Savingbinarydatatothefilesystemrequiresmoreplanningthansavingdatadirectlyintothedatabase.Anaming schememustbechoseninordertoavoidoneusersuploadoverwritinganothers.Also,extrastepsmustbetaken todeletetheuploadedfileifthedatabaseinsertfails. Wenowhavetheabilitytoaddnewcategoriestothesystemwithabrochureandpicture,butweveyettolookat howtoupdateanexistingcategorysbinarydataorhowtocorrectlyremovethebinarydataforadeletedcategory. Wellexplorethesetwotopicsinthenexttutorial. HappyProgramming!

AbouttheAuthor
ScottMitchell,authorofsevenASP/ASP.NETbooksandfounderof4GuysFromRolla.com,hasbeenworkingwith MicrosoftWebtechnologiessince1998.Scottworksasanindependentconsultant,trainer,andwriter.Hislatest bookisSamsTeachYourselfASP.NET2.0in24Hours.Hecanbereachedatmitchell@4GuysFromRolla.com. or viahisblog,whichcanbefoundat http://ScottOnWriting.NET.

SpecialThanksTo
Thistutorialserieswasreviewedbymanyhelpfulreviewers.LeadreviewersforthistutorialwereDaveGardner, TeresaMurphy,andBernadetteLeigh.InterestedinreviewingmyupcomingMSDNarticles?Ifso,dropmealine at mitchell@4GuysFromRolla.com.

17 of17

You might also like