locked
HttpModule: driving me crazy RRS feed

  • Question

  • User1715503494 posted

    Hi,

    I have a simple class for handling a request named UrlRewrite.vb, that implements IHttpModule.
    For testing i've made it simple with only the two modules that where implementend:
     

    App_Code Folder

    1    Namespace MyRequestHandler
    2    Public Class UrlRewrite
    3       Implements IHttpModule
    4 Public Sub Init(ByVal context As System.Web.HttpApplication) Implements System.Web.IHttpModule.Init 5 AddHandler context.BeginRequest, AddressOf context_BeginRequest 6 End Sub 7 8 Private Sub context_BeginRequest(ByVal sender As Object, ByVal e As EventArgs) 9 Dim context As HttpContext = CType(sender, HttpApplication).Context 10 context.RewritePath("~/Default.aspx") 11 End Sub 12 13 Private Sub Dispose() Implements System.Web.IHttpModule.Dispose 14 End Sub 15 16 End Class 17 End Namespace
     

    Than i registered this class in the web.config HttpModules section as follows:

    <httpModules>
    <
    add name="Rewriter" type="MyRequestHandler.UrlRewrite"/>
    <
    add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
    </
    httpModules>

     So now i assume that every request will be rewritten to ~/Default.aspx, wel this is not the case.
    I only get the 404 page telling me that the resource i'm looking for was not found or HTTP Error 404.0 - Not Found
    I don't think the module even gets executed at all.

    Do i need to set something on server level, or extra's in the web.config or .......... i don't know
    Does someone know a solution(s) for my problem? Thanks for your help.

    Dries M


     

     
    Tuesday, January 6, 2009 9:05 AM

Answers

  • User1715503494 posted

    Using your code above...

    Namespace MyRequestHandler
    Public Class UrlRewrite
    	Implements IHttpModule
    
    	Public Sub Init(ByVal context As System.Web.HttpApplication) Implements System.Web.IHttpModule.Init
    		AddHandler context.BeginRequest, AddressOf context_BeginRequest
    	End Sub
    
    	Private Sub context_BeginRequest(ByVal sender As Object, ByVal e As EventArgs)
    		Dim context As HttpContext = CType(sender, HttpApplication).Context
    		If Not System.IO.File.Exists(context.Request.PhysicalPath) Then
    			context.RewritePath("~/Default.aspx")
    		End If
    	End Sub
    
    	Private Sub Dispose() Implements System.Web.IHttpModule.Dispose
    	End Sub
    
    End Class
    End Namespace

    This works like a charm.
    I was looking into rebaseClientPath, what was looking very promising and simple, but that didn't work neider.
    So Sweeperq thanks for you effort and patience.
    Your solution works great.

    One more question, is this going to work for all resoures e.g. javascript, flash, ....etc.

    Thanks again

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, January 6, 2009 3:03 PM

All replies

  • User1696511887 posted

    Are you testing on your local IIS or in Visual Studio?  The reason I ask is that IIS will only rewrite pages that are assigned to the aspnet_isapi.dll by default (.aspx, .asmx, etc.)  You'll need to create mappings for other file types.

    Tuesday, January 6, 2009 10:39 AM
  • User1696511887 posted

    Also, if you are writing your own Url Rewrite module, be sure to rewrite back to the original Url in the Page PreRender.  Otherwise your forms will post back to the ugly urls.  I'm not sure of the VB syntax, but hopefully this gives you the idea:

     

    public class UrlRewrite : IHttpModule
    {
    	private string _OriginalUrl;
    	private string _OriginalQs;
    
    	public void Init(HttpApplication app)
    	{
    		app.BeginRequest += new EventHandler(UrlRewrite_BeginRequest);
    		app.PreRequestHandlerExecute += new EventHandler(UrlRewrite_PreRequestHandlerExecute);
    	}
    
    	private void UrlRewrite_BeginRequest(object sender, EventArgs evt)
    	{
    		HttpApplication app = (HttpApplication)sender;
    		if (app != null)
    		{
    			if (!System.IO.File.Exists(app.Context.Request.PhysicalPath))
    			{
    				string MappedUrl = Helpers.GetRewriteMapping(app.Context.Request.Path);	// I have a helper function outside of the module so I can modify my url rewrites
    				if (!String.IsNullOrEmpty(MappedUrl))
    				{
    					_OriginalUrl = "~" + app.Context.Request.Url.PathAndQuery;
    					_OriginalQs = app.Context.Request.QueryString.ToString();
    					if (String.IsNullOrEmpty(_OriginalQs))
    						HttpContext.Current.RewritePath(MappedUrl);
    					else
    						HttpContext.Current.RewritePath(MappedUrl.Contains("?") ? MappedUrl + "&" + _OriginalQs : MappedUrl + "?" + _OriginalQs);
    				}
    			}
    		}
    	}
    
    	private void UrlRewrite_PreRequestHandlerExecute(object sender, EventArgs evt)
    	{
    		HttpApplication app = (HttpApplication)sender;
    		if (app != null)
    		{
    			if ((app.Context.CurrentHandler is Page) && app.Context.CurrentHandler != null)
    			{
    				Page page = (Page)app.Context.CurrentHandler;
    				page.PreRender += new EventHandler(Page_PreRender);
    			}
    		}
    	}
    
    	private void Page_PreRender(object sender, EventArgs evt)
    	{
    		if (!string.IsNullOrEmpty(_OriginalUrl))
    			HttpContext.Current.RewritePath(_OriginalUrl);
    	}
    
    	public void Dispose()
    	{
    	}
    }
     
    Tuesday, January 6, 2009 10:48 AM
  • User1715503494 posted

    Hi,

    Thanks for the quick response.
    Actually i'm trying to rewrite extensionless on IIS 7.0. Rewriting with extension e.g. pageA.aspx to pageB.aspx works fine.
    But when i try to write extensionless e.g.  /pageA to pageB.aspx i get an 404 error.
    I understood it was possible in IIS 7.0 to rewrite extensionless, but so far i'm not able to accomplish this.

    Is there a setting in the web.config or IIS itself that will do the trick??
    I know there is an UrlRewrite.net dll but i rather not use foreign assemblies exept my own. So therefore i would be nice to do some exentsionless url rewriting in my own HttpModule.

    Thanks
    Dries M

    Tuesday, January 6, 2009 11:10 AM
  • User1696511887 posted

    Add runAllManagedModulesForAllRequests="true" to your modules tag in the <system.webServer> section. Link to reference.

    Tuesday, January 6, 2009 11:26 AM
  • User1715503494 posted

    Add runAllManagedModulesForAllRequests="true" to your modules tag in the <system.webServer> section. Link to reference.

    Thanks Sweeperq
    I just figured it out when you posted, nog the extensionless rewrite works, but the site does not accept css styles anymore (strange, very strange)
    In IIS i added a Managed Module (MyOwn) module and added the application to the default application pool, all the request are handled correct now, but stylesheets are ignored. When i add the application to the classic .net application pool styles are reset [:|]
    On the other hand it went to easy, i'm getting kinda custom to struggling to get things working as i want them to work.

    Maybe you know why the css is ignored?

    Thanks

    Tuesday, January 6, 2009 11:38 AM
  • User1696511887 posted

    Do a request for the stylesheet.  Is it giving you the contents of Default.aspx instead of the css file?  After all, you have just told IIS to send everything to your rewrite module.  That is why I have a file existence check in my code.

    Tuesday, January 6, 2009 12:05 PM
  • User1715503494 posted

    Thats right, it gives me all the content of the page but not the layout, so only text and navigation is displayed in its native form.
    But rewriting works extensionless, now get the best of both worlds but how??

    Tuesday, January 6, 2009 12:12 PM
  • User1696511887 posted

    Do a file existence check in your rewrite module.  If File.Exists don't do anything.  If not, rewrite.

    Tuesday, January 6, 2009 12:20 PM
  • User1715503494 posted

    I understand, but there must be another way, i can't check for all files in my app just to do a rewriting.
    it would be a performance killer.

    Tuesday, January 6, 2009 12:31 PM
  • User1696511887 posted

    If you're that worried about performance, you shouldn't be doing extensionless rewrites--all file types are being processed and served by the aspnet_isapi.dll instead of just the dynamic ones.  The easy solution would be to pick a standard extension like .html and stick to it.  This would allow you to port across different platforms in the future if necessary.

    Secondly, is it really that expensive to check if a file exists?  What makes you think it would be a performance killer? If I'm not mistaken, the new MVC stuff checks for file existence before routing.  I'm sure you have much more process intensive code to worry about.

    Tuesday, January 6, 2009 1:23 PM
  • User1715503494 posted

    Then i must misunderstood what you ment by file checking, the problem is that all css files are loaded, but not applied, must i check on css file existence before rewriting.

    Tuesday, January 6, 2009 1:47 PM
  • User1696511887 posted

    Using your code above...

    Namespace MyRequestHandler
    Public Class UrlRewrite
    	Implements IHttpModule
    
    	Public Sub Init(ByVal context As System.Web.HttpApplication) Implements System.Web.IHttpModule.Init
    		AddHandler context.BeginRequest, AddressOf context_BeginRequest
    	End Sub
    
    	Private Sub context_BeginRequest(ByVal sender As Object, ByVal e As EventArgs)
    		Dim context As HttpContext = CType(sender, HttpApplication).Context
    		If Not System.IO.File.Exists(context.Request.PhysicalPath) Then
    			context.RewritePath("~/Default.aspx")
    		End If
    	End Sub
    
    	Private Sub Dispose() Implements System.Web.IHttpModule.Dispose
    	End Sub
    
    End Class
    End Namespace
    Tuesday, January 6, 2009 2:17 PM
  • User1715503494 posted

    Using your code above...

    Namespace MyRequestHandler
    Public Class UrlRewrite
    	Implements IHttpModule
    
    	Public Sub Init(ByVal context As System.Web.HttpApplication) Implements System.Web.IHttpModule.Init
    		AddHandler context.BeginRequest, AddressOf context_BeginRequest
    	End Sub
    
    	Private Sub context_BeginRequest(ByVal sender As Object, ByVal e As EventArgs)
    		Dim context As HttpContext = CType(sender, HttpApplication).Context
    		If Not System.IO.File.Exists(context.Request.PhysicalPath) Then
    			context.RewritePath("~/Default.aspx")
    		End If
    	End Sub
    
    	Private Sub Dispose() Implements System.Web.IHttpModule.Dispose
    	End Sub
    
    End Class
    End Namespace

    This works like a charm.
    I was looking into rebaseClientPath, what was looking very promising and simple, but that didn't work neider.
    So Sweeperq thanks for you effort and patience.
    Your solution works great.

    One more question, is this going to work for all resoures e.g. javascript, flash, ....etc.

    Thanks again

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, January 6, 2009 3:03 PM
  • User1696511887 posted

    Since you basically set up a wildcard mapping to push everything through the module, yes, it should work for all file types.

    Wednesday, January 7, 2009 12:25 AM