Return not found page from a filter

Topics: Customizing Orchard, General, Nederlands (Dutch), Writing modules
Jun 22, 2013 at 10:26 AM
Is it possible to return the normal not found page from a filter? I can return a new HttpNotFoundResult(), but I want to display the same page as if somebody types a wrong url.
Developer
Jun 22, 2013 at 4:42 PM
Setting the result http code to 404 should work I think but not sure.
Jun 22, 2013 at 5:12 PM
Hi Piedone, the raw result of the HttpNotFoudResult() is:

HTTP/1.1 404 Not Found
Server: ASP.NET Development Server/11.0.0.0
Date: Sat, 22 Jun 2013 16:04:03 GMT
X-AspNet-Version: 4.0.30319
X-AspNetMvc-Version: 4.0
Cache-Control: private
Content-Length: 0
Connection: Close

The user sees a white page without any information. I want Orchard to render the Not Found page for the user. Is that possible?

A part of the code in the filter:
public void OnActionExecuting(ActionExecutingContext filterContext) {
    ....
    filterContext.Result = new HttpNotFoundResult()
    return;
  }
Developer
Jun 23, 2013 at 7:20 PM
Hmm, then I'm not sure. You could take a look how the 404 page is called and try to think backwards.
Jun 23, 2013 at 8:32 PM
Edited Jun 23, 2013 at 8:33 PM
Hi,

Thank you for your tip! I have found some code in UnhandledExceptionFilter and added one line of extra code 'filterContext.HttpContext.Items[typeof(ThemeFilter)] = null;' by searching the Orchard code and trial and error :o).
  var model = _orchardServices.New.NotFound();
  var request = filterContext.RequestContext.HttpContext.Request;
  var url = request.RawUrl;

   // If the url is relative then replace with Requested path
  model.RequestedUrl = request.Url != null && request.Url.OriginalString.Contains(url) & request.Url.OriginalString != url ?
  request.Url.OriginalString : url;

  // Dont get the user stuck in a 'retry loop' by
  // allowing the Referrer to be the same as the Request
   model.ReferrerUrl = request.UrlReferrer != null &&
   request.UrlReferrer.OriginalString != model.RequestedUrl ?
   request.UrlReferrer.OriginalString : null;

   filterContext.HttpContext.Items[typeof(ThemeFilter)] = null;
 
   filterContext.Result = new ShapeResult(filterContext.Controller, model);
   filterContext.RequestContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;

   // prevent IIS 7.0 classic mode from handling the 404/500 itself
   filterContext.RequestContext.HttpContext.Response.TrySkipIisCustomErrors = true;
Thanks for your help!
Jun 23, 2013 at 9:40 PM
Almost there...

The filter must also work for dashboard requests. I want to show a not found page if the user tries to access a page in the dashboard in the normal user theme. With the code above I get the Admin theme. Is it possible to use the user theme even if the request was to the dashboard (without hardcoding the name of the theme)?
Jun 26, 2013 at 8:50 AM
I found a way to replace the admin theme with the normal theme in the filter.
//Add normal theme 
filterContext.HttpContext.Items[typeof (ThemeFilter)] = null;

//Remove Admin theme
var adminUiFilter = new DictionaryEntry();
foreach (var item in filterContext.HttpContext.Items.Cast<DictionaryEntry>().Where(item => item.Key.ToString() == "Orchard.UI.Admin.AdminFilter"))
{
    adminUiFilter = item;
}
if (!String.IsNullOrEmpty(adminUiFilter.Key.ToString())) {
    filterContext.HttpContext.Items.Remove(adminUiFilter.Key);
}