Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Mike Chambers 636 posts 1253 karma points c-trib
    Sep 28, 2010 @ 13:29
    Mike Chambers
    0

    Show stopper....How does Umbraco handle concurrency violations....

    I've just run a test with concurrent users editing the same page via the admin... and am slightly worried that umbraco doesn't deal with concurrency at all...

    eg

    2 users open the same page... the first user edits and saves... the second user edits and saves. I end up with the content that the second user inputted and loose the changes from the first user...

    Eg there is no check to make sure that the content hasn't changed whilst the second user is doing their amends!!!!

    Is this the case? or have I missed a setting somewhere.....

    (umb: 4.5.2, windows 2008, iis7, .net 3.5)

  • Lee Kelleher 4026 posts 15836 karma points MVP 13x admin c-trib
    Sep 28, 2010 @ 14:05
    Lee Kelleher
    0

    Hi Mike,

    Quick question... is the second user loading the content (to edit) before the first user has saved it?

    If so, then yes it will happen exactly as you described - I believe that's how Umbraco is (currently) intended to work. There is no real-time sync/collaboration of content. (for example, like Google Docs)

    Cheers, Lee.

  • Mike Chambers 636 posts 1253 karma points c-trib
    Sep 28, 2010 @ 14:23
    Mike Chambers
    0

    yes, exactly as you have it... for a cms not to have a workflow seems a bit of an oversite and it doesn't have to be realtime... just a "this content has been updated since you loaded it, do you want to overwrite any changes with your version Y/N"

  • Jeroen Breuer 4908 posts 12265 karma points MVP 5x admin c-trib
    Sep 28, 2010 @ 14:29
    Jeroen Breuer
    1

    Maybe a nice feature for Umbraco 5?

  • Douglas Robar 3570 posts 4711 karma points MVP ∞ admin c-trib
    Sep 28, 2010 @ 14:32
    Douglas Robar
    2

    The immediate solution is to use Concierge, which adds check-in/check-out features for content.

    cheers,
    doug.

  • Matt Brailsford 4125 posts 22223 karma points MVP 9x c-trib
    Sep 28, 2010 @ 14:33
    Matt Brailsford
    0

    If both editors hit save, won't you at least have a copy in your version history?

    Granted, it's not a preventing you from overwriting, but you should at least be able to compare with the previous version and do a manual merge?

    Matt

  • Douglas Robar 3570 posts 4711 karma points MVP ∞ admin c-trib
    Sep 28, 2010 @ 14:33
    Douglas Robar
    1

    Here's a short video showing it in action... http://vimeo.com/3866212

    cheers,
    doug.

  • Peter Duncanson 430 posts 1360 karma points c-trib
    Sep 28, 2010 @ 14:45
    Peter Duncanson
    1

    Rails handles this in a nice easy manner. It has a revision number for each item (document/page/node?!?!) which gets written out into the form while you edit. When you try to save it double checks that this number is the same as the document you are about to save to. If it is then the save goes through just fine, if not then someone else has changed the item while you where editing and you have to review the changes and merge in (actually rails just throws and error you can catch and then you have to do all the hard work but you get the idea) before you can save it again.

    This way there is no need for check in/out (which if you've ever tried using in anger can be a pain in the ass) and instead 99% it all works just fine and for that 1% where there is a clash you at least get a heads up without loosing your work or (worse) over-writing someone elses with out knowing about it.

  • Mike Chambers 636 posts 1253 karma points c-trib
    Sep 28, 2010 @ 23:56
    Mike Chambers
    0

    Peter, did a search on Umbraco and Rails and didn't come up with much... am I missing something obvious?

  • Rich Green 2246 posts 4008 karma points
    Sep 29, 2010 @ 08:49
    Rich Green
    0

    Hi Mike, 

    Rails is a completely different framework, nothing to do with Umbraco and won't help you with this particular question.

    Rich

  • Peter Duncanson 430 posts 1360 karma points c-trib
    Sep 29, 2010 @ 17:41
    Peter Duncanson
    0

    Sorry for the confusion Mike. Like Rich says its a completely different framework run on a completely different language! Was just using it as an example of how other setups handle concurrency issue. Should have made that clearer. Its possible that it could be wrapped up into a package which would give this ability to your Umbraco instance. I'm sure it has been added to some of the usual suspects "possible package ideas" lists so will only be a matter of time :)

    Pete

  • Mike Chambers 636 posts 1253 karma points c-trib
    Oct 01, 2010 @ 12:14
    Mike Chambers
    2

    (umb: 4.5.2, windows vista, iis 7, .net 3.5 sp1)

    Ok, so I ended up writing something for umbraco myself, arround action handlers... (basic premise, on page load set a variable to store the UpdateDate of the document and then check the documents current updatedate against this to ensure it hasn't already changed by another user save/publish when I try to save.)

    (ps I couldn't use Document.Version as the save mechanism doesn't seem to update the document version.)  (also I noticed if you look in the audit trail for every single publish you end up with 2 items for the publish in the audit trail....)

    using System;
    using System.Collections.Generic;
    using System.Text;
    using umbraco.cms.businesslogic.web;
    using umbraco.BusinessLogic;
    using umbraco.BasePages;

    namespace UmbracoJPT
    {
        public class Concurrency : ApplicationBase
        {
            public Concurrency()
            {
                Document.BeforeSave += Document_BeforeSave;
                Document.AfterSave += Document_AfterSave;
                Document.BeforePublish += Document_BeforePublish;
                Document.AfterPublish += Document_AfterPublish;
            }
            void Document_BeforeSave(Document sender, umbraco.cms.businesslogic.SaveEventArgs e)
            {
                Log.Add(LogTypes.Custom, sender.Id, "Document_BeforeSave - concurrency");
                if (sender.UpdateDate.ToString() != mcUpdateDate.ToString())
                {
                    //System.Web.HttpContext.Current.Response.Write("CANCEL SAVE<br/>");
                    if (sender.HttpContext.CurrentHandler is BasePage)
                    {
                        ((BasePage)sender.HttpContext.CurrentHandler).ClientTools.ShowSpeechBubble(BasePage.speechBubbleIcon.error, "Concurrency Error", "Updated whilst you have been editing, please reload.");
                    }
                    e.Cancel = true;
                }
            }
            void Document_AfterSave(Document sender, umbraco.cms.businesslogic.SaveEventArgs e)
            {
                Log.Add(LogTypes.Custom, sender.Id, "Document_AfterSave - concurrency");
                mcUpdateDate = sender.UpdateDate;
            }
            void Document_BeforePublish(Document sender, umbraco.cms.businesslogic.PublishEventArgs e)
            {
                Log.Add(LogTypes.Custom, sender.Id, "Document_BeforePublish - concurrency");
                           if (sender.UpdateDate.ToString() != mcUpdateDate.ToString())
                {
                    if (sender.HttpContext.CurrentHandler is BasePage)
                    {
                        ((BasePage)sender.HttpContext.CurrentHandler).ClientTools.ShowSpeechBubble(BasePage.speechBubbleIcon.error, "Concurrency Error", "Updated whilst you have been editing, please reload.");
                    }
                    e.Cancel = true;
                }
            }
            void Document_AfterPublish(Document sender, umbraco.cms.businesslogic.PublishEventArgs e)
            {
                Log.Add(LogTypes.Custom, sender.Id, "Document_AfterPublish - concurrency");
                mcUpdateDate = sender.UpdateDate;
            }
            public DateTime mcUpdateDate
            {
                get { return (DateTime)System.Web.HttpContext.Current.Session["updateDate"]; }
                set
                {
                   System.Web.HttpContext.Current.Session.Add("updateDate", value);
                }
            }
        }
    }

    Compiled into a dll and added into the bin folder.

    And a manuall addition to \umbraco\editContent.aspx

    <%@ Import Namespace="umbraco.cms.businesslogic.web" %>
    <script language="c#" runat=server>
     protected new void Page_Load(object sender, EventArgs e)
            {
                base.Page_Load(sender, e);
                Document document = new Document(Convert.ToInt32(HttpContext.Current.Request.QueryString["id"]));
                if (!IsPostBack)
                {
                    Session.Add("updateDate", document.UpdateDate);
                }           
            }
    </script>

    It seems to work ok, apart from I'd ideally like to persist the updateDate from the pageload in the viewstate, but can't as there isn't a public accessible property on BasePage. And the fact that the e.Cancel of the AfterPublish gives an umbraco default speechbubble rather than my custom one (a 3rd party control cancelled the save) maybe I can hook it into the page validation messages instead...

    But think this could be a decent starting point, any one see any gottchas that I have stumbled into?

  • Mike Chambers 636 posts 1253 karma points c-trib
    Oct 01, 2010 @ 12:17
    Mike Chambers
    0

    one other thing I noticed with this that I have started another post on is that the BeforeSave/BeforePublish get called twice for a single save/publish click from the front end.

  • Peter Duncanson 430 posts 1360 karma points c-trib
    Oct 01, 2010 @ 13:03
    Peter Duncanson
    0

    Great work Mike, speedy too.

    Only issue I can see if is if the user's session times out, the update string in the Session will then be empty and the save will go through, or would Umbraco redirect you to the login screen and by pass the save completely? Not sure. Probably not an issue though.

  • Mike Chambers 636 posts 1253 karma points c-trib
    Oct 01, 2010 @ 13:50
    Mike Chambers
    0

    Think you/I spoke to soon... it seemingly works fine in the instance of editing a page directly... but interferes with right click publish on the nodetree, and the publish all pages from the right click content node...

    bit more work required.. for next week now...

  • Matt Brailsford 4125 posts 22223 karma points MVP 9x c-trib
    Oct 01, 2010 @ 14:00
    Matt Brailsford
    0

    Hi Mike,

    Just a suggestion (if you're concidering packaging it up), you may want to look at attaching the Page_Load functionality dynamically, rather than modifying the editContent.aspx page directly, as this will make it harder to upgrade.

    See the following code example from my Page Notifications package for an example on how to do this:

    http://pagenotifications.codeplex.com/SourceControl/changeset/view/02092bb56200#AppBase.cs

    Matt

  • Mike Chambers 636 posts 1253 karma points c-trib
    Oct 01, 2010 @ 14:23
    Mike Chambers
    0

    yep that looks like a great enhancement, thanks for that.

  • Aximili 177 posts 278 karma points
    Aug 05, 2013 @ 04:44
    Aximili
    0

    Hi, sorry to comment on an old post, but on this piece of code...

    ((BasePage)sender.HttpContext.CurrentHandler)

    I got a warning that sender.HttpContext is deprecated.
    How do you get the BasePage now to show the error bubble?

    The link posted by Matt is really good, but I'd like to show the bubble as well if possible.

Please Sign in or register to post replies

Write your reply to:

Draft