I'm working on a package which involves generating XML feeds from Umbraco content. The feeds integrate with a third party service and they will only accept URLs with .xml file extension. Within the feed I also need to point to further Umbraco content but with .html and .mainfest extensions.
So in a nutshell I am looking for a solution so 1) Umbraco can handle requests for static file extensions. Once I have that, I need to be able to 2) get to the correct Umbraco content (e.g. using a ContentFinder). I'd like to avoid any solution involving IIS changes as it needs to be be installable as an Umbraco package.
I've looked into creating a httpmodule or handler but I'd be interested to hear anyone else's approach who has tackled this. If I go down this route, I'm not sure how I would get the Umbraco context as the requested URL will not automatically map to a node.
I have done something similar with a handler that processed .json extensions. You can create an Umbraco Context but as as you say you are not on a particular route so CurrentPage etc wont exist so you will have to create some sort of crafty way of figuring out some sort of URL. In my case I didnt need to know the path so it wasn't a big issue.
Maybe you could do it by making the URLs actual Umbraco URL's with an appended XML file and then the XML file handler could take over? So something like
I wonder if you could use Umbracos built in tools.
* URL rewriter - could you add a re-write rule to remove the .xml file extension I wonder so that it would point to the file (or at least have a go at trying to find it and fall through to a normal 404 after that). You could deploy this as a package using Package Actions to add in the additions to the config file with ease.
* Add a url alias to the content - a page can be hit via a number of different urls if you add a url alias, this is usable manually if its only a few pages but more likely you want it automated. You could have a DLL that hooks into the DocumentSaved event to add/update a alias with a .xml extension to all content. Again easily deployable and using "Vanilla Umbraco" tools and standards :)
Thanks guys, I have investigated some of the solutions and am making progress - #h5yr
@ismail - this is an interesting approach but I dont want to have to worry about file permissions as its gonna be a package.
@pete - I had considered URL rewriting but the problem is I won't know any details of the URL and I want to avoid a global .XML rewrite - again due to this being a package. I also tried url alias and indeed a URL Provider (similar to a content finder), but unfortunately when you add .xml to the URL, Umbraco will not resolve this as it is deemed a client side request - see Shannon's comment here - http://issues.umbraco.org/issue/U4-5445#comment=67-16816. Otheriwise than that your suggestion would have been a great simple solution!
@peter - this was a great suggestion and got me well along the path. I have a handler intercepting .xml requests and I can determine the node I want to display by chopping the XML part from the URL as you suggested. Currently I simply redirect to the Umbraco path. My problem is though - I only want to do this when a node is found - i.e. sitemap.xml should fall back and be processed by the default handler. I havent figured that part out yet, I'm hoping there's a way.
I'm also trying to figure out how to inject the umbraco URL's response content to my current respose (so I don't have to issue a redirect).
Thanks for your help so far any other thoughts greatly appreciated!
public class FeedXmlHandler : IHttpHandler
{
public bool IsReusable
{
get { return true; }
}
public void ProcessRequest(HttpContext httpContext)
{
// Get the equivalent Umbraco URL from the request
var originalUrl = httpContext.Request.Url.PathAndQuery;
var umbracoPath = originalUrl.Replace(".xml", string.Empty);
// We need to ensure we have an Umbraco context so we can search for our node, see
// http://issues.umbraco.org/issue/U4-5445#comment=67-16816
var httpContextWrapper = new HttpContextWrapper(httpContext);
UmbracoContext.EnsureContext(httpContextWrapper,
ApplicationContext.Current,
new WebSecurity(httpContextWrapper, ApplicationContext.Current),
true);
// Search for a matching node by path (or ID this is passed in the original request)
var node = UmbracoContext.Current.ContentCache.GetByRoute(umbracoPath);
if (node != null)
{
// Return the content of the Umbraco route
httpContext.Server.TransferRequest(umbracoPath);
}
else
{
// Serve static content TODO - can I just pass this back to the default Http Handler?:
Type type = typeof(HttpApplication).Assembly.GetType("System.Web.StaticFileHandler", true);
IHttpHandler handler = (IHttpHandler)Activator.CreateInstance(type, true);
handler.ProcessRequest(httpContext);
}
}
Now I have the requst transferring to my Umbraco node (if it exists), and if not the request is passed back to the static file handler. I would like to pass the request back to a more generic handler, so it can be processed correctly even if its not a static file. Perhaps I am doing this wrong, and I need to look at a httpModule? Anyway thanks for you help so far, I'm 95% of the way there with this I think. Hope this can be of assistance to others.
Handling static file extensions to find content
Hi guys,
I'm working on a package which involves generating XML feeds from Umbraco content. The feeds integrate with a third party service and they will only accept URLs with .xml file extension. Within the feed I also need to point to further Umbraco content but with .html and .mainfest extensions.
So in a nutshell I am looking for a solution so 1) Umbraco can handle requests for static file extensions. Once I have that, I need to be able to 2) get to the correct Umbraco content (e.g. using a ContentFinder). I'd like to avoid any solution involving IIS changes as it needs to be be installable as an Umbraco package.
I've looked into creating a httpmodule or handler but I'd be interested to hear anyone else's approach who has tackled this. If I go down this route, I'm not sure how I would get the Umbraco context as the requested URL will not automatically map to a node.
Barry,
Not sure if this helps but there is uStaticPublish package source code here https://github.com/PetrSnobelt/UmbracoStaticPublish although that is for umbraco html pages.
Regards
Ismail
Hey Barry
I have done something similar with a handler that processed .json extensions. You can create an Umbraco Context but as as you say you are not on a particular route so CurrentPage etc wont exist so you will have to create some sort of crafty way of figuring out some sort of URL. In my case I didnt need to know the path so it wasn't a big issue.
Maybe you could do it by making the URLs actual Umbraco URL's with an appended XML file and then the XML file handler could take over? So something like
And then in your handler figure out the Umbraco route using the part of the URI before the data.xml (or whatever you want to call it)
Sorry there's no code.. But maybe the thought might help you figure out a way. Be interested to see how you tackle it.
Peter
I wonder if you could use Umbracos built in tools.
* URL rewriter - could you add a re-write rule to remove the .xml file extension I wonder so that it would point to the file (or at least have a go at trying to find it and fall through to a normal 404 after that). You could deploy this as a package using Package Actions to add in the additions to the config file with ease.
* Add a url alias to the content - a page can be hit via a number of different urls if you add a url alias, this is usable manually if its only a few pages but more likely you want it automated. You could have a DLL that hooks into the DocumentSaved event to add/update a alias with a .xml extension to all content. Again easily deployable and using "Vanilla Umbraco" tools and standards :)
Simplest solutions often the best.
Pete
Thanks guys, I have investigated some of the solutions and am making progress - #h5yr
@ismail - this is an interesting approach but I dont want to have to worry about file permissions as its gonna be a package.
@pete - I had considered URL rewriting but the problem is I won't know any details of the URL and I want to avoid a global .XML rewrite - again due to this being a package. I also tried url alias and indeed a URL Provider (similar to a content finder), but unfortunately when you add .xml to the URL, Umbraco will not resolve this as it is deemed a client side request - see Shannon's comment here - http://issues.umbraco.org/issue/U4-5445#comment=67-16816. Otheriwise than that your suggestion would have been a great simple solution!
@peter - this was a great suggestion and got me well along the path. I have a handler intercepting .xml requests and I can determine the node I want to display by chopping the XML part from the URL as you suggested. Currently I simply redirect to the Umbraco path. My problem is though - I only want to do this when a node is found - i.e. sitemap.xml should fall back and be processed by the default handler. I havent figured that part out yet, I'm hoping there's a way.
I'm also trying to figure out how to inject the umbraco URL's response content to my current respose (so I don't have to issue a redirect).
Thanks for your help so far any other thoughts greatly appreciated!
Further update, here is my handler code:
Now I have the requst transferring to my Umbraco node (if it exists), and if not the request is passed back to the static file handler. I would like to pass the request back to a more generic handler, so it can be processed correctly even if its not a static file. Perhaps I am doing this wrong, and I need to look at a httpModule? Anyway thanks for you help so far, I'm 95% of the way there with this I think. Hope this can be of assistance to others.
is working on a reply...