I have a requirement from a client to externally access items in the media library, using a virtual 'perma-link'.
They know the media-item's name and its library folder-path, but don't know the library index or the current URL for the item - as obviously both may be constantly changing with each revision to the media item, depending on the content editor's updates.
So, the idea is for them to request a 'virtual' perma-link - based on a virtual folder, the item's library folder-path, and the item's name - and have a custom route intercept the request, route to a controller, which then works out the current media-item URL, and rewrites/redirects the request so it resolves to the current version of the requested media item.
e.g. request: .../docs/<item-path>/<item-name> ==> [controller-search-and-redirect] ==> .../media/<index>/<item-file.ext>
However, obviously, the library item-path can be a variable level of folders deep so the request might vary:
eg .../docs/folder-1/some-pdf-document
or .../docs/folder-1/folder-2/folder-3/another-pdf-document
If I can create a custom route for all requests starting with the virtual folder /docs to a custom controller, where I can parse the request, then recursively searching for the folder-path/name of an item is something I've done often enough before. It's not high-performant, but fortunately this is a relatively low volume request.
However, the part I'm a little bit stuck on is how to create a custom route for .../docs/... to a controller that actions it, given that the requesting URL will vary depending on the folder-path location of the item.
Every example I've seen assumes a fixed structure URL with parameterized segments.
I seen another post recently by Lee Kelleher that used this approach (thanks Lee).
I'd be interested to know if this works for you
using Umbraco.Cms.Web.Common.Controllers;
public class DocsController : UmbracoApiController
{
[HttpGet("docs/{*path}")]
public IActionResult GetDocument(string path)
{
// Put your code here
}
}
I'm not sure if an ApiController would be applicable to this situation. I would have thought an ApiController would be expecting to return either JSON, HTML or similar, not redirect/rewrite to another URL. Would you happen to have the thread reference so I can read the full context and see if it might be useful?
My initial thoughts were to declare and initialize a Custom Route, so that any request that starts with my nominated virtual folder e.g. .../docs/* or whatever I specify - gets routed to a dedicated controller that handles the request.
However, I'm unsure how to set up such a custom route, given the variable request URL.
[HttpGet]
public IActionResult Sitemap()
{
if (_umbracoContextAccessor.TryGetUmbracoContext(out var umbracoContext))
{
IPublishedContent rootNode = umbracoContext.Content.GetAtRoot().FirstOrDefault();
Thanks again for your time and input, but I don't think that's a solution I can use for this Umbraco-8 application.
I suspect that the requirement is to use this type of construct from the documentation - but the part that confuses me is the {action}/{id} of the path, and what my options for specifying the path are, as I'm basically interested in routing any request for /docs/* to MyDocsController
RouteTable.Routes.MapRoute("MyDocs", "Docs/{action}/{id}",
new
{
controller = "MyDocsController",
action = "Index",
id = UrlParameter.Optional
});
The issue had more to do with knowing the specifics of MVC Routing than Umbraco per-se, even though I'm using MapUmbracoRoute
Just required configuring the route to use a WildCard, and the trick there is knowing that syntax - something like:
RouteTable.Routes.MapUmbracoRoute(
"customRoute1",
"docs/{*path}",
new
{
controller = "MyDocs",
action = "Index"
},
new MyCustomContentFinder(),
null,
new string[] { "My", "Custom", "Controllers" }
);
That will route requests of the form .../docs/* to MyDocsController, with the option of finding Umbraco content to pass as a model. I also used the namespace array argument to configure that for the controller.
namespace My.Custom.Controllers
{
public class MyDocsController : Umbraco.Web.Mvc.RenderMvcController
{
public override ActionResult Index(RenderModel model)
{
// do stuff
return Redirect("somewhere");
}
}
}
Creating a Custom Route to Media Library
I have a requirement from a client to externally access items in the media library, using a virtual 'perma-link'.
They know the media-item's name and its library folder-path, but don't know the library index or the current URL for the item - as obviously both may be constantly changing with each revision to the media item, depending on the content editor's updates.
So, the idea is for them to request a 'virtual' perma-link - based on a virtual folder, the item's library folder-path, and the item's name - and have a custom route intercept the request, route to a controller, which then works out the current media-item URL, and rewrites/redirects the request so it resolves to the current version of the requested media item.
e.g.
request: .../docs/<item-path>/<item-name> ==> [controller-search-and-redirect] ==> .../media/<index>/<item-file.ext>
However, obviously, the library item-path can be a variable level of folders deep so the request might vary:
eg
.../docs/folder-1/some-pdf-document
or
.../docs/folder-1/folder-2/folder-3/another-pdf-document
If I can create a custom route for all requests starting with the virtual folder /docs to a custom controller, where I can parse the request, then recursively searching for the folder-path/name of an item is something I've done often enough before. It's not high-performant, but fortunately this is a relatively low volume request.
However, the part I'm a little bit stuck on is how to create a custom route for .../docs/... to a controller that actions it, given that the requesting URL will vary depending on the folder-path location of the item.
Every example I've seen assumes a fixed structure URL with parameterized segments.
Any and all help appreciated.
I seen another post recently by Lee Kelleher that used this approach (thanks Lee).
I'd be interested to know if this works for you
Hi, thanks for the response.
I'm not sure if an ApiController would be applicable to this situation. I would have thought an ApiController would be expecting to return either JSON, HTML or similar, not redirect/rewrite to another URL. Would you happen to have the thread reference so I can read the full context and see if it might be useful?
My initial thoughts were to declare and initialize a Custom Route, so that any request that starts with my nominated virtual folder e.g. .../docs/* or whatever I specify - gets routed to a dedicated controller that handles the request.
However, I'm unsure how to set up such a custom route, given the variable request URL.
You're right that approach won't work. Try this:
Alter Startup.cs Configure method, under .WidthEndpoints add something like this (u.EndpointRouteBuilder.MapControllerRoute...):
Add the sitemap controller, which looks like this: { public class SitemapController : UmbracoPageController, IVirtualPageController
ICompositeViewEngine compositeViewEngine, IUmbracoContextAccessor umbracoContextAccessor, IPublishedValueFallback publishedValueFallback) : base(logger, compositeViewEngine) { _umbracoContextAccessor = umbracoContextAccessor; _publishedValueFallback = publishedValueFallback; }
Thanks again for your time and input, but I don't think that's a solution I can use for this Umbraco-8 application.
I suspect that the requirement is to use this type of construct from the documentation - but the part that confuses me is the {action}/{id} of the path, and what my options for specifying the path are, as I'm basically interested in routing any request for /docs/* to MyDocsController
Ok, I got this figured out and working.
The issue had more to do with knowing the specifics of MVC Routing than Umbraco per-se, even though I'm using MapUmbracoRoute
Just required configuring the route to use a WildCard, and the trick there is knowing that syntax - something like:
That will route requests of the form .../docs/* to MyDocsController, with the option of finding Umbraco content to pass as a model. I also used the namespace array argument to configure that for the controller.
is working on a reply...