U4-2670 - Add event to modify the model before being sent to render

Created by Shannon Deminick 21 Aug 2013, 02:51:22 Updated by Mads Rasmussen 03 Feb 2016, 10:31:02

Is duplicated by: U4-5103

Relates to: U4-5065

Relates to: U4-7036

Relates to: U4-2671

Is required for: U4-2671

This allows people to modify how things are displayed and add security (i.e. change a property editor to label so it's readonly for certain users)

Comments

Jeroen Breuer 25 Mar 2014, 08:56:56

Will something like in this topic also become possible with if this feature is added? http://our.umbraco.org/forum/developers/api-questions/47509-U7-Belle-Customize-the-behavior-of-the-content-view#comment170351


Jeroen Breuer 18 Jun 2014, 07:35:45

Looks like U4-5103 will also be possible once this feature is implemented.


Jeroen Breuer 23 Jul 2014, 08:19:28

This is already possible in Umbraco 7.1. With the following code you can change the media picker start node: public class WebApiHandler : System.Net.Http.DelegatingHandler { protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { if (request.RequestUri.AbsolutePath.ToLower() == "/umbraco/backoffice/umbracoapi/content/getbyid") { return base.SendAsync(request, cancellationToken) .ContinueWith(task => { var response = task.Result; try {
var data = response.Content; var content = ((ObjectContent)(data)).Value as ContentItemDisplay; var mediaPicker = content.Properties.FirstOrDefault(x => x.Alias == "testImage"); if (mediaPicker != null) { if (mediaPicker.Config.ContainsKey("startNodeId")) { mediaPicker.Config["startNodeId"] = "1080"; } else { mediaPicker.Config.Add("startNodeId", "1080"); } } } catch(Exception ex) { LogHelper.Error("Could not change the media picker start node.", ex); } return response; }); }

    return base.SendAsync(request, cancellationToken);
}

}

You can register this code in the ApplicationStarting event: System.Web.Http.GlobalConfiguration.Configuration.MessageHandlers.Add(new WebApiHandler()); For 7.2 it will probably become easier, but this is good workaround for now :).


Shannon Deminick 23 Jul 2014, 15:39:59

Good hack :)


Jeroen Breuer 24 Jul 2014, 12:15:36

More examples: https://gist.github.com/dannydrogt/7450807e81e552704d71 https://gist.github.com/neehouse/cd290386e5bca8c5feb7


Jeroen Breuer 30 Jul 2014, 08:47:36

Example with Archetype: http://our.umbraco.org/projects/backoffice-extensions/archetype/sound-off!/55077-Change-Archetype-prevalues-dynamically?p=0#comment189856


Jeroen Breuer 30 Jul 2014, 12:43:41

In the examples I posted I show how easy it is to change the media picker start node, but for Archetype it already get's a bit harder because I'm missing some info in the web api method: https://github.com/imulus/Archetype/issues/187

Since 7.2 will have the Grid datatype which can also have media pickers it might be nice to test if we can also change those media picker start nodes (or other prevalues) with this event to modify the model.


Jeroen Breuer 07 Oct 2014, 10:53:07

Fully working example with the Hybrid Framework: https://github.com/jbreuer/Hybrid-Framework-for-Umbraco-v7-Best-Practises/blob/master/Umbraco.Extensions/Utilities/WebApiHandler.cs


Jeroen Breuer 09 Jun 2015, 11:07:05

This isn't done yet and it's currently unclear in what version it will be released. Just had a quick talk with Shannon and for now the above examples with the WebApiHandler is the only solution. It's a bit hacky, but still works.


Shannon Deminick 27 Jan 2016, 12:19:30

This is all working now. Here's a (terrible) example. This will change the first tab's label and it's first properties property editor to a 'Label' (readonly).

There are three events on the EditorModelEventManager: SendingContentModel, SendingMediaModel and SendingMemberModel

public class EventStuff : ApplicationEventHandler
    {
        protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
        {
            EditorModelEventManager.SendingContentModel += (sender, e) =>
            {
                e.Model.Tabs.First().Label = "DUH";
                e.Model.Tabs.First().Properties.First().View = "readonlyvalue";
            };
        }
    }


Shannon Deminick 27 Jan 2016, 12:20:29

PR for review: https://github.com/umbraco/Umbraco-CMS/pull/1063


Mads Rasmussen 28 Jan 2016, 08:49:28

I get this ysod in the media section now when opening a folder or media item.

The best overloaded method match for 'Umbraco.Web.Editors.EditorModelEventArgs<Umbraco.Web.Models.ContentEditing.ContentItemDisplay>.EditorModelEventArgs(Umbraco.Web.Models.ContentEditing.ContentItemDisplay, Umbraco.Web.UmbracoContext)' has some invalid arguments
at CallSite.Target(Closure , CallSite , Type , Object , UmbracoContext )
   at System.Dynamic.UpdateDelegates.UpdateAndExecute3[T0,T1,T2,TRet](CallSite site, T0 arg0, T1 arg1, T2 arg2)
   at Umbraco.Web.WebApi.Filters.OutgoingEditorModelEventAttribute.OnActionExecuted(HttpActionExecutedContext actionExecutedContext) in \\psf\Home\Documents\test\Umbraco-CMS\src\Umbraco.Web\WebApi\Filters\OutgoingEditorModelEventAttribute.cs:line 29
   at System.Web.Http.Filters.ActionFilterAttribute.OnActionExecutedAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken)
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.Http.Filters.ActionFilterAttribute.<ExecuteActionFilterAsyncCore>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.Http.Filters.ActionFilterAttribute.<ExecuteActionFilterAsyncCore>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.Http.Filters.ActionFilterAttribute.<ExecuteActionFilterAsyncCore>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.Http.Filters.ActionFilterAttribute.<ExecuteActionFilterAsyncCore>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.Http.Filters.AuthorizationFilterAttribute.<ExecuteAuthorizationFilterAsyncCore>d__2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.Http.Filters.AuthorizationFilterAttribute.<ExecuteAuthorizationFilterAsyncCore>d__2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()


Shannon Deminick 03 Feb 2016, 10:22:02

Fixed in rev: 5d5c6ed33a5973bebad4e924bdfca35f593a3384

@madsrasmussen i'll close this but can you quickly re-test with latest dev-v7 branch?


Mads Rasmussen 03 Feb 2016, 10:31:02

Tested and it works


Priority: Task - Pri 1

Type: Task

State: Fixed

Assignee:

Difficulty: Normal

Category:

Backwards Compatible: True

Fix Submitted:

Affected versions:

Due in version: 7.4.0

Sprint: Sprint 8

Story Points:

Cycle: