This is a migrated thread and some comments may be shown as answers.

[Solved] Grid Edit Popup Validation Bug!

12 Answers 193 Views
Grid
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Andrea
Top achievements
Rank 1
Andrea asked on 04 Aug 2011, 11:19 AM
Hi,

Does anyone ever use IValidatableObject in the data model and PopUp mode for the grid editing at the same time?
Now I've got a  bug when the data model get updated and fails the validation in the view.
Normally if the data model fails  the validation , everyting in the editing PopUp should keep the same as before and the error message should be displayed in the PopUp.
But now the  PopUp turns out to be empty ! Weird!!!
Please note this bug is only for editing PopUp,everything goes fine with the inserting PopUp.I don't know what's the difference between the inserting PopUp and editing PopUp.I think they are similar.
I am wondering if someone has same problem as me since this really drive me crazy.
For example:
I have an entity object Application that inherits IValidatableObject  interface
#region Application 
    [MetadataType(typeof(ApplicationMetaData))]     // Needed for automated data validation 
        public partial class Application : IValidatableObject 
    
        #region IValidatableObject Members 
    
        public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) 
        
            using (AppCatalogContainer acc = new AppCatalogContainer()) 
            
                //check the application name whether exists in database 
                if (acc.Applications.Count(a => (a.Name == this.Name) && (a.Id != this.Id)) > 0) 
                
                    yield return new ValidationResult("application name already exists", new[] { "Name" }); 
                
                //check the application category whether exists in database 
                if (acc.ApplicationCategories.Count(c => c.Id == this.ApplicationCategoryId) == 0) 
                
                    yield return new ValidationResult("category doesn't exist,please re-choose a category", new[] { "ApplicationCategoryId" }); 
                
            
        
    
        #endregion 
    
    
    public class ApplicationMetaData 
    
        //[ScaffoldColumn(false)] 
        public Int32 Id; 
    
        //[Required] 
        [DisplayName("Category"), UIHint("ApplicationCategoryId"), Required] 
        public Int32 ApplicationCategoryId { get; set; } 
    
        [Required(ErrorMessage = "A name is required")] 
        public String Name { get; set; } 
    
        [Required(ErrorMessage = "A description is required")] 
        public String Description { get; set; } 
     
    
    #endregion
The code in the the controller is like this:
public class ApplicationController : Controller
   {
       Repository repo = new Repository();
       //
       // GET: /Application/
      [ValidateInput(false)]
       public ActionResult Index(string id)
       {
           try
           {
               if (!string.IsNullOrEmpty(id))
                   ViewBag.Application = repo.FindApplication(int.Parse(id));
           }
           catch
           {
               ViewBag.Application = null;
           }
           ViewBag.ApplicationCategories = repo.GetApplicationCategories().OrderBy(c => c.Name);
           return View(repo.GetApplications());
       }
       [HttpPost]
       public ActionResult Insert()
       {
           try
           {
               Application newapp = new DataModel.Models.Application();
               if (TryUpdateModel(newapp))
               {
                   repo.InsertApplication(newapp);
                   TempData["Message"] = "Record inserted";
                   return RedirectToAction("Index", this.GridRouteValues());
               }
               TempData["Message"] = "An error occured while saving the record";
               ViewResult result = View("Index", repo.GetApplications());
               result.ViewBag.ApplicationCategories = repo.GetApplicationCategories().OrderBy(c => c.Name);
               return result;
           }
           catch (HttpRequestValidationException ve)
           {
               TempData["Message"] = "Some special characters are not allowed!" + ve.Message;
               return RedirectToAction("Index");
           }
           catch (Exception ex)
           {
               TempData["Message"] = "Error:" + ex.Message;
               InfoLogger.LogException(ex, "ApplicationController::Insert");
               return RedirectToAction("Index");
           }
       }
       [HttpPost]
       public ActionResult Update(int id)
       {
           try
           {
               Application updatedapp = repo.FindApplication(id);
               if (updatedapp == null)
                   return RedirectToAction("Index", this.GridRouteValues());
               if (TryUpdateModel(updatedapp))
               {
                   repo.UpdateApplication(updatedapp);
                   TempData["Message"] = "Record updated";
                   return RedirectToAction("Index", this.GridRouteValues());
               }
               TempData["Message"] = "An error occured while saving the record";
               ViewResult result = View("Index", repo.GetApplications());
               result.ViewBag.ApplicationCategories = repo.GetApplicationCategories().OrderBy(c => c.Name);
               return result;
           }
           catch (HttpRequestValidationException ve)
           {
               TempData["Message"] = "Some special characters are not allowed!" + ve.Message;
               return RedirectToAction("Index");
           }
           catch (Exception ex)
           {
               TempData["Message"] = "Error:" + ex.Message;
               InfoLogger.LogException(ex, "ApplicationController::Update");
               return RedirectToAction("Index");
           }
       }
       [HttpPost]
       [MobileAuthorize(Roles = "Administrators")]
       public ActionResult Delete(int id)
       {
           try
           {
               DataModel.Models.Application g = repo.FindApplication(id);
               if (g == null)
                   return RedirectToAction("Index", this.GridRouteValues());
               repo.DeleteApplication(g);
               TempData["Message"] = "Record deleted";
               return RedirectToAction("Index", this.GridRouteValues());
           }
           catch (Exception ex)
           {
               TempData["Message"] = "Error:" + ex.Message;
               InfoLogger.LogException(ex, "ApplicationController::Delete");
               return RedirectToAction("Index");
           }
       }
     
   }

Thanks

12 Answers, 1 is accepted

Sort by
0
Rosen
Telerik team
answered on 05 Aug 2011, 08:13 AM
Hi Andrea,

Unfortunately, I'm not sure what may be the cause for the behavior you have described judging from the provided information. Therefore, could you please provide a small sample in which this behavior can be observed.

All the best,
Rosen
the Telerik team

Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items

0
Jekin
Top achievements
Rank 1
answered on 23 Aug 2011, 06:08 AM
Hi Telerik team,

I have exact the same issue as Andrea.

I have a meta data class ApplicationMetaData 

 

public class ApplicationMetaData
  
{
  
public Int32 Id;
  
  
[DisplayName("Category"), UIHint("ApplicationCategoryId"), Required]
  
public Int32 ApplicationCategoryId { get; set; }
  
  
[Required(ErrorMessage = "A name is required")]
  
[StringLength(40,ErrorMessage="Field Name can't exceed 40 characters.")]
  
public String Name { get; set; }
  
  
[Required(ErrorMessage = "A description is required")]
  
public String Description { get; set; }
  
}

  

The view is as following:

 

@model IEnumerable<DataModel.Models.Application>
  
@{
  
ViewBag.Title = "Index";
  
}
  
@Html.ValidationSummary()
  
@helper Gridzone()
  
{
  
@(Html.Telerik().Grid(Model).Name("Grid")
  
.Selectable()
  
.ClientEvents(events => events.OnRowSelect("onRowSelected"))
  
.Pageable()
  
.Sortable()
  
.Scrollable()
  
.Pageable()
  
.Filterable()
  
.Resizable(resizing => resizing.Columns(true))
  
.Reorderable(reorder => reorder.Columns(true))
  
.DataKeys(keys => keys.Add(g => g.Id))
  
.Editable(editing => editing.Mode(GridEditMode.PopUp))
  
.ToolBar(commands =>commands.Insert())
  
.DataBinding(dataBinding =>
  
dataBinding.Server()
  
.Select("Index", "Application")
  
.Insert("Insert", "Application")
  
.Update("Update", "Application")
  
.Delete("Delete", "Application"))
  
.Columns(columns =>
  
{
  
columns.Bound(g => g.Id).Width(50).ReadOnly();
  
columns.Bound(g => g.ApplicationCategory.Name).Title("Category").Width(120);
  
columns.Bound(g => g.Name);
  
columns.Bound(g => g.Description);
  
if(Roles.IsUserInRole("Administrators"))
  
{
  
columns.Command(command =>
  
{
  
command.Edit().ButtonType(GridButtonType.ImageAndText);
  
command.Delete().ButtonType(GridButtonType.ImageAndText);
  
}).Width(190);
  
}
  
})
  
)
  
}

 

 

I used server binding data and GridEditMode.PopUp mode to insert/update the Products entry. The validation works fine to insert an new entry, for instance if I didn't input ProductName it will display error message indicating I should input a ProductName on the insert popup window. This is right. But the problem is when I edit an entry on the popup edit window! If I leave the ProductName filed blank, I won't see the error message display. And the editing window just disappeared (in fact it became a strange thing,a close image button. pleae find it in the attachment). I think maybe some java script files are not loaded properly when perform edit.

I have found you provided a demo "GridValidationSampleRazor.zip", but this demo is using Ajax binding. The Ajax bind and popup editing also works well in my project.
http://blogs.telerik.com/aspnetmvcteam/posts/11-01-20/mvc3_and_unobtrusive_validation_support_with_grid_for_asp_net_mvc.aspx
http://www.telerik.com/community/forums/preview-thread/aspnet-mvc/grid/validation-summary-with-grid-popup-editing.aspx

Could you tell me What should I do to fix this issue?? Could you send me a sample project using Server bind and popup mode to edit? Very Appreciated of you!

0
Atanas Korchev
Telerik team
answered on 23 Aug 2011, 06:28 AM
Hi Jekin,

 This is not a known problem and may be caused by a bug. We cannot reproduce it though in our server editing online demo. Please attach a runnable sample project which we can troubleshoot.

All the best,
Atanas Korchev
the Telerik team

Thank you for being the most amazing .NET community! Your unfailing support is what helps us charge forward! We'd appreciate your vote for Telerik in this year's DevProConnections Awards. We are competing in mind-blowing 20 categories and every vote counts! VOTE for Telerik NOW >>

0
Jekin
Top achievements
Rank 1
answered on 23 Aug 2011, 11:35 AM

Thanks very much for your quick reply!

Now I think the key point of my problem is whether I can use custom validation ( implement IValidatableObject()) with server bind and GridEditMode.PopUp mode or not? 
Just like the approach described in this thread: ( I know using Ajax binding works well)
http://www.telerik.com/community/forums/aspnet-mvc/grid/custom-validation-causes-edit-dialog-to-close.aspx

I attached the sample project for you to review, select any one of records, click 'edit' button and input 'Name2' you will see the case I mentioned above.

Looking foraward to your feed back ASAP. Thanks!

0
Rosen
Telerik team
answered on 23 Aug 2011, 02:05 PM
Hello Jekin,

Thank you for the sample. I was able to observe the behavior you have described. However, it is not related to the validation as it is reproducible without the validation code. It is caused the fact that there are duplicate dataKey values in the posted data which are with different  types. As there is a field named Id in the edit form as well as defined as DataKey, when the form is posted there will be two Id values, however the later will be of type string. Due to this type mismatch the edited item in the grid will never be found causing an empty window to be rendered.

In order to correct this you should set either the entity Id field as ScaffoldColumn(false) or change the name of DataKey in grid's declaration:

@(Html.Telerik().Grid(Model).Name("Grid")                 
        .DataKeys(keys => keys.Add(p => p.Id).RouteKey("MyId"))
//...

Greetings,
Rosen
the Telerik team

Thank you for being the most amazing .NET community! Your unfailing support is what helps us charge forward! We'd appreciate your vote for Telerik in this year's DevProConnections Awards. We are competing in mind-blowing 20 categories and every vote counts! VOTE for Telerik NOW >>

0
Jekin
Top achievements
Rank 1
answered on 24 Aug 2011, 04:47 AM
Wow,Great! It works!
Thanks a lot!!!
0
Rick
Top achievements
Rank 2
answered on 20 Sep 2011, 05:47 PM
I am also having an issue with server binding and popup editing when my poco object implements IValidatableObject.

I've seen two things:
1. If the data edits will fail the validation, after I press save in the popup, the grid updates to show the invalid data even though the popup remains on the screen and shows the error message. I don't think the grid should update to show the bad data.
2. The cancel link on the popup change to /controller/update instead of /controller after the data has been submitted the first time and failed validation.
I am using version 2011.2.712.

Thanks!
0
Rosen
Telerik team
answered on 21 Sep 2011, 07:48 AM
Hello Rick,

1. Grid will be bound to the data returned from the action method, therefore you should verify that you are returning the original data.

2. The URL of the buttons depends on how the View is returned. If it is returned from the Update method the URL will contain Update part. However if you set the grid DataBinding Select route it will be reset when cancel is clicked.

If you continue to experience difficulties please provide more details about your scenario and implementation.

All the best,
Rosen
the Telerik team
If you want to get updates on new releases, tips and tricks and sneak peeks at our product labs directly from the developers working on the Telerik Extensions for ASP.MET MVC, subscribe to their blog feed now
0
Rick
Top achievements
Rank 2
answered on 23 Sep 2011, 01:56 AM
Can you help me with the item #1 you mentioned above. You can see from the code that if the TryUpdateModel fails, I'm returning the view again with all the records for a user. I assume that EF 4.1 is using the modified campaign instead of reloading it from the sql server again. So, how do I get EF to ignore the changes I've made to the campaign object?
[HttpPost]
public ActionResult Update(int id)
{
    Campaign campaign = _uow.CampaignRepos.Find(id);
    if (campaign == null)
        RedirectToAction("Index", this.GridRouteValues());
 
    if (TryUpdateModel(campaign))
    {
        _uow.CampaignRepos.Update(campaign);
        _uow.Save();
        return RedirectToAction("Index", this.GridRouteValues());
    }
    else
    {
        return View("Index", _uow.CampaignRepos.AllForSubscriber(((UserIdentity)User.Identity).SubscriberID));
    }
0
Rosen
Telerik team
answered on 26 Sep 2011, 12:31 PM
Hello Rick,

Although, entity framework is outside of the scope of our components nor we are experts on this matter you may consider using DbContext Entity Reload method to refresh the state of the modified object.

Regards,
Rosen
the Telerik team
If you want to get updates on new releases, tips and tricks and sneak peeks at our product labs directly from the developers working on the Telerik Extensions for ASP.MET MVC, subscribe to their blog feed now
0
Rick
Top achievements
Rank 2
answered on 26 Sep 2011, 05:50 PM
Thank you very much for all your help.
0
peter
Top achievements
Rank 1
answered on 30 Sep 2011, 07:56 AM
Hi Rosen ,

I have a problem when try to do custom validation in mvc grid (ajax editing) popup mode that I discrible in following topic:
Grid Ajax Editing - Custom Validate problem
can you help me?
Tags
Grid
Asked by
Andrea
Top achievements
Rank 1
Answers by
Rosen
Telerik team
Jekin
Top achievements
Rank 1
Atanas Korchev
Telerik team
Rick
Top achievements
Rank 2
peter
Top achievements
Rank 1
Share this question
or