Copied to clipboard

Flag this post as spam?

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


  • Nathan Woulfe 447 posts 1664 karma points MVP 5x hq c-trib
    Jan 01, 2019 @ 11:27
    Nathan Woulfe
    0

    Passing custom message/data when a save is cancelled

    Hi all

    In v7, in a save event handler, I've previously passed info around using the AdditionalData dictionary on the IContent item being saved - I've used that to send back custom messages (or data) when the save is cancelled, and then intercepted that response in the browser to do stuff.

    In v8, that dictionary no longer exists. On the SaveEventArgs object there is an AdditionalData dictionary, but it is readonly so not much use.

    Any suggestions as to how I can port similar functionality into v8? Thinking I could use SignalR to broadcast my data from the save handler, but that wouldn't suppress the default Umbraco notification, which is half of what I need to do...

    v7 example

    public class BeforeSaveEventHandler : ApplicationEventHandler
    {
        protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
        {
            ContentService.Saving += Document_Saving;
        }
    
        /// <summary>
        /// Event Handler that gets hit before an item is Saved. 
        /// </summary>
        private static void Document_Saving(IContentService sender, SaveEventArgs<IContent> e)
        {
            IContent content = e.SavedEntities.First();
    
            // logic to determine if save should be cancelled. Let's assume it is.
    
            e.Cancel = true;
    
            // AdditionalData does not exist on the content item in v8, but is available on the SaveEventArgs object, however it is readonly
            content.AdditionalData["SaveCancelled"] = DateTime.Now;
            content.AdditionalData["CancellationReason"] = "A string for the notification";
            content.AdditionalData["MyCustomData"] = someDataToReturn;
        }
    }
    

    I then catch the response in a delegating handler, to check the additional data fields - if they exist, I delete all notifications attached to the content item, then add my own, including the MyCustomData value (it's a JSON blob for the client):

    public class WebApiHandler : DelegatingHandler
    {
        protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            if (request.RequestUri.AbsolutePath.ToLower() == "/umbraco/backoffice/umbracoapi/content/postsave")
            {
                return base.SendAsync(request, cancellationToken)
                    .ContinueWith(task =>
                    {
                        HttpResponseMessage response = task.Result;
                        try
                        {
                            HttpContent data = response.Content;
                            var content = ((ObjectContent)data).Value as ContentItemDisplay;
    
                            if (content != null && content.AdditionalData.ContainsKey("SaveCancelled") && content.AdditionalData.ContainsKey("MyCustomData"))
                            {
                                content.Notifications.Clear();
                                content.Notifications.Add(new Notification
                                {
                                    Header = "Some value,
                                    Message = JsonConvert.SerializeObject(content.AdditionalData["MyCustomData"]),
                                    NotificationType = SpeechBubbleIcon.Error
                                });
    
                            }
                        }
                        catch (Exception ex)
                        {
                            // log errors
                        }
                        return response;
    
                    }, cancellationToken);
            }
    
            return base.SendAsync(request, cancellationToken);
        }
    }
    

    Following that, I have an AngularJS interceptor bound to the postsave url, allowing me to retrieve the returned JSON from the notification.

    Have also tried storing my data in HttpContext.Current.Items, but context is null in the handler (event when trying to get it from the request properties collection).

  • Nathan Woulfe 447 posts 1664 karma points MVP 5x hq c-trib
    Jan 02, 2019 @ 10:28
    Nathan Woulfe
    0

    I've resolved this using the HttpContext to pass the data - in the handler I have to retrieve it like so:

    request.Properties.TryGetValue("MS_HttpContext", out object contextObject);
    var context = contextObject as HttpContextWrapper;
    

    Doesn't seem to work if I access it via the key directly. It's messy but it works.

    Still interested though if there's a more Umbraco way to achieve the same.

Please Sign in or register to post replies

Write your reply to:

Draft