Let me state off the bat that I'm not that familiar with ASP.Net MVC, and I don't think I have time for this project to become familiar and switch.
I'm building a website where there's only one physical page, mysite.com/default.aspx. If a user browses to mysite.com/foo/bar, I (somehow) want my default.aspx to handle that request. I know it sounds very "route"/"controller" oriented...but is there some way to do this without switching over whole-hog to MVC?
Also of note is that the site will also have static images and things that I don't want served up by my page...so the resulting html of mysite.com/foo/bar may have html that includes an img tag with a src of mysite.com/images/foo.gif, so I need to be able to preclude certain folders/files/whatnot from being processed.
What you're talking about is called URL rewriting and yes, an ASP.Net forms application is capable of it. This entry seems to explain the technique fairly well here:
http://weblogs.asp.net/scottgu/archive/2007/02/26/tip-trick-url-rewriting-with-asp-net.aspx
To allow HTTP rewrites to work on files that do not exist in IIS 6 you'll need to implement wildcard mapping. ASP.Net MVC falls prey to this same issue so even though you're not using ASP.Net MVC this article is still relevant:
http://haacked.com/archive/2008/11/26/asp.net-mvc-on-iis-6-walkthrough.aspx
Scroll down to the heading: "IIS6 Extension-less URLs"
If you need to figure out how to get to the IIS property window displayed scroll up a bit for some context. Just ignore the part about .mvc extensions.
You could probably set up IIS to redirect all 404 requests to your website. If I remember correctly, there's a bug in IIS 6 (if that's what you're running) that will return a 200 status code, allowing you to do your normal processing.
Otherwise, you could use the tag in your web.config to handle the redirect--however, I think this might return the 404 error code.
Hope that helps!
I think I have something working, in IIS7...but it seems kind of brittle:
I have an HttpModule, setup like this:
<modules runAllManagedModulesForAllRequests="true">
<remove name="ScriptModule" />
<add name="ScriptModule" preCondition="managedHandler" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add name="MyRewriteModule" preCondition="managedHandler" type="MyWeb.MyRewriteModule, MyWeb" />
</modules>
and my module has code as follows:
void context_BeginRequest(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
HttpRequest request = app.Context.Request;
List<string> ignoreExtensions = new List<string>() { "axd", "gif", "ico" };
if(ignoreExtensions.TrueForAll(s => !request.FilePath.ToLower().EndsWith(s)))
app.Context.RewritePath("~/default.aspx", request.Path, request.QueryString.ToString(), true);
}
Obviously I would cache and expand that list...but overall it seems to work. Can anyone point out any obvious drawbacks?
Just modify your 404 error pages to redirect to default.aspx.
Related
I have created a simple HttpModule which removes whitespaces from response before sending it to the client. This works fine for an aspx page on IIS7.0 but if i create a static html page and call it, the HttpModule does not kick in (the way i know is because the source contains whitespaces, which otherwise should have been removed). Apparently there is something i m not doing right, but dont know what.
My website is in an Application Pool with .NET 4.0 and ManagedPipelineMode = Integrated.
I have added my module as a ManagedModule and refers to an strong-name-key assembly from GAC.
thanks
Edit- here is the system.webserver part from web.config
<system.webServer>
...
<modules runAllManagedModulesForAllRequests="true">
<add name="RemoveWhitespaceHttpModule"
type="HttpModules.Modules.RemoveWhitespaceHttpModule, HttpModules,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=8a83u4bi47o9fo0d"
preCondition="" />
</modules>
<defaultDocument>
<files>
<add value="TestForm.aspx" />
</files>
</defaultDocument>
</system.webServer>
Edit- Fixed it. For anyone interested, this is how my module checks the response and then decides whether to proceed with whitespace removal or not
if (contentType.Equals("text/html")
&& httpContext.Response.StatusCode == 200
&& httpContext.CurrentHandler != null)
{ ... }
The problem was with the third condition above httpContext.CurrentHandler != null. when calling this module for static .html pages, the currentHandler was null and hence the code never went inside to manipulate html. i have removed this third condition and it works now. thanks for your answers everyone
This should do the trick, in the web.config:
<modules runAllManagedModulesForAllRequests="true"></modules>
This is a quick and easy solution, but can cause issues / performance issues.
You need to look at the Handler Mapping in your IIS.
How a handler works is that on IIS, the handler is registered and supposed to handle a particuler type of page. You can look at the "Handler Mappings" in the IIS [In the run command type inetmgr and hit enter. IIS Manager will pop up and look for Handler Mappings in the IIS section.]
I would like to use a configuration in the .config file like this:
<appSettings>
<add key="SiteIsActive" value="false"/>
<add key="SiteNonActive_RedirectTo" value="UnderMaintainance.aspx"/>
</appSettings>
So that, when the setting is set to the false value, the system automatically redirects EVERY REQUEST to the maintainance page.
I tried to do this in this way: using Global.asax's Application_BeginRequest:
protected void Application_BeginRequest(object sender, EventArgs e) {
if ((bool)System.Configuration.ConfigurationManager.AppSettings["SiteIsActive"])
if (this.Request.Path.IndexOf(
System.Configuration.ConfigurationManager.AppSettings["SiteNonActive_RedirectTo"]) == -1)
this.Response.Redirect(
System.Configuration.ConfigurationManager.AppSettings["SiteNonActive_RedirectTo"]);
}
Basically it works, but when redirecting in this way, firefox will show me the page WITHOUT any image or style applied... it's strange, I look at the page source downloaded by the browser and everything is there!
Is this the right way to achieve my objective?
Do I do anything wrong?
Thankyou
PS: Internet Explorer does not behave like firefox, it shows me the redirected page correctly.
PS2: You guys correctly posted me that a feature called App_Offline is available. Well, I would like not using it for one reason: I would like to use my maintainance page not only to show one status, but more statuses, for example:
1) Maintainance
<appSettings>
<add key="SiteIsActive" value="false"/>
<add key="SiteNonActive_RedirectTo" value="UnderMaintainance.aspx?S=Maintainance"/>
</appSettings>
2) Under construction
<appSettings>
<add key="SiteIsActive" value="false"/>
<add key="SiteNonActive_RedirectTo" value="UnderMaintainance.aspx?S=UnderConstr"/>
</appSettings>
3) Temporary inactivity
<appSettings>
<add key="SiteIsActive" value="false"/>
<add key="SiteNonActive_RedirectTo" value="UnderMaintainance.aspx?S=TempInact"/>
</appSettings>
App_Offline does not offer me this.
There's a much simpler way to do this and it uses a special page called App_Offline.htm.
For more information:
App_Offline.htm - by Scott Guthrie
You might also want to read the follow up by Scott about a gotcha with IE6:
App_Offline.htm and working around the "IE Friendly Errors" feature
When not in use just rename it to something like App_offline.disabled then when you need to do maintenance rename it back to App_Offline.htm again.
A further justification for this approach is that if your "maintenance" includes deploying the site or editing your web.config, your UnderMaintainance.aspx page may fail to execute because your site will be in a state of flux whilst it is being uploaded. Or, you may have made a mistake and overwritten these "maintenance" values in your web.config.
App_Offline.htm is great because it means you can really mess up your deployment and no-one will know.
I recently deployed a new version of an ASP.NET website. This site is built from scratch so urls that worked on the old site do not work on the new one. I've discovered that some of the old pages are requested quite a lot, so I'd like to redirect users trying to get those pages to corresponding new ones.
Let's say the old site had this page:
www.mysite.com/mypage.aspx
And the new site has this corresponding page:
www.mysite.com/pages/mypage.aspx
What is a good (the best) way to redirect requests for the old page to the new page?
My first though was using url mappings in web.config, but that doesn't work for me. The reason is that no real redirect occurs so the right page is shown but the url is not updated in the browser, which leads to the problem that all my relative links get messed up.
Of course I could just recreate the old ASPX pages on the new site and redirect from those, but I don't want to have this "garbage files" in my web project.
Preferably I'd like a solution where I could do all this redirecting in one place. That's what I liked about using url mappings in web.config, but that solution had other problems as mentioned.
Any suggestions?
There are 2 things that come to my mind right now.
A find & replace which is cumbersome yet effective. This is probably
or
You can use the html base tag
http://www.w3schools.com/tags/tag_base.asp
http://www.htmlcodetutorial.com/linking/_BASE.html
But keep in mind that this actually changes ALL the url's (including img urls) in a page.
If it's just a few pages, you could register one single handler for each of the urls and then in the handler redirect to the correct page.
For example
<add name="GetMemberPortrait.aspx_*" path="GetMemberPortrait.aspx" verb="*" type="ExposureRoom.Web.GetMemberPortrait" preCondition="integratedMode"/>
In this web.config file entry (in the handlers section) you see that for the path"GetMemberPortrait.aspx" a specific handler has been registered. That is for that specific "aspx" page the hander specified is instantiated.
The handler can just be a .cs file that implements the IHttpHandler interface. And you can use the same handler to handle all such cases.
For each url, you'll need an entry but you can use the same handler. so for example if you have 3 urls that need redirection called
1. page1.aspx
2. page2.aspx
3. page3.aspx
<add name="page1.aspx_*" path="page1.aspx" verb="*" type="SomeNameSpace.RedirectorHandler" preCondition="integratedMode"/>
<add name="page2.aspx_*" path="page2.aspx" verb="*" type="SomeNameSpace.RedirectorHandler" preCondition="integratedMode"/>
<add name="page3.aspx_*" path="page3.aspx" verb="*" type="SomeNameSpace.RedirectorHandler" preCondition="integratedMode"/>
In your handler, you'll get all of the request parameters as well so you can use those to forward on to the redirected page.
Using the URL Rewrite module for IIS, see http://learn.iis.net/page.aspx/460/using-the-url-rewrite-module/
We still have a lot of incoming urls pointing to our old .asp pages. The new .aspx pages are called the same as the old .asp pages, and accept mostly the same values, so they are pretty much interchangeable. Unfortunately we still get both POST and GET requests to the old .asp pages.
We handled these .asp requests in our Asp.Net 2.0 app by adding this in our web.config (system.webserver section):
<handlers>
<add name="ASPClassicForRedirectToASPX"
path="*.asp"
verb="*"
modules="IsapiModule"
scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll"
resourceType="Unspecified"
preCondition="classicMode,runtimeVersionv4.0,bitness32" />
</handlers>
and then checking in BeginRequest if the url ends with .asp, and if it does, do a RewritePath to .aspx
Now we have migrated to asp.net 4.0 and I started to wonder if there is a better way to handle this, and still keep backwards compatibility with the old .asp urls?
what i would do if not allready the case is something like that in the BeginRequest instead of url rewrite (when possible) :
Response.Clear();
Response.Status = "301 Moved Permanently";
Response.AddHeader("Location","New-url");
Response.End();
using a 301 permanent redirect you will make sure that all crawlers and stuff will change their link to the right one that should reduse the calls u get to your .asp pages by a lot. other than that you are stuck with the old direct links to your asp pages at some point im guessing you will have to let them go. Cant support old stuff forever even tho that would be awesome :)
I've defined a route in Application_Start, as so many tutorials have instructed
RouteTable.Routes.Add(
"Files",
new Route("Files/Art",
new FileRouteHandler()));
And created my own RouteHandler. However this doesn't seem to work at all.
When I debug the application, I can see (via a break point) that the route gets added, however when I browse to "http://localhost/MyApplication/Files/Art" I get a browser 404 (not an ASP.net 404).
When I place a break point in the Route Handler it doesn't break when I access the URL. A break point in Application_BeginRequest doesn't break either when accessing the URL.
This is a problem, but I completely understand why I get a generic 404. How would IIS know to process this URL with asp.net, after all it doesn't really exist??
What am I missing here?
Make sure that you have the UrlRoutingModule installed and configured in the web.config. Something similar to what's shown below:
<system.web>
...
<httpModules>
...
<add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
</httpModules>
</system.web>
I knew it was a web server issue...
http://www.asp.net/%28S%28pdfrohu0ajmwt445fanvj2r3%29%29/learn/mvc/tutorial-08-vb.aspx
Short answer: With IIS 6 and below (5.1 in my case) a path such as "Files/Art" doesn't work. It won't be passed to ASP.net. However, a path such as "Files.svc/Art" will work.
The point is that IIS 6 and below needs a file extension to know what ISAPI plug in to use. In my case ".svc" is configured to use ASP.net.
Hope that makes sense...