ProjectTracker Question: State Loss when Insert has BrokenRules

ProjectTracker Question: State Loss when Insert has BrokenRules

Old forum URL: forums.lhotka.net/forums/t/509.aspx


RubyRed93 posted on Thursday, June 29, 2006

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.

cmellon replied on Thursday, June 29, 2006

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

skagen00 replied on Thursday, June 29, 2006

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.

 

 

RubyRed93 replied on Friday, June 30, 2006

skagen00 you rock!  Yes, you speak of the exact problem I was having with ASP.NET.  I'm a long time fan of CSLA, all the way back to the nasty VB 5 version.  I read the book on CSLA.NET, but haven't yet had time to read up on CSLA.NET 2.0.  I haven't been able to find any answers to this problem in the book nor online until now.  This forum is great!  But I would love to hear Rocky comment on this matter.  I hate to use the DetailsView in Edit mode when I should be doing an Insert, but it sounds to me that you've found a work around.  I will look into it further and work with your solution.  Thank you very much!!!

RockfordLhotka replied on Thursday, July 13, 2006

Thanks for bringing this to my attention. I don't have an answer without doing further research, but this is certainly an unforseen issue...
 
What I don't understand, at least initially, is why (in ProjectTracker anyway) the same object isn't carried forward. The GetProject() method should carry the same object. Perhaps in the case of an insert data binding doesn't even populate the controls based on the underlying object? If that's the case then I'd think it is a flaw with how they built data binding, as it would preclude the use of default values from the data source in any case (not just with CSLA objects).

RockfordLhotka replied on Thursday, July 13, 2006

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...)

RubyRed93 replied on Friday, July 14, 2006

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!

RockfordLhotka replied on Friday, July 14, 2006

I still find it hard to believe that there's no provision to show default values when in insert mode... I don't have time to do more in-depth research on it just now, but there must be some answer to this problem...
 
You may want to try posting at www.asp.net (isn't that the ASP.NET forum site?) to see if the ASP.NET gurus have figured something out.
 
Rocky


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

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!


SteveChadbourne replied on Thursday, July 20, 2006

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

RockfordLhotka replied on Thursday, July 20, 2006

Yeah, I looked into that too. And it isn't that CslaDataSource doesn't raise the event - but that data binding doesn't appear to request the data. Apparently they must assume that since they know the shape of the end object, they don't need to create an instance to build the page - which is obviously true.
 
But then you must wonder - how to load default values in a new page? They must have some mechanism for doing this - perhaps there's some event on the grid control that is raised so you can load default values? This isn't something I've researched, but it would be common to all web development, so perhaps ASP.NET 2.0 gurus and/or books have the answer?
 
Rocky


The problem appears to be that if the dataview is in insert mode, the datasource OnSelectObject event does not trigger.

phuff replied on Monday, July 24, 2006

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

RubyRed93 replied on Monday, July 24, 2006

So per this latest post, does CSLA.NET now need to do something to expose these additional values?  For example, KeepInInsertMode via Csla.Web.InsertObjectArgs?

RockfordLhotka replied on Monday, July 24, 2006

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…

skagen00 replied on Monday, July 24, 2006

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