Part 1 – The LiteGridJsonResult
In the last post, I showed how we use a custom JsonResult to send data to liteGrid. Displaying data is great and all, but liteGrid supports client-side editing as well. With the BatchSaveModule, liteGrid will batch up all the client-side changes and send them to the server in one big lump. We need an easy, reusable way to process and apply those changes server-side. Thankfully we now have the LiteGridUpdater class:
public abstract class LiteGridUpdater<TModel, TTarget> where TModel : ILiteGridUpdateModel<TTarget> where TTarget : class, new() { /// <summary> /// Applies updates from the view models. /// </summary> /// <param name="models">The models containing changes.</param> /// <returns>The view models that were applied to the targets. IDs for new entities /// will be synchronized to the real objects.</returns> public TModel[] ApplyUpdates(TModel[] models) { ... } /// <summary> /// Moves the object to a new parent. /// </summary> /// <param name="model"></param> protected virtual void MoveToNewParent(TModel model) { throw new NotImplementedException("Moving items to a new parent is not supported."); } /// <summary> /// Derived classes can implement this if they want to support /// adding new items from liteGrid. Implementors must perform /// three actions: create a new TTarget; apply the updates /// from model to the new TTarget; synchronize the ID of the /// new TTarget with the model. /// </summary> /// <param name="model"></param> /// <returns></returns> protected virtual TTarget CreateAndUpdate(TModel model) { throw new NotImplementedException("Adding new items is not supported."); } /// <summary> /// Derived classes can implement this if they want to support deletes. /// If implemented, this should delete the specified target. /// </summary> /// <param name="model">The view model.</param> /// <param name="target">The object that should be deleted.</param> protected virtual void DoDelete(TModel model, TTarget target) { throw new NotImplementedException("Deleting items is not supported."); } /// <summary> /// Called before a model is updated. You can transform the /// model by overriding this method. /// </summary> /// <param name="model"></param> protected virtual void BeforeUpdateModel(TModel model) { } /// <summary> /// Implemented by derived classes, used to find the specific object /// that should be updated. /// </summary> /// <param name="model"></param> /// <returns></returns> protected abstract TTarget GetTarget(TModel model); }
This generic abstract class will take the data from liteGrid in the form of view models and apply the changes to your “backend” data types. There are only two restrictions. First, the view model must implement the ILiteGridUpdateModel interface (shown below), and the backend type must have a parameterless constructor.
The LiteGridUpdater is implemented using the Template Method Pattern. The core logic of applying the updates is implemented in LiteGridUpdater:
public TModel[] ApplyUpdates(TModel[] models) { if (models == null) { throw new ArgumentNullException("models", "No models were received by the server. Please try again."); } //First, apply any updates and moves. Note that because liteGrid sends things in order, //we are guaranteed to add a new object before we'll process anything that was added as a child //to the new object. foreach (var updatedModel in models) { BeforeUpdateModel(updatedModel); //Get the existing object or create a new one. TTarget target = GetTarget(updatedModel); if (target != null) { updatedModel.MapTo(target); } else { CreateAndUpdate(updatedModel); } //Apply any moves if (updatedModel is ILiteGridMovableModel<TTarget> && ((ILiteGridMovableModel<TTarget>)updatedModel).NewParentId.HasValue) { MoveToNewParent(updatedModel); } } //Now apply any deletes. foreach (var updateModel in models) { if (updateModel.Deleted == true) { DoDelete(updateModel, GetTarget(updateModel)); } } return models; }
Derived classes are responsible for implementing the details for how to perform the various operations, which include create a new entity, deleting an existing entity, and moving an entity (in the case of hierarchical entities). Derived classes don’t necessarily have to implement all the operations. Obviously you don’t need to worry about MoveToNewParent if your entities aren’t hierarchical. If you aren’t allowing the users to add new rows, then you don’t need to worry about implementing the CreateAndUpdate method, either. The same goes for DoDelete. The BeforeUpdateModel method is optional. You can use it to hook in and perform custom actions prior to applying updates (we use it to hook in validation). In fact, the only operation you have to implement in a derived class is GetTarget. This operation receives a view model and is responsible for locating the corresponding backend entity and returning it. In our case, this involves looking the entity up using Castle ActiveRecord, but LiteGridUpdater is not coupled to any data access strategy.
Updates to existing entities are handled by the view model. The ILiteGridUpdateModel defines a single method for performing the updates on an entity:
public interface ILiteGridUpdateModel<TTarget> { /// <summary> /// True if the model was deleted. /// </summary> bool? Deleted { get; } /// <summary> /// Maps the view model to the specified target. /// </summary> /// <param name="target"></param> void MapTo(TTarget target); }
We use AutoMapper in our concrete liteGrid view models, but you are free to implement the update logic as you see fit. Here’s a made up example for a Widget:
public class WidgetViewModel : ILiteGridUpdateModel<Widget> { public int WidgetId { get; set; } public string Name { get; set; } public string Description { get; set; } public bool? Deleted { get; set; } /// <summary> /// Configures AutoMapper mappings. /// </summary> static WidgetViewModel() { Mapper.CreateMap<WidgetViewModel, Widget>(); } /// <summary> /// Creates an uninitialized view model /// </summary> public WidgetViewModel() { } /// <summary> /// Maps the view model to the specified target. /// </summary> /// <param name="target"></param> public void MapTo(Widget target) { Mapper.Map(this, target); } }
After LiteGridUpdater applies the updates, it returns the same view models that it received. These should be pumped back to liteGrid so that it knows what changed and can update its state accordingly.
Prior to creating LiteGridUpdater, we had quite a bit of repeated, complex logic in our system for dealing with liteGrid updates. Now that we have LiteGridUpdater, we have a cleaner, more robust solution, and a lot less duplicate logic.
Again, I really need to find the time to move LiteGridUpdater as well as some of our other liteGrid infrastructure into the liteGrid project as I originally intended. Maybe someday soon I’ll find that mythical block of “free time” that everyone else seems to be enjoying.
Totally informative blog post.I’ve bookmarked it already. Cheers, Hector.
Hi everyone, This page is good and so is the way the theme was expanded. I like some of the comments as well even though I would prefer everyone stays on the subject matter to add value to the message. It will be also encouraging to the writer if we all could share it around (for many of us who use bookmarking services such as a digg, twitter,..). Thanks again.
I found this somewat useful, thank you either way, awesome post
I don’t think I’d be able to do that. But looking at this writing here makes me feel like I could do it.
Hi buddy, your blog’s theme is nice and loving it. Your blog posts are gorgeous. Please continue this awesome work. Best Regards!!
I usually don’t read too many blogs but this one is quite interesting. I’ve read every word here. I will mention this blog to friends and bookmark it to come back later to read more posts.
Thank you. Very useful post.
Thanks for sharing this helpful info!
I am thinking the same thing. Occasionally I just don’t comprehend how folk can think you’re wrong.
I normally don’t take the time to write comments however I found this page very internesting and creative. thank you for the fun read.
thank you admin for the info.
Thanks for sharing this information.
<P>There are obviously some points that we’re missing here… but overall there’s a lot of good stuff in here. If only other online resources were as good! Thx.</P><P>Regards,</P>
I was reading up on another blog similar to this one just now. It was an interesting read. This one is very good too. I will bookmark and come back later.
Hi HI First time hopped here on your site, founde on Yahoo.
I cannot believe the great information on this site
Hi HI First time jumped here on your site, founde on Google. Thank you very much. Your advice and insight is very much appreciated.
Hello everyone. Interesting topic for a blog. I have been checking out a lot of blogs and forums recently. Some are really informative some are entertaining and some are a real crack up. I’ve got to admit it, great job on this blog, I’ll be sure to check back again real soon.
Hello. Great job, if I wasn’t so busy with my school work I read your whole site. Thanks!
Have you ever considered adding additional videos to your site to keep the viewers more involved? I just read through the whole article and it was very nice but since I am more of a visual learner, I find videos to be more helpful. I like what you guys are always up too. Keep up the excellent work. I will return to your website on the regular for some new post.
This is a wonderfull article and I am happy that I stumbled onto it. I have my own blog and in my extra time I love seeing what other people have out there. Please feel free to stop by and leave a comment on my blog anytime!
Nice blog, not like some boring ones. I had a good read, Thnx! Will keep an eye out for more of your blogs.
I had to refresh the page 2 times to view this page for some reason, however, the information here was worth the wait.
This is certainly a excellent post, i’m happy I discovered it. I just wanted to let you know that I like this piece of writing so much, I would think about acquiring you a visitor article author on my site. If you’re serious you need to feel free to contact me at the e mail address I signed up with here. In case you are busy and dont make contact with me right away I understand, and will continue to check out your blog. Thanks
Great Blog I love the lay out and the color scheme is it possible to get a copy of your theme? Please send me an email at [email protected]
Hi I found your site by mistake when i was searching yahoo for this registry issue, I have to say your site is really helpful I also love the design, its amazing!. I dont have that much time to read all your post at the moment but I have bookmarked it and also signed up for your RSS feeds. I will be back in a day or two. thanks for a great site.
It’s a rare find for a nice blog like this. I enjoyed it. Kudos to you. Have a nice day!
There is obviously a lot to learn. There are some good points here.
Interesting blog. I usually like to read blogs like this one. Thanks! Have a great day.
It’s great to see some good bloggers keeping their site up, one of my other favorited website about <a href="http://newdesignerfashion.com">new fashions</a> just stop loading the other hour for no appearant reason.
Just thought you’d be interested to know that I have added your site to my bookmarks.
I’ve check out your other blog topics too and I can say you’ve got great content. Keep it going!
Nice to be visiting your blog again, it has been months for me. Well this article that i’ve been waited for so long. I need this article to complete my assignment in the college, and it has same topic with your article. Thanks, great share.
This really is a awsome page, i’m happy I recently found. I have been looking for guest writters for my blog so if you ever decide thats something you are interested in please feel free to contact me. I will be back to look at out more of your articles later!
Pretty great post, very useful information. Never believed I’d discover the info I want in this article. I have been hunting all over the web for a while now and was starting to get disappointed. Fortunately, I stumbled across your blog and got exactly what I was browsing for.
<P class=MsoNormal style="MARGIN: 0in 0in 10pt"><SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: ‘Arial’,’sans-serif’"><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p> </o:p></SPAN></P><SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: ‘Arial’,’sans-serif’"><P class=MsoNormal style="MARGIN: 0in 0in 10pt"><SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: ‘Arial’,’sans-serif’">Great thought<o:p></o:p></SPAN></P></SPAN>
Im glad I uncovered this post, I believe it. Great Work.
This is a really good read for me. Must admit that you are one of the best bloggers I ever saw. Thanks for posting this useful article.
Really new to this thing, still learning about this thing. This is a great thing that my friend recommended to me, I never getting involved with it but soon will be, thanks! 🙂
Hey, I tried to email you regarding this post but can’t seem to reach you. Please email me when get a moment. Thanks.
I love keeping up to date on everything new so i’ll definitely be bookmarking this site.
When I was I used to have this dog named that loved to play at the lake.. Most days he would want to go down to the water and play for hours. I am always looking for new places to visit on our advantures.
Awesome Posting, I have bookmarked your website and definately will be back again to see others when I have more time. Please feel free to have a look at my personal blog page as well!
Great Article, I have bookmarked your website and will eventually be back to look at others when I have more time. Please feel free to check out my personal webpage as well!
This is a good post, even though I don’t wholly agree with it. You do help to make a few good factors and im still glad I came across it.
The best way to start is to think about the things you really enjoy doing and have a passion for.
can you break it down a little better for us that don’t read English to well?
g00d info as usual here
Do you mind if I quote you on my website if I link back to your website?
lot of good information, I come here all the time and am very happy with your updates, Thank you!
Hi there. I just wanted to advise you that some elements of your website are hard to read for me, as I’m color blind. I am afflicted by protanopia, but there are other forms of color blindness that may also experience difficulties. I can understand the majority of the web site OK, and those elements I have issues with I am able to comprehend by employing a custom browser. Neverthless, it would be nice if you can bear in mind us color-blind people whilst undertaking the next website redesign. Many Thanks.
That is why they are forced to withdraw and put their degree on hold, focusing on work not on education.
amazing stuff thanx
Great post, very informative, thank you for sharing!
Took me time to read all the comments, but I really love the article. It proved to be very useful to me and I am sure to all the commenters here! It’s always nice when you can not only be informed, but also entertained! I’m sure you had fun writing this article.