From 0a585b91dafdeb3362ebbc585b34e0258394e0a8 Mon Sep 17 00:00:00 2001 From: kjac Date: Wed, 8 Oct 2025 14:52:33 +0200 Subject: [PATCH 1/8] Rerwite the "Additional preview environments support" article and correct URL provider references --- ...additional-preview-environments-support.md | 113 ++++++++++++++++-- .../images/external-preview-option.png | Bin 0 -> 13816 bytes .../request-pipeline/outbound-pipeline.md | 9 ++ 3 files changed, 115 insertions(+), 7 deletions(-) create mode 100644 17/umbraco-cms/reference/content-delivery-api/images/external-preview-option.png diff --git a/17/umbraco-cms/reference/content-delivery-api/additional-preview-environments-support.md b/17/umbraco-cms/reference/content-delivery-api/additional-preview-environments-support.md index 5982899349b..1978c417789 100644 --- a/17/umbraco-cms/reference/content-delivery-api/additional-preview-environments-support.md +++ b/17/umbraco-cms/reference/content-delivery-api/additional-preview-environments-support.md @@ -5,21 +5,120 @@ description: >- # Additional preview environments support -{% hint style="warning" %} -The original contents of this article, explaining how to change the backoffice UI, does not apply anymore to Umbraco 15 and above and has been removed. -The way to achieve this beyond Umbraco 14 is to create and register an [Extension](../../customizing/extending-overview) to modify the backoffice UI preview button. -{% endhint %} - With Umbraco, you can save and preview draft content before going live. The preview feature allows you to visualize how a page will look like once it is published, directly from within the backoffice. This is also possible for the Content Delivery API data. You can extend the preview functionality in the backoffice by configuring external preview URLs for client libraries consuming the Content Delivery API. {% hint style="info" %} To get introduced to the preview functionality in the Content Delivery API, please refer to the [Preview concept](https://docs.umbraco.com/umbraco-cms/reference/content-delivery-api#preview) section. {% endhint %} +Generating external preview URLs for the backoffice requires implementation both client- and server-side. + +## Server-side implementation + +On the server-side you'll need a custom `IUrlProvider` implementation. This is responsible for generating the preview URL for a given piece of content. + +An external preview environment likely requires some kind of authentication to allow preview. The URL provider should perform this as well. + +Here's an example of what a URL provider could look like: + +{% code title="MyUrlProvider.cs" lineNumbers="true" %} +```csharp +using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models.PublishedContent; +using Umbraco.Cms.Core.Routing; + +namespace My.Site; + +public class MyUrlProvider : IUrlProvider +{ + public string Alias => "MyUrlProvider"; + + public UrlInfo? GetUrl(IPublishedContent content, UrlMode mode, string? culture, Uri current) + => null; + + public IEnumerable GetOtherUrls(int id, Uri current) + => []; + + public async Task GetPreviewUrlAsync(IContent content, string? culture, string? segment) + { + var token = await GetPreviewTokenAsync(); + return new UrlInfo( + url: new Uri($"https://my.preview.environment/?id={content.Key}&culture={culture}&token={token}"), + provider: Alias, + culture: culture, + message: null, + isExternal: true); + } + + private async Task GetPreviewTokenAsync() + { + // this is where you'll perform auth against the external preview environment and return an auth token + } +} +``` +{% endcode %} + +The URL provider must be registered with Umbraco. This is done with a composer: + +{% code title="MyUrlProvider.cs" lineNumbers="true" %} +```csharp +using Umbraco.Cms.Core.Composing; + +namespace My.Site; + +public class MyUrlProviderComposer : IComposer +{ + public void Compose(IUmbracoBuilder builder) + => builder.AddUrlProvider(); +} +``` +{% endcode %} + +## Client-side implementation + +On the client-side you'll need an extension of: + +- Type: `workspaceActionMenuItem`. +- Kind: `previewOption`. + {% hint style="info" %} -Support for configuring additional preview environments in the Content Delivery API was introduced in version 12.3. +You can read more about extensions in the [Extending the Umbraco Backoffice](https://docs.umbraco.com/welcome/getting-started/developing-websites-with-umbraco/extending-the-umbraco-backoffice) article. {% endhint %} +Here's a sample extension: + +```json +{ + "name": "My UrlProvider", + "alias": "My.UrlProvider", + "extensions": [ + { + "type": "workspaceActionMenuItem", + "kind": "previewOption", + "alias": "My.PreviewOption", + "name": "My Preview Option", + "forWorkspaceActions": "Umb.WorkspaceAction.Document.SaveAndPreview", + "weight": 99, + "meta": { + "icon": "icon-umbraco", + "label": "My preview option", + "urlProviderAlias": "MyUrlProvider" + } + } + ] +} +``` + +This extension works with the URL provider above, because the `urlProviderAlias` of the extension matches the `Alias` of the URL provider. + +Save the extension as `umbraco-package.json` in a folder under `App_Plugins` and (re)start the site. The result is a new preview option in a pop-up over the "Save and preview" button: + +![External preview options in a pop-up over the "Save and preview" button](images/external-preview-option.png) + {% hint style="info" %} -An upcoming release of Umbraco will allow users to configure custom preview URLs directly in the backoffice. +The default "Save and preview" button is also an extension of this type. + +In other words, multiple preview options can co-exist. If you have multiple external environments, you can create preview options for all of them. + +The extension `weight` determines the order of appearance. A `weight` above 100 will swap the default preview option with the custom one. {% endhint %} diff --git a/17/umbraco-cms/reference/content-delivery-api/images/external-preview-option.png b/17/umbraco-cms/reference/content-delivery-api/images/external-preview-option.png new file mode 100644 index 0000000000000000000000000000000000000000..7843053e0aa6847b926a2e5ca30a10ac7f1da64e GIT binary patch literal 13816 zcmaKTWmsE5*DbUZw?ZjU+^x8Kp|}<(R;+lDpvAR7(c(^UFYX>F?ob>Og1bA#@8NyF z`#ty9{gLD(IcH{{*=w!6XV09lPb#ul=8B<)qXR5MD?C$BwAT!29H?8x!z> z=&UX)iBK^{x(j?kvXoE;&Zv&YxHog{V|R49!tLal1Idv~qSylAo30Fwv-_ z)Pkp{F9KkW&TV9OxRL^{tszZz*N;KCxgw5Cpfl=j3&}+f=>CybB}5Ny2((d4?Hq8> zoWXBM)pO`vI%i?k@LDo7{7+0=oW(V^4is!^)rc>-!*W=qDc`^%uSXSBjQZUxK;bM( z{f=#V;V=kyY|7Ad%+O}6;p0*pDit#oIFr)SK47fQxiAv9OK|LBa&eGP5>@TBPJH%S z+*_~9t2IxBNv+VKVp_D&yoRVfhg@<77%G*NhlQMqic3oB4jr2(=g&MLs-AMkgp{3` z-QG9PCq3IL+$tZ#mpV}ai}+2T%^u`X)+E(q2;r+R(4LQA2`?p-3_UB8!^>CJPq+*S zcyV@q?gE>SU?QDCqY7tcyZKwHZNkRJHfs(NK5T)cbg5g*gu(GzMK)}u}A|mo9?#=IAI==r}6~s7>IXL)Rx}ERi?kS?2ynN^A zXd<-!!O_{d)`}sB(Q9&Q^5(E{`Q-F>RO>%jZK1f(>Ia{;?2#?vr=-qh?Ddm=jA;wOawwP0Kb{WBQfz0-g}?dV1}Tn`7+Jb zaq-LfM6!ha63U6)kU>>j&=|acP4tTMP zhLhYUVxmT>2 zEUKEsZ?RVsS7_B;OO(xs=xT-p^x_Q^Y2S`Da|{~$7hHjE-db%T5wIz;$KY-nt#YIY z=}xEuK5@W(#@NV7KZW1h6#Immjjc3sIw4_UaC$nale6X)h%kCr#_GH)WZ zwN=>8&aSDs`317RzJ8feSf00FN$1xpU9G7KmV@4(xVdHAwDj}@Z;HiKY5Dn+fvy#) z6O=XWkMZavUcGuXU1^ln(<22+jI1{8=kmI;ZU481K}}6Ry6)flNH@mfGZ1 zRIq)0eVbZZtV==p1qA^1c0a>vn308TK3sMF3m{^2|cUbAy#u0WHTk2 zQ(6&t>T%h>MwD#u%y`~8y14Yt%*>=AFv&;roldk{C(r!X#M%+GNw4n>-@A>gtE&NX zYfSsGYieo^k``($U!Gh{sm3QJ_Qul47OUkUBM1r#ra|_+9xmt5P*GPR*xUbVE&N-L z7Dq)x%Q0wmy+7@zfbKc1NAfRadtD!u=~PSVY1(aUZJj+_FFQZnx`6*3EYzZ5V60E6 zir0rl=$W>cffyw9tj$6dQPp-AyhYn4Y4R6I6`kYTJTI9MM#21ZS__xM>>YpeWO0t# z@9Z)?wunJ4)mtN}>m1Fx4YtJMPxrNa`bQ!+8}TBiJ^0TrXo=JM?d5*kAekE-C4sqDBqPp2|%B-0U^#WUe50iu~c{8X>YxIvweSa9uyp` z-s%c+J(!mO2C`n66cDKOwcd#LdJRf?uaX{~_KlvX1q5{TG>80-8ER=6B7Neo&xF^N1YlD0dE?ak7tTb7pnyx z!W!4Nw`JG+A{8$}I2aj2pYh=Lcux%x1z_^tu#JeFojn+b0y}9nC0gt@v~kHZqOOhy zd^I>Y*mko8wwnOxoVeJX67;#{DN@N;Td>Tc6A(yA<+hBAi+hpeL3F+~Y6@!r zrHgtcJwDt`b@=%K*h2gBTce1G(*&urv-1}bXMjeL3Zlc-2ytH&*>KLs5ZfrU6F?!k zd~Uz1tE&sR9uNUG(uj#IeaT8qmH+(t4HXqtP*4yq0fDrI1wBHR&y{ZM^7**kxwE9Lq27Xg8v zpa1^;-u>>d@#gXFSkvnV2-Z;TerocL*V+ufKW+uUZa}h;Z|ZiYS5y?4@MNo-{nmKa zc(z2KoT4HPz-CsxhLhD03NDA04{K{{KzN~IUu5%(B)s~dn)C0pC~!fr=(NyWvCfa;WW zo6(7G{rU0oSw8?SZ^GS{%{K;O`L=7gYLhRD1)u2>K6J)<7PU;3BqblxUB|`E-Rydp z#&;0Y(IJjcuk;mgF{yw9!u$Br?Xe6+04pAQzl&_4*8oY9SoO{TOzJ*;vaqnI@xF0t zaXnN3&HzD6fnZf_GskA=xl6a?b8R5@_|LTc;YzRl?nu}MoFVM?48OJY^#zC*|L*SY zFB1N!!FUF4zejImOrk$}_K@D`-x{g>_T&g3gE5Wot`6_dhS_HydiwgD_NJMTamdT= zkj79by#Ev^CjZ+jtt8^JB??5rv3R(>yuaPAw1qW9&X((G0FE#*HSIhLu>+X0=yePs z6?Xk)00kBm*>TfIz_EmY`S~VF);EpOSRgb9`DS6L3BGd zsiFa#AYu6Oajy${t5e*HEn=6>T2XNiV$w}4G)XYp`p)$C}>)P(cix=Of3bFJW?Rw3)0POlz z`91jpw;5GbR8%j!xzZU(gozAo0F{bj0pk{S677+fyhBW ze^xtfD#XRd%gf2F+#Po?P*Y1@bN`r}nrimG;R0l~cEPegicHY^A4lXn-mcNnNZ*Is z*Mx-q#~n{&fcG689jSPD64(q{svOs4oSdAV4LO9?=NUpgq1`cQX+zD<+u`>r2-l0w zI966xv~+X}Ju??$s*ZM-DY<_Sn+k#KBDcmvNGZpF9c?pO%c_x`k&*E%WL!5x$R$@b zOY9e^U|dQHk)hv%3moYMAX@-gIQ(~ZzG0II^`!CI5OJA>DznST3wWB8+QC~smw!nF zu;BD~?*Xo{949|&Jr=`6ehKho3t$((r5f|$w{2~02fj`XfDk=CJ_3*=T-d%j-%jN) ze&Jv5whc&!?Ly5@p#4v^7Rt9*hr>YDAmFn11_g(lmWSu_bsJ0nM0|XFw}Bh{XJut& zLkX(vw(PzunMQ)XRV6TAVT?Y&4pAE-F#+>|92^~u0X{uPH##dxcd-p{+ zoLImi`{*R9>njI`_dkdIDRm&l=KH8KcDtEu^o-+jy~bHBU0$16Ol@uLD00z~@|uY@ z4`%>%ia^A&nX91V;hDDMTG`)MEY&IxjfkjKNto5BG!%t4+K-oLmd!+~VCnRvEDGXjXSH9mK)OP>4Xc!`3}Tew6-0~qXW+3@lya*vJI z0NnZmUSWLq;+uZQZ>My91P9VDoIqqOr#+ngI6B4odK*GOC!aN`!~3x* zu)4acl)~`?xZ9Z6*v@Bk!R$Lm0iKn|dmjU7At3DYEiNno7T0%+vSyElhJazSo#z0M z*OS6&8X6tVKtmJgb9XfX@p9v{U&2hvZ2tTA(|#K;bEQPEo-LCHvft3~@HK!vg@Agc z(WDS#A{%<2N&||V%4v!m78aJGM4y|R3!L;EwD`ilIBxgP%_Sck*kY554D3!7x!`xl z0Rv-s{6%XGsttnRN`5v=D(ViW7lU5LxdX|ffZLINY~|3v(9jy>dMVHIa!-0qS64Sb zKmVB>;K3?7a}J{C{4+B%6Iw!@AjsX`-VVU|gI;;5Vlo>LO0j?h=}V)XGQ7n_x81wB z+n5K4?-t{kqrebWYO;XE~Sv@=ifne39vet7IAUDZ6Xg7}d$kr%W z(Dz>8$B!SMD-AO;MZG4=bh*LCb$~!UCkhAE{l%K4NxVy?+Uy9o7rW~x-u2cq;XuRZ zK%i6u;N$J>odQtdITQoox7tc?@y2SYO)w`X2S^2if#z$0Xbm5~U>f9<-kn$U2PT3w z9QqK?a!U5``_10~iZ?bkblN}gMl3Gs-VkL@7YTr&L`c< z*XX(I{H1EJT~I$TJ@ssZKr(J$Rsc>sIX`bLN5l0mD%vKK$4eJg`43j+j3H^Y{coan zFaM!aNttgsm|PrknfCpn{%E8iuc*j!iNdlJ4$L!i^YX0VExbTVHK&E4MzupH>d6U| zIeuYwJo%PWia%A7VdG0K>JB-~k8ZpX5&1)yRNlPUqtwxI$N0JT{Y^az6sk88DgMdRd;(1yLu1t2|ICLm?0JskLTgseL z{<*M2#auuwALAi6;{WRxnwq1a@Wr96@UwnlhTxDf4UCV=-jrnnP6Q^JgJWZTD<;_! zKGzdFk1|l83S*u!XtvhXjG^D;{@TsW?UxMAe>4ru~-`W>iIeFh(6YizwVx3o0nN@W~i{{w@OJVEPEPdKa_2_+Ng zUd6(@_%Nz#i0ju zn4W{dd=hF&Gibj`OG__z**C2?%q8p86OaZB@yw0|_OuUc(w^@*K{L3nu8vw%0!k~l zOFT3RU)m@-dz|N*>=0;T|D|}o~+}fInZylyt_E*dfM6{Bo^jjciiph02t5XrW7`LSbrnBn3sX@&O6C7uXAm z0n>NWdO)2576DWubuHyoRoNMJ^Wl$n+*N=bTFr?3=VWs9{W{zd@pMF?>Qxp}K%fS7;pRVjrN+*f# z6bi~NXxg$bf$)>QD$B$WPYvUVe+Manx_EEXjj-4L8xvA+ZPa3|OrMK^a zu$XWQ*ymK-rZfmw<(qmbc`V42yG&Xer1?5{WJGB{o$^oG&NqB=7xjE)|BE=P%TiZe zdxOv+CHB(^JuL=?z1$=C1pUXorZ^-fw3xvJ1G5g#O5hH>9F2#krbPIMW1mQ&efxU3 z1Ic%JxQ!b}CB90#q=vTCW*n(Xv$S#^Gi)qj(Jcb;_x}MUmDGfpBslaNKBf6W@8n^r zvg-js0m#B4>GI1otWl`qKTvD{Dpkemy&5D96V3}fyNGyed{%(vD6*q-!62P@%J+~D zdqHv;s8;bbE@$zT=igImDtu@9e&YVD8w@f$%WJd7r=lZPzrHAr@FX!8Wo6A9@Vzhu zy#Eu@#5e?N4d*jUjE$E*$1z&Hp5BKtQ%NxuDC?DCEpVhL6~6e422>g+6oaS3qJ;)0 z6x}aOJohD0?;vc@e88jcS;8V~%2d4ThKCwJ%UC4UE~@4&rI$LWPHa(}tSFy#r+!LL}J>8!P%#`6Lr8$LO*5 zTs?=!+Ms$`hL^$Jb;F+fS0=gc|Ft&*NlhtW{h&0@ToxdsFr=r;&?#5h@WSxY1h{q8 zm}gu89gzN~gVK3gMh1p{A=2Ossp6(4NJ^Ta(rU3vXn1iGtz@MkyKZyhTwUESYED)N z5%yXar+h$AQ*F9JKvjIto9n%Unxz(8$t=TwoMeRG$@P_)79P?%i}q%BrK0P z!G?V14ar!q0<_d9m%&haKm{GeY}l;E#%)2U2D_Eyl>*8S_XBX zV>9_XE7rW0%fiETb`BAzH=;t9g;tIHI#(L24EtJbaoxQJdb)lW!72s|jM}+HTxR!3 zw`1a(`4u7rhfn*B=TBY`n;FBA31B?Z@`TEJ0-ez^FGa}m2)XX}e_}>w%B_^eiq!67 z4nq6Zu)lSdZRZKR<_r&Gl|;3F+x0gpZ=SUISNDV03i(gsfm}3;7N;C3}5B96LN`ZW0QR*J<*;$X6uO zy}K8?`Yql;GvZ{cIttiL?yGuqA&O9}o{V^hpEfri>|UUZePii08th%dQfn=P43+>) zN>on+cU&2qkujl|%*QUrXfKmV2>Yq(>x-PC9rTn{@}FgiX+|_u%Ds9?^nJ~|fM;(s zWP)U>r3(;X?=@_ZSYV+0tK0 zv;%$4IO2V4RdQ{=qB^{r>TH9%6U=4#l_BcTmKrU}h=jUaN0-6JOIfju2i432u^`bMmV%>q!b@4h)9hme3w<%333O9Wy@k$6m-pYJd`@4pV-rh;P(5ux*nR1FJ9etm zg)0yPS4sB^{dx+Gu*{xXqJNqi<$S!>c0cX*x&IBfzv6ZEE?ydUQ9}05?SF5#tX+cv zduTp(F7&;i@!MMd+JA5=GVwr=l-@AS@HC<@JpQ;bAFbd!_IMvlH?>`(vXIs3-x<@L z2vQ^#cOoLYjkavN-4<+&NKMMpg^X($jhOG9WesXkFq~V8X+FX3qlbW`S*rr-KbT-1 zxoaSN*CF1sO4AQAiK@`NY)Ny4|3^hswOpe-Iuq=KFU&7$GVl{z0}5;kCmoOE0=A>_ z*ZU_9l(@AGmbepFnrU`hl+U%Pp3oI@W$;AY*!EdL_^RcW(`8x!XM&u<7{d$hfuigXTlNIqA`H^!o3hpLf{W_QIUu4<*K3gea`^ zR_Z(q$d~VHK$H1`BO20(Ck^nq3I<71Ou@Hs)sL6Qf>y-aMw7xJGKL4@A?Nt4AempA z())rePli^oWIE%#F!z6seB%6M_Ui^v`bH%;0VUnJrLXn;nh;Nr9;j?2$%6IUwr66& zIF9LF!*G7d;~y5fyAT}rwrg53K_8seby-})2TKc)J7DE(^DD>V=mWW9nUB{iFc+w? zwaOM7qv3}i&CB5XVQ--(_EnaODc_TC79z_5(**2OPAArE-|*iSMcMrM+SG|-qgDIw za8N|-f<@^N<IZgd!E{%)!q7kSOy}hJ&pPQPx7qq?7o=c9ZlK z*$q}5MbEIYrr^^l54oQmulD=Hnz2Lk!`y4G zOwYmsd#7#m(Pq}SyXrN*$N3>ngub5VTmkp~UXy6l-T_+0GLe5-tuxxA1DoR7SWHT( z)dkE`XbjxB5pUU)Zl5ak0Q1beai9`b{?y^2w^sz;a6b^51%HNR!2bxN@ynOJm6Ej= zXtkm4G?J=)EF>I#$3xF?O|8fmRd`*&QWDABN@P+A#@EOSeogA>g1zqL@>q?FMzTo5FX?F>E9VESk9$#coTwx zO@BacB%(AIIzG@>WP#Baq-?B~ZOxq+_S#to+VCo})Fbt!o#AxFa(wS<-VUa}aHfo# zw{>t;u^*ABcjU@ilw~4iO(B=)|7KMrMIsd?yRS{CR-|VdG1alR?a!jk0p+< z)|5ZNI$p86V&+A9)}~R7*toKbv2A5lUWrnT)MVD4foxkjmUhJwrpuJB422|yTdvQQ zd%l-=E-pz8q#+q^Bma(E(3^WJ>tbFry*rv)5a>QYlgV2tI-ZB)R`d`WJ%3sn_l@Yp z_Kq~G3_gN0OzqL2&2Q-LM?OUX8B62kG$X-W6yLETAB^}<+-LmkS5IDxvJrzLaQ|h$q7= z8OAL~n?B6nV8P-??wU^qU(D)bm@Os`r#wmWdtOlV+*ewhcfq3`AtQHUetEB0_}crM zs50DL54>!3=CPvjDL9XX6@@WlY9g?dHU@A?{~6CQ7k(G$4^X3UY~Kdky8Gc8Lxd(w z2cD`AyY14muF=3;8N!yxfruPB`1J>%TH;d|tUgwwkp!xYorzMC^~c(j!FpFt(*;3H zL(uNb=${)nik$kDhdYH0YQEYBOp|A$26v=l#lh+OC!FPal91|Zc}~Jb^E~VCj7T^&-w(X_fij`e_6gxp`U2t zitfjq77L2xM6;bt@-~c9M_stv`P9U#w*Nl!R+mWteVe#*RMdcF992uhcGf})=4Lm4cZY)VAP z8kPV@ovC*O4-$kq@@{hyKu_7&B z86}3dPey_nO=b?22yeb7-lV@e6j7^ zdKz-s~=BCmre;-)YG`uc0XVS58J{#2!!eiq_14! z;@;EI#9)KI!f+g=edz)5=lF`S$BWg|AIAf%yX?W|5aeiP%z%h6lnK$!fldATmcQhN zWv$(v_I2m&$|Hl2bBFb^ShQOqio@Q4xgusZK6g=Lx9q}^$$J>v$K){yGnNjUNf&hr zYl+r2B42@n5kZ!FV$39}R#9P7$|}~w(%)moaj}JmBq#ez0u@9eI};Fm(kSC-Iz*8w z5K0iF&�g#?G=#&|~D6`M%xGWGQzhbomCG5U7NSeYxO^cCqS@Mu~pSdEmmur3~1t zRk<)CZaLE5U&LIRM>vr`_`nC-GjQweCG91M+6&*7o-2Cl-c0V}hFDQvMt<U|$Pzwb8_MAX|ljs@!tpHHR1R^<^8LueCOLmp(wAU8$s0DiGCAIhY>DCtZlzMeyz1HMDkdlic}y(lSz@A zmvZk!3;LL~RnOW0yCS=%B@fX)U10LJZLo)7K#)%xg%CQNk1(tJIDJs0p$XTjGdWi9 zcY7HNPVV}aJ*mu@$-;y?oj)3FPMO=J+(rw|A~Bx)@B%eBelG{M zuwAV+f@L%Ke%-=gr0F$rfsijLS?G5l{{6W3Sd(luPQ$|AGlb)Axu0Z8iAHg?)^RgA zUv%_V?b4f(MH@SdP5b3DkQuBfWY3ZBC5g(W3fxueCzCT9|6%ZV zmg3xeUwR#7GA4{R@%!UF5difL;v@j+=hH5WY|OBtXFdfTD`P z-f5%poTqduMir&ax)x-$FoIU&X8Qh!-lozp2c%&at}1-%hS1G^n$Axo_u$G0(rfQ) z`}gjGls8h@=)LjQdJ@A(A_#hAY!+B5RUXyt0OB5QbU$CjEhx&NzkK=UuMJ*xt2QAM ziIMuHcX2p(e|`E6HSEh1_u@y0%ufhY1L&Y9VuAldxe)K@@KE(M$a?uBYxc69wBOu3 zT+#i8N>Mmud*uF{;1QGev=Sru59;jOg>CDGjwxclK*T_8!dtgMQN61;pZCEt-;4Yd zUj`?^(XOGxM>;QMJH-8SK*G?6=#Z}IUifIFAA73wbp_S^#gx@j<|UP{Z~H8g9L#W7 zEu%|~talMZVLam&M9%QW-*zCREM5^clRtJ2+bGX1;r6;Tixn=&7cXt67Iy6tw~9F}dfZ^+3)?3;{}UCO zbP^SoB6LPdVfJJRqqhDfMTWYWd~?f5w_c?vqgJU$(Cyz%>L;FFI6_40ptb#EZz9+F zp8VQ~cI8mkeHua?dM*=#hu@k7ks!D}9_26Hj-B;Pi9|g$oEhh2v8vF_uR2w={V}-7 z8oq0vF?fY=DCE)oNYk^qU}v6H+s`@%pSD3D73v({b69ezNVHh$nV`8xsPp=V2vW|W zXWh}oY8Q1-*UMYoNw*@ln#*A#74O2q_OqiA^>hh<%ep^-5C2w@L?ir7czkGEXmUX` z^2v~CT>||sfL~xw7-A?mx;dLpgxH_;;74oJYGG;lJXTVRen3BLh!TKpxi+;~B9kST zZ^xKpqkov~#V38?(4357EjgmvDnAl}2q8T2sBFLRr42LvPT@nt>tk<{uvZGm!t^Gk+J zRgMTl{l3KHzOyw^g^{e2+xk(6b0Nw7kCq zSx&o6q<7_9kqk&Kv*BksL^EZmEC1R-OnVBQ|;^9`aMI-M)o>x5Li2uYJPA{VW zK}17AmeJoz%i@%G>+Y`IyR;#t<;;n|8dz5l$|+GJ&2^{lIl zNX4L8WpY7hEAn0EMK>=h#R8dM;OnftnD47)n~qnccn$6SW#uV%YM<}U{hUxmF~v_F z{l;)l^zFYC??G`WhCXU*a~@o>3%anPd~_8;W9TqG(|D~EH323%JaDYvPf9^l#0f_c zMRDz3A98xMHzY-qpObIF>t|qxbTVis@?D{)8@2eW`nIVwbbh${X&*`o3C|CaIa451 zBspINH9C7G#ImErT?~>)$z;(nO?`0P(^M%p`mk(>F`wtDFgzj1O*BHWqceZy(PcyS z^{lG*KoG0~IRCe$X(~T+zz>#+FEEb=kZSAwsCUha%%j(4k&QcWvS{Uf-Pl{k2gy-U z-KU7PP;e>B(-)46a&WTa)5DftitF9l)ej5sn!r>a(?a#gvR^%`mtE6N|~keqS&l`YNtQN_sku2dO4$xF5PUm(o7wcSL8%JlYNF? zp$f;%8pQP$XqDw2Ar;5iR1Qa3UF>;3f`Zcdy0LElN-Nt_gv9Q zy2|QWeeD_TLZ}jRb^4uOHFT*2Q@r=&7V#Vj4*ikW#ASgPV)W(Ds&?Lj__r7PU9$6H za5JD3nng4``3S@)3kRm)ZaiHd!A=oJ;T5K(Qcsx$gR6AfwGZ9mQv2b-{sk8}Xecw-z#^81HSL_Hu&VA! zXVwLW>q%I@kts^^)I7P*q~{117jI)m8n z7U~)>l3Eu@v7}c#TSWpE7V&FH8lCFgN{F9o!T9=v)s*Fn2<+LFpTz`iut8KLuCqf4 z9_Sq#4nNvzJN*L@0W6d5ct^>(bTX{yt}r(7UC)3-nx!NOrU`tma^i7=`u02eX8Vfa zck+8GhP23yOKc(gKt-oT6L%4@sKnT4Co${y8NwGu${o`B5jucL?G?pp-*C4rf~ROX zg6JVjo2^2D|L$v1kKAS&>NM@=@fuWd)=q@k|8A|~rqy8#nM)d*f(a*5l8&Q0-~gk6pk?6oANv+xTsoU2o16_M<)wiPB}7+9|qxN zA|65OeIH~l$;MC8R#x>0{RsbX`+uX3Cv9n(-3(obTdke_^Xs>U{;BKu^_@4tFQJ(z4EPn>`b5TGT#RAW8{Q%5Eg=E zQ<|Ad22Sz~`0X8dDF##-mg467EmNKzl!^IA@Mos%9JmQ7GfD|KZ`=Z?#Kk*4zqB#G zQ~YGFJR2!KcvdXI3qST9q~DCT6}fLaWu!-B)Y5wAXGZ*6Q>0fp-HIdxkb?J(cu@bdhyUsrk?Pt3Z+{PKMm zPt1E81)sE_%1W8-jhhjgwUd)M;e_N+DQ5nV_k?a>cP&?Ja+#U&{HZNh77U|o^vCbM z#hhZq9aXDwV-%ZSUvQ7W-O=KDTaSz3&tH53XDr#QZNkqm=->az_?H!>lUdU8%C|FU z=0{fgEt!m?`xnMYdCT#uoC`6Hkp{XOLB$K_ofF{fZ1h32J)FAth#g;ryvQx1_kP!G zVFk*!=ihpKhkmB*_4#4_JDyUMK#;SfjYmF)5#LVsEcfxPhofaeB(2>1B&`HW-DR!_ z3mcjflk!}%DD=o1LLKzC2%<%rIN1U`Y?Es;*qM+K$OJoEkk3`;e6#a?c?a0VyqRJ+ z8K0DtgB8}1a`C)QNC3mn$D%xb`?L7dhR|C{RG$|480g_%FrnmqecfD%eyt?xs!p|h zOwyvxPe#3sv^SEWlT40y`G4DC(=3vqdU=q-i*R5A$>c-^5o=KKKQohy3^4tMa@M5khYpLfdVZTj0GjeGm …; + public virtual UrlInfo GetUrl(IPublishedContent content, UrlMode mode, string? culture, Uri current) {…} public virtual IEnumerable GetOtherUrls(int id, Uri current) {…} + + public virtual Task GetPreviewUrlAsync(IContent content, string? culture, string? segment) + {…} } ``` @@ -199,6 +204,10 @@ public interface IUrlProvider UrlInfo? GetUrl(IPublishedContent content, UrlMode mode, string? culture, Uri current); IEnumerable GetOtherUrls(int id, Uri current); + + Task GetPreviewUrlAsync(IContent content, string? culture, string? segment); + + public string Alias { get; } } ``` From 25f93483cbbd702a282915611aea2b9736bff8ab Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Thu, 9 Oct 2025 09:46:16 +0200 Subject: [PATCH 2/8] Update 17/umbraco-cms/reference/content-delivery-api/additional-preview-environments-support.md --- .../additional-preview-environments-support.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/17/umbraco-cms/reference/content-delivery-api/additional-preview-environments-support.md b/17/umbraco-cms/reference/content-delivery-api/additional-preview-environments-support.md index 1978c417789..3fe76d838c7 100644 --- a/17/umbraco-cms/reference/content-delivery-api/additional-preview-environments-support.md +++ b/17/umbraco-cms/reference/content-delivery-api/additional-preview-environments-support.md @@ -5,7 +5,7 @@ description: >- # Additional preview environments support -With Umbraco, you can save and preview draft content before going live. The preview feature allows you to visualize how a page will look like once it is published, directly from within the backoffice. This is also possible for the Content Delivery API data. You can extend the preview functionality in the backoffice by configuring external preview URLs for client libraries consuming the Content Delivery API. +With Umbraco, you can save and preview draft content before going live. The preview feature allows you to visualize how a page will look once it is published, directly from within the backoffice. This is also possible for the Content Delivery API data. You can extend the preview functionality in the backoffice by configuring external preview URLs for client libraries consuming the Content Delivery API. {% hint style="info" %} To get introduced to the preview functionality in the Content Delivery API, please refer to the [Preview concept](https://docs.umbraco.com/umbraco-cms/reference/content-delivery-api#preview) section. From c2a6cd0b0cd3b6ece8e0503f4584da951f17f87d Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Thu, 9 Oct 2025 09:46:27 +0200 Subject: [PATCH 3/8] Update 17/umbraco-cms/reference/content-delivery-api/additional-preview-environments-support.md --- .../additional-preview-environments-support.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/17/umbraco-cms/reference/content-delivery-api/additional-preview-environments-support.md b/17/umbraco-cms/reference/content-delivery-api/additional-preview-environments-support.md index 3fe76d838c7..3b9583cd75e 100644 --- a/17/umbraco-cms/reference/content-delivery-api/additional-preview-environments-support.md +++ b/17/umbraco-cms/reference/content-delivery-api/additional-preview-environments-support.md @@ -8,7 +8,7 @@ description: >- With Umbraco, you can save and preview draft content before going live. The preview feature allows you to visualize how a page will look once it is published, directly from within the backoffice. This is also possible for the Content Delivery API data. You can extend the preview functionality in the backoffice by configuring external preview URLs for client libraries consuming the Content Delivery API. {% hint style="info" %} -To get introduced to the preview functionality in the Content Delivery API, please refer to the [Preview concept](https://docs.umbraco.com/umbraco-cms/reference/content-delivery-api#preview) section. +To learn more about the preview functionality in the Content Delivery API, see the [Preview concept](https://docs.umbraco.com/umbraco-cms/reference/content-delivery-api#preview) section. {% endhint %} Generating external preview URLs for the backoffice requires implementation both client- and server-side. From a15d9c6a9fe4e126b1f7bae58595b2e2e1dc3234 Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Thu, 9 Oct 2025 09:46:34 +0200 Subject: [PATCH 4/8] Update 17/umbraco-cms/reference/content-delivery-api/additional-preview-environments-support.md --- .../additional-preview-environments-support.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/17/umbraco-cms/reference/content-delivery-api/additional-preview-environments-support.md b/17/umbraco-cms/reference/content-delivery-api/additional-preview-environments-support.md index 3b9583cd75e..756a8d445f1 100644 --- a/17/umbraco-cms/reference/content-delivery-api/additional-preview-environments-support.md +++ b/17/umbraco-cms/reference/content-delivery-api/additional-preview-environments-support.md @@ -11,7 +11,7 @@ With Umbraco, you can save and preview draft content before going live. The prev To learn more about the preview functionality in the Content Delivery API, see the [Preview concept](https://docs.umbraco.com/umbraco-cms/reference/content-delivery-api#preview) section. {% endhint %} -Generating external preview URLs for the backoffice requires implementation both client- and server-side. +Generating external preview URLs for the backoffice requires implementation on both the client and server sides. ## Server-side implementation From 1c4f3ae6945d991988ba1cc5faa0457d20acc17e Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Thu, 9 Oct 2025 09:46:42 +0200 Subject: [PATCH 5/8] Update 17/umbraco-cms/reference/content-delivery-api/additional-preview-environments-support.md --- .../additional-preview-environments-support.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/17/umbraco-cms/reference/content-delivery-api/additional-preview-environments-support.md b/17/umbraco-cms/reference/content-delivery-api/additional-preview-environments-support.md index 756a8d445f1..7240cfd1ed4 100644 --- a/17/umbraco-cms/reference/content-delivery-api/additional-preview-environments-support.md +++ b/17/umbraco-cms/reference/content-delivery-api/additional-preview-environments-support.md @@ -15,7 +15,7 @@ Generating external preview URLs for the backoffice requires implementation on b ## Server-side implementation -On the server-side you'll need a custom `IUrlProvider` implementation. This is responsible for generating the preview URL for a given piece of content. +On the server-side, you'll need a custom `IUrlProvider` implementation. This is responsible for generating the preview URL for a given piece of content. An external preview environment likely requires some kind of authentication to allow preview. The URL provider should perform this as well. From c524ef6fb4340a040604548759546092f059cb55 Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Thu, 9 Oct 2025 09:46:49 +0200 Subject: [PATCH 6/8] Update 17/umbraco-cms/reference/content-delivery-api/additional-preview-environments-support.md --- .../additional-preview-environments-support.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/17/umbraco-cms/reference/content-delivery-api/additional-preview-environments-support.md b/17/umbraco-cms/reference/content-delivery-api/additional-preview-environments-support.md index 7240cfd1ed4..1b65243cc27 100644 --- a/17/umbraco-cms/reference/content-delivery-api/additional-preview-environments-support.md +++ b/17/umbraco-cms/reference/content-delivery-api/additional-preview-environments-support.md @@ -58,7 +58,7 @@ public class MyUrlProvider : IUrlProvider ``` {% endcode %} -The URL provider must be registered with Umbraco. This is done with a composer: +The URL provider must be registered with Umbraco using a composer: {% code title="MyUrlProvider.cs" lineNumbers="true" %} ```csharp From 21739d4f4f4831261725e6fe0a0a4459f2a735c7 Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Thu, 9 Oct 2025 09:46:56 +0200 Subject: [PATCH 7/8] Update 17/umbraco-cms/reference/content-delivery-api/additional-preview-environments-support.md --- .../additional-preview-environments-support.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/17/umbraco-cms/reference/content-delivery-api/additional-preview-environments-support.md b/17/umbraco-cms/reference/content-delivery-api/additional-preview-environments-support.md index 1b65243cc27..53ebdf4ee6b 100644 --- a/17/umbraco-cms/reference/content-delivery-api/additional-preview-environments-support.md +++ b/17/umbraco-cms/reference/content-delivery-api/additional-preview-environments-support.md @@ -76,7 +76,7 @@ public class MyUrlProviderComposer : IComposer ## Client-side implementation -On the client-side you'll need an extension of: +On the client side, you'll need an extension of: - Type: `workspaceActionMenuItem`. - Kind: `previewOption`. From 1fd400476da44077ebd2c7105cdc089ca07e30cb Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Thu, 9 Oct 2025 09:47:04 +0200 Subject: [PATCH 8/8] Update 17/umbraco-cms/reference/content-delivery-api/additional-preview-environments-support.md --- .../additional-preview-environments-support.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/17/umbraco-cms/reference/content-delivery-api/additional-preview-environments-support.md b/17/umbraco-cms/reference/content-delivery-api/additional-preview-environments-support.md index 53ebdf4ee6b..cd22ac1bbe4 100644 --- a/17/umbraco-cms/reference/content-delivery-api/additional-preview-environments-support.md +++ b/17/umbraco-cms/reference/content-delivery-api/additional-preview-environments-support.md @@ -109,7 +109,7 @@ Here's a sample extension: } ``` -This extension works with the URL provider above, because the `urlProviderAlias` of the extension matches the `Alias` of the URL provider. +This extension works with the URL provider above because the `urlProviderAlias` of the extension matches the `Alias` of the URL provider. Save the extension as `umbraco-package.json` in a folder under `App_Plugins` and (re)start the site. The result is a new preview option in a pop-up over the "Save and preview" button: