Can custom IHttpHandler revert to default request handling? - asp.net

I'm writing a custom HttpHandler to process web requests for a web framework I'm writing but trying to find a way to programatically "ignore" the request if no url route is matched. What I mean by ignore is if no predefined route matches the incoming request url to then default to the standard request processing you would get if you were using a raw ASP.Net web application.
The only way I can find that actually works so far is to remove the custom http handler for a specific path, e.g.:
<location path="Test">
<system.webServer>
<handlers>
<remove name="DefaultHandler"/>
</handlers>
</system.webServer>
</location>
I'm not massively satisfyed with this solution and would like to implement something akin to MVC's IgnoreRoute("..."). Digging through ths source though is a bit of a thankless task and I can't see where it's actually doing it.
So ideally I'd like to know if it's possible to somehow exit the custom http handler and let the application handle it in a default manner or find out how MVC does this.
Anyone have any ideas?
Thanks.

I don't think you can do it in an Httphandler.
Consider using an HttpModule. This is also how MCV routing works.

Related

Executing a managed module for a rewritten URL in IIS7 Integrated Mode

In my ASP.NET app, I have two HTTP modules. One of them is used for rewriting URLs, the other is used for app-specific stuff (custom authentication .. etc). The URL-Rewriting module is executed for all requests, while the other module is only executed for managed file extensions, like .aspx
Here's how the modules are defined in web.config (note that preCondition is blank for UrlRewriteModule. This cause it to get executed for all requests):
<system.webServer>
<modules>
<add name="UrlRewriteModule" type="MySite.UrlRewriteModule" preCondition="" />
<add name="SiteModule" type="MySite.SiteModule" preCondition="managedHandler" />
</modules>
</system.webServer>
In UrlRewriteModule I use RewritePath() to rewrite some URLs (directory-like) into files with query strings. For example, from "/p/5/some-thoughts-about-the-future/" to "/post.aspx?id=5"
Now, I was under the impression that when a URL gets rewritten, IIS7 executes the managed module (SiteModule in this case) if the new URL is for a managed extension (like .aspx). But, this doesn't seem to be the case. I noticed that SiteModule doesn't get executed for any rewritten URLs.
Am I missing something (or doing something wrong) or is this the normal behavior in IIS7?
I came across Server.TransferRequest() which actually solves the problem (behind the scence, it involves creating a new child request). But, this can also cause a lot of overhead esp. under server load, and I generally prefer to avoid it.
So, is there a way to get SiteModule to execute whenever a URL gets rewritten without using Server.TransferRequest()?
Thanks!

Basic authentication in asp.net avoided if runAllManagedModulesForAllRequests="True"

We have one module which does internal redirection to real aspx pages. He is also in charge for directly serving cached/compressed HTML/txt/cs/js output to client.
Here is how web.config looks like for modules section:
<modules runAllManagedModulesForAllRequests="True">
<remove name="RequestInterceptor" />
<add type="Lib.Request.RequestInterceptor" name="RequestInterceptor" />
<remove name="Session" />
<add type="System.Web.SessionState.SessionStateModule" name="Session" />
</modules>
Basic authentication is turned on on IIS7. When first visitor comes to site login popup shows and he is correctly authenticated, and then pages which he visits get cached.
When next visitor comes authentication pop up doesn't show up, unless he visits a page which was not visited by previous visitor (page that is not cached). Once the cache has expired, authentication works again until the page content gets cached, and so on.
Is there a way to force authentication for every visitor? Maybe we need to add basic authentication module to module section of web.config (how to do that)?
Thanks in advance.
Cheers
While searching for an answer to a related question I came across this post:
Don't use runAllManagedModulesForAllRequests="true" when getting your MVC routing to work
It seems to be common advice to make your modules section of your
web.config say . In
fact this is quite a drastic thing to do to solve the routing problem
and has global effects that could CAUSE ERRORS. ... This highly
recommended fix can cause other problems. These problems come in the
form of making all your registered HTTP modules run on every request,
not just managed requests (e.g. .aspx). This means modules will run on
ever .jpg .gif .css .html .pdf etc.
And, while I'm not using MVC in my WCF REST Service, it did fix my (other) problem and this advice against inappropriate or overuse of runAllManagedModulesForAllRequests may be warranted.
Because httpmodule intercepts each request, server is not able to map appropriate handler for static files, dynamic files, and among others secuirty authentication.

What's the difference between making a handler w/ ashx/axd and using something I made up myself in ASP.NET?

This is probably very simple but it's really confusing me. When I implement the IHttpHandler, I create a handler and then register it like so in the web.config:
IIS6 Portion:
<httpHandlers>
<add verb="*" path="*.randomextension" type="MyProgramNameSpace.MyHandler" />
</httpHandlers>
IIS7 Portion:
<handlers>
<add name="mine" verb="*" path="*. randomextension" type ="MyProgramNameSpace.MyHandler" />
</handlers>
It seems to work quite well and get to use different handlers and options for it. It let's me skip the Page class and so forth by directly accessing the pipeline. However, every so often I keep running into documentation where it says I need to use something about ashx or axd with something.
What is all this about? How does this have to do w/ handler creations?
This is probably very easy but for some reason I'm completely confused when going about this ashx or axd handler.
The .asxh handler is simply a pre-existing/pre-defined generic handler mapping. Unlike the .aspx handler, you are not restricted to deriving from Page, and you don't get the full ASP.NET page handler event pipeline. Generally, you use .ashx files to handle non-page requests that take as input or return as output non-standard content.
The different from an .ashx handler and a custom IHttpHandler is not much, really. A lot of configuration is predefined for .ashx files, but, you are bound to that extension. With a full custom IHttpHandler, you have complete and total freedom, but need to configure it from the ground up.
There really isn't a difference. .ashx files implement IHttpHandler just like you are doing. Only .ashx is a pre-registered handler so you don't need to add it to the web.config yourself it's already done for you.
If you are deciding to use the extension by file type your handler is appropriate.
If on the other hand, you are trying to return data, without a particular extension, the ashx/ahd extension is just as good.
For example, if you have a collection of images stored in a database, you could register a .JPG handler, that would pull the image from the database instead of the hard drive. You could also create an ASHX that could return any image type.
Registering an extension could make the url look more "normal" to the end user, while an ashx looks more generic (even geeky).

Is it possible to restrict certain ASMX web service methods to GET or POST only?

Unfortunately, I'm doing some work on a (legacy) project that is build with ASP.NET Web Forms. I can't migrate it to ASP.NET MVC (so please don't suggest that as an answer).
I wish to create an API to expose some of our data. So, I went a head and made a web service. Pretty simple stuff. BUT, for the first few methods, I wish to expose them only as HTTP-GET. For my last method, I wish to expose this only as HTTP-POST.
I'm so used to using ASP.NET MVC, which is why I really love this RESTful way of programming, but I'm not sure how to do this with my web service?
I'm using a URL Rewriter, so that handles the 'RESTfull' consuming of the api (it's lame, but it works).
So, is there a way to block a web service to only accept the HTTP verb?
Add the following above the method declaration:
[ScriptMethod(UseHttpGet = false)]
This forces the method to respond only to POST. Set to true if you want the method to respond to GET. The gotcha here is that you need to be using ASP.NET 3.5 or the ASP.NET AJAX Extensions for ASP.NET 2.0. You can read more about this here
You can enable GET in the web.config, using:
<configuration>
<system.web>
<webServices>
<protocols>
<add name="HttpGet"/>
<add name="HttpPost"/>
</protocols>
</webServices>
</system.web>
</configuration>
To restrict a single method to POST, you can test HttpContext.Current.Request.HttpMethod at runtime.
I'm pretty sure the .net web service class accepts only posted variables.

Something faster than HttpHandlers?

What is the fastest way to execute a method on an ASP.NET website?
The scenario is pretty simple: I have a method which should be executed when a web page is hit. Nothing else is happening on the page, the only rendered output is a "done" message. I want the processing to be as fast as possible.
Every single hit is unique, so caching is not an option.
My plan is to use an HttpHandler and configure it in web.config (mypage.ashx) rather than a regular .aspx page. This should reduce the overhead significantly.
So my question is really: Is there a faster way to accomplish this than using HttpHandlers?
Depending on what you're doing, I wouldn't expect to see a lot of improvement over just using an HttpHandler. I'd start by just writing the HttpHandler and seeing how it performs. If you need it to be faster, try looking more closely at the things you're actually doing while processing the request and seeing what can be optimized. For example, if you're doing any logging to a database, try writing to a local database instead of across a network. If it's still not fast enough, then maybe look into writing something lower level. Until that point though, I'd stick with whatever's easiest for you to write.
For reference, I've written an ad server in ASP.NET (using HttpHandlers) that can serve an ad (including targeting and logging the impression to a local database) in 0-15ms under load. I thought I was doing quite a bit of processing - but that's a pretty good response time IMHO.
Update after several months:
If you clear all the HttpModules that are included by default, this will remove a fair amount of overhead. By default, the following HttpModules are included in every site via the machine-level web.config file:
OutputCache
Session (for session state)
WindowsAuthentication
FormsAuthentication
PassportAuthentication
RoleManager
UrlAuthorization
FileAuthorization
AnonymousIdentification
Profile
ErrorHandler
ServiceModel
Like I said above, my ad server doesn't use any of these, so I've just done this in that app's web.config:
<httpModules>
<clear />
</httpModules>
If you need some of those, but not all, you can remove the ones you don't need:
<httpModules>
<remove name="PassportAuthentication" />
<remove name="Session" />
</httpModules>
ASP.NET MVC Note: ASP.NET MVC requires the session state module unless you do something specific to workaround it. See this question for more information: How can I disable session state in ASP.NET MVC?
Update for IIS7: Unfortunately, things aren't quite as simple in IIS7. Here is how to clear HTTP Modules in IIS7
I'm not sure what your exact scenario is, but if all your page is doing is processing some data, you don't really need an aspx page or an http handler at all. You could write an ASMX web service or WCF service to do what you need and this would most likely be less overhead. The WCF service doesn't even have to be hosted in ASP.NET. You can host it from a Windows service or console app, and call it in-proc using named pipes. This would probably reduce the overhead for calling the data processing code significantly.
If you really have to use asp.net, you can also just hook into AuthorizeRequest step and intercept the request from there, do your processing and write your Done response directly.

Resources