ASP.NET WebForms change insert operation into update at runtime

243 Views Asked by At

Let's say I have a page with FormView where there is a form allowing to register article into database. User can fill some properties like Number, Description etc. I use EntityDataSource.

I can perform insert/update operations. The problem is that in some cases (exactly if IsDeleted property of the object with the same Number is set to true) I want to cancell Insert operation and perform Update instead. To do so I started with such thing:

protected void ArticleFormView_ItemInserting( object sender, FormViewInsertEventArgs e )
{
   string articleNo = e.Values[ "Number" ].ToString();

   // ...some other things...

   if ( this.ShouldUpdateInsteadOfInsert( articleNo ) )
   {
      e.Cancel = true; //cancel insert 
      this.ArticleFormView.ChangeMode( FormViewMode.Edit );
      this.ArticleFormView.UpdateItem( false );
      return;
   }
}

This successfully cancels Insert and invokes Update. However in the ArticleFormView_ItemUpdating event handler property NewValues of FormViewUpdateEventArgs object has some default values - not the ones entered by user.

protected void ArticleFormView_ItemUpdating( object sender, FormViewUpdateEventArgs e )
{
    // e.NewValues["Number"] - not the same as 
    // e.Values["Number"] from ArticleFormView_ItemInserting
}

Is there a possibility to make it work this way?

I could manually create an Entity object in ItemInserting and assign all values manually, but object has 200+ fields so I'm looking for a better approach.

I'll apreciate any good solution for this case.

1

There are 1 best solutions below

0
Ryfcia On

Still, if anyone knows a better solution, please respond.

I managed to write a code that maps the values using reflection. I do not invoke Update method, but I perform a database update manually in ItemInserting.

protected void ArticleFormView_ItemInserting( object sender, FormViewInsertEventArgs e )
{
   string articleNo = e.Values[ "Number" ].ToString();

   // ...some other things...

   if ( this.ShouldUpdateInsteadOfInsert( articleNo ) ) // (property IsDeleted = true)
   {
       // cancel insert 
       e.Cancel = true; 

       using ( StoreEntities ctx = new StoreEntities() )
       {
            // get "deleted" article
            var restoredArticle = ctx.Articles.First( i => i.Number == articleNo );

            // "restore" it
            restoredArticle.IsDeleted = false;

            var type = restoredArticle.GetType();
            foreach ( var propertyInfo in type.GetProperties() )
            {
                if ( propertyInfo.CanWrite )
                {
                    // ignore some values that should not be changed
                    if ( propertyInfo.Name == "Number" || propertyInfo.Name == "IsDeleted" || propertyInfo.Name == "ID" || propertyInfo.Name == "EntityKey" )
                        continue;

                    // update other properties, handle non convertible types separately
                    if ( propertyInfo.PropertyType == typeof( int ) )
                        propertyInfo.SetValue( restoredArticle, e.Values[ propertyInfo.Name ] == null ? (int?)null : Convert.ToInt32( e.Values[ propertyInfo.Name ] ), null );
                    else if ( propertyInfo.PropertyType == typeof( decimal ) )
                        propertyInfo.SetValue( restoredArticle, e.Values[ propertyInfo.Name ] == null ? (decimal?)null : Convert.ToDecimal( e.Values[ propertyInfo.Name ] ), null );
                    else
                        propertyInfo.SetValue( restoredArticle, e.Values[ propertyInfo.Name ], null );
                }
            }
            ctx.SaveChanges();
        }

      return;
   }
}