IIS URL rewrite not working, the input URL not even captured? - asp.net-mvc

The Failed Request Tracing works fine to log failed rewritings. I can view the log files and at least understand why the rewriting not working.
The regex pattern has passed a matching test OK, but the input URLs I enter in the browser are not even captured. All the URLs mapped to controller actions are captured (my website is an ASP.NET MVC app) however the URL I need to be rewritten is not mapped to any, the page shows 404. But I expect it to be rewritten to some working URL (to test it out, so that instead of showing 404, it should be rewritten to the target url and shows the returned content from there).
My URL rewriting rule uses a Reverse Proxy template.
I hope what I understand here is correct. How can I diagnose this? My purpose is just to do something like turning IIS into a reverse proxy by capturing all requests through my website, check if any matching the defined regex pattern before requesting to the rewritten URL and returning back the content to the original client.
Update
For those who may not know about ASP.NET MVC:
Suppose my website has a controller called HomeController with action Index and the URL mapped to it is /Home/Index.
The URL I mean not mapped to any action here may be /Home/TestProxy
Here the HomeController does not expose any action TestProxy and also there is not any routing rule maps /Home/TestProxy to any action. So in this case the ASP.NET MVC app will shows a 404 page.
As I said above, for the URLs mapped to a valid controller action, they seem to be captured and considered as input URLs (before being checked against the rewriting rule). But for URLs not mapped to any controller action (showing 404), I don't see any logged as input URLs (so of course they will not be checked against the rewriting rule and it won't work).
Update 2
Actually my tested URL is not even mapped to a controller so looks like it's not logged by the Failed Requests Tracing rule I setup. Now I've tried using a URL mapped to a controller but not to any action (it still shows 404) but successfully logged by the Failed Request Tracing rule. I can see this in the log file:
<EventData>
<Data Name="ContextId">{80000034-0000-F000-B63F-84710C7967BB}</Data>
<Data Name="Pattern">testproxy/(.*)</Data>
<Data Name="Input">home/testproxy/index</Data>
<Data Name="Negate">false</Data>
<Data Name="Matched">true</Data>
</EventData>
So it reported a matched pattern, but still the page shows 404, whereas I expected it to return the content from the rewritten url (which should be http://10.0.0.5/index - I confirm that this URL works if requested directly, it's just another simple published website on local network). I don't even know if this is possible now or I did something wrong here.

URL rewrite inbound rule get executed before controller action.It is appreciated if you could post full error message in your Failed request tracing log.
If the request http://10.0.0.5/index but return 404 from IIS. It sounds like your ARR proxy was not enabled at all. First of all, please try to disable reverse proxy outbound rule. Then go to IIS manager->server node->application request routing cache->Server proxy setting->Enable proxy.
Update:
The rewrite rule has worked and it seems that the request was stopped by
[HttpException]: The controller for path '/questions/62078944/iis-url-rewrite-not-working-the-input-url-not-even-captured' was not found or does not implement IController.
at System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType)
at System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory)
at System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStepImpl(IExecutionStep step)
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
-->"

Related

ServiceStack DefaultRedirectPath not triggering

I'm using ServiceStack in an MVC4, VS2012 project running on windows7. I'm attempting to call a default "/search" route when the application loads. To do this I have the following code in my AppHost Configure method
Plugins.Add(new RazorFormat());
SetConfig(new EndpointHostConfig
{
ServiceStackHandlerFactoryPath = "api",
DefaultRedirectPath = "/search"
});
If I call this route directly (via /api/search) it works correctly. However when I run my project I simply get a HTTP Error 403.14 - Forbidden error. It's appears to be attempting to locate a static source document from the website root (I've removed all of these) rather than the dynamic route specified in DefaultRedirectPath
I've also added a HttpHandler via the CatchAllHandlers method to see if the route is being attempted but it appears the DefaultRedirect is simply not happening.
Any suggestions would be greatly appreciated. From everything I've read this should just work.
I'm assuming that you've set up your /api path correctly in web.config too.
DefaultRedirectPath is just a simple redirect used when you request the root of your API (i.e. "/api"). It literally returns a 302 with your DefaultRedirectPath as the Location header (combined with the application root URL, if your ASP.NET application isn't at the root of the server). In other words, it's not a "route", just a relative URL. And in your case, it will redirect to /search in the root of your application, not to /api/search.
It should work, if you use DefaultRedirectPath = "/api/search".
However, when ServiceStack isn't at the root of the website, it will use MetadataRedirectPath first, and only if that is null or empty, DefaultRedirectPath. So you'll need to set MetadataRedirectPath to null, if this is what you want.
As for your test with CatchAllHandlers, as far as I can tell, CatchAllHandlers will actually cause your DefaultRedirect to not be used - the CatchAllHandler will be used as a handler, and the DefaultRedirectHandler that does the DefaultRedirectPath redirect won't ever come into play.
That will take care of redirecting from "/api" to "/api/search".
MVC is in control of your root url - the "api" addition to web.config and AppHost.Config does exactly that - keep ServiceStack only in control of "/api", while letting MVC take care of the rest. So, with that setup, if you want a redirect from "/" to "/api/search", you'd need to do it in the MVC home controller.

http module cant get correct page url

Hi i got a very noob question to ask . I am using http module to do a access right. Let say the user is 'admin' then he got authorized to view the page.The http module will get the access right from the database based on the page url, thereafter the http module will determine the user is allowed to access or not .
Here is my sample coding :
public void Init(HttpApplication context)
{
context.AcquireRequestState += new EventHandler(context_AcquireRequestState1);
}
void context_AcquireRequestState1(object sender, EventArgs e)
{
try
{
string requestUrl = application.Request.AppRelativeCurrentExecutionFilePath.ToString().Trim();
//return last string of .aspx
string requestAspx = requestUrl.Substring(requestUrl.LastIndexOf('/') + 1).Trim();
}
but the httpmodule will run several time. It cant get the url correctly.
For example first time it may get ~/Module/Admin/Role/RoleManagementList.aspx.
then second time will get the wrong url ~/favicon.ico.Can anyone help me solve this problem? thank you so much
You are not getting the "wrong" url. The user's browser is simply making a different request for a different resource. You http module will execute for each http request, which will mean one for each resource in addition to the "page" such as favicons (displayed in the browsers url, and sometimes requested even if you don't have one) or images, external .css, external .js files, etc. referenced on the page (unless they are directly served by IIS bypassing the ASP.NET stack). You will need to consider all of these urls in your module.
Depending on how tightly you control your deployment environment,you may also/instead be able to exempt certain file extensions from every hitting asp.net by having IIS simply serve them directly. See http://msdn.microsoft.com/en-us/library/ms972953.aspx

MVC .NET Urls aren't routed using the RouteCollection

We're using MVC .NET and the RouteCollection class to route URLs in our web app. This functions normally until we pass a URL containing the the text "PRN" anywhere inside the URL. When this happens, the routing will not occur and a 400 Page Not Found error is returned to the client. It's like something is throwing the error before the routing collection is even consulted, because the route the URL should take is never touched (by that I mean the underlying code's break-point is never hit, though the exact same URL without the string "PRN" will hit the break-point).
So I thought it might be a page validation issue, that maybe Microsoft decided to throw exceptions when the URL contains the phrase "PRN" because it is like "print" or "porn" but if that were the case then we'd see the "A potentially dangerous Request.Form value was detected from the client" error, but we don't.
Researching this has been a hassle because Google thinks PRN should return results for "porn", which means 98% of my search results are invalid (and inappropriate). Using the "-porn" clause in Google drops your results down to about 10-30 hits, all useless.
Does anyone know why a URL containing the string "PRN" will not route properly? If you have any posts or threads to point me to, that would be awesome (again, Google has failed me).

Rails 404 handler for non-Rails URLs

I've inherited a site with hundreds of scattered HTML and non-framework PHP files, which I am porting to Ruby on Rails 3.0.
As functionality is added in the Rails app, the corresponding pages are deleted from the document root; but, because there are often links to these in Google or from external sites, simply returning a 404 is not acceptable.
A URL like '/contact.php' should redirect to '/app/contact/', for example.
For the first few cases of this, I created simple stub html files at the old locations, with Meta tags within to perform the redirect. This doesn't scale well, particularly once I start replacing product pages, of which there are thousands.
My preference is to delete the old pages, then have the 404 handler dispatch these to the new Rails app, which will examine the URL using regexes and database lookup to try to figure out what the replacement page is, then issue a 301 redirect to that new page.
In httpd.conf, I placed the directive:
ErrorDocument 404 /app/error/handle404
# /app/error is a rails url.
When I hit "http://localhost/does-not-exist", this causes my ErrorController to be invoked, as expected.
However, within the controller, I cannot find the original path ("/does-not-exist") anywhere in request, request.headers, or ENV - I've been calling likely methods like request.request_uri (which contains /app/error/handle404), and examining request.headers and ENV without finding the expected original path.
The Apache access_log shows only the request for /does-not-exist, indicating that it transparently invoked /app/error/handle404 (without doing a redirect or causing a second request to be made).
How can I get access to the original URL?
Edit: to clarify, here is the sequence of events:
User hits legacy path like http://mysite/foo.php, probably coming from some ancient link from a blog.
...but foo.php no longer exists!
this is a 404, thus Apache invokes ErrorDocument
directive is "ErrorDocument 404 /railsapp/error/handle404"
Rails routes this to ErrorController action "handle404" - this is working correctly
problem: in ErrorController, request.request.uri, request.headers do not provide any clue as to which URL the user was actually trying to get to, like "/foo.php"; I need to know the original URL to serve up an appropriate replacement page.
As I couldn't find the original, non-rewritten URL in the Rails request, I ended up doing it in PHP - plain, old-fashioned, non-framework PHP with explicit mysqli_*() calls.
The PHP error handler receives the necessary information in the $_SERVER hash; $_SERVER['REQUEST_URI'] contains the original URI that I needed.
I look this up in a database, and if I find a corresponding entry, issue a 301 redirect to the new location; if there's no entry, I simply display a 404 page to the user.
Simplified (PHP):
$url = $_SERVER['REQUEST_URI'];
$redir = lookupRedirect($url); # database stuff here
if (! $redir) {
include ('404.phtml');
} else {
header("Status: 301");
header("Location: " . $redir['new_url']);
}
It's an ugly kluge, but I just couldn't find a way to make the Rails app aware of the error URL.

Verify that a URL maps to an actual route in ASP.Net MVC

To support legacy URLs in my application, I use a regex to convert URLs of the form /Repo/{ixRepo}/{sSlug}/{sAction} to the new form /Repo/{sName}/{sAction}, using the ixRepo to get the correct sName. This works well, and I can redirect the user to the new URL with a RedirectResult.
However, I'd like to catch legacy URLs with an invalid action before I redirect the user. How can I verify if a URL string will map to a registered route? MVC clearly does this internally to map a request to the correct action, but I'd like to do it by hand.
So far, I've come up with this:
var rd = Url.RouteCollection.GetRouteData(new HttpContextWrapper(new HttpContext(
new HttpRequest("", newPath, ""),
new HttpResponse(null))));
which appears to always return a System.Web.Routing.RouteData, even for bad routes. I can't find a way to check if the route was accepted as a catch all, or if actually mapping to a route that's registered on the controller.
How can I use MVC's routing system to check if a URL maps to a valid controller/action via a registered route?
(I've seen ASP.NET MVC - Verify the Existence of a Route, but that's really inelegant. MVC has a routing system built in, and I'd like to use that.)
Wrong question. Anything can be a route, whether or not it actually maps to an action.
I think you're asking, "Will this execute OK, or will it 404?" That's a different question.
For that, you need to do what MVC does. Look in the MVC source at MvcHandler.ProcessRequestInit and then ControllerActionInvoker.InvokeAction to see how MVC looks up the controller and action, respectively.
If you know the controller and ask for valid actions, just do some reflection stuff as done in here.
If the redirected url goes to your application, then you can check if the url goes to a valid route. Some code on haacked.com http://haacked.com/archive/2007/12/17/testing-routes-in-asp.net-mvc.aspx does route testing as a unit test. After this you have controller and action as routedata and you have to do, what Craig said "do the same as mvc does".
The routing system maps request uris to route handler. The mvc route handler (class) throws an exception if it fails. There is no checking.
You can add constraints to your routes. If you constrain the action property. Then checking if the url goes to a valid route my be what you want.

Resources