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

Popular posts from this blog

javascript - jQuery: Add class depending on URL in the best way -

caching - How to check if a url path exists in the service worker cache -

Redirect to a HTTPS version using .htaccess -