Problem deleting MembershipUser

Topics: Web Client Software Factory, User Forum
Jul 29, 2008 at 1:11 PM
Hi everybody.

I was warking sometime ago with SCSF and now I have to change to WCSF, and I'm having some troubles.

Now I'm stopped trying to deleting a MembershipUser.  I follow the same steps to create a DataGrid binding to an ObjectContainerDataSource which DataType is System.WebSecurity.MembershipUser, setting the DataKey to "UserName" property of MembershipUser. DataGrid is presented correctly with columns selected and Delete link, but when I click that link, an exception is thrown, and UserDataSource_Deleted event is not raised, so I can't call the _presenter.

This is the exception and the stack trace.

System.MissingMethodException: No hay constructor sin parámetros definido para este objeto. (Not constructor without parameters defined for this object)

[MissingMethodException: No hay constructor sin parámetros definido para este objeto.]
   System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandle& ctor, Boolean& bNeedSecurityCheck) +0
   System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean fillCache) +103
   System.RuntimeType.CreateInstanceImpl(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean fillCache) +268
   System.Activator.CreateInstance(Type type, Boolean nonPublic) +66
   System.Activator.CreateInstance(Type type) +6
   Microsoft.Practices.Web.UI.WebControls.ObjectContainerDataSourceView.CreateInstance() +38
   Microsoft.Practices.Web.UI.WebControls.ObjectContainerDataSourceView.ExecuteDelete(IDictionary keys, IDictionary oldValues) +266
   System.Web.UI.DataSourceView.Delete(IDictionary keys, IDictionary oldValues, DataSourceViewOperationCallback callback) +75
   System.Web.UI.WebControls.GridView.HandleDelete(GridViewRow row, Int32 rowIndex) +927
   System.Web.UI.WebControls.GridView.HandleEvent(EventArgs e, Boolean causesValidation, String validationGroup) +1134
   System.Web.UI.WebControls.GridView.RaisePostBackEvent(String eventArgument) +199
   System.Web.UI.WebControls.GridView.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +7
   System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +11
   System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +177
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1746

Could someone help me, or say me what it would be caused?

Thanks in advance.

Jul 29, 2008 at 8:08 PM
From looking at the stack trace and a bit of guesswork and poking around in the code, I think the problem is that MembershipUser does not have a public default constructor (a constructor with no parameters).  There is a protected default constructor, but that cannot be used by the ObjectContainerDataSourceView (OCDSV) in the ExecuteDelete method because the OCDSV creates an instance of the object that was deleted to pass to the OnDeleted event handler which get triggered from ExecuteDelete. 

I would suggest either not using the OCDSV in this case, OR subclassing MembershipUser and exposing a default constructor and using your new class as a presentation object. 
I really don't like either of those I'll also ping a few folks to see if they have any better ideas and have them reply here.

Good luck,
Michael Puleio -- patterns & practices  
Jul 31, 2008 at 4:55 AM
Edited Jul 31, 2008 at 4:58 AM

Michael is correct, objects bound to the ObjectContainerDataSource (OCDS from now on) need to have a public default constructor. This is required because as he mentioned, the control always creates new instances even to perform a delete or an update operation.

Why? The driver behind this behavior is consistency:

- There are cases in which the object you want to delete/update does not exist within the control because the deleting/updating operation is being executed before the control is filled with data objects (try with server sorting/paging enabled in the OCDS and with Viewstate enabled in the databound control). In these cases the only feasible alternative is to create a new instance and raise the corresponding event with that instance.

- There are other cases in which the object already exists in the DS control. In these cases, we sticked to the idea of always creating a new instance even if it is already there to keep a single simple behavior across different usage scenarios.

I believe, from what I have seen in the community, that this approach works in most of the cases. However, a different and valid approach is to create the data object instance only if it is not there. Interestingly, surfing the web I found this post where Adrian Brown introduces changes to the OCDS source code. With the modifications, the OCDS uses the existing instance if it is already in place. This approach can help you Sergio because you might not need to have a default constructor in your objects, because the instances can be reused. Note that you will have to ensure that the DataSource property of the OCDS is set before delete/update operations are executed.

Hope this helps,

Mariano Szklanny