This is my first post and let me apologize for not having the ProjectTracker application up and running. I'm working on my own application while looking at the book and code. I'm having an issue with my app and wondering about the best possible solution. It also appears to me, without running the app, that the ProjectTracker may have a similar issue with ProjectEdit page?
When entering data into a form via the DetailsView and this newly created object fails to insert, won't the user's entered data be lost (controls cleared). It appears to me that Bind will once again be applied to the controls via the EditItemTemplate where an empty object exists?
Hope my question makes sense and that someone can clear this up for me as to how to avoid such data loss and re-entry. My app notifies the user regarding broken rules, but controls are cleared. Maybe this is not the case and I've completely gone off the deep end with my code. Thanks in advance.
Hi,
Are you talking about ASP.NET app or winforms?
If its ASP.net and your performing a post back for validation I think you will need to rebind the textboxes, I'm a little rusty with asp.net. Another option is to enable viewstate on your contols so that your textboxes retain the user entered data when a postback occurs.
Regards
Craig
You are running across a problem I experienced - you're talking about ASP.NET.
What I believe I will end up always doing (and I did with a little prototype) is to create a new business object and bind it in edit mode, rather than ever use the insert mode.
It is a little fuzzy to me exactly what I ran into (I was also new to CSLA at the time), but from your e-mail I'm absolutely sure you're running into the same issues I did. Here's a link to my old post: http://www.searchcsla.com/Details.aspx?msn_id=25495 Look at the "second part of my problem". This is before I decided to stay away from the insert mode. (On a side note, the issue with the datamapper seems to have remedied itself in the updated 2.x CSLA downloads, but that's irrelevant)
So as I mentioned, from here on out I will likely be avoiding the insert mode when using the CslaDataSource, and will instead create a new object and bind the new object to it in edit mode. After I took that avenue with my first prototype I was pleased with the direction I took. It may not be "consistent" with the usage of the object the CslaDataSource was meant to solve, but it's a lot easier to deal with for me.
Obviously, you're trying to work through the example in the book so alternative approaches don't help you work through your current problem - but I believe the answer is that it's just a problem with the example application - so I'd suggest not getting too hung up on it. I just think there is just a problem with using the detailsview in insert mode in conjunction with CSLA.
Yeah, there are two things going on here.
First, it does appear that the DetailsView control doesn't read values from the data source when in insert mode - which (imo) is a poor choice on Microsoft's part, and may render insert mode largely useless in some cases...
Second, there is an issue with my code in the ProjectEdit form - when handling the ItemInserted event. The code should read
Protected Sub DetailsView1_ItemInserted( _
ByVal sender As Object, _
ByVal e As System.Web.UI.WebControls.DetailsViewInsertedEventArgs) _
Handles DetailsView1.ItemInserted
Dim project As Project = GetProject()
If Not project.IsNew Then
Response.Redirect("ProjectEdit.aspx?id=" & project.Id.ToString)
End If
End Sub
In the original, I was blindly redirecting, even if the insert failed. That's not good, so this only does a redirect in the case of success (the new object isn't new any more).
But this doesn't make values appear in the DetailsView on insert. And I don't see how to make that happen, because it doesn't appear that DetailsView is populating the controls in this case (which is odd, because it DOES ask the datasource control for a data source - so why it would then ignore that data source I don't know...)
Thank you for taking the time to respond and address this! I just wanted to make sure that some of us weren't completely off track here and missing something somewhere. Maybe Microsoft will address this soon. Thanks again!
From: RubyRed93 [mailto:cslanet@lhotka.net]
Sent: Friday, July 14, 2006 7:52 AM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] ProjectTracker Question: State Loss when Insert has BrokenRules
The problem appears to be that if the dataview is in insert mode, the datasource OnSelectObject event does not trigger.
I have tried all sort of workarounds and the easiest way round this seems to be to always use the dataview in edit mode as the post above suggested.
This means removing any code in ApplyAuthorisationRules() that sets the dataview mode:
if (obj.IsNew)
this.DetailsView1.DefaultMode = DetailsViewMode.Insert;
else
this.DetailsView1.DefaultMode = DetailsViewMode.Edit;
and also remove the datasource insertobject event. You may also need to check when the ID is passed/allowed to be updated. All works fine now.
Steve
The problem appears to be that if the dataview is in insert mode, the datasource OnSelectObject event does not trigger.
When DetailsView goes into Insert mode, the DetailsView does not request data from the data source because it doesn’t need it to render UI to create a new record. This makes the Insert scenario faster and prevents requesting data from the database when the data isn’t needed.
If you need to show default values in the Insert UI, there are two different ways you can go. The first is suggested above- you can add a new “default” record to your database, then edit it when the user clicks “Insert”. The other (arguably simpler) way to go is to handle the DetailsView’s DataBound event, check if the control is in Insert mode, and if so populate the UI with default values. The drawback to this approach is that the default field values are stored with the web application rather than with the data.
One post touched on how to handle an error during insertion. The best thing to do is to handle the ItemInserted event. The exception is available in the event arguments, along with a Boolean property called KeepInInsertMode which will keep the DetailsView from rebinding. Setting KeepInInsertMode to true will preserve the user’s entered values instead of clearing them. There’s a similar property on DetailsViewUpdatedEventArgs called KeepInEditMode to leave the user’s values in the edit UI.
Hope this helps…
Polita
That is great info phuff!
Certainly the KeepInInsertMode is easy enough to do – just change the existing ItemInserted event handler to this:
Protected Sub DetailsView1_ItemInserted( _
ByVal sender As Object, _
ByVal e As System.Web.UI.WebControls.DetailsViewInsertedEventArgs) _
Handles DetailsView1.ItemInserted
Dim project As Project = GetProject()
If Not project.IsNew Then
Response.Redirect("ProjectEdit.aspx?id=" & project.Id.ToString)
Else
e.KeepInInsertMode = True
End If
End Sub
That does keep the existing values in the control.
The lack of decent support for loading default data values is unfortunate. The ItemCreated event appears to be the correct answer here (not DataBind), but it is such a hack:
Protected Sub DetailsView1_ItemCreated( _
ByVal sender As Object, ByVal e As System.EventArgs) Handles DetailsView1.ItemCreated
Dim obj As Project = GetProject()
CType(DetailsView1.Rows(0).Cells(1).Controls(0), TextBox).Text = obj.Id.ToString
CType(DetailsView1.Rows(1).Cells(1).Controls(0), TextBox).Text = obj.Name
CType(DetailsView1.Rows(2).Cells(1).Controls(0), TextBox).Text = obj.Started
CType(DetailsView1.Rows(3).Cells(1).Controls(0), TextBox).Text = obj.Ended
CType(DetailsView1.FindControl("TextBox1"), System.Web.UI.WebControls.TextBox).Text = obj.Description
End Sub
It rather boggles my mind that this is the best way to load default values into a DetailsView…
Frankly I will continue to utilize the object in the edit mode. The object goes to the database only to the extent you need it to. When assigning the business object in the selectobject, if it's a matter of Customer.NewCustomer(), that's really not going to be much and likely nothing if it's set to RunLocal. The consistency of the UI (only having one path - that of editing an object that may or may not be new and then saving the object which may or may not have broken rules) is the way to go IMO.
I plan on utilizing lean wizards when creating new records for users - that which will help the user "initialize" their new record (along with duplicate checking) prior to being dumped into the main maintenence form with their new (but partially populated) object. Even if I wasn't using wizards, I'd go with the edit mode over insert mode.
(If I remember right, it's also one less template to configure and keep in synch when dealing with something such as a FormView).
Chris
Copyright (c) Marimer LLC