Link to home
Start Free TrialLog in
Avatar of bamoon
bamoonFlag for Afghanistan

asked on

Calling a shared method for XMLtextWriter

I have the following code in a class name Invoice.  I am trying to call each of the below procedures from my form class by using Invoice.OpenInvoice()... getting an error "Access of a shared member through an instance".  How do I call these shared methods from my form?

Shared Sub OpenInvoices()
'writes XML declaration..start tag called from load event of form
        Dim writer As New XmlTextWriter(Path, Nothing)
        writer.Formatting = Formatting.Indented
        writer.WriteStartDocument()
        writer.WriteStartElement("Invoices")
        writer.Close()
    End Sub

'writes invoice elements for each invoice click event  
 Public Sub WriteInvoice(ByVal writer As XmlTextWriter)
        writer.WriteStartElement("Invoice")
        writer.WriteAttributeString("Customer", sCustomerName)
        writer.WriteElementString("OrderTotal", CStr(dOrderTotal))
        writer.WriteElementString("Discount", CStr(dDiscountAmount))
        writer.WriteElementString("InvoiceTotal", CStr(dInvoiceTotal))
        writer.WriteEndElement()
    End Sub
'writes end tag and closes
    Shared Sub CloseInvoices()
        Dim writer As New XmlTextWriter(Path, Nothing)
        writer.WriteEndElement()
        writer.Close()
    End Sub
Avatar of thenrich
thenrich

try this: instead of 'Invoice.OpenInvoice' Import the class that has OpenInvoice and then just call OpenInvoice from the Form
Your trying to Access it through The Instance of Invoice and you don't need too.
Avatar of bamoon

ASKER

Ok that seemed to clear up that error now I have the error "Object reference not set to an instance of an object" on the line writer.WriteStartElement("Invoice") under WriteInvoice
You need to Dimension 'writer'. That function is not shared and therefore does not have writer in it's scope from the shared functions.
Avatar of bamoon

ASKER

For some reason the program does not seem to be writing my top start element, error message when opening file .."XML document must have a top level element. Error processing resource 'file:..."  I had dimensioned writer in the form class then changed the code to dimension in the Invoice class.  But now this seems now to be a problem in OpenInvoices.
Revert all of your code to what you started with and simply mark the WriteInvoice() and CloseInvoice() functions as Shared.
Javert93 ,
He'd still need to Dim a writer varibale for the Public Sub WriteInvoice(ByVal writer As XmlTextWriter) sub
Avatar of bamoon

ASKER

I changed it back and made all methods shared. now on open I get the error message System.IO.IOException: The process can not access the file because it is being used by another process. I have a module level variable Path in the invoice class and dim Path in the form class.

you need to put a writer.close in the  Public Sub WriteInvoice(ByVal writer As XmlTextWriter)
Avatar of bamoon

ASKER

I tried that still the same error.
it's very unclear to me what you are trying to even do...
It doesn't make any sense to me.
Make everything un-shared intantiate the class and call it by.

Invoice.CloseInvoices
Invoice.WriteInvoice
or
Invoice.OpenInvoices

Why do you even have those subs marked as shared?
Once you have a pointer to the writer why not just keep it around:

Imports System.Xml
Public Class Invoice
    Public Function OpenInvoices() As XmlTextWriter
        Try
            'writes XML declaration..start tag called from load event of form
            Dim writer As New XmlTextWriter("Path", Nothing)
            writer.Formatting = Formatting.Indented
            writer.WriteStartDocument()
            writer.WriteStartElement("Invoices")
            writer.Close()
            Return writer
        Catch ex As Exception
            MsgBox(ex.Message)
            Return Nothing
        End Try
    End Function

    'writes invoice elements for each invoice click event  
    Public Function WriteInvoice(ByVal writer As XmlTextWriter) As XmlTextWriter
        Try
            writer.WriteStartElement("Invoice")
            writer.WriteAttributeString("Customer", "sCustomerName")
            writer.WriteElementString("OrderTotal", CStr("dOrderTotal"))
            writer.WriteElementString("Discount", CStr("dDiscountAmount"))
            writer.WriteElementString("InvoiceTotal", CStr("dInvoiceTotal"))
            writer.WriteEndElement()
            Return writer
        Catch ex As Exception
            MsgBox(ex.Message)
            Return Nothing
        End Try
    End Function
    'writes end tag and closes

    Public Function CloseInvoices(ByVal writer As XmlTextWriter) As Boolean
        Try
            writer.WriteEndElement()
            writer.Close()
            Return True
        Catch ex As Exception
            MsgBox(ex.Message)
            Return False
        End Try
    End Function
End Class
Works perfectly - take the:
 
writer.Close()

out of the OpenInvoice function and here is what I put in the form to test it:


''' Form test code
    Dim I1 As New Invoice
        I1.CloseInvoices(I1.WriteInvoice(I1.OpenInvoices))
Avatar of bamoon

ASKER

still getting the execption file being used.
I can't help then, I tested the code I posted and it works fine.

ASKER CERTIFIED SOLUTION
Avatar of thenrich
thenrich

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
One of two things will cause the IO exception: either the file is open by another process (or the same process), or you do not have permission to access the file. Try downloading process explorer from http://www.sysinternals.com for the former issue, and check the security permissions on both the file and the directory for the latter issue.
Avatar of bamoon

ASKER

Here is all of it..the file is on my personal computer so I know it's not being used, and I do have permission to access.

'Invoice Class
Imports Microsoft.VisualBasic

Imports System.Xml

Module mItotal
    Public dInvoiceTotal As Decimal
    Public sCustomerName As String
    Public dOrderTotal As Decimal
    Public dDiscountAmount As Decimal
   
End Module

Public Class Invoice

    Public InvInfo As InvoiceInfo
   

    Public Property CustomerName() As String
        Get
            Return sCustomerName
        End Get
        Set(ByVal value As String)
            sCustomerName = value
        End Set
    End Property

    Public Property OrderTotal() As Decimal
        Get
            Return dOrderTotal
        End Get
        Set(ByVal value As Decimal)
            dOrderTotal = value
        End Set
    End Property

    Public ReadOnly Property DiscountAmount() As Decimal
        Get
            Return dDiscountAmount
        End Get
    End Property

    Public ReadOnly Property InvoiceTotal() As Decimal
        Get
            Return dInvoiceTotal
        End Get
    End Property

    Public Sub AddItem(ByVal UnitPrice As Decimal, _
            ByVal Quantity As Integer)
        dOrderTotal = dOrderTotal + (UnitPrice * Quantity)
        dDiscountAmount = Discount(dOrderTotal)
        dInvoiceTotal = dOrderTotal - dDiscountAmount

    End Sub
    Private Function Discount(ByVal OrderTotal As Decimal) As Decimal
        Dim dDiscountPct As Decimal
        Select Case OrderTotal
            Case Is >= 500
                dDiscountPct = 0.3
            Case Is >= 200
                dDiscountPct = 0.2
            Case Is >= 100
                dDiscountPct = 0.1
            Case Else
                dDiscountPct = 0
        End Select
        Return Math.Round(OrderTotal * dDiscountPct, 2)
    End Function
    Structure InvoiceInfo
        Dim Cust As String
        Dim OTotal As Decimal
        Dim ITotal As Decimal
        Dim DAmt As Decimal
    End Structure
    Public Function OpenInvoices(ByVal Path As String) As XmlTextWriter

        Try
            'writes XML declaration..start tag called from load event of form
            Dim writer As New XmlTextWriter(Path, Nothing)
            writer.Formatting = Formatting.Indented
            writer.WriteStartDocument()
            writer.WriteStartElement("Invoices")
            'writer.Close()
            Return writer
        Catch ex As Exception
            MsgBox(ex.Message)
            Return Nothing
        End Try
    End Function

    'writes invoice elements for each invoice click event  
    Public Function WriteInvoice(ByVal writer As XmlTextWriter) As XmlTextWriter
        Try
            writer.WriteStartElement("Invoice")
            writer.WriteAttributeString("Customer", "sCustomerName")
            writer.WriteElementString("OrderTotal", CStr("dOrderTotal"))
            writer.WriteElementString("Discount", CStr("dDiscountAmount"))
            writer.WriteElementString("InvoiceTotal", CStr("dInvoiceTotal"))
            writer.WriteEndElement()
            Return writer
        Catch ex As Exception
            MsgBox(ex.Message)
            Return Nothing
        End Try
    End Function


    'writes end tag and closes

    Public Function CloseInvoices(ByVal writer As XmlTextWriter) As Boolean
        Try
            writer.WriteEndElement()
            writer.Close()
            Return True
        Catch ex As Exception
            MsgBox(ex.Message)
            Return False
        End Try
    End Function

End Class

'Form Class

Option Explicit On

Imports System.Xml
Module mQ
    Public qInvoice As New Queue
    Public SortedItemList As New SortedList(5)
End Module
Partial Class Invoice_aspx


    Dim Invoice As Invoice
    Dim Path As String = "..\Invoices.xml"
    Dim writer As New XmlTextWriter(Path, Nothing)
   
    Public Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
       
        Invoice = New Invoice()
        txtCustomerName.Focus()
        btnNewInvoice.Enabled = False


        Dim ItemEntry As DictionaryEntry
        If SortedItemList.Count = 0 Then
            SortedItemList.Add(1000, 19.95)
            SortedItemList.Add(2000, 9.95)
            SortedItemList.Add(3000, 29.95)
            SortedItemList.Add(4000, 69.95)
            SortedItemList.Add(5000, 129.95)

            For Each ItemEntry In SortedItemList
                cmbItem.Items.Add(ItemEntry.Key)
            Next
        End If
        Invoice.OpenInvoices(Path)
    End Sub
    Private Sub btnadditem_click(ByVal sender As System.Object, _
            ByVal e As System.EventArgs) Handles btnAddItem.Click
       
        Invoice.AddItem(CDec(txtUnitPrice.Text), CInt(txtQuantity.Text))
        lblOrderTotal.Text = FormatNumber(Invoice.OrderTotal)
        lblDiscountAmount.Text = FormatNumber(Invoice.DiscountAmount)
        lblInvoiceTotal.Text = FormatNumber(Invoice.InvoiceTotal)

        txtUnitPrice.Text = ""
        txtQuantity.Text = ""
        txtUnitPrice.Focus()
        btnNewInvoice.Enabled = True
        InvoiceTotal(iIndex) = CDec(Me.lblInvoiceTotal.Text)
        iIndex += 1
        InvoiceArray.Add(Invoice.InvoiceTotal)


    End Sub

    Private Sub btnNewInvoice_Click(ByVal sender As System.Object, _
            ByVal e As System.EventArgs) Handles btnNewInvoice.Click

        Invoice.CustomerName = txtCustomerName.Text
        MsgBox("Order Total: " & _
                    FormatCurrency(Invoice.OrderTotal) & _
                    ControlChars.CrLf & _
                "Discount Amount: " & _
                    FormatCurrency(Invoice.DiscountAmount) & _
                    ControlChars.CrLf & _
                "Invoice Total: " & _
                    FormatCurrency(Invoice.InvoiceTotal), , _
                "Invoice for Customer " & Invoice.CustomerName)
        Invoice.WriteInvoice(writer)
        Invoice.OrderTotal = 0
        Invoice = New Invoice()
        lblOrderTotal.Text = ""
        lblDiscountAmount.Text = ""
        lblInvoiceTotal.Text = ""
        txtCustomerName.Text = ""
        txtUnitPrice.Text = ""
        txtQuantity.Text = ""
        cmbItem.SelectedItem.Selected = False
        txtCustomerName.Focus()
        btnNewInvoice.Enabled = False
        qInvoice.Enqueue(Invoice.CustomerName & " " & FormatCurrency(Invoice.InvoiceTotal))

    End Sub

    Sub btnExit_Click(ByVal sender As Object, ByVal e As System.EventArgs)
       
        Invoice.CloseInvoices(writer)

    End Sub

    Public Sub cmbItem_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs)
       
        txtUnitPrice.Text = SortedItemList.Item(CInt(cmbItem.SelectedItem.Value))

    End Sub

   

   
End Class
Module mInvoice
    Public InvoiceTotal(4) As Decimal
    Public iIndex As Integer
    Public dInvoiceTotal As Decimal
    Public InvoiceArray As New ArrayList(4)
End Module
This is an ASP.NET application? The most likely problem is that IUSER_<Machine Name> does not have access to the file. You need to explicitly give this account write permissions on the folder and file before you can access it. Under a default installation, anonymous reuqests to a Web Application run under the IUSER_<Machine Name> account, which does not have permission to write to the file system (note that you need to replace <Machine Name> with the name of your computer). Also, watch out for the execute permission (especially if the file is accessible from IIS), because that could allow a remote user to write an executable to the directory and execute it.
Yea - he's right. Depending on which OS your using if you right mouse click on the directory you should find a tab to allow you to set ASP.NET permissions.
Avatar of bamoon

ASKER

How do I give IUSER_ <Maching Name> permission?  The file that is created is not read only.
Why does this seem to be the never ending question?
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial