Solved

adding logging capabilities to update, insert, delete events in details view

Posted on 2014-01-10
21
333 Views
Last Modified: 2014-01-13
Hello,

I am working on a web form that uses a details view.
It is functional using it without any customization.

I would like to add some logging when the user performs any crud functionality.

I would like to ask for some help, and/ or example on how to execute vb.net functions when the links on the details view are clicked.

<asp:CommandField ShowDeleteButton="True" ShowEditButton="True" ShowInsertButton="True" InsertText="Insert" UpdateText="Update" DeleteText="Delete" ButtonType="Link" />

Open in new window

0
Comment
Question by:metropia
  • 13
  • 8
21 Comments
 

Author Comment

by:metropia
ID: 39771646
I started by adding on the details view control tag:

<asp:DetailsView 
ID="dvRecipeItem" 
OnItemInserting="dvRecipeItem_ItemInserting"
OnItemInserted="dvRecipeItem_ItemInserted"
...
....

Open in new window


and then on the code behind:

   Private Sub dvRecipeItem_ItemInserted(sender As Object, e As System.Web.UI.WebControls.DetailsViewInsertedEventArgs) Handles dvRecipeItem.ItemInserted

    End Sub

    Private Sub dvRecipeItem_ItemInserting(sender As Object, e As System.Web.UI.WebControls.DetailsViewInsertEventArgs) Handles dvRecipeItem.ItemInserting
    End Sub

Open in new window


but i get an error:
BC30456: 'dvRecipeItem_ItemInserted' is not a member of 'ASP.default_aspx'.
0
 
LVL 13

Expert Comment

by:Jesus Rodriguez
ID: 39771650
You need to create a handler for this events on the backend code. Use on ItemCommand instead for it. Look at here

http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.detailsview.itemcommand(v=vs.110).aspx
0
 

Author Comment

by:metropia
ID: 39771664
thank you Jesus.

should it look like this then:

asp
                            OnItemCommand="DetailsViewCommandEventHandler"
                            OnItemInserting="dvRecipeItem_ItemInserting"
                            OnItemInserted="dvRecipeItem_ItemInserted"

Open in new window

code behind:
    Public Event ItemCommand As DetailsViewCommandEventHandler

    Private Sub dvRecipeItem_ItemInserted(sender As Object, e As System.Web.UI.WebControls.DetailsViewInsertedEventArgs) Handles dvRecipeItem.ItemInserted
    End Sub

    Private Sub dvRecipeItem_ItemInserting(sender As Object, e As System.Web.UI.WebControls.DetailsViewInsertEventArgs) Handles dvRecipeItem.ItemInserting

    End Sub

Open in new window

0
 

Author Comment

by:metropia
ID: 39771729
I tried also:

    OnItemCommand="dvRecipeItem_CommandEventHandler"
    OnItemInserting="dvRecipeItem_ItemInserting"
    OnItemInserted="dvRecipeItem_ItemInserted">

    Private Sub dvRecipeItem_CommandEventHandler(source As Object, e As DetailsViewCommandEventHandler)
    End Sub

    Private Sub dvRecipeItem_ItemInserted(sender As Object, e As System.Web.UI.WebControls.DetailsViewInsertedEventArgs) Handles dvRecipeItem.ItemInserted
    End Sub

    Private Sub dvRecipeItem_ItemInserting(sender As Object, e As System.Web.UI.WebControls.DetailsViewInsertEventArgs) Handles dvRecipeItem.ItemInserting
    End Sub

Open in new window


But not compiling.
Would you be able to tell me what I am missing?
0
 

Author Comment

by:metropia
ID: 39771758
Ok this works:

OnItemCommand="dvRecipeItem_ItemCommandEventHandler"

Protected Sub dvRecipeItem_ItemCommandEventHandler(sender As [Object], e As DetailsViewCommandEventArgs)

    If e.CommandName = "Insert" Then
    End If

End Sub
0
 
LVL 13

Expert Comment

by:Jesus Rodriguez
ID: 39771785
That's the correct way to do it. You control all the commands on the OnItemCommand Event Handler

Select Case e,CommandName
 Case "Insert"
     ' Your procedure for insert
 Case "Delete"
    'Your process for deleting
 ...
End Select


ALso you can do a small Procedure that do the log and call it like this

Public Sub RegisterFuction(Cmd as string, Rcd as String)
   'Do the process to save the User,Date and command that execute and also the record that affect where Rcd will be the Id of the affected record and Cmd the command that was executed
End Sub


and then in the OnItemCommand handler before the Case
Dim Record as string=Your Record Viewing
RegisterFunction(e.CommandName.ToString,Record)
Select Case e,CommandName
 Case "Insert"
     ' Your procedure for insert
 Case "Delete"
    'Your process for deleting
 ...
End Select
0
 

Author Comment

by:metropia
ID: 39771798
i have a question related to what i am trying to do Jesus, do you know how to access the current record on the detilas view?

I tried this:
 If Not IsNothing(Me.dvRecipeItem.Rows(0).FindControl("ItemNumber"))

But it always shows as Nothing. I think that is not how you get the value needed.

Thank you for your help.
0
 
LVL 13

Expert Comment

by:Jesus Rodriguez
ID: 39771812
You need to add datakeynames=[id] as an attribute to your detailsview  (id is whatever your primary key is). Like this more or less
<asp:DetailsView ID="DetailsView1" runat="server" AllowPaging="True" AutoGenerateRows="False"  DataKeyNames="DocumentID" DataSourceID="SqlDataSource1"   OnPageIndexChanged="DetailsView1_PageIndexChanged" DataMember="DefaultView">

Open in new window


and then

Dim temp as string=ItemsDetailsView.DataKey.Value.ToString()
      //or
Dim ID as string= ItemsDetailsView.DataKey(0).ToString()
0
 

Author Comment

by:metropia
ID: 39771850
I have one DataKeyNames:
DataKeyNames="Id" 

Open in new window


But I need the values of these databound fields:
<asp:BoundField DataField="ItemNumber" HeaderText="Item Number" SortExpression="ItemNumber" ApplyFormatInEditMode="True" />
<asp:BoundField DataField="ModifiedBy" HeaderText="Modified By" SortExpression="ModifiedBy" ApplyFormatInEditMode="True" />

Open in new window

Do I have to add more DataKeyNames?

Like:
DataKeyNames="Id" 
DataKeyNames="ItemNumber" 
DataKeyNames="ModifiedBy" 

Open in new window

0
 
LVL 13

Accepted Solution

by:
Jesus Rodriguez earned 500 total points
ID: 39771865
You can do that and then get the list of the datakey values like this example said

http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.detailsview.datakey(v=vs.80).aspx?cs-save-lang=1&cs-lang=vb

or do a search on the SQL/Database for the record with this Id and get the values or Get the values from the controls displayed

Dim  txtMessageTitle as TextBox = TryCast(detailsViewName.FindControl("txtMessageTitle"), TextBox)  
Dim text as string= txtMessageTitle.Text

Also if you have a chance look at here
http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.detailsview.rows(v=vs.110).aspx
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 

Author Comment

by:metropia
ID: 39772268
Jesus,

I have been trying to make this work but I am not getting the values I need.

All am a looking right now is to obtain the value from ItemNumber, and ModifiedBy which I believe are row 1, and 4, cells 1 respectively.

Can you look at my code and tell me what I am doing wrong? Perhaps I am refering the row, cell incorrectly?

I really need to get this done :/

Any help would be great.


<Fields>
<asp:BoundField DataField="Id" HeaderText="Id" ReadOnly="True" SortExpression="Id" ApplyFormatInEditMode="True" />
<asp:BoundField DataField="ItemNumber" HeaderText="Item Number" SortExpression="ItemNumber" ApplyFormatInEditMode="True" />
<asp:BoundField DataField="VersionNumber" HeaderText="VersionNumber" SortExpression="VersionNumber" ApplyFormatInEditMode="True" />
<asp:BoundField DataField="ModifiedDateTime" HeaderText="Modified Date Time" SortExpression="ModifiedDateTime" ApplyFormatInEditMode="True" />
<asp:BoundField DataField="ModifiedBy" HeaderText="Modified By" SortExpression="ModifiedBy" ApplyFormatInEditMode="True" />

Protected Sub dvRecipeItem_ItemCommandEventHandler(sender As [Object], e As DetailsViewCommandEventArgs)

If e.CommandName = "Insert" Then
    If Not IsNothing(Me.dvRecipeItem.Rows(1).Cells(1).Text.ToString()) Then
    ' Log Insert
        Dim strItemNumber As String = Me.dvRecipeItem.Rows(1).Cells(1).Text.ToString()
        Dim strModifiedBy As String = Me.dvRecipeItem.Rows(4).Cells(1).Text.ToString()
        Dim myAppLog As New AppLogClass(inEventCode:="Recipe-Insert", inItemCode:=strItemNumber, inDetailCode:=Membership.GetUser.UserName, inDescription:="Item Inserted By: " & strModifiedBy, inNote:=strModifiedBy)
        myAppLog.Save()
    End If
End If
End Sub

Open in new window

0
 

Author Comment

by:metropia
ID: 39776934
Hello,

I think I understand what I have to do, in theory.

By declaring the DataKeyNames, I can use them to query the entity model and get the entire record, is this correct?

Dim strItemNumber As String = Me.dvRecipeItem.DataKey(1).ToString()   -- ID
Dim strModifiedBy As String = Me.dvRecipeItem.DataKey(2).ToString()      -- ItemNumber

If e.CommandName = "Update" Then
    If Not IsNothing(Me.dvRecipeItem.DataKey(1).ToString()) Then
        ' Log Update
        Dim strItemNumber As String = Me.dvRecipeItem.DataKey(1).ToString()
        Dim strModifiedBy As String = Me.dvRecipeItem.DataKey(2).ToString()
        Dim myAppLog As New AppLogClass(inEventCode:="Recipe-Update", inItemCode:=strItemNumber, inDetailCode:=Membership.GetUser.UserName, inDescription:="Item Updated By: " & strModifiedBy, inNote:=strModifiedBy)
                myAppLog.Save()
    End If
End If

Open in new window


I would like to ask for your help with the syntax of the code that queries the entity model to get the record using the DataKeys.

Would you be able to help me with this?

Thank you much
0
 
LVL 13

Expert Comment

by:Jesus Rodriguez
ID: 39776975
In this code that you got her
If e.CommandName = "Insert" Then
    If Not IsNothing(Me.dvRecipeItem.Rows(1).Cells(1).Text.ToString()) Then
    ' Log Insert
        Dim strItemNumber As String = Me.dvRecipeItem.Rows(1).Cells(1).Text.ToString()
        Dim strModifiedBy As String = Me.dvRecipeItem.Rows(4).Cells(1).Text.ToString()
        Dim myAppLog As New AppLogClass(inEventCode:="Recipe-Insert", inItemCode:=strItemNumber, inDetailCode:=Membership.GetUser.UserName, inDescription:="Item Inserted By: " & strModifiedBy, inNote:=strModifiedBy)
        myAppLog.Save()
    End If
End If

Open in new window


Your getting the values from different rows
Dim strItemNumber As String = Me.dvRecipeItem.Rows(1).Cells(1).Text.ToString()
Dim strModifiedBy As String = Me.dvRecipeItem.Rows(4).Cells(1).Text.ToString()

and I suppose that you want from the same row but different cell
Dim strItemNumber As String = Me.dvRecipeItem.Rows(1).Cells(1).Text.ToString()
Dim strModifiedBy As String = Me.dvRecipeItem.Rows(1).Cells(4).Text.ToString()

or no ?? Also remember that the index begins in 0 and not in 1, the first cell will have the index(0)

also as I said to you before you can get it from the displayed text like
Dim  txtMessageTitle as TextBox = TryCast(detailsViewName.FindControl("txtMessageTitle"), TextBox)  

Can you post an image of your detail view right now ??
0
 

Author Comment

by:metropia
ID: 39777129
Jesus,

This is my current code. I am not using Row, Cells anymore, I am using DataKeyNames,

I want to be able to query the entity model using the DataKey to get the record and then save it in the log table.

Thisis my idea, but it is not working so far:

Dim myContext As New OLTPEntities
Dim myRecipeRecord = myContext.RefineRecipe.Where("it.Id=" & Me.dvRecipeItem.DataKey(1).ToString()).First

'Update (log 1 row in AppLog with list of new field values in Notes field,  Example:  “ID=1, ItemNumber=12204, etc.”)

If e.CommandName = "Update" Then
    If Not IsNothing(Me.dvRecipeItem.DataKey(1).ToString()) Then
        ' Log Update
        Dim strItemNumber As String = Me.dvRecipeItem.DataKey(1).ToString()
        Dim strModifiedBy As String = Me.dvRecipeItem.DataKey(2).ToString()
        Dim myAppLog As New AppLogClass(inEventCode:="Recipe-Update", inItemCode:=strItemNumber, inDetailCode:=Membership.GetUser.UserName, inDescription:="Item Updated By: " & strModifiedBy, inNote:=myRecipeRecord.ToString())
                myAppLog.Save()
    End If
End If

Open in new window


The inNote is the column in the data table that will contain the entire record:

 inNote:=myRecipeRecord.ToString()

I am getting a message:

 Dim myRecipeRecord = myContext.RefineRecipe.Where("it.Id=" & Me.dvRecipeItem.DataKey(1).ToString()).First

 System.InvalidOperationException: Sequence contains no elements



Do you have any insight as to why this error? is my query using wrong syntax?
0
 

Author Comment

by:metropia
ID: 39777184
I modified this line:

Dim myRecipeRecord = myContext.RefineRecipe.Where("it.Id=" & Me.dvRecipeItem.DataKey(1).ToString()).First

Open in new window


to:
Dim myRecipeRecord = myContext.RefineRecipe.Where("it.Id=" & Me.dvRecipeItem.DataKey(0).ToString())

Open in new window


and the erros went away, and I am able to write to database, but the value being passed is:

System.Data.Objects.ObjectQuery`1[Recipe.RefineRecipe]

instead that the actual values.
0
 
LVL 13

Expert Comment

by:Jesus Rodriguez
ID: 39777214
Do a break point on this line
Dim myRecipeRecord = myContext.RefineRecipe.Where("it.Id=" & Me.dvRecipeItem.DataKey(0).ToString())

and try to Cast the values on each properties for myRecipeRecord  on the debugger to see which item returns the values
0
 

Author Comment

by:metropia
ID: 39777249
valuesI added FirstOrDefault after ToString:

Dim myRecipeRecord = myContext.RefineRecipe.Where("it.Id=" & Me.dvRecipeItem.DataKey(0).ToString()).FirstOrDefault()


I can see the values in the watch window. Then I get to the part that saves the record to the log table:

inNote:=myRecipeRecord.ToString()

When I go to the data table and see what got saved, I see only this:

Recipe.RefineRecipe


What happened to the values? How do I save those as a single record in the column Note?
0
 
LVL 13

Expert Comment

by:Jesus Rodriguez
ID: 39777329
On the Breakpoint, when the program pass over step by step, select  myRecipeRecord from the whole
Dim myRecipeRecord = myContext.RefineRecipe.Where("it.Id=" & Me.dvRecipeItem.DataKey(0).ToString()).FirstOrDefault()

and then hit Shift+F9 (quick watch) and look for the values between the properties and you will get how to cast/Trycast or diretcast your expression to get the value
0
 

Author Comment

by:metropia
ID: 39777364
I see the Recipe.RefineRecipe is:

(New System.Linq.SystemCore_EnumerableDebugView(Of Recipe.RefineRecipe)(myRecipeRecord)).Items(0)

and then every column appears as:

(New System.Linq.SystemCore_EnumerableDebugView(Of Recipe.RefineRecipe)(myRecipeRecord)).Items(0)._AgitatorEmptySpeed
(New System.Linq.SystemCore_EnumerableDebugView(Of Recipe.RefineRecipe)(myRecipeRecord)).Items(0)._BulkTankTemp

and so on.

Do I have to specify every one of the columns? I am sorry this is the first time I am working with entity framework and I am having trouble understanding it.
0
 
LVL 13

Expert Comment

by:Jesus Rodriguez
ID: 39777450
I think that you can specify the index only like myRecipeRecord.Items(0).Item(0) or something like that
0
 

Author Comment

by:metropia
ID: 39777778
It is not saving the record. It only saves:

Recipe.RefineRecipe
0

Featured Post

What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

User art_snob (http://www.experts-exchange.com/M_6114203.html) encountered strange behavior of Android Web browser on his Mobile Web site. It took a while to find the true cause. It happens so, that the Android Web browser (at least up to OS ver. 2.…
Introduction This article shows how to use the open source plupload control to upload multiple images. The images are resized on the client side before uploading and the upload is done in chunks. Background I had to provide a way for user…
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
Here's a very brief overview of the methods PRTG Network Monitor (https://www.paessler.com/prtg) offers for monitoring bandwidth, to help you decide which methods you´d like to investigate in more detail.  The methods are covered in more detail in o…

760 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

26 Experts available now in Live!

Get 1:1 Help Now