Avatar billede Slettet bruger
25. januar 2006 - 10:52 Der er 33 kommentarer og
1 løsning

Asp:TemplateField og FileUpload

Hejsa,

Jeg har et DetailsView, der fremviser data om et medlem fra en database. DetailsView skal samtidig stå for indsættelse og opdatering af medlemmer og det virker da også ok.

Jeg har dog et lille problem med hensyn til upload af billede til et medlem. I mit DetailsView har jeg et TemplateField, hvor der er en FileUpload kontrol.

Før indsættelse af et eventuelt billede, skal der først valideres på det valgte billede. Dette gør jeg så i "dt_MemberDetails_ItemInserting", der er den event der køres før selve DetailsView_ItemInserted kaldes.

"dt_MemberDetails_ItemInserting" har jeg så følgende kode:

        FileUpload fu = dt_MemberDetails.Rows[8].FindControl("fu_LogoUpload") as FileUpload;
        if (fu.HasFile)
        {
            string fileFolder = Server.MapPath("../grafik/logo/");
            string filePath = null;

            ArrayList fileList = new ArrayList();
            fileList.Add("image/jpeg");
            fileList.Add("image/gif");
            fileList.Add("image/png");

            if (fileList.Contains(fu.PostedFile.ContentType))
            {
                if (fu.PostedFile.ContentLength <= 10000)
                {
                    filePath = fileFolder + fu.FileName;
                    fu.SaveAs(filePath);
                }
                else
                {
                    label_Response.Text += " Logo kan højst være 10 kilobyte";
                    label_Response.ForeColor = Color.FromName("Red");
                }
            }
            else
            {
                label_Response.Text += " Filnavn ikke godkendt<br>Filer af typen .jpg, .gif eller .png forventet";
                label_Response.ForeColor = Color.FromName("Red");
            }
        }

Fint nok. Ser ud til at fungere når jeg udskriver filnavnet der er det der skal skrives til databasen, men....

Hvordan får jeg tilknyttet filnavnet fra FileUpload kontrollen til mit objekt? Altså det objekt DetailsView gør brug af til fremvisning af brugerdata og som sendes med ned til mine metoder i min dataklasse?
Avatar billede dr_chaos Nybegynder
25. januar 2006 - 10:59 #1
hvordan ser dit objekt ud ?
Avatar billede Slettet bruger
25. januar 2006 - 11:06 #2
public class Medlem
{
    private int id;
    private string firmanavn;
    private string kontaktperson;
    private string adresse;
    private string postnummer;
    private string bynavn;
    private string telefon;
    private string hjemmeside;
    private string email;
    private string logo;
    private int brancheId;
    private string branchenavn;
   
    public Medlem()
    {}

    // FirmaId
    public int Id
    {
        get { return id; }
        set { id = value; }
    }

    // Firmanavn
    public string Firmanavn
    {
        get { return firmanavn; }
        set { firmanavn = value; }
    }

    // Kontaktperson
    public string Kontaktperson
    {
        get { return kontaktperson; }
        set { kontaktperson = value; }
    }

    // Adresse
    public string Adresse
    {
        get { return adresse; }
        set { adresse = value; }
    }

    // Postnummer
    public string Postnummer
    {
        get { return postnummer; }
        set { postnummer = value; }
    }

    // Bynavn
    public string Bynavn
    {
        get { return bynavn; }
        set { bynavn = value; }
    }

    // Telefon
    public string Telefon
    {
        get { return telefon; }
        set { telefon = value; }
    }

    // Hjemmeside
    public string Hjemmeside
    {
        get { return hjemmeside; }
        set { hjemmeside = value; }
    }

    // Email
    public string Email
    {
        get { return email; }
        set { email = value; }
    }

    // Logo
    public string Logo
    {
        get { return logo; }
        set { logo = value; }
    }

    // BrancheId
    public int BrancheId
    {
        get { return brancheId; }
        set { brancheId = value; }
    }

    // Branchenavn
    public string Branchenavn
    {
        get { return branchenavn; }
        set { branchenavn = value; }
    }
}
Avatar billede Slettet bruger
25. januar 2006 - 11:27 #3
Så det jeg konkret vil gøre er, at sætte Medlem.Logo = FileUpload.FileName (Ikke skrevet korrekt her).
Og derefter sende objektet ned til InsertMember, som er en metode i mit datalag, der er sat til at modtage objekter af typen Medlem.
Avatar billede dr_chaos Nybegynder
25. januar 2006 - 11:40 #4
for at kunne gøre det skal du have fat i det objekt der bruges i objectdatasourcen og vises med detailsview.
Har du mulighed for at få fat i det objekt eller gemme det i en session eller lignende ?
Avatar billede Slettet bruger
25. januar 2006 - 11:56 #5
Ja, jeg benytter en ObjectDataSource med et dataobject som kilde/parameter.
Det ligger ikke i session, men hentes ved hver forespørgsel - altså når der er valgt et medlem fra gridview.
Avatar billede dr_chaos Nybegynder
25. januar 2006 - 12:44 #6
prøv lige at vise mig hele din kode.
Avatar billede Slettet bruger
25. januar 2006 - 13:09 #7
Hvilken kode helt konkret?
Selve objektet er som skrevet herover.

Jeg har så et detailsView:

<asp:DetailsView ID="dt_MemberDetails" DataKeyNames="Id" runat="server" AutoGenerateRows="False" DataSourceID="ods_MemberDetails"
        Height="50px" Width="100%" BorderStyle="Solid" BorderWidth="1px" AutoGenerateEditButton="True" AutoGenerateInsertButton="True" OnItemInserted="dt_MemberDetails_ItemInserted" OnItemUpdated="dt_MemberDetails_ItemUpdated" CellPadding="2" HeaderText="Medlemsdata" HeaderStyle-Font-Bold="true" HeaderStyle-BackColor="#CCCC99">
        <Fields>
            <asp:BoundField DataField="Firmanavn" HeaderText="Firmanavn" SortExpression="Firmanavn" >
                <HeaderStyle Width="100px" />
            </asp:BoundField>
            <asp:BoundField DataField="Kontaktperson" HeaderText="Kontaktperson" SortExpression="Kontaktperson" />
            <asp:BoundField DataField="Adresse" HeaderText="Adresse" SortExpression="Adresse" />
            <asp:TemplateField HeaderText="Postnummer" SortExpression="Postnummer">
                <EditItemTemplate>
                    <asp:DropDownList ID="ddl_Postalcodes" runat="server" DataSourceID="ods_Postalcodes"
                        DataTextField="Postnummer" DataValueField="Postnummer" SelectedValue='<%# Bind("Postnummer", "{0}") %>'>
                    </asp:DropDownList>
                </EditItemTemplate>
                <InsertItemTemplate>
                    <asp:DropDownList ID="ddl_Postalcodes" runat="server" DataSourceID="ods_Postalcodes"
                        DataTextField="Postnummer" DataValueField="Postnummer" DataSource='<%# Eval("Postnummer") %>' SelectedValue='<%# Bind("Postnummer") %>'>
                    </asp:DropDownList>
                </InsertItemTemplate>
                <ItemTemplate>
                    <asp:Label ID="Label2" runat="server" Text='<%# Bind("Postnummer") %>'></asp:Label>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:BoundField DataField="Telefon" HeaderText="Telefon" SortExpression="Telefon" />
            <asp:BoundField DataField="Hjemmeside" HeaderText="Hjemmeside" SortExpression="Hjemmeside" />
            <asp:BoundField DataField="Email" HeaderText="Email" SortExpression="Email" />
            <asp:TemplateField HeaderText="Branchenavn" SortExpression="Branchenavn">
                <EditItemTemplate>
                    <asp:DropDownList ID="ddl_Business" runat="server" DataSourceID="ods_Business"
                        DataTextField="Branchenavn" DataValueField="BrancheId" SelectedValue='<%# Bind("BrancheId", "{0}") %>'>
                    </asp:DropDownList>
                </EditItemTemplate>
                <InsertItemTemplate>
                    <asp:DropDownList ID="ddl_Business" runat="server" DataSourceID="ods_Business"
                        DataTextField="Branchenavn" DataValueField="BrancheId" DataSource='<%# Eval("BrancheId") %>' SelectedValue='<%# Bind("BrancheId", "{0}") %>'>
                    </asp:DropDownList>
                </InsertItemTemplate>
                <ItemTemplate>
                    <asp:Label ID="Label1" runat="server" Text='<%# Bind("Branchenavn") %>'></asp:Label>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:BoundField DataField="Id" HeaderText="Id" SortExpression="Id" />
        </Fields>
        <HeaderStyle BackColor="#CCCC99" Font-Bold="True" />
    </asp:DetailsView>

Bemærk at TemplateField med fileUpload ikke er der, da jeg har testet videre uden dette, da det gav mig en fejl om at System.Boolean ikke kunne konverteres til System.String.

Så har jeg en ObjectDataSource:

<asp:ObjectDataSource ID="ods_MemberDetails" runat="server" OldValuesParameterFormatString="original_{0}"
        SelectMethod="GetMemberDetails" TypeName="MedlemDB" DataObjectTypeName="Medlem" InsertMethod="InsertMember" UpdateMethod="UpdateMember" OnUpdated="ods_MemberDetails_Updated">
        <SelectParameters>
            <asp:ControlParameter ControlID="gv_MemberList" Name="id" PropertyName="SelectedValue"
                Type="Int32" />
        </SelectParameters>
    </asp:ObjectDataSource>

Som jo så er den, der sender værdierne ned vha. UpdateMember-metoden.
Avatar billede dr_chaos Nybegynder
25. januar 2006 - 13:19 #8
du skal have fat i det objekt som Filename skal tilhøre .
til det skal du bruge det id som identificerer det som du har i dit details view.
Den skulle meget gerne ligge i
dt_MemberDetails.DataKeys[0].Value.
Med den kan du hente det rigtige objekt og sætte filename på den.
Avatar billede Slettet bruger
25. januar 2006 - 14:09 #9
Mit spørgsmål er så. Hvordan tilgår jeg objektet?
Du har da ledt mig en lille bitte smule på vej, men udgangspunktet var at jeg ikke kunne finde en måde at tilgå objektet i detailsview. Jeg går ikke ud fra at jeg skal oprette et helt nyt objekt, men bare tilgå det eksisterende objekt og skrive til attributten Logo fra min eventhandler (ItemInserting eller ItemUpdating).
Avatar billede dr_chaos Nybegynder
25. januar 2006 - 14:11 #10
Jeg tror måske at det vil være nemmest at oprette et nyt objekt og indlæse de eksisterende data og så opdatere detailsview.
Avatar billede Slettet bruger
25. januar 2006 - 14:16 #11
I min DetailsView_ItemInserting eventhandler gør jeg nu følgende:
ods_MemberDetails.InsertParameters.Add("Logo", "TestLogo");

Dette hvis der er et filename.

Den kombilerer, men indsætter ikke logo-strengen i databasen.

Hvordan ville du gøre det andet du beskriver?
Avatar billede Slettet bruger
25. januar 2006 - 14:17 #12
Vil egentlig helst være fri for at oprette et nyt objekt, da det at tilføje i mine øjne gør at fejl nemmest undgåes.
Kan jeg ikke på en måde tilføje parametre til det eksisterende objekt?
Avatar billede dr_chaos Nybegynder
25. januar 2006 - 14:19 #13
jo men så skal du have fat i det eksisterende objekt.
Det kan du måske gøre i objectdatasource selected.
hvor du kan får en returnvalue.
prøv at case den til dit medlems object og se om den ikke indeholder de oplysninger som vises i dit detailsview.
Avatar billede Slettet bruger
25. januar 2006 - 14:26 #14
Jeg er kørt totalt fast her...
Avatar billede dr_chaos Nybegynder
25. januar 2006 - 14:31 #15
hvis du tilføjer et Selected event til den objectdatasource og laver en funktion i codebehind:
protected void DataSource_selected(object sender, ObjectDataSourceStatusEventArgs e)
    {
        Medlem m= (Medlem)e.ReturnValue;
        Response.Write(m.Firmanavn);
    }
Avatar billede dr_chaos Nybegynder
25. januar 2006 - 14:31 #16
prøv at se om det virker.
Avatar billede Slettet bruger
25. januar 2006 - 14:40 #17
Virker fint.
Men jeg kan ikke bruge den fra min ItemInserting-event.
Er det ikke der jeg skal finde FileUpload.FileName og lægge den på objektet?
Avatar billede Slettet bruger
25. januar 2006 - 14:54 #18
Det kunne forestille mig at lave ville være noget i retning af:

        Tjek det valgte logo til upload
        FileUpload fu = dt_MemberDetails.Rows[8].FindControl("fu_LogoUpload") as FileUpload;
        if (fu.HasFile)
        {
            string fileFolder = Server.MapPath("../grafik/logo/");
            string filePath = null;

            ArrayList fileList = new ArrayList();
            fileList.Add("image/jpeg");
            fileList.Add("image/gif");
            fileList.Add("image/png");

            if (fileList.Contains(fu.PostedFile.ContentType))
            {
                if (fu.PostedFile.ContentLength <= 10000)
                {
                    filePath = fileFolder + fu.FileName;
                    fu.SaveAs(filePath);

Medlem m = ods_MemberDetails.(hent objekt fra objektdatasource);
m.Logo = fu.FileName;
ods_MemberDetails.(tilføj objektet overskriv/eller tilføj værdien for logo)
                }
                else
                {
                    label_Response.Text += " Logo kan højst være 10 kilobyte";
                    label_Response.ForeColor = Color.FromName("Red");
                }
            }
            else
            {
                label_Response.Text += " Filnavn ikke godkendt<br>Filer af typen .jpg, .gif eller .png forventet";
                label_Response.ForeColor = Color.FromName("Red");
            }
        }

Er det helt umuligt at lave det?
Det virker omsonst at oprette et helt nyt objekt og overskrive det valgte fra ObjektDataSource. Kan man ikke referere til objektet og kalde dets properties direkte og dermed bare tilføje en streng til det?
Avatar billede Slettet bruger
25. januar 2006 - 15:27 #19
Hejsa.

Har prøvet med den eventhandler du snakkede om for ObjectDataSource-kontrollen:

protected void ods_MemberDetails_Selected(object sender, ObjectDataSourceStatusEventArgs e)
    {
        m = (Medlem)e.ReturnValue;
    }

Jeg har så erlæret m i toppen som en protected Medlem variabel.

Derfra kan jeg så tilgå properties på m i min ItemInserting eventhandler:

m.Logo = "TesterIgenLogo";

Men, men... Logo bliver så bare ikke skrevet med til den underliggende database.
Har du nogen ide om hvordan jeg "attacher" den nye værdi så den rent faktisk bliver skrevet til objectdatasource'en?
Avatar billede dr_chaos Nybegynder
25. januar 2006 - 15:32 #20
prøv at kalde ObjectDataSource.Update();
Avatar billede Slettet bruger
25. januar 2006 - 15:39 #21
Der sker ikke noget :-(
Avatar billede Slettet bruger
25. januar 2006 - 15:40 #22
Er der ikke en metode, hvor man erstatte objektet i ObjectDataSource med m?

Altså:

protected void ods_MemberDetails_Selected(object sender, ObjectDataSourceStatusEventArgs e)
    {
        m = (Medlem)e.ReturnValue;
    }

m.Logo = "TesterIgenLogo";

ObjectDataSource.Update(m); ???
Avatar billede dr_chaos Nybegynder
25. januar 2006 - 15:51 #23
prøv at lave en objectdatasource updating event og tilhørende funktion.
protected void objectData_Updating(object sender, ObjectDataSourceMethodEventArgs e)
    {
        e.InputParameters["Logo"] = m.Logo;
    }
Avatar billede dr_chaos Nybegynder
25. januar 2006 - 16:17 #24
prøv også og tjekke din update metode i objektet om den bliver kørt.
Avatar billede dr_chaos Nybegynder
25. januar 2006 - 16:17 #25
og om de rigtige værdier kommer med.
Avatar billede Slettet bruger
25. januar 2006 - 19:34 #26
Jeg får en object reference not set to an instance of an object.
Avatar billede dr_chaos Nybegynder
25. januar 2006 - 19:40 #27
prøv at udskrive alle InputParameters med

for(int i=0; i<e.InputParameters.Count; i++)
{
System.Diagnostics.Debug.WriteLine(e.InputParameters[i].ToString())
}
System.Diagnostics.Debug.WriteLine skriver en linie i output vinduet og er genialt til debugging.
genvejen til vinduet er ctrl+alt+o
Avatar billede Slettet bruger
26. januar 2006 - 09:59 #28
Jeg har ændret lidt på det hele.
Kom i tanker om at jeg jo ikke kan bruge:

"protected void ods_MemberDetails_Selected(object sender, ObjectDataSourceStatusEventArgs e)
    {
        m = (Medlem)e.ReturnValue;
    }"

Da det jo er en insert sætning og der derfor ikke findes en selected. Eller måske gør der, men så er det jo et andet objekt.

"prøv at lave en objectdatasource updating event og tilhørende funktion.
protected void objectData_Updating(object sender, ObjectDataSourceMethodEventArgs e)
    {
        e.InputParameters["Logo"] = m.Logo;
    }"

Ovenstående kan jeg åbenbart heller ikke, får fejlen:

System.NotSupportedException: The OrderedDictionary is readonly and cannot be modified. at System.Collections.Specialized.OrderedDictionary.set_Item(Object key, Object value) at Medlemmer.ods_MemberDetails_Inserting(Object sender, ObjectDataSourceMethodEventArgs e).
Avatar billede dr_chaos Nybegynder
26. januar 2006 - 10:04 #29
selected burde vise det rigtige objekt da den afvikles hver eneste gang der foretages en select af object datasourcen og dermed også når du vil se detajler i dit detailsview.

vender lige tilbage om lidt skal lige undersøge noget
Avatar billede dr_chaos Nybegynder
26. januar 2006 - 10:13 #30
du kan bestemme værdierne som ryger ned til din update funktion på denne måde:
  protected void objectData_Updating(object sender, ObjectDataSourceMethodEventArgs e)
    {
        IDictionary paramsFromPage = e.InputParameters;

        Medlem m = new Medlem();

        m.Firmanavn = paramsFromPage["Firmanavn"].ToString();
        m.Kontaktperson = paramsFromPage["Kontaktperson"].ToString();
        m.Adresse = paramsFromPage["Adresse"].ToString();
        m.Postnummer = paramsFromPage["Postnummer"].ToString();
        m.Logo = ditfilename;

        paramsFromPage.Clear();
        paramsFromPage.Add("m", m);
    }

Det er bare et eksempel så derfor er alle værdier ikke med.
På denne måde kan du sætte dine værdier.
Avatar billede Slettet bruger
26. januar 2006 - 10:32 #31
Jeg har lavet en til updating og en til inserting:

protected void ods_MemberDetails_Updating(object sender, ObjectDataSourceMethodEventArgs e)
    {
        IDictionary paramsFromPage = e.InputParameters;

        Medlem m = new Medlem();

        m.Firmanavn = paramsFromPage["Firmanavn"].ToString();
        m.Kontaktperson = paramsFromPage["Kontaktperson"].ToString();
        m.Adresse = paramsFromPage["Adresse"].ToString();
        m.Postnummer = paramsFromPage["Postnummer"].ToString();
        m.Telefon = paramsFromPage["Telefon"].ToString();
        m.Hjemmeside = paramsFromPage["Hjemmeside"].ToString();
        m.Email = paramsFromPage["Email"].ToString();
        m.Logo = "LogoTestFraSide";
        m.BrancheId = Int32.Parse(paramsFromPage["BrancheId"].ToString());

        paramsFromPage.Clear();
        paramsFromPage.Add("m", m);
    }

protected void ods_MemberDetails_Inserting(object sender, ObjectDataSourceMethodEventArgs e)
    {
        IDictionary paramsFromPage = e.InputParameters;

        Medlem m = new Medlem();

        m.Firmanavn = paramsFromPage["Firmanavn"].ToString();
        m.Kontaktperson = paramsFromPage["Kontaktperson"].ToString();
        m.Adresse = paramsFromPage["Adresse"].ToString();
        m.Postnummer = paramsFromPage["Postnummer"].ToString();
        m.Telefon = paramsFromPage["Telefon"].ToString();
        m.Hjemmeside = paramsFromPage["Hjemmeside"].ToString();
        m.Email = paramsFromPage["Email"].ToString();
        m.Logo = "LogoTestFraSide";
        m.BrancheId = Int32.Parse(paramsFromPage["BrancheId"].ToString());

        paramsFromPage.Clear();
        paramsFromPage.Add("m", m);
    }

Jeg går ud fra at det er den sidste der bliver afviklet i mit tilfælde.
Jeg får fejlen:

System.NullReferenceException: Object reference not set to an instance of an object. at Medlemmer.ods_MemberDetails_Inserting(Object sender, ObjectDataSourceMethodEventArgs e) in *************************************:line 167 at System.Web.UI.WebControls.ObjectDataSourceView.OnInserting(ObjectDataSourceMethodEventArgs e) at System.Web.UI.WebControls.ObjectDataSourceView.ExecuteInsert(IDictionary values) at System.Web.UI.DataSourceView.Insert(IDictionary values, DataSourceViewOperationCallback callback)
Avatar billede dr_chaos Nybegynder
26. januar 2006 - 10:33 #32
hvad linie er det ?
Avatar billede Slettet bruger
26. januar 2006 - 10:44 #33
m.Firmanavn = paramsFromPage["Firmanavn"].ToString();
Avatar billede Slettet bruger
08. februar 2006 - 20:24 #34
Det er nogle gange svært at se skoven for bar' træer.
Jeg har nu lavet det på den måde, at mit detailsview itemInserting event indeholder selve koden, der tjekker om en fil er postet.
Hvis den er postet, sættes detailsviewEventargs values["Logo"] lig med det postede filename og filen lægges samtidig op i en mappe.

Havde jeg bare vidst at det ikke var på objectdatasource kontrollen ændringerne skulle sættes, men der i mod på selve detailsview før den blev sendt til objectdatasource :-)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester