c# - Errors when trying to use custom route in Umbraco 7 to generate sitemap.xml -
i building umbraco 7 site , have created sitemap document type renders xml sitemap in razor view.
this works fine , runs url /sitemap/.
i trying use custom routing make sitemap available @ /sitemap.xml. following various online advice i've created implementation of iapplicationeventhandler
following method:
public void onapplicationinitialized(umbracoapplicationbase umbracoapplication, applicationcontext applicationcontext) { //custom route routetable.routes.mapumbracoroute( "sitemap", "sitemap.xml", new { controller = "xmlsitemap" }, new xmlsitemaproutehandler()); }
the xmlsitemaproutehandler
implements umbracovirtualnoderoutehandler
, overrides following method:
protected override ipublishedcontent findcontent(requestcontext requestcontext, umbracocontext umbracocontext) { var umbracohelper = new umbracohelper(umbracocontext); return umbracohelper.typedcontent(_sitemapnodeid); }
for have simple controller associated:
public class xmlsitemapcontroller : rendermvccontroller { public override actionresult index(rendermodel model) { return this.currenttemplate(model); } }
when load /sitemap.xml in browser following exception:
value cannot null. parameter name: umbracocontext
this @ line var umbracohelper = new umbracohelper(umbracocontext);
. same when use umbracocontext.current
in place of umbracocontext
.
it seems umbracocontext not being created. application uses dependency injection (structuremap) , specify binding umbracocontext:
for<umbraco.web.umbracocontext>().use(() => umbraco.web.umbracocontext.current);
i wondered if related .xml extension tried changing custom route url "sitemapxml". when load url following exception:
the routedata must contain item named 'action' non-empty string value.
i did find advice here suggests it's possible use umbracocontext.ensurecontext
in such cases, i've tried updating route handler method following:
protected override ipublishedcontent findcontent(requestcontext requestcontext, umbracocontext umbracocontext) { var httpbase = new system.web.httpcontextwrapper(system.web.httpcontext.current); umbracocontext.ensurecontext( httpbase, umbraco.core.applicationcontext.current, new umbraco.web.security.websecurity(httpbase, umbraco.core.applicationcontext.current), true); var umbracohelper = new umbracohelper(umbracocontext.current); return umbracohelper.typedcontent(1090); }
although code reporting ensurecontext method obsolete @ least see umbracocontext.current valid reference. however, still exception, time:
object reference not set instance of object.
this thrown umbraco assembly @ umbraco.web.mvc.umbracovirtualnoderoutehandler.gethttphandler(requestcontext requestcontext)
.
so i'm stuck. had thought relatively easy provide custom route this. perhaps i'm taking wrong approach entirely. advice appreciated.
had same problem , looked bit further. problem appears in umbracovirtualnoderoutehandler.gethttphandler(requestcontext requestcontext)
because umbracocontext.current
null needed create publishedcontentrequest
. don't think can solve inherit umbracovirtualnoderoutehandler
.
my solution implement iroutehandler instead , take code umbraco.web:
public class xmlsitemaproutehandler : iroutehandler { public ihttphandler gethttphandler(requestcontext requestcontext) { umbracocontext current = umbracocontext.current; if (current == null) { var httpbase = new system.web.httpcontextwrapper(system.web.httpcontext.current); current = umbracocontext.ensurecontext( httpbase, applicationcontext.current, new websecurity(httpbase, applicationcontext.current), umbracoconfig.for.umbracosettings(), urlproviderresolver.current.providers, false); } ipublishedcontent publishedcontent = this.findcontent(requestcontext, current); if (publishedcontent == null) { return new notfoundhandler(); } uri originalrequesturl = requestcontext.httpcontext.request.url; uri cleanedumbracourl = uriutility.uritoumbraco(originalrequesturl); current.publishedcontentrequest = new publishedcontentrequest(cleanedumbracourl, current.routingcontext, umbracoconfig.for.umbracosettings().webrouting, (string s) => roles.provider.getrolesforuser(s)) { publishedcontent = publishedcontent }; this.preparepublishedcontentrequest(current.publishedcontentrequest); rendermodel value = new rendermodel(current.publishedcontentrequest.publishedcontent, current.publishedcontentrequest.culture); requestcontext.routedata.datatokens.add("umbraco", value); requestcontext.routedata.datatokens.add("umbraco-doc-request", current.publishedcontentrequest); requestcontext.routedata.datatokens.add("umbraco-context", current); requestcontext.routedata.datatokens.add("umbraco-custom-route", true); return new mvchandler(requestcontext); } protected ipublishedcontent findcontent(requestcontext requestcontext, umbracocontext umbracocontext) { var umbracohelper = new umbracohelper(umbracocontext); return umbracohelper.typedcontent(_sitemapnodeid); } protected virtual void preparepublishedcontentrequest(publishedcontentrequest publishedcontentrequest) { publishedcontentrequest.prepare(); } }
you need custom route-extension:
public static route mapxmlsitemaproute(this routecollection routes, string name, string url, object defaults, xmlsitemaproutehandler virtualnodehandler, object constraints = null, string[] namespaces = null) { route route = routes.maproute(name, url, defaults, constraints, namespaces); route.routehandler = virtualnodehandler; return route; }
you can create route in implementation of iapplicationeventhandler
:
routetable.routes.mapxmlsitemaproute( "sitemap", "sitemap.xml", new { controller = "xmlsitemap", action = "index" }, new xmlsitemaproutehandler());
Comments
Post a Comment